作者 郭文星

123

正在显示 58 个修改的文件 包含 4601 行增加1 行删除

要显示太多修改。

为保证性能只显示 58 of 58+ 个文件。

1 /nbproject/ 1 /nbproject/
2 /thinkphp/ 2 /thinkphp/
3 -/vendor/  
4 /runtime/* 3 /runtime/*
5 /addons/* 4 /addons/*
6 /application/database.php 5 /application/database.php
  1 +<?php
  2 +
  3 +require_once __DIR__ . '/composer/autoload_real.php';
  4 +
  5 +return ComposerAutoloaderInita171a4a837511915e525c40585d599c6::getLoader();
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of Composer.
  5 + *
  6 + * (c) Nils Adermann <naderman@naderman.de>
  7 + * Jordi Boggiano <j.boggiano@seld.be>
  8 + *
  9 + * For the full copyright and license information, please view the LICENSE
  10 + * file that was distributed with this source code.
  11 + */
  12 +
  13 +namespace Composer\Autoload;
  14 +
  15 +/**
  16 + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
  17 + *
  18 + * $loader = new \Composer\Autoload\ClassLoader();
  19 + *
  20 + * // register classes with namespaces
  21 + * $loader->add('Symfony\Component', __DIR__.'/component');
  22 + * $loader->add('Symfony', __DIR__.'/framework');
  23 + *
  24 + * // activate the autoloader
  25 + * $loader->register();
  26 + *
  27 + * // to enable searching the include path (eg. for PEAR packages)
  28 + * $loader->setUseIncludePath(true);
  29 + *
  30 + * In this example, if you try to use a class in the Symfony\Component
  31 + * namespace or one of its children (Symfony\Component\Console for instance),
  32 + * the autoloader will first look for the class under the component/
  33 + * directory, and it will then fallback to the framework/ directory if not
  34 + * found before giving up.
  35 + *
  36 + * This class is loosely based on the Symfony UniversalClassLoader.
  37 + *
  38 + * @author Fabien Potencier <fabien@symfony.com>
  39 + * @author Jordi Boggiano <j.boggiano@seld.be>
  40 + * @see https://www.php-fig.org/psr/psr-0/
  41 + * @see https://www.php-fig.org/psr/psr-4/
  42 + */
  43 +class ClassLoader
  44 +{
  45 + /** @var \Closure(string):void */
  46 + private static $includeFile;
  47 +
  48 + /** @var ?string */
  49 + private $vendorDir;
  50 +
  51 + // PSR-4
  52 + /**
  53 + * @var array[]
  54 + * @psalm-var array<string, array<string, int>>
  55 + */
  56 + private $prefixLengthsPsr4 = array();
  57 + /**
  58 + * @var array[]
  59 + * @psalm-var array<string, array<int, string>>
  60 + */
  61 + private $prefixDirsPsr4 = array();
  62 + /**
  63 + * @var array[]
  64 + * @psalm-var array<string, string>
  65 + */
  66 + private $fallbackDirsPsr4 = array();
  67 +
  68 + // PSR-0
  69 + /**
  70 + * @var array[]
  71 + * @psalm-var array<string, array<string, string[]>>
  72 + */
  73 + private $prefixesPsr0 = array();
  74 + /**
  75 + * @var array[]
  76 + * @psalm-var array<string, string>
  77 + */
  78 + private $fallbackDirsPsr0 = array();
  79 +
  80 + /** @var bool */
  81 + private $useIncludePath = false;
  82 +
  83 + /**
  84 + * @var string[]
  85 + * @psalm-var array<string, string>
  86 + */
  87 + private $classMap = array();
  88 +
  89 + /** @var bool */
  90 + private $classMapAuthoritative = false;
  91 +
  92 + /**
  93 + * @var bool[]
  94 + * @psalm-var array<string, bool>
  95 + */
  96 + private $missingClasses = array();
  97 +
  98 + /** @var ?string */
  99 + private $apcuPrefix;
  100 +
  101 + /**
  102 + * @var self[]
  103 + */
  104 + private static $registeredLoaders = array();
  105 +
  106 + /**
  107 + * @param ?string $vendorDir
  108 + */
  109 + public function __construct($vendorDir = null)
  110 + {
  111 + $this->vendorDir = $vendorDir;
  112 + self::initializeIncludeClosure();
  113 + }
  114 +
  115 + /**
  116 + * @return string[]
  117 + */
  118 + public function getPrefixes()
  119 + {
  120 + if (!empty($this->prefixesPsr0)) {
  121 + return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
  122 + }
  123 +
  124 + return array();
  125 + }
  126 +
  127 + /**
  128 + * @return array[]
  129 + * @psalm-return array<string, array<int, string>>
  130 + */
  131 + public function getPrefixesPsr4()
  132 + {
  133 + return $this->prefixDirsPsr4;
  134 + }
  135 +
  136 + /**
  137 + * @return array[]
  138 + * @psalm-return array<string, string>
  139 + */
  140 + public function getFallbackDirs()
  141 + {
  142 + return $this->fallbackDirsPsr0;
  143 + }
  144 +
  145 + /**
  146 + * @return array[]
  147 + * @psalm-return array<string, string>
  148 + */
  149 + public function getFallbackDirsPsr4()
  150 + {
  151 + return $this->fallbackDirsPsr4;
  152 + }
  153 +
  154 + /**
  155 + * @return string[] Array of classname => path
  156 + * @psalm-return array<string, string>
  157 + */
  158 + public function getClassMap()
  159 + {
  160 + return $this->classMap;
  161 + }
  162 +
  163 + /**
  164 + * @param string[] $classMap Class to filename map
  165 + * @psalm-param array<string, string> $classMap
  166 + *
  167 + * @return void
  168 + */
  169 + public function addClassMap(array $classMap)
  170 + {
  171 + if ($this->classMap) {
  172 + $this->classMap = array_merge($this->classMap, $classMap);
  173 + } else {
  174 + $this->classMap = $classMap;
  175 + }
  176 + }
  177 +
  178 + /**
  179 + * Registers a set of PSR-0 directories for a given prefix, either
  180 + * appending or prepending to the ones previously set for this prefix.
  181 + *
  182 + * @param string $prefix The prefix
  183 + * @param string[]|string $paths The PSR-0 root directories
  184 + * @param bool $prepend Whether to prepend the directories
  185 + *
  186 + * @return void
  187 + */
  188 + public function add($prefix, $paths, $prepend = false)
  189 + {
  190 + if (!$prefix) {
  191 + if ($prepend) {
  192 + $this->fallbackDirsPsr0 = array_merge(
  193 + (array) $paths,
  194 + $this->fallbackDirsPsr0
  195 + );
  196 + } else {
  197 + $this->fallbackDirsPsr0 = array_merge(
  198 + $this->fallbackDirsPsr0,
  199 + (array) $paths
  200 + );
  201 + }
  202 +
  203 + return;
  204 + }
  205 +
  206 + $first = $prefix[0];
  207 + if (!isset($this->prefixesPsr0[$first][$prefix])) {
  208 + $this->prefixesPsr0[$first][$prefix] = (array) $paths;
  209 +
  210 + return;
  211 + }
  212 + if ($prepend) {
  213 + $this->prefixesPsr0[$first][$prefix] = array_merge(
  214 + (array) $paths,
  215 + $this->prefixesPsr0[$first][$prefix]
  216 + );
  217 + } else {
  218 + $this->prefixesPsr0[$first][$prefix] = array_merge(
  219 + $this->prefixesPsr0[$first][$prefix],
  220 + (array) $paths
  221 + );
  222 + }
  223 + }
  224 +
  225 + /**
  226 + * Registers a set of PSR-4 directories for a given namespace, either
  227 + * appending or prepending to the ones previously set for this namespace.
  228 + *
  229 + * @param string $prefix The prefix/namespace, with trailing '\\'
  230 + * @param string[]|string $paths The PSR-4 base directories
  231 + * @param bool $prepend Whether to prepend the directories
  232 + *
  233 + * @throws \InvalidArgumentException
  234 + *
  235 + * @return void
  236 + */
  237 + public function addPsr4($prefix, $paths, $prepend = false)
  238 + {
  239 + if (!$prefix) {
  240 + // Register directories for the root namespace.
  241 + if ($prepend) {
  242 + $this->fallbackDirsPsr4 = array_merge(
  243 + (array) $paths,
  244 + $this->fallbackDirsPsr4
  245 + );
  246 + } else {
  247 + $this->fallbackDirsPsr4 = array_merge(
  248 + $this->fallbackDirsPsr4,
  249 + (array) $paths
  250 + );
  251 + }
  252 + } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
  253 + // Register directories for a new namespace.
  254 + $length = strlen($prefix);
  255 + if ('\\' !== $prefix[$length - 1]) {
  256 + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
  257 + }
  258 + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
  259 + $this->prefixDirsPsr4[$prefix] = (array) $paths;
  260 + } elseif ($prepend) {
  261 + // Prepend directories for an already registered namespace.
  262 + $this->prefixDirsPsr4[$prefix] = array_merge(
  263 + (array) $paths,
  264 + $this->prefixDirsPsr4[$prefix]
  265 + );
  266 + } else {
  267 + // Append directories for an already registered namespace.
  268 + $this->prefixDirsPsr4[$prefix] = array_merge(
  269 + $this->prefixDirsPsr4[$prefix],
  270 + (array) $paths
  271 + );
  272 + }
  273 + }
  274 +
  275 + /**
  276 + * Registers a set of PSR-0 directories for a given prefix,
  277 + * replacing any others previously set for this prefix.
  278 + *
  279 + * @param string $prefix The prefix
  280 + * @param string[]|string $paths The PSR-0 base directories
  281 + *
  282 + * @return void
  283 + */
  284 + public function set($prefix, $paths)
  285 + {
  286 + if (!$prefix) {
  287 + $this->fallbackDirsPsr0 = (array) $paths;
  288 + } else {
  289 + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
  290 + }
  291 + }
  292 +
  293 + /**
  294 + * Registers a set of PSR-4 directories for a given namespace,
  295 + * replacing any others previously set for this namespace.
  296 + *
  297 + * @param string $prefix The prefix/namespace, with trailing '\\'
  298 + * @param string[]|string $paths The PSR-4 base directories
  299 + *
  300 + * @throws \InvalidArgumentException
  301 + *
  302 + * @return void
  303 + */
  304 + public function setPsr4($prefix, $paths)
  305 + {
  306 + if (!$prefix) {
  307 + $this->fallbackDirsPsr4 = (array) $paths;
  308 + } else {
  309 + $length = strlen($prefix);
  310 + if ('\\' !== $prefix[$length - 1]) {
  311 + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
  312 + }
  313 + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
  314 + $this->prefixDirsPsr4[$prefix] = (array) $paths;
  315 + }
  316 + }
  317 +
  318 + /**
  319 + * Turns on searching the include path for class files.
  320 + *
  321 + * @param bool $useIncludePath
  322 + *
  323 + * @return void
  324 + */
  325 + public function setUseIncludePath($useIncludePath)
  326 + {
  327 + $this->useIncludePath = $useIncludePath;
  328 + }
  329 +
  330 + /**
  331 + * Can be used to check if the autoloader uses the include path to check
  332 + * for classes.
  333 + *
  334 + * @return bool
  335 + */
  336 + public function getUseIncludePath()
  337 + {
  338 + return $this->useIncludePath;
  339 + }
  340 +
  341 + /**
  342 + * Turns off searching the prefix and fallback directories for classes
  343 + * that have not been registered with the class map.
  344 + *
  345 + * @param bool $classMapAuthoritative
  346 + *
  347 + * @return void
  348 + */
  349 + public function setClassMapAuthoritative($classMapAuthoritative)
  350 + {
  351 + $this->classMapAuthoritative = $classMapAuthoritative;
  352 + }
  353 +
  354 + /**
  355 + * Should class lookup fail if not found in the current class map?
  356 + *
  357 + * @return bool
  358 + */
  359 + public function isClassMapAuthoritative()
  360 + {
  361 + return $this->classMapAuthoritative;
  362 + }
  363 +
  364 + /**
  365 + * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
  366 + *
  367 + * @param string|null $apcuPrefix
  368 + *
  369 + * @return void
  370 + */
  371 + public function setApcuPrefix($apcuPrefix)
  372 + {
  373 + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
  374 + }
  375 +
  376 + /**
  377 + * The APCu prefix in use, or null if APCu caching is not enabled.
  378 + *
  379 + * @return string|null
  380 + */
  381 + public function getApcuPrefix()
  382 + {
  383 + return $this->apcuPrefix;
  384 + }
  385 +
  386 + /**
  387 + * Registers this instance as an autoloader.
  388 + *
  389 + * @param bool $prepend Whether to prepend the autoloader or not
  390 + *
  391 + * @return void
  392 + */
  393 + public function register($prepend = false)
  394 + {
  395 + spl_autoload_register(array($this, 'loadClass'), true, $prepend);
  396 +
  397 + if (null === $this->vendorDir) {
  398 + return;
  399 + }
  400 +
  401 + if ($prepend) {
  402 + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
  403 + } else {
  404 + unset(self::$registeredLoaders[$this->vendorDir]);
  405 + self::$registeredLoaders[$this->vendorDir] = $this;
  406 + }
  407 + }
  408 +
  409 + /**
  410 + * Unregisters this instance as an autoloader.
  411 + *
  412 + * @return void
  413 + */
  414 + public function unregister()
  415 + {
  416 + spl_autoload_unregister(array($this, 'loadClass'));
  417 +
  418 + if (null !== $this->vendorDir) {
  419 + unset(self::$registeredLoaders[$this->vendorDir]);
  420 + }
  421 + }
  422 +
  423 + /**
  424 + * Loads the given class or interface.
  425 + *
  426 + * @param string $class The name of the class
  427 + * @return true|null True if loaded, null otherwise
  428 + */
  429 + public function loadClass($class)
  430 + {
  431 + if ($file = $this->findFile($class)) {
  432 + $includeFile = self::$includeFile;
  433 + $includeFile($file);
  434 +
  435 + return true;
  436 + }
  437 +
  438 + return null;
  439 + }
  440 +
  441 + /**
  442 + * Finds the path to the file where the class is defined.
  443 + *
  444 + * @param string $class The name of the class
  445 + *
  446 + * @return string|false The path if found, false otherwise
  447 + */
  448 + public function findFile($class)
  449 + {
  450 + // class map lookup
  451 + if (isset($this->classMap[$class])) {
  452 + return $this->classMap[$class];
  453 + }
  454 + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
  455 + return false;
  456 + }
  457 + if (null !== $this->apcuPrefix) {
  458 + $file = apcu_fetch($this->apcuPrefix.$class, $hit);
  459 + if ($hit) {
  460 + return $file;
  461 + }
  462 + }
  463 +
  464 + $file = $this->findFileWithExtension($class, '.php');
  465 +
  466 + // Search for Hack files if we are running on HHVM
  467 + if (false === $file && defined('HHVM_VERSION')) {
  468 + $file = $this->findFileWithExtension($class, '.hh');
  469 + }
  470 +
  471 + if (null !== $this->apcuPrefix) {
  472 + apcu_add($this->apcuPrefix.$class, $file);
  473 + }
  474 +
  475 + if (false === $file) {
  476 + // Remember that this class does not exist.
  477 + $this->missingClasses[$class] = true;
  478 + }
  479 +
  480 + return $file;
  481 + }
  482 +
  483 + /**
  484 + * Returns the currently registered loaders indexed by their corresponding vendor directories.
  485 + *
  486 + * @return self[]
  487 + */
  488 + public static function getRegisteredLoaders()
  489 + {
  490 + return self::$registeredLoaders;
  491 + }
  492 +
  493 + /**
  494 + * @param string $class
  495 + * @param string $ext
  496 + * @return string|false
  497 + */
  498 + private function findFileWithExtension($class, $ext)
  499 + {
  500 + // PSR-4 lookup
  501 + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
  502 +
  503 + $first = $class[0];
  504 + if (isset($this->prefixLengthsPsr4[$first])) {
  505 + $subPath = $class;
  506 + while (false !== $lastPos = strrpos($subPath, '\\')) {
  507 + $subPath = substr($subPath, 0, $lastPos);
  508 + $search = $subPath . '\\';
  509 + if (isset($this->prefixDirsPsr4[$search])) {
  510 + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
  511 + foreach ($this->prefixDirsPsr4[$search] as $dir) {
  512 + if (file_exists($file = $dir . $pathEnd)) {
  513 + return $file;
  514 + }
  515 + }
  516 + }
  517 + }
  518 + }
  519 +
  520 + // PSR-4 fallback dirs
  521 + foreach ($this->fallbackDirsPsr4 as $dir) {
  522 + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
  523 + return $file;
  524 + }
  525 + }
  526 +
  527 + // PSR-0 lookup
  528 + if (false !== $pos = strrpos($class, '\\')) {
  529 + // namespaced class name
  530 + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
  531 + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
  532 + } else {
  533 + // PEAR-like class name
  534 + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
  535 + }
  536 +
  537 + if (isset($this->prefixesPsr0[$first])) {
  538 + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
  539 + if (0 === strpos($class, $prefix)) {
  540 + foreach ($dirs as $dir) {
  541 + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
  542 + return $file;
  543 + }
  544 + }
  545 + }
  546 + }
  547 + }
  548 +
  549 + // PSR-0 fallback dirs
  550 + foreach ($this->fallbackDirsPsr0 as $dir) {
  551 + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
  552 + return $file;
  553 + }
  554 + }
  555 +
  556 + // PSR-0 include paths.
  557 + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
  558 + return $file;
  559 + }
  560 +
  561 + return false;
  562 + }
  563 +
  564 + /**
  565 + * @return void
  566 + */
  567 + private static function initializeIncludeClosure()
  568 + {
  569 + if (self::$includeFile !== null) {
  570 + return;
  571 + }
  572 +
  573 + /**
  574 + * Scope isolated include.
  575 + *
  576 + * Prevents access to $this/self from included files.
  577 + *
  578 + * @param string $file
  579 + * @return void
  580 + */
  581 + self::$includeFile = \Closure::bind(static function($file) {
  582 + include $file;
  583 + }, null, null);
  584 + }
  585 +}
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of Composer.
  5 + *
  6 + * (c) Nils Adermann <naderman@naderman.de>
  7 + * Jordi Boggiano <j.boggiano@seld.be>
  8 + *
  9 + * For the full copyright and license information, please view the LICENSE
  10 + * file that was distributed with this source code.
  11 + */
  12 +
  13 +namespace Composer;
  14 +
  15 +use Composer\Autoload\ClassLoader;
  16 +use Composer\Semver\VersionParser;
  17 +
  18 +/**
  19 + * This class is copied in every Composer installed project and available to all
  20 + *
  21 + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
  22 + *
  23 + * To require its presence, you can require `composer-runtime-api ^2.0`
  24 + *
  25 + * @final
  26 + */
  27 +class InstalledVersions
  28 +{
  29 + /**
  30 + * @var mixed[]|null
  31 + * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
  32 + */
  33 + private static $installed;
  34 +
  35 + /**
  36 + * @var bool|null
  37 + */
  38 + private static $canGetVendors;
  39 +
  40 + /**
  41 + * @var array[]
  42 + * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
  43 + */
  44 + private static $installedByVendor = array();
  45 +
  46 + /**
  47 + * Returns a list of all package names which are present, either by being installed, replaced or provided
  48 + *
  49 + * @return string[]
  50 + * @psalm-return list<string>
  51 + */
  52 + public static function getInstalledPackages()
  53 + {
  54 + $packages = array();
  55 + foreach (self::getInstalled() as $installed) {
  56 + $packages[] = array_keys($installed['versions']);
  57 + }
  58 +
  59 + if (1 === \count($packages)) {
  60 + return $packages[0];
  61 + }
  62 +
  63 + return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
  64 + }
  65 +
  66 + /**
  67 + * Returns a list of all package names with a specific type e.g. 'library'
  68 + *
  69 + * @param string $type
  70 + * @return string[]
  71 + * @psalm-return list<string>
  72 + */
  73 + public static function getInstalledPackagesByType($type)
  74 + {
  75 + $packagesByType = array();
  76 +
  77 + foreach (self::getInstalled() as $installed) {
  78 + foreach ($installed['versions'] as $name => $package) {
  79 + if (isset($package['type']) && $package['type'] === $type) {
  80 + $packagesByType[] = $name;
  81 + }
  82 + }
  83 + }
  84 +
  85 + return $packagesByType;
  86 + }
  87 +
  88 + /**
  89 + * Checks whether the given package is installed
  90 + *
  91 + * This also returns true if the package name is provided or replaced by another package
  92 + *
  93 + * @param string $packageName
  94 + * @param bool $includeDevRequirements
  95 + * @return bool
  96 + */
  97 + public static function isInstalled($packageName, $includeDevRequirements = true)
  98 + {
  99 + foreach (self::getInstalled() as $installed) {
  100 + if (isset($installed['versions'][$packageName])) {
  101 + return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
  102 + }
  103 + }
  104 +
  105 + return false;
  106 + }
  107 +
  108 + /**
  109 + * Checks whether the given package satisfies a version constraint
  110 + *
  111 + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
  112 + *
  113 + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
  114 + *
  115 + * @param VersionParser $parser Install composer/semver to have access to this class and functionality
  116 + * @param string $packageName
  117 + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
  118 + * @return bool
  119 + */
  120 + public static function satisfies(VersionParser $parser, $packageName, $constraint)
  121 + {
  122 + $constraint = $parser->parseConstraints((string) $constraint);
  123 + $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
  124 +
  125 + return $provided->matches($constraint);
  126 + }
  127 +
  128 + /**
  129 + * Returns a version constraint representing all the range(s) which are installed for a given package
  130 + *
  131 + * It is easier to use this via isInstalled() with the $constraint argument if you need to check
  132 + * whether a given version of a package is installed, and not just whether it exists
  133 + *
  134 + * @param string $packageName
  135 + * @return string Version constraint usable with composer/semver
  136 + */
  137 + public static function getVersionRanges($packageName)
  138 + {
  139 + foreach (self::getInstalled() as $installed) {
  140 + if (!isset($installed['versions'][$packageName])) {
  141 + continue;
  142 + }
  143 +
  144 + $ranges = array();
  145 + if (isset($installed['versions'][$packageName]['pretty_version'])) {
  146 + $ranges[] = $installed['versions'][$packageName]['pretty_version'];
  147 + }
  148 + if (array_key_exists('aliases', $installed['versions'][$packageName])) {
  149 + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
  150 + }
  151 + if (array_key_exists('replaced', $installed['versions'][$packageName])) {
  152 + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
  153 + }
  154 + if (array_key_exists('provided', $installed['versions'][$packageName])) {
  155 + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
  156 + }
  157 +
  158 + return implode(' || ', $ranges);
  159 + }
  160 +
  161 + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
  162 + }
  163 +
  164 + /**
  165 + * @param string $packageName
  166 + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
  167 + */
  168 + public static function getVersion($packageName)
  169 + {
  170 + foreach (self::getInstalled() as $installed) {
  171 + if (!isset($installed['versions'][$packageName])) {
  172 + continue;
  173 + }
  174 +
  175 + if (!isset($installed['versions'][$packageName]['version'])) {
  176 + return null;
  177 + }
  178 +
  179 + return $installed['versions'][$packageName]['version'];
  180 + }
  181 +
  182 + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
  183 + }
  184 +
  185 + /**
  186 + * @param string $packageName
  187 + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
  188 + */
  189 + public static function getPrettyVersion($packageName)
  190 + {
  191 + foreach (self::getInstalled() as $installed) {
  192 + if (!isset($installed['versions'][$packageName])) {
  193 + continue;
  194 + }
  195 +
  196 + if (!isset($installed['versions'][$packageName]['pretty_version'])) {
  197 + return null;
  198 + }
  199 +
  200 + return $installed['versions'][$packageName]['pretty_version'];
  201 + }
  202 +
  203 + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
  204 + }
  205 +
  206 + /**
  207 + * @param string $packageName
  208 + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
  209 + */
  210 + public static function getReference($packageName)
  211 + {
  212 + foreach (self::getInstalled() as $installed) {
  213 + if (!isset($installed['versions'][$packageName])) {
  214 + continue;
  215 + }
  216 +
  217 + if (!isset($installed['versions'][$packageName]['reference'])) {
  218 + return null;
  219 + }
  220 +
  221 + return $installed['versions'][$packageName]['reference'];
  222 + }
  223 +
  224 + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
  225 + }
  226 +
  227 + /**
  228 + * @param string $packageName
  229 + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
  230 + */
  231 + public static function getInstallPath($packageName)
  232 + {
  233 + foreach (self::getInstalled() as $installed) {
  234 + if (!isset($installed['versions'][$packageName])) {
  235 + continue;
  236 + }
  237 +
  238 + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
  239 + }
  240 +
  241 + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
  242 + }
  243 +
  244 + /**
  245 + * @return array
  246 + * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
  247 + */
  248 + public static function getRootPackage()
  249 + {
  250 + $installed = self::getInstalled();
  251 +
  252 + return $installed[0]['root'];
  253 + }
  254 +
  255 + /**
  256 + * Returns the raw installed.php data for custom implementations
  257 + *
  258 + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
  259 + * @return array[]
  260 + * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
  261 + */
  262 + public static function getRawData()
  263 + {
  264 + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
  265 +
  266 + if (null === self::$installed) {
  267 + // only require the installed.php file if this file is loaded from its dumped location,
  268 + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
  269 + if (substr(__DIR__, -8, 1) !== 'C') {
  270 + self::$installed = include __DIR__ . '/installed.php';
  271 + } else {
  272 + self::$installed = array();
  273 + }
  274 + }
  275 +
  276 + return self::$installed;
  277 + }
  278 +
  279 + /**
  280 + * Returns the raw data of all installed.php which are currently loaded for custom implementations
  281 + *
  282 + * @return array[]
  283 + * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
  284 + */
  285 + public static function getAllRawData()
  286 + {
  287 + return self::getInstalled();
  288 + }
  289 +
  290 + /**
  291 + * Lets you reload the static array from another file
  292 + *
  293 + * This is only useful for complex integrations in which a project needs to use
  294 + * this class but then also needs to execute another project's autoloader in process,
  295 + * and wants to ensure both projects have access to their version of installed.php.
  296 + *
  297 + * A typical case would be PHPUnit, where it would need to make sure it reads all
  298 + * the data it needs from this class, then call reload() with
  299 + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
  300 + * the project in which it runs can then also use this class safely, without
  301 + * interference between PHPUnit's dependencies and the project's dependencies.
  302 + *
  303 + * @param array[] $data A vendor/composer/installed.php data set
  304 + * @return void
  305 + *
  306 + * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
  307 + */
  308 + public static function reload($data)
  309 + {
  310 + self::$installed = $data;
  311 + self::$installedByVendor = array();
  312 + }
  313 +
  314 + /**
  315 + * @return array[]
  316 + * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
  317 + */
  318 + private static function getInstalled()
  319 + {
  320 + if (null === self::$canGetVendors) {
  321 + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
  322 + }
  323 +
  324 + $installed = array();
  325 +
  326 + if (self::$canGetVendors) {
  327 + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
  328 + if (isset(self::$installedByVendor[$vendorDir])) {
  329 + $installed[] = self::$installedByVendor[$vendorDir];
  330 + } elseif (is_file($vendorDir.'/composer/installed.php')) {
  331 + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
  332 + $required = require $vendorDir.'/composer/installed.php';
  333 + $installed[] = self::$installedByVendor[$vendorDir] = $required;
  334 + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
  335 + self::$installed = $installed[count($installed) - 1];
  336 + }
  337 + }
  338 + }
  339 + }
  340 +
  341 + if (null === self::$installed) {
  342 + // only require the installed.php file if this file is loaded from its dumped location,
  343 + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
  344 + if (substr(__DIR__, -8, 1) !== 'C') {
  345 + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
  346 + $required = require __DIR__ . '/installed.php';
  347 + self::$installed = $required;
  348 + } else {
  349 + self::$installed = array();
  350 + }
  351 + }
  352 +
  353 + if (self::$installed !== array()) {
  354 + $installed[] = self::$installed;
  355 + }
  356 +
  357 + return $installed;
  358 + }
  359 +}
  1 +
  2 +Copyright (c) Nils Adermann, Jordi Boggiano
  3 +
  4 +Permission is hereby granted, free of charge, to any person obtaining a copy
  5 +of this software and associated documentation files (the "Software"), to deal
  6 +in the Software without restriction, including without limitation the rights
  7 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8 +copies of the Software, and to permit persons to whom the Software is furnished
  9 +to do so, subject to the following conditions:
  10 +
  11 +The above copyright notice and this permission notice shall be included in all
  12 +copies or substantial portions of the Software.
  13 +
  14 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20 +THE SOFTWARE.
  21 +
  1 +<?php
  2 +
  3 +// autoload_classmap.php @generated by Composer
  4 +
  5 +$vendorDir = dirname(__DIR__);
  6 +$baseDir = dirname($vendorDir);
  7 +
  8 +return array(
  9 + 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
  10 + 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
  11 + 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
  12 + 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
  13 + 'Stringable' => $vendorDir . '/myclabs/php-enum/stubs/Stringable.php',
  14 + 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
  15 + 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
  16 +);
  1 +<?php
  2 +
  3 +// autoload_files.php @generated by Composer
  4 +
  5 +$vendorDir = dirname(__DIR__);
  6 +$baseDir = dirname($vendorDir);
  7 +
  8 +return array(
  9 + '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
  10 + 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
  11 + '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
  12 + '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
  13 + '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
  14 + '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
  15 + '2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
  16 + '9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
  17 + '488987c28e9b5e95a1ce6b6bcb94606c' => $vendorDir . '/karsonzhang/fastadmin-addons/src/common.php',
  18 + 'f0e7e63bbb278a92db02393536748c5f' => $vendorDir . '/overtrue/wechat/src/Kernel/Support/Helpers.php',
  19 + '6747f579ad6817f318cc3a7e7a0abb93' => $vendorDir . '/overtrue/wechat/src/Kernel/Helpers.php',
  20 + '1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php',
  21 + 'cc56288302d9df745d97c934d6a6e5f0' => $vendorDir . '/topthink/think-queue/src/common.php',
  22 +);
  1 +<?php
  2 +
  3 +// autoload_namespaces.php @generated by Composer
  4 +
  5 +$vendorDir = dirname(__DIR__);
  6 +$baseDir = dirname($vendorDir);
  7 +
  8 +return array(
  9 + 'Pimple' => array($vendorDir . '/pimple/pimple/src'),
  10 + 'HTMLPurifier' => array($vendorDir . '/ezyang/htmlpurifier/library'),
  11 +);
  1 +<?php
  2 +
  3 +// autoload_psr4.php @generated by Composer
  4 +
  5 +$vendorDir = dirname(__DIR__);
  6 +$baseDir = dirname($vendorDir);
  7 +
  8 +return array(
  9 + 'think\\helper\\' => array($vendorDir . '/topthink/think-helper/src'),
  10 + 'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'),
  11 + 'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
  12 + 'think\\' => array($baseDir . '/thinkphp/library/think', $vendorDir . '/karsonzhang/fastadmin-addons/src', $vendorDir . '/topthink/think-queue/src'),
  13 + 'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'),
  14 + 'Tx\\' => array($vendorDir . '/txthinking/mailer/src'),
  15 + 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
  16 + 'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'),
  17 + 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
  18 + 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
  19 + 'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'),
  20 + 'Symfony\\Contracts\\Cache\\' => array($vendorDir . '/symfony/cache-contracts'),
  21 + 'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'),
  22 + 'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
  23 + 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
  24 + 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
  25 + 'Symfony\\Component\\Cache\\' => array($vendorDir . '/symfony/cache'),
  26 + 'Symfony\\Bridge\\PsrHttpMessage\\' => array($vendorDir . '/symfony/psr-http-message-bridge'),
  27 + 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
  28 + 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
  29 + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
  30 + 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
  31 + 'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'),
  32 + 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
  33 + 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
  34 + 'PhpZip\\' => array($vendorDir . '/nelexa/zip/src'),
  35 + 'PhpOffice\\PhpSpreadsheet\\' => array($vendorDir . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet'),
  36 + 'Overtrue\\Socialite\\' => array($vendorDir . '/overtrue/socialite/src'),
  37 + 'Overtrue\\Pinyin\\' => array($vendorDir . '/overtrue/pinyin/src'),
  38 + 'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'),
  39 + 'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
  40 + 'Matrix\\' => array($vendorDir . '/markbaker/matrix/classes/src'),
  41 + 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
  42 + 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
  43 + 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
  44 + 'EasyWeChat\\' => array($vendorDir . '/overtrue/wechat/src'),
  45 + 'EasyWeChatComposer\\' => array($vendorDir . '/easywechat-composer/easywechat-composer/src'),
  46 + 'Complex\\' => array($vendorDir . '/markbaker/complex/classes/src'),
  47 +);
  1 +<?php
  2 +
  3 +// autoload_real.php @generated by Composer
  4 +
  5 +class ComposerAutoloaderInita171a4a837511915e525c40585d599c6
  6 +{
  7 + private static $loader;
  8 +
  9 + public static function loadClassLoader($class)
  10 + {
  11 + if ('Composer\Autoload\ClassLoader' === $class) {
  12 + require __DIR__ . '/ClassLoader.php';
  13 + }
  14 + }
  15 +
  16 + /**
  17 + * @return \Composer\Autoload\ClassLoader
  18 + */
  19 + public static function getLoader()
  20 + {
  21 + if (null !== self::$loader) {
  22 + return self::$loader;
  23 + }
  24 +
  25 + require __DIR__ . '/platform_check.php';
  26 +
  27 + spl_autoload_register(array('ComposerAutoloaderInita171a4a837511915e525c40585d599c6', 'loadClassLoader'), true, true);
  28 + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
  29 + spl_autoload_unregister(array('ComposerAutoloaderInita171a4a837511915e525c40585d599c6', 'loadClassLoader'));
  30 +
  31 + require __DIR__ . '/autoload_static.php';
  32 + call_user_func(\Composer\Autoload\ComposerStaticInita171a4a837511915e525c40585d599c6::getInitializer($loader));
  33 +
  34 + $loader->register(true);
  35 +
  36 + $filesToLoad = \Composer\Autoload\ComposerStaticInita171a4a837511915e525c40585d599c6::$files;
  37 + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
  38 + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
  39 + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
  40 +
  41 + require $file;
  42 + }
  43 + }, null, null);
  44 + foreach ($filesToLoad as $fileIdentifier => $file) {
  45 + $requireFile($fileIdentifier, $file);
  46 + }
  47 +
  48 + return $loader;
  49 + }
  50 +}
  1 +<?php
  2 +
  3 +// autoload_static.php @generated by Composer
  4 +
  5 +namespace Composer\Autoload;
  6 +
  7 +class ComposerStaticInita171a4a837511915e525c40585d599c6
  8 +{
  9 + public static $files = array (
  10 + '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
  11 + 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
  12 + '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
  13 + '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
  14 + '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
  15 + '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
  16 + '2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
  17 + '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
  18 + '488987c28e9b5e95a1ce6b6bcb94606c' => __DIR__ . '/..' . '/karsonzhang/fastadmin-addons/src/common.php',
  19 + 'f0e7e63bbb278a92db02393536748c5f' => __DIR__ . '/..' . '/overtrue/wechat/src/Kernel/Support/Helpers.php',
  20 + '6747f579ad6817f318cc3a7e7a0abb93' => __DIR__ . '/..' . '/overtrue/wechat/src/Kernel/Helpers.php',
  21 + '1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
  22 + 'cc56288302d9df745d97c934d6a6e5f0' => __DIR__ . '/..' . '/topthink/think-queue/src/common.php',
  23 + );
  24 +
  25 + public static $prefixLengthsPsr4 = array (
  26 + 't' =>
  27 + array (
  28 + 'think\\helper\\' => 13,
  29 + 'think\\composer\\' => 15,
  30 + 'think\\captcha\\' => 14,
  31 + 'think\\' => 6,
  32 + ),
  33 + 'Z' =>
  34 + array (
  35 + 'ZipStream\\' => 10,
  36 + ),
  37 + 'T' =>
  38 + array (
  39 + 'Tx\\' => 3,
  40 + ),
  41 + 'S' =>
  42 + array (
  43 + 'Symfony\\Polyfill\\Php80\\' => 23,
  44 + 'Symfony\\Polyfill\\Php73\\' => 23,
  45 + 'Symfony\\Polyfill\\Mbstring\\' => 26,
  46 + 'Symfony\\Contracts\\Service\\' => 26,
  47 + 'Symfony\\Contracts\\EventDispatcher\\' => 34,
  48 + 'Symfony\\Contracts\\Cache\\' => 24,
  49 + 'Symfony\\Component\\VarExporter\\' => 30,
  50 + 'Symfony\\Component\\HttpFoundation\\' => 33,
  51 + 'Symfony\\Component\\Finder\\' => 25,
  52 + 'Symfony\\Component\\EventDispatcher\\' => 34,
  53 + 'Symfony\\Component\\Cache\\' => 24,
  54 + 'Symfony\\Bridge\\PsrHttpMessage\\' => 30,
  55 + ),
  56 + 'P' =>
  57 + array (
  58 + 'Psr\\SimpleCache\\' => 16,
  59 + 'Psr\\Log\\' => 8,
  60 + 'Psr\\Http\\Message\\' => 17,
  61 + 'Psr\\Http\\Client\\' => 16,
  62 + 'Psr\\EventDispatcher\\' => 20,
  63 + 'Psr\\Container\\' => 14,
  64 + 'Psr\\Cache\\' => 10,
  65 + 'PhpZip\\' => 7,
  66 + 'PhpOffice\\PhpSpreadsheet\\' => 25,
  67 + ),
  68 + 'O' =>
  69 + array (
  70 + 'Overtrue\\Socialite\\' => 19,
  71 + 'Overtrue\\Pinyin\\' => 16,
  72 + ),
  73 + 'M' =>
  74 + array (
  75 + 'MyCLabs\\Enum\\' => 13,
  76 + 'Monolog\\' => 8,
  77 + 'Matrix\\' => 7,
  78 + ),
  79 + 'G' =>
  80 + array (
  81 + 'GuzzleHttp\\Psr7\\' => 16,
  82 + 'GuzzleHttp\\Promise\\' => 19,
  83 + 'GuzzleHttp\\' => 11,
  84 + ),
  85 + 'E' =>
  86 + array (
  87 + 'EasyWeChat\\' => 11,
  88 + 'EasyWeChatComposer\\' => 19,
  89 + ),
  90 + 'C' =>
  91 + array (
  92 + 'Complex\\' => 8,
  93 + ),
  94 + );
  95 +
  96 + public static $prefixDirsPsr4 = array (
  97 + 'think\\helper\\' =>
  98 + array (
  99 + 0 => __DIR__ . '/..' . '/topthink/think-helper/src',
  100 + ),
  101 + 'think\\composer\\' =>
  102 + array (
  103 + 0 => __DIR__ . '/..' . '/topthink/think-installer/src',
  104 + ),
  105 + 'think\\captcha\\' =>
  106 + array (
  107 + 0 => __DIR__ . '/..' . '/topthink/think-captcha/src',
  108 + ),
  109 + 'think\\' =>
  110 + array (
  111 + 0 => __DIR__ . '/../..' . '/thinkphp/library/think',
  112 + 1 => __DIR__ . '/..' . '/karsonzhang/fastadmin-addons/src',
  113 + 2 => __DIR__ . '/..' . '/topthink/think-queue/src',
  114 + ),
  115 + 'ZipStream\\' =>
  116 + array (
  117 + 0 => __DIR__ . '/..' . '/maennchen/zipstream-php/src',
  118 + ),
  119 + 'Tx\\' =>
  120 + array (
  121 + 0 => __DIR__ . '/..' . '/txthinking/mailer/src',
  122 + ),
  123 + 'Symfony\\Polyfill\\Php80\\' =>
  124 + array (
  125 + 0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
  126 + ),
  127 + 'Symfony\\Polyfill\\Php73\\' =>
  128 + array (
  129 + 0 => __DIR__ . '/..' . '/symfony/polyfill-php73',
  130 + ),
  131 + 'Symfony\\Polyfill\\Mbstring\\' =>
  132 + array (
  133 + 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
  134 + ),
  135 + 'Symfony\\Contracts\\Service\\' =>
  136 + array (
  137 + 0 => __DIR__ . '/..' . '/symfony/service-contracts',
  138 + ),
  139 + 'Symfony\\Contracts\\EventDispatcher\\' =>
  140 + array (
  141 + 0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts',
  142 + ),
  143 + 'Symfony\\Contracts\\Cache\\' =>
  144 + array (
  145 + 0 => __DIR__ . '/..' . '/symfony/cache-contracts',
  146 + ),
  147 + 'Symfony\\Component\\VarExporter\\' =>
  148 + array (
  149 + 0 => __DIR__ . '/..' . '/symfony/var-exporter',
  150 + ),
  151 + 'Symfony\\Component\\HttpFoundation\\' =>
  152 + array (
  153 + 0 => __DIR__ . '/..' . '/symfony/http-foundation',
  154 + ),
  155 + 'Symfony\\Component\\Finder\\' =>
  156 + array (
  157 + 0 => __DIR__ . '/..' . '/symfony/finder',
  158 + ),
  159 + 'Symfony\\Component\\EventDispatcher\\' =>
  160 + array (
  161 + 0 => __DIR__ . '/..' . '/symfony/event-dispatcher',
  162 + ),
  163 + 'Symfony\\Component\\Cache\\' =>
  164 + array (
  165 + 0 => __DIR__ . '/..' . '/symfony/cache',
  166 + ),
  167 + 'Symfony\\Bridge\\PsrHttpMessage\\' =>
  168 + array (
  169 + 0 => __DIR__ . '/..' . '/symfony/psr-http-message-bridge',
  170 + ),
  171 + 'Psr\\SimpleCache\\' =>
  172 + array (
  173 + 0 => __DIR__ . '/..' . '/psr/simple-cache/src',
  174 + ),
  175 + 'Psr\\Log\\' =>
  176 + array (
  177 + 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
  178 + ),
  179 + 'Psr\\Http\\Message\\' =>
  180 + array (
  181 + 0 => __DIR__ . '/..' . '/psr/http-message/src',
  182 + 1 => __DIR__ . '/..' . '/psr/http-factory/src',
  183 + ),
  184 + 'Psr\\Http\\Client\\' =>
  185 + array (
  186 + 0 => __DIR__ . '/..' . '/psr/http-client/src',
  187 + ),
  188 + 'Psr\\EventDispatcher\\' =>
  189 + array (
  190 + 0 => __DIR__ . '/..' . '/psr/event-dispatcher/src',
  191 + ),
  192 + 'Psr\\Container\\' =>
  193 + array (
  194 + 0 => __DIR__ . '/..' . '/psr/container/src',
  195 + ),
  196 + 'Psr\\Cache\\' =>
  197 + array (
  198 + 0 => __DIR__ . '/..' . '/psr/cache/src',
  199 + ),
  200 + 'PhpZip\\' =>
  201 + array (
  202 + 0 => __DIR__ . '/..' . '/nelexa/zip/src',
  203 + ),
  204 + 'PhpOffice\\PhpSpreadsheet\\' =>
  205 + array (
  206 + 0 => __DIR__ . '/..' . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet',
  207 + ),
  208 + 'Overtrue\\Socialite\\' =>
  209 + array (
  210 + 0 => __DIR__ . '/..' . '/overtrue/socialite/src',
  211 + ),
  212 + 'Overtrue\\Pinyin\\' =>
  213 + array (
  214 + 0 => __DIR__ . '/..' . '/overtrue/pinyin/src',
  215 + ),
  216 + 'MyCLabs\\Enum\\' =>
  217 + array (
  218 + 0 => __DIR__ . '/..' . '/myclabs/php-enum/src',
  219 + ),
  220 + 'Monolog\\' =>
  221 + array (
  222 + 0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog',
  223 + ),
  224 + 'Matrix\\' =>
  225 + array (
  226 + 0 => __DIR__ . '/..' . '/markbaker/matrix/classes/src',
  227 + ),
  228 + 'GuzzleHttp\\Psr7\\' =>
  229 + array (
  230 + 0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
  231 + ),
  232 + 'GuzzleHttp\\Promise\\' =>
  233 + array (
  234 + 0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
  235 + ),
  236 + 'GuzzleHttp\\' =>
  237 + array (
  238 + 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
  239 + ),
  240 + 'EasyWeChat\\' =>
  241 + array (
  242 + 0 => __DIR__ . '/..' . '/overtrue/wechat/src',
  243 + ),
  244 + 'EasyWeChatComposer\\' =>
  245 + array (
  246 + 0 => __DIR__ . '/..' . '/easywechat-composer/easywechat-composer/src',
  247 + ),
  248 + 'Complex\\' =>
  249 + array (
  250 + 0 => __DIR__ . '/..' . '/markbaker/complex/classes/src',
  251 + ),
  252 + );
  253 +
  254 + public static $prefixesPsr0 = array (
  255 + 'P' =>
  256 + array (
  257 + 'Pimple' =>
  258 + array (
  259 + 0 => __DIR__ . '/..' . '/pimple/pimple/src',
  260 + ),
  261 + ),
  262 + 'H' =>
  263 + array (
  264 + 'HTMLPurifier' =>
  265 + array (
  266 + 0 => __DIR__ . '/..' . '/ezyang/htmlpurifier/library',
  267 + ),
  268 + ),
  269 + );
  270 +
  271 + public static $classMap = array (
  272 + 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
  273 + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
  274 + 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
  275 + 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
  276 + 'Stringable' => __DIR__ . '/..' . '/myclabs/php-enum/stubs/Stringable.php',
  277 + 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
  278 + 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
  279 + );
  280 +
  281 + public static function getInitializer(ClassLoader $loader)
  282 + {
  283 + return \Closure::bind(function () use ($loader) {
  284 + $loader->prefixLengthsPsr4 = ComposerStaticInita171a4a837511915e525c40585d599c6::$prefixLengthsPsr4;
  285 + $loader->prefixDirsPsr4 = ComposerStaticInita171a4a837511915e525c40585d599c6::$prefixDirsPsr4;
  286 + $loader->prefixesPsr0 = ComposerStaticInita171a4a837511915e525c40585d599c6::$prefixesPsr0;
  287 + $loader->classMap = ComposerStaticInita171a4a837511915e525c40585d599c6::$classMap;
  288 +
  289 + }, null, ClassLoader::class);
  290 + }
  291 +}
此 diff 太大无法显示。
  1 +<?php return array(
  2 + 'root' => array(
  3 + 'name' => 'karsonzhang/fastadmin',
  4 + 'pretty_version' => '1.x-dev',
  5 + 'version' => '1.9999999.9999999.9999999-dev',
  6 + 'reference' => '033af96e1a05ef67ae55ba8d2870b54fffb17fcf',
  7 + 'type' => 'project',
  8 + 'install_path' => __DIR__ . '/../../',
  9 + 'aliases' => array(),
  10 + 'dev' => true,
  11 + ),
  12 + 'versions' => array(
  13 + 'easywechat-composer/easywechat-composer' => array(
  14 + 'pretty_version' => '1.4.1',
  15 + 'version' => '1.4.1.0',
  16 + 'reference' => '3fc6a7ab6d3853c0f4e2922539b56cc37ef361cd',
  17 + 'type' => 'composer-plugin',
  18 + 'install_path' => __DIR__ . '/../easywechat-composer/easywechat-composer',
  19 + 'aliases' => array(),
  20 + 'dev_requirement' => false,
  21 + ),
  22 + 'ezyang/htmlpurifier' => array(
  23 + 'pretty_version' => 'v4.16.0',
  24 + 'version' => '4.16.0.0',
  25 + 'reference' => '523407fb06eb9e5f3d59889b3978d5bfe94299c8',
  26 + 'type' => 'library',
  27 + 'install_path' => __DIR__ . '/../ezyang/htmlpurifier',
  28 + 'aliases' => array(),
  29 + 'dev_requirement' => false,
  30 + ),
  31 + 'guzzlehttp/guzzle' => array(
  32 + 'pretty_version' => '7.7.0',
  33 + 'version' => '7.7.0.0',
  34 + 'reference' => 'fb7566caccf22d74d1ab270de3551f72a58399f5',
  35 + 'type' => 'library',
  36 + 'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
  37 + 'aliases' => array(),
  38 + 'dev_requirement' => false,
  39 + ),
  40 + 'guzzlehttp/promises' => array(
  41 + 'pretty_version' => '2.0.0',
  42 + 'version' => '2.0.0.0',
  43 + 'reference' => '3a494dc7dc1d7d12e511890177ae2d0e6c107da6',
  44 + 'type' => 'library',
  45 + 'install_path' => __DIR__ . '/../guzzlehttp/promises',
  46 + 'aliases' => array(),
  47 + 'dev_requirement' => false,
  48 + ),
  49 + 'guzzlehttp/psr7' => array(
  50 + 'pretty_version' => '2.5.0',
  51 + 'version' => '2.5.0.0',
  52 + 'reference' => 'b635f279edd83fc275f822a1188157ffea568ff6',
  53 + 'type' => 'library',
  54 + 'install_path' => __DIR__ . '/../guzzlehttp/psr7',
  55 + 'aliases' => array(),
  56 + 'dev_requirement' => false,
  57 + ),
  58 + 'karsonzhang/fastadmin' => array(
  59 + 'pretty_version' => '1.x-dev',
  60 + 'version' => '1.9999999.9999999.9999999-dev',
  61 + 'reference' => '033af96e1a05ef67ae55ba8d2870b54fffb17fcf',
  62 + 'type' => 'project',
  63 + 'install_path' => __DIR__ . '/../../',
  64 + 'aliases' => array(),
  65 + 'dev_requirement' => false,
  66 + ),
  67 + 'karsonzhang/fastadmin-addons' => array(
  68 + 'pretty_version' => '1.3.3',
  69 + 'version' => '1.3.3.0',
  70 + 'reference' => 'f5bb4dabda55271b08371a8ae9355a205be48c56',
  71 + 'type' => 'library',
  72 + 'install_path' => __DIR__ . '/../karsonzhang/fastadmin-addons',
  73 + 'aliases' => array(),
  74 + 'dev_requirement' => false,
  75 + ),
  76 + 'maennchen/zipstream-php' => array(
  77 + 'pretty_version' => '2.2.6',
  78 + 'version' => '2.2.6.0',
  79 + 'reference' => '30ad6f93cf3efe4192bc7a4c9cad11ff8f4f237f',
  80 + 'type' => 'library',
  81 + 'install_path' => __DIR__ . '/../maennchen/zipstream-php',
  82 + 'aliases' => array(),
  83 + 'dev_requirement' => false,
  84 + ),
  85 + 'markbaker/complex' => array(
  86 + 'pretty_version' => '3.0.2',
  87 + 'version' => '3.0.2.0',
  88 + 'reference' => '95c56caa1cf5c766ad6d65b6344b807c1e8405b9',
  89 + 'type' => 'library',
  90 + 'install_path' => __DIR__ . '/../markbaker/complex',
  91 + 'aliases' => array(),
  92 + 'dev_requirement' => false,
  93 + ),
  94 + 'markbaker/matrix' => array(
  95 + 'pretty_version' => '3.0.1',
  96 + 'version' => '3.0.1.0',
  97 + 'reference' => '728434227fe21be27ff6d86621a1b13107a2562c',
  98 + 'type' => 'library',
  99 + 'install_path' => __DIR__ . '/../markbaker/matrix',
  100 + 'aliases' => array(),
  101 + 'dev_requirement' => false,
  102 + ),
  103 + 'monolog/monolog' => array(
  104 + 'pretty_version' => '2.9.1',
  105 + 'version' => '2.9.1.0',
  106 + 'reference' => 'f259e2b15fb95494c83f52d3caad003bbf5ffaa1',
  107 + 'type' => 'library',
  108 + 'install_path' => __DIR__ . '/../monolog/monolog',
  109 + 'aliases' => array(),
  110 + 'dev_requirement' => false,
  111 + ),
  112 + 'myclabs/php-enum' => array(
  113 + 'pretty_version' => '1.8.4',
  114 + 'version' => '1.8.4.0',
  115 + 'reference' => 'a867478eae49c9f59ece437ae7f9506bfaa27483',
  116 + 'type' => 'library',
  117 + 'install_path' => __DIR__ . '/../myclabs/php-enum',
  118 + 'aliases' => array(),
  119 + 'dev_requirement' => false,
  120 + ),
  121 + 'nelexa/zip' => array(
  122 + 'pretty_version' => '3.3.3',
  123 + 'version' => '3.3.3.0',
  124 + 'reference' => '501b52f6fc393a599b44ff348a42740e1eaac7c6',
  125 + 'type' => 'library',
  126 + 'install_path' => __DIR__ . '/../nelexa/zip',
  127 + 'aliases' => array(),
  128 + 'dev_requirement' => false,
  129 + ),
  130 + 'overtrue/pinyin' => array(
  131 + 'pretty_version' => '3.0.6',
  132 + 'version' => '3.0.6.0',
  133 + 'reference' => '3b781d267197b74752daa32814d3a2cf5d140779',
  134 + 'type' => 'library',
  135 + 'install_path' => __DIR__ . '/../overtrue/pinyin',
  136 + 'aliases' => array(),
  137 + 'dev_requirement' => false,
  138 + ),
  139 + 'overtrue/socialite' => array(
  140 + 'pretty_version' => '2.0.24',
  141 + 'version' => '2.0.24.0',
  142 + 'reference' => 'ee7e7b000ec7d64f2b8aba1f6a2eec5cdf3f8bec',
  143 + 'type' => 'library',
  144 + 'install_path' => __DIR__ . '/../overtrue/socialite',
  145 + 'aliases' => array(),
  146 + 'dev_requirement' => false,
  147 + ),
  148 + 'overtrue/wechat' => array(
  149 + 'pretty_version' => '4.9.0',
  150 + 'version' => '4.9.0.0',
  151 + 'reference' => '92791f5d957269c633b9aa175f842f6006f945b1',
  152 + 'type' => 'library',
  153 + 'install_path' => __DIR__ . '/../overtrue/wechat',
  154 + 'aliases' => array(),
  155 + 'dev_requirement' => false,
  156 + ),
  157 + 'paragonie/random_compat' => array(
  158 + 'pretty_version' => 'v9.99.100',
  159 + 'version' => '9.99.100.0',
  160 + 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
  161 + 'type' => 'library',
  162 + 'install_path' => __DIR__ . '/../paragonie/random_compat',
  163 + 'aliases' => array(),
  164 + 'dev_requirement' => false,
  165 + ),
  166 + 'phpoffice/phpspreadsheet' => array(
  167 + 'pretty_version' => '1.19.0',
  168 + 'version' => '1.19.0.0',
  169 + 'reference' => 'a9ab55bfae02eecffb3df669a2e19ba0e2f04bbf',
  170 + 'type' => 'library',
  171 + 'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet',
  172 + 'aliases' => array(),
  173 + 'dev_requirement' => false,
  174 + ),
  175 + 'pimple/pimple' => array(
  176 + 'pretty_version' => 'v3.5.0',
  177 + 'version' => '3.5.0.0',
  178 + 'reference' => 'a94b3a4db7fb774b3d78dad2315ddc07629e1bed',
  179 + 'type' => 'library',
  180 + 'install_path' => __DIR__ . '/../pimple/pimple',
  181 + 'aliases' => array(),
  182 + 'dev_requirement' => false,
  183 + ),
  184 + 'psr/cache' => array(
  185 + 'pretty_version' => '1.0.1',
  186 + 'version' => '1.0.1.0',
  187 + 'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
  188 + 'type' => 'library',
  189 + 'install_path' => __DIR__ . '/../psr/cache',
  190 + 'aliases' => array(),
  191 + 'dev_requirement' => false,
  192 + ),
  193 + 'psr/cache-implementation' => array(
  194 + 'dev_requirement' => false,
  195 + 'provided' => array(
  196 + 0 => '1.0|2.0',
  197 + ),
  198 + ),
  199 + 'psr/container' => array(
  200 + 'pretty_version' => '2.0.2',
  201 + 'version' => '2.0.2.0',
  202 + 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
  203 + 'type' => 'library',
  204 + 'install_path' => __DIR__ . '/../psr/container',
  205 + 'aliases' => array(),
  206 + 'dev_requirement' => false,
  207 + ),
  208 + 'psr/event-dispatcher' => array(
  209 + 'pretty_version' => '1.0.0',
  210 + 'version' => '1.0.0.0',
  211 + 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0',
  212 + 'type' => 'library',
  213 + 'install_path' => __DIR__ . '/../psr/event-dispatcher',
  214 + 'aliases' => array(),
  215 + 'dev_requirement' => false,
  216 + ),
  217 + 'psr/event-dispatcher-implementation' => array(
  218 + 'dev_requirement' => false,
  219 + 'provided' => array(
  220 + 0 => '1.0',
  221 + ),
  222 + ),
  223 + 'psr/http-client' => array(
  224 + 'pretty_version' => '1.0.2',
  225 + 'version' => '1.0.2.0',
  226 + 'reference' => '0955afe48220520692d2d09f7ab7e0f93ffd6a31',
  227 + 'type' => 'library',
  228 + 'install_path' => __DIR__ . '/../psr/http-client',
  229 + 'aliases' => array(),
  230 + 'dev_requirement' => false,
  231 + ),
  232 + 'psr/http-client-implementation' => array(
  233 + 'dev_requirement' => false,
  234 + 'provided' => array(
  235 + 0 => '1.0',
  236 + ),
  237 + ),
  238 + 'psr/http-factory' => array(
  239 + 'pretty_version' => '1.0.2',
  240 + 'version' => '1.0.2.0',
  241 + 'reference' => 'e616d01114759c4c489f93b099585439f795fe35',
  242 + 'type' => 'library',
  243 + 'install_path' => __DIR__ . '/../psr/http-factory',
  244 + 'aliases' => array(),
  245 + 'dev_requirement' => false,
  246 + ),
  247 + 'psr/http-factory-implementation' => array(
  248 + 'dev_requirement' => false,
  249 + 'provided' => array(
  250 + 0 => '1.0',
  251 + ),
  252 + ),
  253 + 'psr/http-message' => array(
  254 + 'pretty_version' => '1.1',
  255 + 'version' => '1.1.0.0',
  256 + 'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba',
  257 + 'type' => 'library',
  258 + 'install_path' => __DIR__ . '/../psr/http-message',
  259 + 'aliases' => array(),
  260 + 'dev_requirement' => false,
  261 + ),
  262 + 'psr/http-message-implementation' => array(
  263 + 'dev_requirement' => false,
  264 + 'provided' => array(
  265 + 0 => '1.0',
  266 + ),
  267 + ),
  268 + 'psr/log' => array(
  269 + 'pretty_version' => '1.1.4',
  270 + 'version' => '1.1.4.0',
  271 + 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
  272 + 'type' => 'library',
  273 + 'install_path' => __DIR__ . '/../psr/log',
  274 + 'aliases' => array(),
  275 + 'dev_requirement' => false,
  276 + ),
  277 + 'psr/log-implementation' => array(
  278 + 'dev_requirement' => false,
  279 + 'provided' => array(
  280 + 0 => '1.0.0 || 2.0.0 || 3.0.0',
  281 + ),
  282 + ),
  283 + 'psr/simple-cache' => array(
  284 + 'pretty_version' => '1.0.1',
  285 + 'version' => '1.0.1.0',
  286 + 'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
  287 + 'type' => 'library',
  288 + 'install_path' => __DIR__ . '/../psr/simple-cache',
  289 + 'aliases' => array(),
  290 + 'dev_requirement' => false,
  291 + ),
  292 + 'psr/simple-cache-implementation' => array(
  293 + 'dev_requirement' => false,
  294 + 'provided' => array(
  295 + 0 => '1.0|2.0',
  296 + ),
  297 + ),
  298 + 'ralouphie/getallheaders' => array(
  299 + 'pretty_version' => '3.0.3',
  300 + 'version' => '3.0.3.0',
  301 + 'reference' => '120b605dfeb996808c31b6477290a714d356e822',
  302 + 'type' => 'library',
  303 + 'install_path' => __DIR__ . '/../ralouphie/getallheaders',
  304 + 'aliases' => array(),
  305 + 'dev_requirement' => false,
  306 + ),
  307 + 'symfony/cache' => array(
  308 + 'pretty_version' => 'v5.4.25',
  309 + 'version' => '5.4.25.0',
  310 + 'reference' => 'e2013521c0f07473ae69a01fce0af78fc3ec0f23',
  311 + 'type' => 'library',
  312 + 'install_path' => __DIR__ . '/../symfony/cache',
  313 + 'aliases' => array(),
  314 + 'dev_requirement' => false,
  315 + ),
  316 + 'symfony/cache-contracts' => array(
  317 + 'pretty_version' => 'v2.5.2',
  318 + 'version' => '2.5.2.0',
  319 + 'reference' => '64be4a7acb83b6f2bf6de9a02cee6dad41277ebc',
  320 + 'type' => 'library',
  321 + 'install_path' => __DIR__ . '/../symfony/cache-contracts',
  322 + 'aliases' => array(),
  323 + 'dev_requirement' => false,
  324 + ),
  325 + 'symfony/cache-implementation' => array(
  326 + 'dev_requirement' => false,
  327 + 'provided' => array(
  328 + 0 => '1.0|2.0',
  329 + ),
  330 + ),
  331 + 'symfony/deprecation-contracts' => array(
  332 + 'pretty_version' => 'v2.5.2',
  333 + 'version' => '2.5.2.0',
  334 + 'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66',
  335 + 'type' => 'library',
  336 + 'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
  337 + 'aliases' => array(),
  338 + 'dev_requirement' => false,
  339 + ),
  340 + 'symfony/event-dispatcher' => array(
  341 + 'pretty_version' => 'v5.4.22',
  342 + 'version' => '5.4.22.0',
  343 + 'reference' => '1df20e45d56da29a4b1d8259dd6e950acbf1b13f',
  344 + 'type' => 'library',
  345 + 'install_path' => __DIR__ . '/../symfony/event-dispatcher',
  346 + 'aliases' => array(),
  347 + 'dev_requirement' => false,
  348 + ),
  349 + 'symfony/event-dispatcher-contracts' => array(
  350 + 'pretty_version' => 'v2.5.2',
  351 + 'version' => '2.5.2.0',
  352 + 'reference' => 'f98b54df6ad059855739db6fcbc2d36995283fe1',
  353 + 'type' => 'library',
  354 + 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts',
  355 + 'aliases' => array(),
  356 + 'dev_requirement' => false,
  357 + ),
  358 + 'symfony/event-dispatcher-implementation' => array(
  359 + 'dev_requirement' => false,
  360 + 'provided' => array(
  361 + 0 => '2.0',
  362 + ),
  363 + ),
  364 + 'symfony/finder' => array(
  365 + 'pretty_version' => 'v5.4.21',
  366 + 'version' => '5.4.21.0',
  367 + 'reference' => '078e9a5e1871fcfe6a5ce421b539344c21afef19',
  368 + 'type' => 'library',
  369 + 'install_path' => __DIR__ . '/../symfony/finder',
  370 + 'aliases' => array(),
  371 + 'dev_requirement' => false,
  372 + ),
  373 + 'symfony/http-foundation' => array(
  374 + 'pretty_version' => 'v5.4.25',
  375 + 'version' => '5.4.25.0',
  376 + 'reference' => 'f66be2706075c5f6325d2fe2b743a57fb5d23f6b',
  377 + 'type' => 'library',
  378 + 'install_path' => __DIR__ . '/../symfony/http-foundation',
  379 + 'aliases' => array(),
  380 + 'dev_requirement' => false,
  381 + ),
  382 + 'symfony/polyfill-mbstring' => array(
  383 + 'pretty_version' => 'v1.27.0',
  384 + 'version' => '1.27.0.0',
  385 + 'reference' => '8ad114f6b39e2c98a8b0e3bd907732c207c2b534',
  386 + 'type' => 'library',
  387 + 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
  388 + 'aliases' => array(),
  389 + 'dev_requirement' => false,
  390 + ),
  391 + 'symfony/polyfill-php73' => array(
  392 + 'pretty_version' => 'v1.27.0',
  393 + 'version' => '1.27.0.0',
  394 + 'reference' => '9e8ecb5f92152187c4799efd3c96b78ccab18ff9',
  395 + 'type' => 'library',
  396 + 'install_path' => __DIR__ . '/../symfony/polyfill-php73',
  397 + 'aliases' => array(),
  398 + 'dev_requirement' => false,
  399 + ),
  400 + 'symfony/polyfill-php80' => array(
  401 + 'pretty_version' => 'v1.27.0',
  402 + 'version' => '1.27.0.0',
  403 + 'reference' => '7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936',
  404 + 'type' => 'library',
  405 + 'install_path' => __DIR__ . '/../symfony/polyfill-php80',
  406 + 'aliases' => array(),
  407 + 'dev_requirement' => false,
  408 + ),
  409 + 'symfony/psr-http-message-bridge' => array(
  410 + 'pretty_version' => 'v2.2.0',
  411 + 'version' => '2.2.0.0',
  412 + 'reference' => '28a732c05bbad801304ad5a5c674cf2970508993',
  413 + 'type' => 'symfony-bridge',
  414 + 'install_path' => __DIR__ . '/../symfony/psr-http-message-bridge',
  415 + 'aliases' => array(),
  416 + 'dev_requirement' => false,
  417 + ),
  418 + 'symfony/service-contracts' => array(
  419 + 'pretty_version' => 'v1.1.2',
  420 + 'version' => '1.1.2.0',
  421 + 'reference' => '191afdcb5804db960d26d8566b7e9a2843cab3a0',
  422 + 'type' => 'library',
  423 + 'install_path' => __DIR__ . '/../symfony/service-contracts',
  424 + 'aliases' => array(),
  425 + 'dev_requirement' => false,
  426 + ),
  427 + 'symfony/var-exporter' => array(
  428 + 'pretty_version' => 'v4.4.43',
  429 + 'version' => '4.4.43.0',
  430 + 'reference' => '4a7a3a3d55c471d396e6d28011368b7b83cb518b',
  431 + 'type' => 'library',
  432 + 'install_path' => __DIR__ . '/../symfony/var-exporter',
  433 + 'aliases' => array(),
  434 + 'dev_requirement' => false,
  435 + ),
  436 + 'topthink/framework' => array(
  437 + 'pretty_version' => 'dev-master',
  438 + 'version' => 'dev-master',
  439 + 'reference' => '096811899433eb0eb0988f1fe1db56ebb521bf34',
  440 + 'type' => 'think-framework',
  441 + 'install_path' => __DIR__ . '/../../thinkphp',
  442 + 'aliases' => array(
  443 + 0 => '9999999-dev',
  444 + ),
  445 + 'dev_requirement' => false,
  446 + ),
  447 + 'topthink/think-captcha' => array(
  448 + 'pretty_version' => 'v1.0.7',
  449 + 'version' => '1.0.7.0',
  450 + 'reference' => '0c55455df26a1626a60d0dc35d2d89002b741d44',
  451 + 'type' => 'library',
  452 + 'install_path' => __DIR__ . '/../topthink/think-captcha',
  453 + 'aliases' => array(),
  454 + 'dev_requirement' => false,
  455 + ),
  456 + 'topthink/think-helper' => array(
  457 + 'pretty_version' => 'v1.0.7',
  458 + 'version' => '1.0.7.0',
  459 + 'reference' => '5f92178606c8ce131d36b37a57c58eb71e55f019',
  460 + 'type' => 'library',
  461 + 'install_path' => __DIR__ . '/../topthink/think-helper',
  462 + 'aliases' => array(),
  463 + 'dev_requirement' => false,
  464 + ),
  465 + 'topthink/think-installer' => array(
  466 + 'pretty_version' => 'v1.0.14',
  467 + 'version' => '1.0.14.0',
  468 + 'reference' => 'eae1740ac264a55c06134b6685dfb9f837d004d1',
  469 + 'type' => 'composer-plugin',
  470 + 'install_path' => __DIR__ . '/../topthink/think-installer',
  471 + 'aliases' => array(),
  472 + 'dev_requirement' => false,
  473 + ),
  474 + 'topthink/think-queue' => array(
  475 + 'pretty_version' => 'v1.1.6',
  476 + 'version' => '1.1.6.0',
  477 + 'reference' => '250650eb0e8ea5af4cfdc7ae46f3f4e0a24ac245',
  478 + 'type' => 'think-extend',
  479 + 'install_path' => __DIR__ . '/../topthink/think-queue',
  480 + 'aliases' => array(),
  481 + 'dev_requirement' => false,
  482 + ),
  483 + 'txthinking/mailer' => array(
  484 + 'pretty_version' => 'v2.0.1',
  485 + 'version' => '2.0.1.0',
  486 + 'reference' => '09013cf9dad3aac195f66ae5309e8c3343c018e9',
  487 + 'type' => 'library',
  488 + 'install_path' => __DIR__ . '/../txthinking/mailer',
  489 + 'aliases' => array(),
  490 + 'dev_requirement' => false,
  491 + ),
  492 + ),
  493 +);
  1 +<?php
  2 +
  3 +// platform_check.php @generated by Composer
  4 +
  5 +$issues = array();
  6 +
  7 +if (!(PHP_VERSION_ID >= 70400)) {
  8 + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.';
  9 +}
  10 +
  11 +if ($issues) {
  12 + if (!headers_sent()) {
  13 + header('HTTP/1.1 500 Internal Server Error');
  14 + }
  15 + if (!ini_get('display_errors')) {
  16 + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
  17 + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
  18 + } elseif (!headers_sent()) {
  19 + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
  20 + }
  21 + }
  22 + trigger_error(
  23 + 'Composer detected issues in your platform: ' . implode(' ', $issues),
  24 + E_USER_ERROR
  25 + );
  26 +}
  1 +.idea/
  2 +/vendor
  3 +composer.lock
  4 +extensions.php
  5 +.php_cs.cache
  1 +<?php
  2 +
  3 +$header = <<<EOF
  4 +This file is part of the EasyWeChatComposer.
  5 +
  6 +(c) 张铭阳 <mingyoungcheung@gmail.com>
  7 +
  8 +This source file is subject to the MIT license that is bundled
  9 +with this source code in the file LICENSE.
  10 +EOF;
  11 +
  12 +return PhpCsFixer\Config::create()
  13 + ->setRiskyAllowed(true)
  14 + ->setRules([
  15 + '@Symfony' => true,
  16 + 'header_comment' => ['header' => $header],
  17 + 'declare_strict_types' => true,
  18 + 'ordered_imports' => true,
  19 + 'strict_comparison' => true,
  20 + 'no_empty_comment' => false,
  21 + 'yoda_style' => false,
  22 + ])
  23 + ->setFinder(
  24 + PhpCsFixer\Finder::create()
  25 + ->exclude('vendor')
  26 + ->notPath('src/Laravel/config.php', 'src/Laravel/routes.php')
  27 + ->in(__DIR__)
  28 + )
  29 +;
  1 +language: php
  2 +
  3 +php:
  4 + - 7.0
  5 + - 7.1
  6 + - 7.2
  7 + - 7.3
  8 +
  9 +install:
  10 + - travis_retry composer install --no-interaction --no-suggest
  11 +
  12 +script: ./vendor/bin/phpunit
  1 +MIT License
  2 +
  3 +Copyright (c) 张铭阳
  4 +
  5 +Permission is hereby granted, free of charge, to any person obtaining a copy
  6 +of this software and associated documentation files (the "Software"), to deal
  7 +in the Software without restriction, including without limitation the rights
  8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9 +copies of the Software, and to permit persons to whom the Software is
  10 +furnished to do so, subject to the following conditions:
  11 +
  12 +The above copyright notice and this permission notice shall be included in all
  13 +copies or substantial portions of the Software.
  14 +
  15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 +SOFTWARE.
  1 +<p align="center">
  2 + <h1 align="center">EasyWeChat Composer Plugin</h1>
  3 +</p>
  4 +
  5 +<p align="center">
  6 + <a href="https://travis-ci.org/mingyoung/easywechat-composer"><img src="https://travis-ci.org/mingyoung/easywechat-composer.svg" alt="Build Status"></a>
  7 + <a href="https://scrutinizer-ci.com/g/mingyoung/easywechat-composer/?branch=master"><img src="https://scrutinizer-ci.com/g/mingyoung/easywechat-composer/badges/quality-score.png?b=master" alt="Scrutinizer Code Quality"></a>
  8 + <a href="https://packagist.org/packages/easywechat-composer/easywechat-composer"><img src="https://poser.pugx.org/easywechat-composer/easywechat-composer/v/stable.svg" alt="Latest Stable Version"></a>
  9 + <a href="https://packagist.org/packages/easywechat-composer/easywechat-composer"><img src="https://poser.pugx.org/easywechat-composer/easywechat-composer/d/total.svg" alt="Total Downloads"></a>
  10 + <a href="https://packagist.org/packages/easywechat-composer/easywechat-composer"><img src="https://poser.pugx.org/easywechat-composer/easywechat-composer/license.svg" alt="License"></a>
  11 +</p>
  12 +
  13 +Usage
  14 +---
  15 +
  16 +Set the `type` to be `easywechat-extension` in your package composer.json file:
  17 +
  18 +```json
  19 +{
  20 + "name": "your/package",
  21 + "type": "easywechat-extension"
  22 +}
  23 +```
  24 +
  25 +Specify server observer classes in the extra section:
  26 +
  27 +```json
  28 +{
  29 + "name": "your/package",
  30 + "type": "easywechat-extension",
  31 + "extra": {
  32 + "observers": [
  33 + "Acme\\Observers\\Handler"
  34 + ]
  35 + }
  36 +}
  37 +```
  38 +
  39 +Examples
  40 +---
  41 +* [easywechat-composer/open-platform-testcase](https://github.com/mingyoung/open-platform-testcase)
  42 +
  43 +Server Delegation
  44 +---
  45 +
  46 +> 目前仅支持 Laravel
  47 +
  48 +1.`config/app.php` 中添加 `EasyWeChatComposer\Laravel\ServiceProvider::class`
  49 +
  50 +2.**本地项目**`.env` 文件中添加如下配置:
  51 +
  52 +```
  53 +EASYWECHAT_DELEGATION=true # false 则不启用
  54 +EASYWECHAT_DELEGATION_HOST=https://example.com # 线上域名
  55 +```
  1 +{
  2 + "name": "easywechat-composer/easywechat-composer",
  3 + "description": "The composer plugin for EasyWeChat",
  4 + "type": "composer-plugin",
  5 + "license": "MIT",
  6 + "authors": [
  7 + {
  8 + "name": "张铭阳",
  9 + "email": "mingyoungcheung@gmail.com"
  10 + }
  11 + ],
  12 + "require": {
  13 + "php": ">=7.0",
  14 + "composer-plugin-api": "^1.0 || ^2.0"
  15 + },
  16 + "require-dev": {
  17 + "composer/composer": "^1.0 || ^2.0",
  18 + "phpunit/phpunit": "^6.5 || ^7.0"
  19 + },
  20 + "autoload": {
  21 + "psr-4": {
  22 + "EasyWeChatComposer\\": "src/"
  23 + }
  24 + },
  25 + "autoload-dev": {
  26 + "psr-4": {
  27 + "EasyWeChatComposer\\Tests\\": "tests/"
  28 + }
  29 + },
  30 + "extra": {
  31 + "class": "EasyWeChatComposer\\Plugin"
  32 + },
  33 + "minimum-stability": "dev",
  34 + "prefer-stable": true
  35 +}
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3 + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.0/phpunit.xsd"
  4 + bootstrap="vendor/autoload.php"
  5 + colors="true"
  6 + forceCoversAnnotation="true"
  7 + beStrictAboutCoversAnnotation="true"
  8 + beStrictAboutOutputDuringTests="true"
  9 + beStrictAboutTodoAnnotatedTests="true"
  10 + verbose="true">
  11 + <testsuite name="EasyWeChatComposer Test">
  12 + <directory suffix="Test.php">tests</directory>
  13 + </testsuite>
  14 +
  15 + <filter>
  16 + <whitelist processUncoveredFilesFromWhitelist="true">
  17 + <directory suffix=".php">src</directory>
  18 + </whitelist>
  19 + </filter>
  20 +</phpunit>
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Commands;
  15 +
  16 +use Composer\Command\BaseCommand;
  17 +use Symfony\Component\Console\Helper\Table;
  18 +use Symfony\Component\Console\Input\InputInterface;
  19 +use Symfony\Component\Console\Output\OutputInterface;
  20 +
  21 +class ExtensionsCommand extends BaseCommand
  22 +{
  23 + /**
  24 + * Configures the current command.
  25 + */
  26 + protected function configure()
  27 + {
  28 + $this->setName('easywechat:extensions')
  29 + ->setDescription('Lists all installed extensions.');
  30 + }
  31 +
  32 + /**
  33 + * Executes the current command.
  34 + *
  35 + * @param InputInterface $input
  36 + * @param OutputInterface $output
  37 + */
  38 + protected function execute(InputInterface $input, OutputInterface $output)
  39 + {
  40 + $extensions = require __DIR__.'/../../extensions.php';
  41 +
  42 + if (empty($extensions) || !is_array($extensions)) {
  43 + return $output->writeln('<info>No extension installed.</info>');
  44 + }
  45 +
  46 + $table = new Table($output);
  47 + $table->setHeaders(['Name', 'Observers'])
  48 + ->setRows(
  49 + array_map([$this, 'getRows'], array_keys($extensions), $extensions)
  50 + )->render();
  51 + }
  52 +
  53 + /**
  54 + * @param string $name
  55 + * @param array $extension
  56 + *
  57 + * @return array
  58 + */
  59 + protected function getRows($name, $extension)
  60 + {
  61 + return [$name, implode("\n", $extension['observers'] ?? [])];
  62 + }
  63 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Commands;
  15 +
  16 +use Composer\Plugin\Capability\CommandProvider;
  17 +
  18 +class Provider implements CommandProvider
  19 +{
  20 + /**
  21 + * Retrieves an array of commands.
  22 + *
  23 + * @return \Composer\Command\BaseCommand[]
  24 + */
  25 + public function getCommands()
  26 + {
  27 + return [
  28 + new ExtensionsCommand(),
  29 + ];
  30 + }
  31 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Contracts;
  15 +
  16 +interface Encrypter
  17 +{
  18 + /**
  19 + * Encrypt the given value.
  20 + *
  21 + * @param string $value
  22 + *
  23 + * @return string
  24 + */
  25 + public function encrypt($value);
  26 +
  27 + /**
  28 + * Decrypt the given value.
  29 + *
  30 + * @param string $payload
  31 + *
  32 + * @return string
  33 + */
  34 + public function decrypt($payload);
  35 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Delegation;
  15 +
  16 +use EasyWeChatComposer\EasyWeChat;
  17 +
  18 +class DelegationOptions
  19 +{
  20 + /**
  21 + * @var array
  22 + */
  23 + protected $config = [
  24 + 'enabled' => false,
  25 + ];
  26 +
  27 + /**
  28 + * @return $this
  29 + */
  30 + public function enable()
  31 + {
  32 + $this->config['enabled'] = true;
  33 +
  34 + return $this;
  35 + }
  36 +
  37 + /**
  38 + * @return $this
  39 + */
  40 + public function disable()
  41 + {
  42 + $this->config['enabled'] = false;
  43 +
  44 + return $this;
  45 + }
  46 +
  47 + /**
  48 + * @param bool $ability
  49 + *
  50 + * @return $this
  51 + */
  52 + public function ability($ability)
  53 + {
  54 + $this->config['enabled'] = (bool) $ability;
  55 +
  56 + return $this;
  57 + }
  58 +
  59 + /**
  60 + * @param string $host
  61 + *
  62 + * @return $this
  63 + */
  64 + public function toHost($host)
  65 + {
  66 + $this->config['host'] = $host;
  67 +
  68 + return $this;
  69 + }
  70 +
  71 + /**
  72 + * Destructor.
  73 + */
  74 + public function __destruct()
  75 + {
  76 + EasyWeChat::mergeConfig([
  77 + 'delegation' => $this->config,
  78 + ]);
  79 + }
  80 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Delegation;
  15 +
  16 +use EasyWeChatComposer\Traits\MakesHttpRequests;
  17 +
  18 +class DelegationTo
  19 +{
  20 + use MakesHttpRequests;
  21 +
  22 + /**
  23 + * @var \EasyWeChat\Kernel\ServiceContainer
  24 + */
  25 + protected $app;
  26 +
  27 + /**
  28 + * @var array
  29 + */
  30 + protected $identifiers = [];
  31 +
  32 + /**
  33 + * @param \EasyWeChat\Kernel\ServiceContainer $app
  34 + * @param string $identifier
  35 + */
  36 + public function __construct($app, $identifier)
  37 + {
  38 + $this->app = $app;
  39 +
  40 + $this->push($identifier);
  41 + }
  42 +
  43 + /**
  44 + * @param string $identifier
  45 + */
  46 + public function push($identifier)
  47 + {
  48 + $this->identifiers[] = $identifier;
  49 + }
  50 +
  51 + /**
  52 + * @param string $identifier
  53 + *
  54 + * @return $this
  55 + */
  56 + public function __get($identifier)
  57 + {
  58 + $this->push($identifier);
  59 +
  60 + return $this;
  61 + }
  62 +
  63 + /**
  64 + * @param string $method
  65 + * @param array $arguments
  66 + *
  67 + * @return mixed
  68 + */
  69 + public function __call($method, $arguments)
  70 + {
  71 + $config = array_intersect_key($this->app->getConfig(), array_flip(['app_id', 'secret', 'token', 'aes_key', 'response_type', 'component_app_id', 'refresh_token']));
  72 +
  73 + $data = [
  74 + 'config' => $config,
  75 + 'application' => get_class($this->app),
  76 + 'identifiers' => $this->identifiers,
  77 + 'method' => $method,
  78 + 'arguments' => $arguments,
  79 + ];
  80 +
  81 + return $this->request('easywechat-composer/delegate', $data);
  82 + }
  83 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Delegation;
  15 +
  16 +use EasyWeChat;
  17 +use EasyWeChatComposer\Http\DelegationResponse;
  18 +
  19 +class Hydrate
  20 +{
  21 + /**
  22 + * @var array
  23 + */
  24 + protected $attributes;
  25 +
  26 + /**
  27 + * @param array $attributes
  28 + */
  29 + public function __construct(array $attributes)
  30 + {
  31 + $this->attributes = $attributes;
  32 + }
  33 +
  34 + /**
  35 + * @return array
  36 + */
  37 + public function handle()
  38 + {
  39 + $app = $this->createsApplication()->shouldntDelegate();
  40 +
  41 + foreach ($this->attributes['identifiers'] as $identifier) {
  42 + $app = $app->$identifier;
  43 + }
  44 +
  45 + return call_user_func_array([$app, $this->attributes['method']], $this->attributes['arguments']);
  46 + }
  47 +
  48 + /**
  49 + * @return \EasyWeChat\Kernel\ServiceContainer
  50 + */
  51 + protected function createsApplication()
  52 + {
  53 + $application = $this->attributes['application'];
  54 +
  55 + if ($application === EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Application::class) {
  56 + return $this->createsOpenPlatformApplication('officialAccount');
  57 + }
  58 +
  59 + if ($application === EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Application::class) {
  60 + return $this->createsOpenPlatformApplication('miniProgram');
  61 + }
  62 +
  63 + return new $application($this->buildConfig($this->attributes['config']));
  64 + }
  65 +
  66 + protected function createsOpenPlatformApplication($type)
  67 + {
  68 + $config = $this->attributes['config'];
  69 +
  70 + $authorizerAppId = $config['app_id'];
  71 +
  72 + $config['app_id'] = $config['component_app_id'];
  73 +
  74 + return EasyWeChat\Factory::openPlatform($this->buildConfig($config))->$type($authorizerAppId, $config['refresh_token']);
  75 + }
  76 +
  77 + protected function buildConfig(array $config)
  78 + {
  79 + $config['response_type'] = DelegationResponse::class;
  80 +
  81 + return $config;
  82 + }
  83 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer;
  15 +
  16 +use EasyWeChatComposer\Delegation\DelegationOptions;
  17 +
  18 +class EasyWeChat
  19 +{
  20 + /**
  21 + * @var array
  22 + */
  23 + protected static $config = [];
  24 +
  25 + /**
  26 + * Encryption key.
  27 + *
  28 + * @var string
  29 + */
  30 + protected static $encryptionKey;
  31 +
  32 + /**
  33 + * @param array $config
  34 + */
  35 + public static function mergeConfig(array $config)
  36 + {
  37 + static::$config = array_merge(static::$config, $config);
  38 + }
  39 +
  40 + /**
  41 + * @return array
  42 + */
  43 + public static function config()
  44 + {
  45 + return static::$config;
  46 + }
  47 +
  48 + /**
  49 + * Set encryption key.
  50 + *
  51 + * @param string $key
  52 + *
  53 + * @return static
  54 + */
  55 + public static function setEncryptionKey(string $key)
  56 + {
  57 + static::$encryptionKey = $key;
  58 +
  59 + return new static();
  60 + }
  61 +
  62 + /**
  63 + * Get encryption key.
  64 + *
  65 + * @return string
  66 + */
  67 + public static function getEncryptionKey(): string
  68 + {
  69 + return static::$encryptionKey;
  70 + }
  71 +
  72 + /**
  73 + * @return \EasyWeChatComposer\Delegation\DelegationOptions
  74 + */
  75 + public static function withDelegation()
  76 + {
  77 + return new DelegationOptions();
  78 + }
  79 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Encryption;
  15 +
  16 +use EasyWeChatComposer\Contracts\Encrypter;
  17 +use EasyWeChatComposer\Exceptions\DecryptException;
  18 +use EasyWeChatComposer\Exceptions\EncryptException;
  19 +
  20 +class DefaultEncrypter implements Encrypter
  21 +{
  22 + /**
  23 + * @var string
  24 + */
  25 + protected $key;
  26 +
  27 + /**
  28 + * @var string
  29 + */
  30 + protected $cipher;
  31 +
  32 + /**
  33 + * @param string $key
  34 + * @param string $cipher
  35 + */
  36 + public function __construct($key, $cipher = 'AES-256-CBC')
  37 + {
  38 + $this->key = $key;
  39 + $this->cipher = $cipher;
  40 + }
  41 +
  42 + /**
  43 + * Encrypt the given value.
  44 + *
  45 + * @param string $value
  46 + *
  47 + * @return string
  48 + *
  49 + * @throws \EasyWeChatComposer\Exceptions\EncryptException
  50 + */
  51 + public function encrypt($value)
  52 + {
  53 + $iv = random_bytes(openssl_cipher_iv_length($this->cipher));
  54 +
  55 + $value = openssl_encrypt($value, $this->cipher, $this->key, 0, $iv);
  56 +
  57 + if ($value === false) {
  58 + throw new EncryptException('Could not encrypt the data.');
  59 + }
  60 +
  61 + $iv = base64_encode($iv);
  62 +
  63 + return base64_encode(json_encode(compact('iv', 'value')));
  64 + }
  65 +
  66 + /**
  67 + * Decrypt the given value.
  68 + *
  69 + * @param string $payload
  70 + *
  71 + * @return string
  72 + *
  73 + * @throws \EasyWeChatComposer\Exceptions\DecryptException
  74 + */
  75 + public function decrypt($payload)
  76 + {
  77 + $payload = json_decode(base64_decode($payload), true);
  78 +
  79 + $iv = base64_decode($payload['iv']);
  80 +
  81 + $decrypted = openssl_decrypt($payload['value'], $this->cipher, $this->key, 0, $iv);
  82 +
  83 + if ($decrypted === false) {
  84 + throw new DecryptException('Could not decrypt the data.');
  85 + }
  86 +
  87 + return $decrypted;
  88 + }
  89 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Exceptions;
  15 +
  16 +use Exception;
  17 +
  18 +class DecryptException extends Exception
  19 +{
  20 + //
  21 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Exceptions;
  15 +
  16 +use Exception;
  17 +
  18 +class DelegationException extends Exception
  19 +{
  20 + /**
  21 + * @var string
  22 + */
  23 + protected $exception;
  24 +
  25 + /**
  26 + * @param string $exception
  27 + */
  28 + public function setException($exception)
  29 + {
  30 + $this->exception = $exception;
  31 +
  32 + return $this;
  33 + }
  34 +
  35 + /**
  36 + * @return string
  37 + */
  38 + public function getException()
  39 + {
  40 + return $this->exception;
  41 + }
  42 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Exceptions;
  15 +
  16 +use Exception;
  17 +
  18 +class EncryptException extends Exception
  19 +{
  20 + //
  21 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer;
  15 +
  16 +use EasyWeChat\Kernel\Contracts\EventHandlerInterface;
  17 +use Pimple\Container;
  18 +use ReflectionClass;
  19 +
  20 +class Extension
  21 +{
  22 + /**
  23 + * @var \Pimple\Container
  24 + */
  25 + protected $app;
  26 +
  27 + /**
  28 + * @var string
  29 + */
  30 + protected $manifestPath;
  31 +
  32 + /**
  33 + * @var array|null
  34 + */
  35 + protected $manifest;
  36 +
  37 + /**
  38 + * @param \Pimple\Container $app
  39 + */
  40 + public function __construct(Container $app)
  41 + {
  42 + $this->app = $app;
  43 + $this->manifestPath = __DIR__.'/../extensions.php';
  44 + }
  45 +
  46 + /**
  47 + * Get observers.
  48 + *
  49 + * @return array
  50 + */
  51 + public function observers(): array
  52 + {
  53 + if ($this->shouldIgnore()) {
  54 + return [];
  55 + }
  56 +
  57 + $observers = [];
  58 +
  59 + foreach ($this->getManifest() as $name => $extra) {
  60 + $observers = array_merge($observers, $extra['observers'] ?? []);
  61 + }
  62 +
  63 + return array_map([$this, 'listObserver'], array_filter($observers, [$this, 'validateObserver']));
  64 + }
  65 +
  66 + /**
  67 + * @param mixed $observer
  68 + *
  69 + * @return bool
  70 + */
  71 + protected function isDisable($observer): bool
  72 + {
  73 + return in_array($observer, $this->app->config->get('disable_observers', []));
  74 + }
  75 +
  76 + /**
  77 + * Get the observers should be ignore.
  78 + *
  79 + * @return bool
  80 + */
  81 + protected function shouldIgnore(): bool
  82 + {
  83 + return !file_exists($this->manifestPath) || $this->isDisable('*');
  84 + }
  85 +
  86 + /**
  87 + * Validate the given observer.
  88 + *
  89 + * @param mixed $observer
  90 + *
  91 + * @return bool
  92 + *
  93 + * @throws \ReflectionException
  94 + */
  95 + protected function validateObserver($observer): bool
  96 + {
  97 + return !$this->isDisable($observer)
  98 + && (new ReflectionClass($observer))->implementsInterface(EventHandlerInterface::class)
  99 + && $this->accessible($observer);
  100 + }
  101 +
  102 + /**
  103 + * Determine whether the given observer is accessible.
  104 + *
  105 + * @param string $observer
  106 + *
  107 + * @return bool
  108 + */
  109 + protected function accessible($observer): bool
  110 + {
  111 + if (!method_exists($observer, 'getAccessor')) {
  112 + return true;
  113 + }
  114 +
  115 + return in_array(get_class($this->app), (array) $observer::getAccessor());
  116 + }
  117 +
  118 + /**
  119 + * @param mixed $observer
  120 + *
  121 + * @return array
  122 + */
  123 + protected function listObserver($observer): array
  124 + {
  125 + $condition = method_exists($observer, 'onCondition') ? $observer::onCondition() : '*';
  126 +
  127 + return [$observer, $condition];
  128 + }
  129 +
  130 + /**
  131 + * Get the easywechat manifest.
  132 + *
  133 + * @return array
  134 + */
  135 + protected function getManifest(): array
  136 + {
  137 + if (!is_null($this->manifest)) {
  138 + return $this->manifest;
  139 + }
  140 +
  141 + return $this->manifest = file_exists($this->manifestPath) ? require $this->manifestPath : [];
  142 + }
  143 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Http;
  15 +
  16 +class DelegationResponse extends Response
  17 +{
  18 + /**
  19 + * @return string
  20 + */
  21 + public function getBodyContents()
  22 + {
  23 + return $this->response->getBodyContents();
  24 + }
  25 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Http;
  15 +
  16 +use EasyWeChat\Kernel\Contracts\Arrayable;
  17 +use EasyWeChat\Kernel\Http\Response as HttpResponse;
  18 +use JsonSerializable;
  19 +
  20 +class Response implements Arrayable, JsonSerializable
  21 +{
  22 + /**
  23 + * @var \EasyWeChat\Kernel\Http\Response
  24 + */
  25 + protected $response;
  26 +
  27 + /**
  28 + * @var array
  29 + */
  30 + protected $array;
  31 +
  32 + /**
  33 + * @param \EasyWeChat\Kernel\Http\Response $response
  34 + */
  35 + public function __construct(HttpResponse $response)
  36 + {
  37 + $this->response = $response;
  38 + }
  39 +
  40 + /**
  41 + * @see \ArrayAccess::offsetExists
  42 + *
  43 + * @param string $offset
  44 + *
  45 + * @return bool
  46 + */
  47 + public function offsetExists($offset)
  48 + {
  49 + return isset($this->toArray()[$offset]);
  50 + }
  51 +
  52 + /**
  53 + * @see \ArrayAccess::offsetGet
  54 + *
  55 + * @param string $offset
  56 + *
  57 + * @return mixed
  58 + */
  59 + public function offsetGet($offset)
  60 + {
  61 + return $this->toArray()[$offset] ?? null;
  62 + }
  63 +
  64 + /**
  65 + * @see \ArrayAccess::offsetSet
  66 + *
  67 + * @param string $offset
  68 + * @param mixed $value
  69 + */
  70 + public function offsetSet($offset, $value)
  71 + {
  72 + //
  73 + }
  74 +
  75 + /**
  76 + * @see \ArrayAccess::offsetUnset
  77 + *
  78 + * @param string $offset
  79 + */
  80 + public function offsetUnset($offset)
  81 + {
  82 + //
  83 + }
  84 +
  85 + /**
  86 + * Get the instance as an array.
  87 + *
  88 + * @return array
  89 + */
  90 + public function toArray()
  91 + {
  92 + return $this->array ?: $this->array = $this->response->toArray();
  93 + }
  94 +
  95 + /**
  96 + * Convert the object into something JSON serializable.
  97 + *
  98 + * @return array
  99 + */
  100 + public function jsonSerialize()
  101 + {
  102 + return $this->toArray();
  103 + }
  104 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Laravel\Http\Controllers;
  15 +
  16 +use EasyWeChatComposer\Delegation\Hydrate;
  17 +use EasyWeChatComposer\Encryption\DefaultEncrypter;
  18 +use Illuminate\Http\Request;
  19 +use Throwable;
  20 +
  21 +class DelegatesController
  22 +{
  23 + /**
  24 + * @param \Illuminate\Http\Request $request
  25 + * @param \EasyWeChatComposer\Encryption\DefaultEncrypter $encrypter
  26 + *
  27 + * @return \Illuminate\Http\Response
  28 + */
  29 + public function __invoke(Request $request, DefaultEncrypter $encrypter)
  30 + {
  31 + try {
  32 + $data = json_decode($encrypter->decrypt($request->get('encrypted')), true);
  33 +
  34 + $hydrate = new Hydrate($data);
  35 +
  36 + $response = $hydrate->handle();
  37 +
  38 + return response()->json([
  39 + 'response_type' => get_class($response),
  40 + 'response' => $encrypter->encrypt($response->getBodyContents()),
  41 + ]);
  42 + } catch (Throwable $t) {
  43 + return [
  44 + 'exception' => get_class($t),
  45 + 'message' => $t->getMessage(),
  46 + ];
  47 + }
  48 + }
  49 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Laravel;
  15 +
  16 +use EasyWeChatComposer\EasyWeChat;
  17 +use EasyWeChatComposer\Encryption\DefaultEncrypter;
  18 +use Illuminate\Foundation\Application;
  19 +use Illuminate\Support\Arr;
  20 +use Illuminate\Support\Facades\Cache;
  21 +use Illuminate\Support\Facades\Route;
  22 +use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
  23 +use RuntimeException;
  24 +
  25 +class ServiceProvider extends LaravelServiceProvider
  26 +{
  27 + /**
  28 + * Bootstrap any application services.
  29 + */
  30 + public function boot()
  31 + {
  32 + $this->registerRoutes();
  33 + $this->publishes([
  34 + __DIR__.'/config.php' => config_path('easywechat-composer.php'),
  35 + ]);
  36 +
  37 + EasyWeChat::setEncryptionKey(
  38 + $defaultKey = $this->getKey()
  39 + );
  40 +
  41 + EasyWeChat::withDelegation()
  42 + ->toHost($this->config('delegation.host'))
  43 + ->ability($this->config('delegation.enabled'));
  44 +
  45 + $this->app->when(DefaultEncrypter::class)->needs('$key')->give($defaultKey);
  46 + }
  47 +
  48 + /**
  49 + * Register routes.
  50 + */
  51 + protected function registerRoutes()
  52 + {
  53 + Route::prefix('easywechat-composer')->namespace('EasyWeChatComposer\Laravel\Http\Controllers')->group(function () {
  54 + $this->loadRoutesFrom(__DIR__.'/routes.php');
  55 + });
  56 + }
  57 +
  58 + /**
  59 + * Register any application services.
  60 + */
  61 + public function register()
  62 + {
  63 + $this->configure();
  64 + }
  65 +
  66 + /**
  67 + * Register config.
  68 + */
  69 + protected function configure()
  70 + {
  71 + $this->mergeConfigFrom(
  72 + __DIR__.'/config.php', 'easywechat-composer'
  73 + );
  74 + }
  75 +
  76 + /**
  77 + * Get the specified configuration value.
  78 + *
  79 + * @param string|null $key
  80 + * @param mixed $default
  81 + *
  82 + * @return mixed
  83 + */
  84 + protected function config($key = null, $default = null)
  85 + {
  86 + $config = $this->app['config']->get('easywechat-composer');
  87 +
  88 + if (is_null($key)) {
  89 + return $config;
  90 + }
  91 +
  92 + return Arr::get($config, $key, $default);
  93 + }
  94 +
  95 + /**
  96 + * @return string
  97 + */
  98 + protected function getKey()
  99 + {
  100 + return $this->config('encryption.key') ?: $this->getMd5Key();
  101 + }
  102 +
  103 + /**
  104 + * @return string
  105 + */
  106 + protected function getMd5Key()
  107 + {
  108 + $ttl = (version_compare(Application::VERSION, '5.8') === -1) ? 30 : 1800;
  109 +
  110 + return Cache::remember('easywechat-composer.encryption_key', $ttl, function () {
  111 + throw_unless(file_exists($path = base_path('composer.lock')), RuntimeException::class, 'No encryption key provided.');
  112 +
  113 + return md5_file($path);
  114 + });
  115 + }
  116 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) mingyoung <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +return [
  15 +
  16 + 'encryption' => [
  17 +
  18 + 'key' => env('EASYWECHAT_KEY'),
  19 +
  20 + ],
  21 +
  22 + 'delegation' => [
  23 +
  24 + 'enabled' => env('EASYWECHAT_DELEGATION', false),
  25 +
  26 + 'host' => env('EASYWECHAT_DELEGATION_HOST'),
  27 + ],
  28 +
  29 +];
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +use Illuminate\Support\Facades\Route;
  15 +
  16 +Route::post('delegate', 'DelegatesController');
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer;
  15 +
  16 +use Composer\Plugin\PluginInterface;
  17 +
  18 +class ManifestManager
  19 +{
  20 + const PACKAGE_TYPE = 'easywechat-extension';
  21 +
  22 + const EXTRA_OBSERVER = 'observers';
  23 +
  24 + /**
  25 + * The vendor path.
  26 + *
  27 + * @var string
  28 + */
  29 + protected $vendorPath;
  30 +
  31 + /**
  32 + * The manifest path.
  33 + *
  34 + * @var string
  35 + */
  36 + protected $manifestPath;
  37 +
  38 + /**
  39 + * @param string $vendorPath
  40 + * @param string|null $manifestPath
  41 + */
  42 + public function __construct(string $vendorPath, string $manifestPath = null)
  43 + {
  44 + $this->vendorPath = $vendorPath;
  45 + $this->manifestPath = $manifestPath ?: $vendorPath.'/easywechat-composer/easywechat-composer/extensions.php';
  46 + }
  47 +
  48 + /**
  49 + * Remove manifest file.
  50 + *
  51 + * @return $this
  52 + */
  53 + public function unlink()
  54 + {
  55 + if (file_exists($this->manifestPath)) {
  56 + @unlink($this->manifestPath);
  57 + }
  58 +
  59 + return $this;
  60 + }
  61 +
  62 + /**
  63 + * Build the manifest file.
  64 + */
  65 + public function build()
  66 + {
  67 + $packages = [];
  68 +
  69 + if (file_exists($installed = $this->vendorPath.'/composer/installed.json')) {
  70 + $packages = json_decode(file_get_contents($installed), true);
  71 + if (version_compare(PluginInterface::PLUGIN_API_VERSION, '2.0.0', 'ge')) {
  72 + $packages = $packages['packages'];
  73 + }
  74 + }
  75 +
  76 + $this->write($this->map($packages));
  77 + }
  78 +
  79 + /**
  80 + * @param array $packages
  81 + *
  82 + * @return array
  83 + */
  84 + protected function map(array $packages): array
  85 + {
  86 + $manifest = [];
  87 +
  88 + $packages = array_filter($packages, function ($package) {
  89 + if(isset($package['type'])){
  90 + return $package['type'] === self::PACKAGE_TYPE;
  91 + }
  92 + });
  93 +
  94 + foreach ($packages as $package) {
  95 + $manifest[$package['name']] = [self::EXTRA_OBSERVER => $package['extra'][self::EXTRA_OBSERVER] ?? []];
  96 + }
  97 +
  98 + return $manifest;
  99 + }
  100 +
  101 + /**
  102 + * Write the manifest array to a file.
  103 + *
  104 + * @param array $manifest
  105 + */
  106 + protected function write(array $manifest)
  107 + {
  108 + file_put_contents(
  109 + $this->manifestPath,
  110 + '<?php return '.var_export($manifest, true).';'
  111 + );
  112 +
  113 + $this->invalidate($this->manifestPath);
  114 + }
  115 +
  116 + /**
  117 + * Invalidate the given file.
  118 + *
  119 + * @param string $file
  120 + */
  121 + protected function invalidate($file)
  122 + {
  123 + if (function_exists('opcache_invalidate')) {
  124 + @opcache_invalidate($file, true);
  125 + }
  126 + }
  127 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer;
  15 +
  16 +use Composer\Composer;
  17 +use Composer\EventDispatcher\EventSubscriberInterface;
  18 +use Composer\Installer\PackageEvent;
  19 +use Composer\Installer\PackageEvents;
  20 +use Composer\IO\IOInterface;
  21 +use Composer\Plugin\Capable;
  22 +use Composer\Plugin\PluginInterface;
  23 +use Composer\Script\Event;
  24 +use Composer\Script\ScriptEvents;
  25 +
  26 +class Plugin implements PluginInterface, EventSubscriberInterface, Capable
  27 +{
  28 + /**
  29 + * @var bool
  30 + */
  31 + protected $activated = true;
  32 +
  33 + /**
  34 + * Apply plugin modifications to Composer.
  35 + */
  36 + public function activate(Composer $composer, IOInterface $io)
  37 + {
  38 + //
  39 + }
  40 +
  41 + /**
  42 + * Remove any hooks from Composer.
  43 + *
  44 + * This will be called when a plugin is deactivated before being
  45 + * uninstalled, but also before it gets upgraded to a new version
  46 + * so the old one can be deactivated and the new one activated.
  47 + */
  48 + public function deactivate(Composer $composer, IOInterface $io)
  49 + {
  50 + //
  51 + }
  52 +
  53 + /**
  54 + * Prepare the plugin to be uninstalled.
  55 + *
  56 + * This will be called after deactivate.
  57 + */
  58 + public function uninstall(Composer $composer, IOInterface $io)
  59 + {
  60 + }
  61 +
  62 + /**
  63 + * @return array
  64 + */
  65 + public function getCapabilities()
  66 + {
  67 + return [
  68 + 'Composer\Plugin\Capability\CommandProvider' => 'EasyWeChatComposer\Commands\Provider',
  69 + ];
  70 + }
  71 +
  72 + /**
  73 + * Listen events.
  74 + *
  75 + * @return array
  76 + */
  77 + public static function getSubscribedEvents()
  78 + {
  79 + return [
  80 + PackageEvents::PRE_PACKAGE_UNINSTALL => 'prePackageUninstall',
  81 + ScriptEvents::POST_AUTOLOAD_DUMP => 'postAutoloadDump',
  82 + ];
  83 + }
  84 +
  85 + /**
  86 + * @param \Composer\Installer\PackageEvent
  87 + */
  88 + public function prePackageUninstall(PackageEvent $event)
  89 + {
  90 + if ($event->getOperation()->getPackage()->getName() === 'overtrue/wechat') {
  91 + $this->activated = false;
  92 + }
  93 + }
  94 +
  95 + public function postAutoloadDump(Event $event)
  96 + {
  97 + if (!$this->activated) {
  98 + return;
  99 + }
  100 +
  101 + $manifest = new ManifestManager(
  102 + rtrim($event->getComposer()->getConfig()->get('vendor-dir'), '/')
  103 + );
  104 +
  105 + $manifest->unlink()->build();
  106 + }
  107 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Traits;
  15 +
  16 +use EasyWeChat\Kernel\Http\StreamResponse;
  17 +use EasyWeChat\Kernel\Traits\ResponseCastable;
  18 +use EasyWeChatComposer\Contracts\Encrypter;
  19 +use EasyWeChatComposer\EasyWeChat;
  20 +use EasyWeChatComposer\Encryption\DefaultEncrypter;
  21 +use EasyWeChatComposer\Exceptions\DelegationException;
  22 +use GuzzleHttp\Client;
  23 +use GuzzleHttp\ClientInterface;
  24 +
  25 +trait MakesHttpRequests
  26 +{
  27 + use ResponseCastable;
  28 +
  29 + /**
  30 + * @var \GuzzleHttp\ClientInterface
  31 + */
  32 + protected $httpClient;
  33 +
  34 + /**
  35 + * @var \EasyWeChatComposer\Contracts\Encrypter
  36 + */
  37 + protected $encrypter;
  38 +
  39 + /**
  40 + * @param string $endpoint
  41 + * @param array $payload
  42 + *
  43 + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
  44 + *
  45 + * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  46 + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  47 + * @throws \GuzzleHttp\Exception\GuzzleException
  48 + */
  49 + protected function request($endpoint, array $payload)
  50 + {
  51 + $response = $this->getHttpClient()->request('POST', $endpoint, [
  52 + 'form_params' => $this->buildFormParams($payload),
  53 + ]);
  54 +
  55 + $parsed = $this->parseResponse($response);
  56 +
  57 + return $this->detectAndCastResponseToType(
  58 + $this->getEncrypter()->decrypt($parsed['response']),
  59 + ($parsed['response_type'] === StreamResponse::class) ? 'raw' : $this->app['config']['response_type']
  60 + );
  61 + }
  62 +
  63 + /**
  64 + * @param array $payload
  65 + *
  66 + * @return array
  67 + */
  68 + protected function buildFormParams($payload)
  69 + {
  70 + return [
  71 + 'encrypted' => $this->getEncrypter()->encrypt(json_encode($payload)),
  72 + ];
  73 + }
  74 +
  75 + /**
  76 + * @param \Psr\Http\Message\ResponseInterface $response
  77 + *
  78 + * @return array
  79 + */
  80 + protected function parseResponse($response)
  81 + {
  82 + $result = json_decode((string) $response->getBody(), true);
  83 +
  84 + if (isset($result['exception'])) {
  85 + throw (new DelegationException($result['message']))->setException($result['exception']);
  86 + }
  87 +
  88 + return $result;
  89 + }
  90 +
  91 + /**
  92 + * @return \GuzzleHttp\ClientInterface
  93 + */
  94 + protected function getHttpClient(): ClientInterface
  95 + {
  96 + return $this->httpClient ?: $this->httpClient = new Client([
  97 + 'base_uri' => $this->app['config']['delegation']['host'],
  98 + ]);
  99 + }
  100 +
  101 + /**
  102 + * @return \EasyWeChatComposer\Contracts\Encrypter
  103 + */
  104 + protected function getEncrypter(): Encrypter
  105 + {
  106 + return $this->encrypter ?: $this->encrypter = new DefaultEncrypter(
  107 + EasyWeChat::getEncryptionKey()
  108 + );
  109 + }
  110 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Traits;
  15 +
  16 +use EasyWeChat\Kernel\BaseClient;
  17 +use EasyWeChatComposer\Delegation\DelegationTo;
  18 +use EasyWeChatComposer\EasyWeChat;
  19 +
  20 +trait WithAggregator
  21 +{
  22 + /**
  23 + * Aggregate.
  24 + */
  25 + protected function aggregate()
  26 + {
  27 + foreach (EasyWeChat::config() as $key => $value) {
  28 + $this['config']->set($key, $value);
  29 + }
  30 + }
  31 +
  32 + /**
  33 + * @return bool
  34 + */
  35 + public function shouldDelegate($id)
  36 + {
  37 + return $this['config']->get('delegation.enabled')
  38 + && $this->offsetGet($id) instanceof BaseClient;
  39 + }
  40 +
  41 + /**
  42 + * @return $this
  43 + */
  44 + public function shouldntDelegate()
  45 + {
  46 + $this['config']->set('delegation.enabled', false);
  47 +
  48 + return $this;
  49 + }
  50 +
  51 + /**
  52 + * @param string $id
  53 + *
  54 + * @return \EasyWeChatComposer\Delegation
  55 + */
  56 + public function delegateTo($id)
  57 + {
  58 + return new DelegationTo($this, $id);
  59 + }
  60 +}
  1 +<?php
  2 +
  3 +declare(strict_types=1);
  4 +
  5 +/*
  6 + * This file is part of the EasyWeChatComposer.
  7 + *
  8 + * (c) 张铭阳 <mingyoungcheung@gmail.com>
  9 + *
  10 + * This source file is subject to the MIT license that is bundled
  11 + * with this source code in the file LICENSE.
  12 + */
  13 +
  14 +namespace EasyWeChatComposer\Tests;
  15 +
  16 +use EasyWeChatComposer\ManifestManager;
  17 +use PHPUnit\Framework\TestCase;
  18 +
  19 +class ManifestManagerTest extends TestCase
  20 +{
  21 + private $vendorPath;
  22 + private $manifestPath;
  23 +
  24 + protected function getManifestManager()
  25 + {
  26 + return new ManifestManager(
  27 + $this->vendorPath = __DIR__.'/__fixtures__/vendor/',
  28 + $this->manifestPath = __DIR__.'/__fixtures__/extensions.php'
  29 + );
  30 + }
  31 +
  32 + public function testUnlink()
  33 + {
  34 + $this->assertInstanceOf(ManifestManager::class, $this->getManifestManager()->unlink());
  35 + $this->assertFalse(file_exists($this->manifestPath));
  36 + }
  37 +}
  1 +# [4.16.0](https://github.com/ezyang/htmlpurifier/compare/v4.15.0...v4.16.0) (2022-09-18)
  2 +
  3 +
  4 +### Features
  5 +
  6 +* add semantic release ([#307](https://github.com/ezyang/htmlpurifier/issues/307)) ([db31243](https://github.com/ezyang/htmlpurifier/commit/db312435cb9d8d73395f75f9642a43ba6de5e903)), closes [#322](https://github.com/ezyang/htmlpurifier/issues/322) [#323](https://github.com/ezyang/htmlpurifier/issues/323) [#326](https://github.com/ezyang/htmlpurifier/issues/326) [#327](https://github.com/ezyang/htmlpurifier/issues/327) [#328](https://github.com/ezyang/htmlpurifier/issues/328) [#329](https://github.com/ezyang/htmlpurifier/issues/329) [#330](https://github.com/ezyang/htmlpurifier/issues/330) [#331](https://github.com/ezyang/htmlpurifier/issues/331) [#332](https://github.com/ezyang/htmlpurifier/issues/332) [#333](https://github.com/ezyang/htmlpurifier/issues/333) [#337](https://github.com/ezyang/htmlpurifier/issues/337) [#335](https://github.com/ezyang/htmlpurifier/issues/335) [ezyang/htmlpurifier#334](https://github.com/ezyang/htmlpurifier/issues/334) [#336](https://github.com/ezyang/htmlpurifier/issues/336) [#338](https://github.com/ezyang/htmlpurifier/issues/338)
  1 +
  2 +CREDITS
  3 +
  4 +Almost everything written by Edward Z. Yang (Ambush Commander). Lots of thanks
  5 +to the DevNetwork Community for their help (see docs/ref-devnetwork.html for
  6 +more details), Feyd especially (namely IPv6 and optimization). Thanks to RSnake
  7 +for letting me package his fantastic XSS cheatsheet for a smoketest.
  8 +
  9 + vim: et sw=4 sts=4
  1 + GNU LESSER GENERAL PUBLIC LICENSE
  2 + Version 2.1, February 1999
  3 +
  4 + Copyright (C) 1991, 1999 Free Software Foundation, Inc.
  5 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  6 + Everyone is permitted to copy and distribute verbatim copies
  7 + of this license document, but changing it is not allowed.
  8 +
  9 +[This is the first released version of the Lesser GPL. It also counts
  10 + as the successor of the GNU Library Public License, version 2, hence
  11 + the version number 2.1.]
  12 +
  13 + Preamble
  14 +
  15 + The licenses for most software are designed to take away your
  16 +freedom to share and change it. By contrast, the GNU General Public
  17 +Licenses are intended to guarantee your freedom to share and change
  18 +free software--to make sure the software is free for all its users.
  19 +
  20 + This license, the Lesser General Public License, applies to some
  21 +specially designated software packages--typically libraries--of the
  22 +Free Software Foundation and other authors who decide to use it. You
  23 +can use it too, but we suggest you first think carefully about whether
  24 +this license or the ordinary General Public License is the better
  25 +strategy to use in any particular case, based on the explanations below.
  26 +
  27 + When we speak of free software, we are referring to freedom of use,
  28 +not price. Our General Public Licenses are designed to make sure that
  29 +you have the freedom to distribute copies of free software (and charge
  30 +for this service if you wish); that you receive source code or can get
  31 +it if you want it; that you can change the software and use pieces of
  32 +it in new free programs; and that you are informed that you can do
  33 +these things.
  34 +
  35 + To protect your rights, we need to make restrictions that forbid
  36 +distributors to deny you these rights or to ask you to surrender these
  37 +rights. These restrictions translate to certain responsibilities for
  38 +you if you distribute copies of the library or if you modify it.
  39 +
  40 + For example, if you distribute copies of the library, whether gratis
  41 +or for a fee, you must give the recipients all the rights that we gave
  42 +you. You must make sure that they, too, receive or can get the source
  43 +code. If you link other code with the library, you must provide
  44 +complete object files to the recipients, so that they can relink them
  45 +with the library after making changes to the library and recompiling
  46 +it. And you must show them these terms so they know their rights.
  47 +
  48 + We protect your rights with a two-step method: (1) we copyright the
  49 +library, and (2) we offer you this license, which gives you legal
  50 +permission to copy, distribute and/or modify the library.
  51 +
  52 + To protect each distributor, we want to make it very clear that
  53 +there is no warranty for the free library. Also, if the library is
  54 +modified by someone else and passed on, the recipients should know
  55 +that what they have is not the original version, so that the original
  56 +author's reputation will not be affected by problems that might be
  57 +introduced by others.
  58 +
  59 + Finally, software patents pose a constant threat to the existence of
  60 +any free program. We wish to make sure that a company cannot
  61 +effectively restrict the users of a free program by obtaining a
  62 +restrictive license from a patent holder. Therefore, we insist that
  63 +any patent license obtained for a version of the library must be
  64 +consistent with the full freedom of use specified in this license.
  65 +
  66 + Most GNU software, including some libraries, is covered by the
  67 +ordinary GNU General Public License. This license, the GNU Lesser
  68 +General Public License, applies to certain designated libraries, and
  69 +is quite different from the ordinary General Public License. We use
  70 +this license for certain libraries in order to permit linking those
  71 +libraries into non-free programs.
  72 +
  73 + When a program is linked with a library, whether statically or using
  74 +a shared library, the combination of the two is legally speaking a
  75 +combined work, a derivative of the original library. The ordinary
  76 +General Public License therefore permits such linking only if the
  77 +entire combination fits its criteria of freedom. The Lesser General
  78 +Public License permits more lax criteria for linking other code with
  79 +the library.
  80 +
  81 + We call this license the "Lesser" General Public License because it
  82 +does Less to protect the user's freedom than the ordinary General
  83 +Public License. It also provides other free software developers Less
  84 +of an advantage over competing non-free programs. These disadvantages
  85 +are the reason we use the ordinary General Public License for many
  86 +libraries. However, the Lesser license provides advantages in certain
  87 +special circumstances.
  88 +
  89 + For example, on rare occasions, there may be a special need to
  90 +encourage the widest possible use of a certain library, so that it becomes
  91 +a de-facto standard. To achieve this, non-free programs must be
  92 +allowed to use the library. A more frequent case is that a free
  93 +library does the same job as widely used non-free libraries. In this
  94 +case, there is little to gain by limiting the free library to free
  95 +software only, so we use the Lesser General Public License.
  96 +
  97 + In other cases, permission to use a particular library in non-free
  98 +programs enables a greater number of people to use a large body of
  99 +free software. For example, permission to use the GNU C Library in
  100 +non-free programs enables many more people to use the whole GNU
  101 +operating system, as well as its variant, the GNU/Linux operating
  102 +system.
  103 +
  104 + Although the Lesser General Public License is Less protective of the
  105 +users' freedom, it does ensure that the user of a program that is
  106 +linked with the Library has the freedom and the wherewithal to run
  107 +that program using a modified version of the Library.
  108 +
  109 + The precise terms and conditions for copying, distribution and
  110 +modification follow. Pay close attention to the difference between a
  111 +"work based on the library" and a "work that uses the library". The
  112 +former contains code derived from the library, whereas the latter must
  113 +be combined with the library in order to run.
  114 +
  115 + GNU LESSER GENERAL PUBLIC LICENSE
  116 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  117 +
  118 + 0. This License Agreement applies to any software library or other
  119 +program which contains a notice placed by the copyright holder or
  120 +other authorized party saying it may be distributed under the terms of
  121 +this Lesser General Public License (also called "this License").
  122 +Each licensee is addressed as "you".
  123 +
  124 + A "library" means a collection of software functions and/or data
  125 +prepared so as to be conveniently linked with application programs
  126 +(which use some of those functions and data) to form executables.
  127 +
  128 + The "Library", below, refers to any such software library or work
  129 +which has been distributed under these terms. A "work based on the
  130 +Library" means either the Library or any derivative work under
  131 +copyright law: that is to say, a work containing the Library or a
  132 +portion of it, either verbatim or with modifications and/or translated
  133 +straightforwardly into another language. (Hereinafter, translation is
  134 +included without limitation in the term "modification".)
  135 +
  136 + "Source code" for a work means the preferred form of the work for
  137 +making modifications to it. For a library, complete source code means
  138 +all the source code for all modules it contains, plus any associated
  139 +interface definition files, plus the scripts used to control compilation
  140 +and installation of the library.
  141 +
  142 + Activities other than copying, distribution and modification are not
  143 +covered by this License; they are outside its scope. The act of
  144 +running a program using the Library is not restricted, and output from
  145 +such a program is covered only if its contents constitute a work based
  146 +on the Library (independent of the use of the Library in a tool for
  147 +writing it). Whether that is true depends on what the Library does
  148 +and what the program that uses the Library does.
  149 +
  150 + 1. You may copy and distribute verbatim copies of the Library's
  151 +complete source code as you receive it, in any medium, provided that
  152 +you conspicuously and appropriately publish on each copy an
  153 +appropriate copyright notice and disclaimer of warranty; keep intact
  154 +all the notices that refer to this License and to the absence of any
  155 +warranty; and distribute a copy of this License along with the
  156 +Library.
  157 +
  158 + You may charge a fee for the physical act of transferring a copy,
  159 +and you may at your option offer warranty protection in exchange for a
  160 +fee.
  161 +
  162 + 2. You may modify your copy or copies of the Library or any portion
  163 +of it, thus forming a work based on the Library, and copy and
  164 +distribute such modifications or work under the terms of Section 1
  165 +above, provided that you also meet all of these conditions:
  166 +
  167 + a) The modified work must itself be a software library.
  168 +
  169 + b) You must cause the files modified to carry prominent notices
  170 + stating that you changed the files and the date of any change.
  171 +
  172 + c) You must cause the whole of the work to be licensed at no
  173 + charge to all third parties under the terms of this License.
  174 +
  175 + d) If a facility in the modified Library refers to a function or a
  176 + table of data to be supplied by an application program that uses
  177 + the facility, other than as an argument passed when the facility
  178 + is invoked, then you must make a good faith effort to ensure that,
  179 + in the event an application does not supply such function or
  180 + table, the facility still operates, and performs whatever part of
  181 + its purpose remains meaningful.
  182 +
  183 + (For example, a function in a library to compute square roots has
  184 + a purpose that is entirely well-defined independent of the
  185 + application. Therefore, Subsection 2d requires that any
  186 + application-supplied function or table used by this function must
  187 + be optional: if the application does not supply it, the square
  188 + root function must still compute square roots.)
  189 +
  190 +These requirements apply to the modified work as a whole. If
  191 +identifiable sections of that work are not derived from the Library,
  192 +and can be reasonably considered independent and separate works in
  193 +themselves, then this License, and its terms, do not apply to those
  194 +sections when you distribute them as separate works. But when you
  195 +distribute the same sections as part of a whole which is a work based
  196 +on the Library, the distribution of the whole must be on the terms of
  197 +this License, whose permissions for other licensees extend to the
  198 +entire whole, and thus to each and every part regardless of who wrote
  199 +it.
  200 +
  201 +Thus, it is not the intent of this section to claim rights or contest
  202 +your rights to work written entirely by you; rather, the intent is to
  203 +exercise the right to control the distribution of derivative or
  204 +collective works based on the Library.
  205 +
  206 +In addition, mere aggregation of another work not based on the Library
  207 +with the Library (or with a work based on the Library) on a volume of
  208 +a storage or distribution medium does not bring the other work under
  209 +the scope of this License.
  210 +
  211 + 3. You may opt to apply the terms of the ordinary GNU General Public
  212 +License instead of this License to a given copy of the Library. To do
  213 +this, you must alter all the notices that refer to this License, so
  214 +that they refer to the ordinary GNU General Public License, version 2,
  215 +instead of to this License. (If a newer version than version 2 of the
  216 +ordinary GNU General Public License has appeared, then you can specify
  217 +that version instead if you wish.) Do not make any other change in
  218 +these notices.
  219 +
  220 + Once this change is made in a given copy, it is irreversible for
  221 +that copy, so the ordinary GNU General Public License applies to all
  222 +subsequent copies and derivative works made from that copy.
  223 +
  224 + This option is useful when you wish to copy part of the code of
  225 +the Library into a program that is not a library.
  226 +
  227 + 4. You may copy and distribute the Library (or a portion or
  228 +derivative of it, under Section 2) in object code or executable form
  229 +under the terms of Sections 1 and 2 above provided that you accompany
  230 +it with the complete corresponding machine-readable source code, which
  231 +must be distributed under the terms of Sections 1 and 2 above on a
  232 +medium customarily used for software interchange.
  233 +
  234 + If distribution of object code is made by offering access to copy
  235 +from a designated place, then offering equivalent access to copy the
  236 +source code from the same place satisfies the requirement to
  237 +distribute the source code, even though third parties are not
  238 +compelled to copy the source along with the object code.
  239 +
  240 + 5. A program that contains no derivative of any portion of the
  241 +Library, but is designed to work with the Library by being compiled or
  242 +linked with it, is called a "work that uses the Library". Such a
  243 +work, in isolation, is not a derivative work of the Library, and
  244 +therefore falls outside the scope of this License.
  245 +
  246 + However, linking a "work that uses the Library" with the Library
  247 +creates an executable that is a derivative of the Library (because it
  248 +contains portions of the Library), rather than a "work that uses the
  249 +library". The executable is therefore covered by this License.
  250 +Section 6 states terms for distribution of such executables.
  251 +
  252 + When a "work that uses the Library" uses material from a header file
  253 +that is part of the Library, the object code for the work may be a
  254 +derivative work of the Library even though the source code is not.
  255 +Whether this is true is especially significant if the work can be
  256 +linked without the Library, or if the work is itself a library. The
  257 +threshold for this to be true is not precisely defined by law.
  258 +
  259 + If such an object file uses only numerical parameters, data
  260 +structure layouts and accessors, and small macros and small inline
  261 +functions (ten lines or less in length), then the use of the object
  262 +file is unrestricted, regardless of whether it is legally a derivative
  263 +work. (Executables containing this object code plus portions of the
  264 +Library will still fall under Section 6.)
  265 +
  266 + Otherwise, if the work is a derivative of the Library, you may
  267 +distribute the object code for the work under the terms of Section 6.
  268 +Any executables containing that work also fall under Section 6,
  269 +whether or not they are linked directly with the Library itself.
  270 +
  271 + 6. As an exception to the Sections above, you may also combine or
  272 +link a "work that uses the Library" with the Library to produce a
  273 +work containing portions of the Library, and distribute that work
  274 +under terms of your choice, provided that the terms permit
  275 +modification of the work for the customer's own use and reverse
  276 +engineering for debugging such modifications.
  277 +
  278 + You must give prominent notice with each copy of the work that the
  279 +Library is used in it and that the Library and its use are covered by
  280 +this License. You must supply a copy of this License. If the work
  281 +during execution displays copyright notices, you must include the
  282 +copyright notice for the Library among them, as well as a reference
  283 +directing the user to the copy of this License. Also, you must do one
  284 +of these things:
  285 +
  286 + a) Accompany the work with the complete corresponding
  287 + machine-readable source code for the Library including whatever
  288 + changes were used in the work (which must be distributed under
  289 + Sections 1 and 2 above); and, if the work is an executable linked
  290 + with the Library, with the complete machine-readable "work that
  291 + uses the Library", as object code and/or source code, so that the
  292 + user can modify the Library and then relink to produce a modified
  293 + executable containing the modified Library. (It is understood
  294 + that the user who changes the contents of definitions files in the
  295 + Library will not necessarily be able to recompile the application
  296 + to use the modified definitions.)
  297 +
  298 + b) Use a suitable shared library mechanism for linking with the
  299 + Library. A suitable mechanism is one that (1) uses at run time a
  300 + copy of the library already present on the user's computer system,
  301 + rather than copying library functions into the executable, and (2)
  302 + will operate properly with a modified version of the library, if
  303 + the user installs one, as long as the modified version is
  304 + interface-compatible with the version that the work was made with.
  305 +
  306 + c) Accompany the work with a written offer, valid for at
  307 + least three years, to give the same user the materials
  308 + specified in Subsection 6a, above, for a charge no more
  309 + than the cost of performing this distribution.
  310 +
  311 + d) If distribution of the work is made by offering access to copy
  312 + from a designated place, offer equivalent access to copy the above
  313 + specified materials from the same place.
  314 +
  315 + e) Verify that the user has already received a copy of these
  316 + materials or that you have already sent this user a copy.
  317 +
  318 + For an executable, the required form of the "work that uses the
  319 +Library" must include any data and utility programs needed for
  320 +reproducing the executable from it. However, as a special exception,
  321 +the materials to be distributed need not include anything that is
  322 +normally distributed (in either source or binary form) with the major
  323 +components (compiler, kernel, and so on) of the operating system on
  324 +which the executable runs, unless that component itself accompanies
  325 +the executable.
  326 +
  327 + It may happen that this requirement contradicts the license
  328 +restrictions of other proprietary libraries that do not normally
  329 +accompany the operating system. Such a contradiction means you cannot
  330 +use both them and the Library together in an executable that you
  331 +distribute.
  332 +
  333 + 7. You may place library facilities that are a work based on the
  334 +Library side-by-side in a single library together with other library
  335 +facilities not covered by this License, and distribute such a combined
  336 +library, provided that the separate distribution of the work based on
  337 +the Library and of the other library facilities is otherwise
  338 +permitted, and provided that you do these two things:
  339 +
  340 + a) Accompany the combined library with a copy of the same work
  341 + based on the Library, uncombined with any other library
  342 + facilities. This must be distributed under the terms of the
  343 + Sections above.
  344 +
  345 + b) Give prominent notice with the combined library of the fact
  346 + that part of it is a work based on the Library, and explaining
  347 + where to find the accompanying uncombined form of the same work.
  348 +
  349 + 8. You may not copy, modify, sublicense, link with, or distribute
  350 +the Library except as expressly provided under this License. Any
  351 +attempt otherwise to copy, modify, sublicense, link with, or
  352 +distribute the Library is void, and will automatically terminate your
  353 +rights under this License. However, parties who have received copies,
  354 +or rights, from you under this License will not have their licenses
  355 +terminated so long as such parties remain in full compliance.
  356 +
  357 + 9. You are not required to accept this License, since you have not
  358 +signed it. However, nothing else grants you permission to modify or
  359 +distribute the Library or its derivative works. These actions are
  360 +prohibited by law if you do not accept this License. Therefore, by
  361 +modifying or distributing the Library (or any work based on the
  362 +Library), you indicate your acceptance of this License to do so, and
  363 +all its terms and conditions for copying, distributing or modifying
  364 +the Library or works based on it.
  365 +
  366 + 10. Each time you redistribute the Library (or any work based on the
  367 +Library), the recipient automatically receives a license from the
  368 +original licensor to copy, distribute, link with or modify the Library
  369 +subject to these terms and conditions. You may not impose any further
  370 +restrictions on the recipients' exercise of the rights granted herein.
  371 +You are not responsible for enforcing compliance by third parties with
  372 +this License.
  373 +
  374 + 11. If, as a consequence of a court judgment or allegation of patent
  375 +infringement or for any other reason (not limited to patent issues),
  376 +conditions are imposed on you (whether by court order, agreement or
  377 +otherwise) that contradict the conditions of this License, they do not
  378 +excuse you from the conditions of this License. If you cannot
  379 +distribute so as to satisfy simultaneously your obligations under this
  380 +License and any other pertinent obligations, then as a consequence you
  381 +may not distribute the Library at all. For example, if a patent
  382 +license would not permit royalty-free redistribution of the Library by
  383 +all those who receive copies directly or indirectly through you, then
  384 +the only way you could satisfy both it and this License would be to
  385 +refrain entirely from distribution of the Library.
  386 +
  387 +If any portion of this section is held invalid or unenforceable under any
  388 +particular circumstance, the balance of the section is intended to apply,
  389 +and the section as a whole is intended to apply in other circumstances.
  390 +
  391 +It is not the purpose of this section to induce you to infringe any
  392 +patents or other property right claims or to contest validity of any
  393 +such claims; this section has the sole purpose of protecting the
  394 +integrity of the free software distribution system which is
  395 +implemented by public license practices. Many people have made
  396 +generous contributions to the wide range of software distributed
  397 +through that system in reliance on consistent application of that
  398 +system; it is up to the author/donor to decide if he or she is willing
  399 +to distribute software through any other system and a licensee cannot
  400 +impose that choice.
  401 +
  402 +This section is intended to make thoroughly clear what is believed to
  403 +be a consequence of the rest of this License.
  404 +
  405 + 12. If the distribution and/or use of the Library is restricted in
  406 +certain countries either by patents or by copyrighted interfaces, the
  407 +original copyright holder who places the Library under this License may add
  408 +an explicit geographical distribution limitation excluding those countries,
  409 +so that distribution is permitted only in or among countries not thus
  410 +excluded. In such case, this License incorporates the limitation as if
  411 +written in the body of this License.
  412 +
  413 + 13. The Free Software Foundation may publish revised and/or new
  414 +versions of the Lesser General Public License from time to time.
  415 +Such new versions will be similar in spirit to the present version,
  416 +but may differ in detail to address new problems or concerns.
  417 +
  418 +Each version is given a distinguishing version number. If the Library
  419 +specifies a version number of this License which applies to it and
  420 +"any later version", you have the option of following the terms and
  421 +conditions either of that version or of any later version published by
  422 +the Free Software Foundation. If the Library does not specify a
  423 +license version number, you may choose any version ever published by
  424 +the Free Software Foundation.
  425 +
  426 + 14. If you wish to incorporate parts of the Library into other free
  427 +programs whose distribution conditions are incompatible with these,
  428 +write to the author to ask for permission. For software which is
  429 +copyrighted by the Free Software Foundation, write to the Free
  430 +Software Foundation; we sometimes make exceptions for this. Our
  431 +decision will be guided by the two goals of preserving the free status
  432 +of all derivatives of our free software and of promoting the sharing
  433 +and reuse of software generally.
  434 +
  435 + NO WARRANTY
  436 +
  437 + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
  438 +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
  439 +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
  440 +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
  441 +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
  442 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  443 +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
  444 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
  445 +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  446 +
  447 + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
  448 +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
  449 +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
  450 +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
  451 +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
  452 +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
  453 +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
  454 +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
  455 +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  456 +DAMAGES.
  457 +
  458 + END OF TERMS AND CONDITIONS
  459 +
  460 + How to Apply These Terms to Your New Libraries
  461 +
  462 + If you develop a new library, and you want it to be of the greatest
  463 +possible use to the public, we recommend making it free software that
  464 +everyone can redistribute and change. You can do so by permitting
  465 +redistribution under these terms (or, alternatively, under the terms of the
  466 +ordinary General Public License).
  467 +
  468 + To apply these terms, attach the following notices to the library. It is
  469 +safest to attach them to the start of each source file to most effectively
  470 +convey the exclusion of warranty; and each file should have at least the
  471 +"copyright" line and a pointer to where the full notice is found.
  472 +
  473 + <one line to give the library's name and a brief idea of what it does.>
  474 + Copyright (C) <year> <name of author>
  475 +
  476 + This library is free software; you can redistribute it and/or
  477 + modify it under the terms of the GNU Lesser General Public
  478 + License as published by the Free Software Foundation; either
  479 + version 2.1 of the License, or (at your option) any later version.
  480 +
  481 + This library is distributed in the hope that it will be useful,
  482 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  483 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  484 + Lesser General Public License for more details.
  485 +
  486 + You should have received a copy of the GNU Lesser General Public
  487 + License along with this library; if not, write to the Free Software
  488 + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  489 +
  490 +Also add information on how to contact you by electronic and paper mail.
  491 +
  492 +You should also get your employer (if you work as a programmer) or your
  493 +school, if any, to sign a "copyright disclaimer" for the library, if
  494 +necessary. Here is a sample; alter the names:
  495 +
  496 + Yoyodyne, Inc., hereby disclaims all copyright interest in the
  497 + library `Frob' (a library for tweaking knobs) written by James Random Hacker.
  498 +
  499 + <signature of Ty Coon>, 1 April 1990
  500 + Ty Coon, President of Vice
  501 +
  502 +That's all there is to it!
  503 +
  504 + vim: et sw=4 sts=4
  1 +HTML Purifier [![Build Status](https://github.com/ezyang/htmlpurifier/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/ezyang/htmlpurifier/actions/workflows/ci.yml)
  2 +=============
  3 +
  4 +HTML Purifier is an HTML filtering solution that uses a unique combination
  5 +of robust whitelists and aggressive parsing to ensure that not only are
  6 +XSS attacks thwarted, but the resulting HTML is standards compliant.
  7 +
  8 +HTML Purifier is oriented towards richly formatted documents from
  9 +untrusted sources that require CSS and a full tag-set. This library can
  10 +be configured to accept a more restrictive set of tags, but it won't be
  11 +as efficient as more bare-bones parsers. It will, however, do the job
  12 +right, which may be more important.
  13 +
  14 +Places to go:
  15 +
  16 +* See INSTALL for a quick installation guide
  17 +* See docs/ for developer-oriented documentation, code examples and
  18 + an in-depth installation guide.
  19 +* See WYSIWYG for information on editors like TinyMCE and FCKeditor
  20 +
  21 +HTML Purifier can be found on the web at: [http://htmlpurifier.org/](http://htmlpurifier.org/)
  22 +
  23 +## Installation
  24 +
  25 +Package available on [Composer](https://packagist.org/packages/ezyang/htmlpurifier).
  26 +
  27 +If you're using Composer to manage dependencies, you can use
  28 +
  29 + $ composer require ezyang/htmlpurifier
  1 +{
  2 + "name": "ezyang/htmlpurifier",
  3 + "description": "Standards compliant HTML filter written in PHP",
  4 + "type": "library",
  5 + "keywords": ["html"],
  6 + "homepage": "http://htmlpurifier.org/",
  7 + "license": "LGPL-2.1-or-later",
  8 + "authors": [
  9 + {
  10 + "name": "Edward Z. Yang",
  11 + "email": "admin@htmlpurifier.org",
  12 + "homepage": "http://ezyang.com"
  13 + }
  14 + ],
  15 + "require": {
  16 + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0"
  17 + },
  18 + "require-dev": {
  19 + "cerdic/css-tidy": "^1.7 || ^2.0",
  20 + "simpletest/simpletest": "dev-master"
  21 + },
  22 + "autoload": {
  23 + "psr-0": { "HTMLPurifier": "library/" },
  24 + "files": ["library/HTMLPurifier.composer.php"],
  25 + "exclude-from-classmap": [
  26 + "/library/HTMLPurifier/Language/"
  27 + ]
  28 + },
  29 + "suggest": {
  30 + "cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
  31 + "ext-iconv": "Converts text to and from non-UTF-8 encodings",
  32 + "ext-bcmath": "Used for unit conversion and imagecrash protection",
  33 + "ext-tidy": "Used for pretty-printing HTML"
  34 + },
  35 + "config": {
  36 + "sort-packages": true
  37 + },
  38 + "repositories": [
  39 + {
  40 + "type": "vcs",
  41 + "url": "https://github.com/ezyang/simpletest.git"
  42 + }
  43 + ]
  44 +}
  1 +<?php
  2 +
  3 +/**
  4 + * This is a stub include that automatically configures the include path.
  5 + */
  6 +
  7 +set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
  8 +require_once 'HTMLPurifier/Bootstrap.php';
  9 +require_once 'HTMLPurifier.autoload.php';
  10 +
  11 +// vim: et sw=4 sts=4
  1 +<?php
  2 +
  3 +/**
  4 + * @file
  5 + * Legacy autoloader for systems lacking spl_autoload_register
  6 + *
  7 + */
  8 +
  9 +spl_autoload_register(function($class)
  10 +{
  11 + return HTMLPurifier_Bootstrap::autoload($class);
  12 +});
  13 +
  14 +// vim: et sw=4 sts=4
  1 +<?php
  2 +
  3 +/**
  4 + * @file
  5 + * Convenience file that registers autoload handler for HTML Purifier.
  6 + * It also does some sanity checks.
  7 + */
  8 +
  9 +if (function_exists('spl_autoload_register') && function_exists('spl_autoload_unregister')) {
  10 + // We need unregister for our pre-registering functionality
  11 + HTMLPurifier_Bootstrap::registerAutoload();
  12 + if (function_exists('__autoload')) {
  13 + // Be polite and ensure that userland autoload gets retained
  14 + spl_autoload_register('__autoload');
  15 + }
  16 +} elseif (!function_exists('__autoload')) {
  17 + require dirname(__FILE__) . '/HTMLPurifier.autoload-legacy.php';
  18 +}
  19 +
  20 +// phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.zend_ze1_compatibility_modeRemoved
  21 +if (ini_get('zend.ze1_compatibility_mode')) {
  22 + trigger_error("HTML Purifier is not compatible with zend.ze1_compatibility_mode; please turn it off", E_USER_ERROR);
  23 +}
  24 +
  25 +// vim: et sw=4 sts=4
  1 +<?php
  2 +if (!defined('HTMLPURIFIER_PREFIX')) {
  3 + define('HTMLPURIFIER_PREFIX', dirname(__FILE__));
  4 +}
  1 +<?php
  2 +
  3 +/**
  4 + * @file
  5 + * Defines a function wrapper for HTML Purifier for quick use.
  6 + * @note ''HTMLPurifier()'' is NOT the same as ''new HTMLPurifier()''
  7 + */
  8 +
  9 +/**
  10 + * Purify HTML.
  11 + * @param string $html String HTML to purify
  12 + * @param mixed $config Configuration to use, can be any value accepted by
  13 + * HTMLPurifier_Config::create()
  14 + * @return string
  15 + */
  16 +function HTMLPurifier($html, $config = null)
  17 +{
  18 + static $purifier = false;
  19 + if (!$purifier) {
  20 + $purifier = new HTMLPurifier();
  21 + }
  22 + return $purifier->purify($html, $config);
  23 +}
  24 +
  25 +// vim: et sw=4 sts=4
  1 +<?php
  2 +
  3 +/**
  4 + * @file
  5 + * This file was auto-generated by generate-includes.php and includes all of
  6 + * the core files required by HTML Purifier. Use this if performance is a
  7 + * primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
  8 + * FILE, changes will be overwritten the next time the script is run.
  9 + *
  10 + * @version 4.15.0
  11 + *
  12 + * @warning
  13 + * You must *not* include any other HTML Purifier files before this file,
  14 + * because 'require' not 'require_once' is used.
  15 + *
  16 + * @warning
  17 + * This file requires that the include path contains the HTML Purifier
  18 + * library directory; this is not auto-set.
  19 + */
  20 +
  21 +require 'HTMLPurifier.php';
  22 +require 'HTMLPurifier/Arborize.php';
  23 +require 'HTMLPurifier/AttrCollections.php';
  24 +require 'HTMLPurifier/AttrDef.php';
  25 +require 'HTMLPurifier/AttrTransform.php';
  26 +require 'HTMLPurifier/AttrTypes.php';
  27 +require 'HTMLPurifier/AttrValidator.php';
  28 +require 'HTMLPurifier/Bootstrap.php';
  29 +require 'HTMLPurifier/Definition.php';
  30 +require 'HTMLPurifier/CSSDefinition.php';
  31 +require 'HTMLPurifier/ChildDef.php';
  32 +require 'HTMLPurifier/Config.php';
  33 +require 'HTMLPurifier/ConfigSchema.php';
  34 +require 'HTMLPurifier/ContentSets.php';
  35 +require 'HTMLPurifier/Context.php';
  36 +require 'HTMLPurifier/DefinitionCache.php';
  37 +require 'HTMLPurifier/DefinitionCacheFactory.php';
  38 +require 'HTMLPurifier/Doctype.php';
  39 +require 'HTMLPurifier/DoctypeRegistry.php';
  40 +require 'HTMLPurifier/ElementDef.php';
  41 +require 'HTMLPurifier/Encoder.php';
  42 +require 'HTMLPurifier/EntityLookup.php';
  43 +require 'HTMLPurifier/EntityParser.php';
  44 +require 'HTMLPurifier/ErrorCollector.php';
  45 +require 'HTMLPurifier/ErrorStruct.php';
  46 +require 'HTMLPurifier/Exception.php';
  47 +require 'HTMLPurifier/Filter.php';
  48 +require 'HTMLPurifier/Generator.php';
  49 +require 'HTMLPurifier/HTMLDefinition.php';
  50 +require 'HTMLPurifier/HTMLModule.php';
  51 +require 'HTMLPurifier/HTMLModuleManager.php';
  52 +require 'HTMLPurifier/IDAccumulator.php';
  53 +require 'HTMLPurifier/Injector.php';
  54 +require 'HTMLPurifier/Language.php';
  55 +require 'HTMLPurifier/LanguageFactory.php';
  56 +require 'HTMLPurifier/Length.php';
  57 +require 'HTMLPurifier/Lexer.php';
  58 +require 'HTMLPurifier/Node.php';
  59 +require 'HTMLPurifier/PercentEncoder.php';
  60 +require 'HTMLPurifier/PropertyList.php';
  61 +require 'HTMLPurifier/PropertyListIterator.php';
  62 +require 'HTMLPurifier/Queue.php';
  63 +require 'HTMLPurifier/Strategy.php';
  64 +require 'HTMLPurifier/StringHash.php';
  65 +require 'HTMLPurifier/StringHashParser.php';
  66 +require 'HTMLPurifier/TagTransform.php';
  67 +require 'HTMLPurifier/Token.php';
  68 +require 'HTMLPurifier/TokenFactory.php';
  69 +require 'HTMLPurifier/URI.php';
  70 +require 'HTMLPurifier/URIDefinition.php';
  71 +require 'HTMLPurifier/URIFilter.php';
  72 +require 'HTMLPurifier/URIParser.php';
  73 +require 'HTMLPurifier/URIScheme.php';
  74 +require 'HTMLPurifier/URISchemeRegistry.php';
  75 +require 'HTMLPurifier/UnitConverter.php';
  76 +require 'HTMLPurifier/VarParser.php';
  77 +require 'HTMLPurifier/VarParserException.php';
  78 +require 'HTMLPurifier/Zipper.php';
  79 +require 'HTMLPurifier/AttrDef/CSS.php';
  80 +require 'HTMLPurifier/AttrDef/Clone.php';
  81 +require 'HTMLPurifier/AttrDef/Enum.php';
  82 +require 'HTMLPurifier/AttrDef/Integer.php';
  83 +require 'HTMLPurifier/AttrDef/Lang.php';
  84 +require 'HTMLPurifier/AttrDef/Switch.php';
  85 +require 'HTMLPurifier/AttrDef/Text.php';
  86 +require 'HTMLPurifier/AttrDef/URI.php';
  87 +require 'HTMLPurifier/AttrDef/CSS/Number.php';
  88 +require 'HTMLPurifier/AttrDef/CSS/AlphaValue.php';
  89 +require 'HTMLPurifier/AttrDef/CSS/Background.php';
  90 +require 'HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
  91 +require 'HTMLPurifier/AttrDef/CSS/Border.php';
  92 +require 'HTMLPurifier/AttrDef/CSS/Color.php';
  93 +require 'HTMLPurifier/AttrDef/CSS/Composite.php';
  94 +require 'HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
  95 +require 'HTMLPurifier/AttrDef/CSS/Filter.php';
  96 +require 'HTMLPurifier/AttrDef/CSS/Font.php';
  97 +require 'HTMLPurifier/AttrDef/CSS/FontFamily.php';
  98 +require 'HTMLPurifier/AttrDef/CSS/Ident.php';
  99 +require 'HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
  100 +require 'HTMLPurifier/AttrDef/CSS/Length.php';
  101 +require 'HTMLPurifier/AttrDef/CSS/ListStyle.php';
  102 +require 'HTMLPurifier/AttrDef/CSS/Multiple.php';
  103 +require 'HTMLPurifier/AttrDef/CSS/Percentage.php';
  104 +require 'HTMLPurifier/AttrDef/CSS/TextDecoration.php';
  105 +require 'HTMLPurifier/AttrDef/CSS/URI.php';
  106 +require 'HTMLPurifier/AttrDef/HTML/Bool.php';
  107 +require 'HTMLPurifier/AttrDef/HTML/Nmtokens.php';
  108 +require 'HTMLPurifier/AttrDef/HTML/Class.php';
  109 +require 'HTMLPurifier/AttrDef/HTML/Color.php';
  110 +require 'HTMLPurifier/AttrDef/HTML/ContentEditable.php';
  111 +require 'HTMLPurifier/AttrDef/HTML/FrameTarget.php';
  112 +require 'HTMLPurifier/AttrDef/HTML/ID.php';
  113 +require 'HTMLPurifier/AttrDef/HTML/Pixels.php';
  114 +require 'HTMLPurifier/AttrDef/HTML/Length.php';
  115 +require 'HTMLPurifier/AttrDef/HTML/LinkTypes.php';
  116 +require 'HTMLPurifier/AttrDef/HTML/MultiLength.php';
  117 +require 'HTMLPurifier/AttrDef/URI/Email.php';
  118 +require 'HTMLPurifier/AttrDef/URI/Host.php';
  119 +require 'HTMLPurifier/AttrDef/URI/IPv4.php';
  120 +require 'HTMLPurifier/AttrDef/URI/IPv6.php';
  121 +require 'HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php';
  122 +require 'HTMLPurifier/AttrTransform/Background.php';
  123 +require 'HTMLPurifier/AttrTransform/BdoDir.php';
  124 +require 'HTMLPurifier/AttrTransform/BgColor.php';
  125 +require 'HTMLPurifier/AttrTransform/BoolToCSS.php';
  126 +require 'HTMLPurifier/AttrTransform/Border.php';
  127 +require 'HTMLPurifier/AttrTransform/EnumToCSS.php';
  128 +require 'HTMLPurifier/AttrTransform/ImgRequired.php';
  129 +require 'HTMLPurifier/AttrTransform/ImgSpace.php';
  130 +require 'HTMLPurifier/AttrTransform/Input.php';
  131 +require 'HTMLPurifier/AttrTransform/Lang.php';
  132 +require 'HTMLPurifier/AttrTransform/Length.php';
  133 +require 'HTMLPurifier/AttrTransform/Name.php';
  134 +require 'HTMLPurifier/AttrTransform/NameSync.php';
  135 +require 'HTMLPurifier/AttrTransform/Nofollow.php';
  136 +require 'HTMLPurifier/AttrTransform/SafeEmbed.php';
  137 +require 'HTMLPurifier/AttrTransform/SafeObject.php';
  138 +require 'HTMLPurifier/AttrTransform/SafeParam.php';
  139 +require 'HTMLPurifier/AttrTransform/ScriptRequired.php';
  140 +require 'HTMLPurifier/AttrTransform/TargetBlank.php';
  141 +require 'HTMLPurifier/AttrTransform/TargetNoopener.php';
  142 +require 'HTMLPurifier/AttrTransform/TargetNoreferrer.php';
  143 +require 'HTMLPurifier/AttrTransform/Textarea.php';
  144 +require 'HTMLPurifier/ChildDef/Chameleon.php';
  145 +require 'HTMLPurifier/ChildDef/Custom.php';
  146 +require 'HTMLPurifier/ChildDef/Empty.php';
  147 +require 'HTMLPurifier/ChildDef/List.php';
  148 +require 'HTMLPurifier/ChildDef/Required.php';
  149 +require 'HTMLPurifier/ChildDef/Optional.php';
  150 +require 'HTMLPurifier/ChildDef/StrictBlockquote.php';
  151 +require 'HTMLPurifier/ChildDef/Table.php';
  152 +require 'HTMLPurifier/DefinitionCache/Decorator.php';
  153 +require 'HTMLPurifier/DefinitionCache/Null.php';
  154 +require 'HTMLPurifier/DefinitionCache/Serializer.php';
  155 +require 'HTMLPurifier/DefinitionCache/Decorator/Cleanup.php';
  156 +require 'HTMLPurifier/DefinitionCache/Decorator/Memory.php';
  157 +require 'HTMLPurifier/HTMLModule/Bdo.php';
  158 +require 'HTMLPurifier/HTMLModule/CommonAttributes.php';
  159 +require 'HTMLPurifier/HTMLModule/Edit.php';
  160 +require 'HTMLPurifier/HTMLModule/Forms.php';
  161 +require 'HTMLPurifier/HTMLModule/Hypertext.php';
  162 +require 'HTMLPurifier/HTMLModule/Iframe.php';
  163 +require 'HTMLPurifier/HTMLModule/Image.php';
  164 +require 'HTMLPurifier/HTMLModule/Legacy.php';
  165 +require 'HTMLPurifier/HTMLModule/List.php';
  166 +require 'HTMLPurifier/HTMLModule/Name.php';
  167 +require 'HTMLPurifier/HTMLModule/Nofollow.php';
  168 +require 'HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
  169 +require 'HTMLPurifier/HTMLModule/Object.php';
  170 +require 'HTMLPurifier/HTMLModule/Presentation.php';
  171 +require 'HTMLPurifier/HTMLModule/Proprietary.php';
  172 +require 'HTMLPurifier/HTMLModule/Ruby.php';
  173 +require 'HTMLPurifier/HTMLModule/SafeEmbed.php';
  174 +require 'HTMLPurifier/HTMLModule/SafeObject.php';
  175 +require 'HTMLPurifier/HTMLModule/SafeScripting.php';
  176 +require 'HTMLPurifier/HTMLModule/Scripting.php';
  177 +require 'HTMLPurifier/HTMLModule/StyleAttribute.php';
  178 +require 'HTMLPurifier/HTMLModule/Tables.php';
  179 +require 'HTMLPurifier/HTMLModule/Target.php';
  180 +require 'HTMLPurifier/HTMLModule/TargetBlank.php';
  181 +require 'HTMLPurifier/HTMLModule/TargetNoopener.php';
  182 +require 'HTMLPurifier/HTMLModule/TargetNoreferrer.php';
  183 +require 'HTMLPurifier/HTMLModule/Text.php';
  184 +require 'HTMLPurifier/HTMLModule/Tidy.php';
  185 +require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
  186 +require 'HTMLPurifier/HTMLModule/Tidy/Name.php';
  187 +require 'HTMLPurifier/HTMLModule/Tidy/Proprietary.php';
  188 +require 'HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php';
  189 +require 'HTMLPurifier/HTMLModule/Tidy/Strict.php';
  190 +require 'HTMLPurifier/HTMLModule/Tidy/Transitional.php';
  191 +require 'HTMLPurifier/HTMLModule/Tidy/XHTML.php';
  192 +require 'HTMLPurifier/Injector/AutoParagraph.php';
  193 +require 'HTMLPurifier/Injector/DisplayLinkURI.php';
  194 +require 'HTMLPurifier/Injector/Linkify.php';
  195 +require 'HTMLPurifier/Injector/PurifierLinkify.php';
  196 +require 'HTMLPurifier/Injector/RemoveEmpty.php';
  197 +require 'HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
  198 +require 'HTMLPurifier/Injector/SafeObject.php';
  199 +require 'HTMLPurifier/Lexer/DOMLex.php';
  200 +require 'HTMLPurifier/Lexer/DirectLex.php';
  201 +require 'HTMLPurifier/Node/Comment.php';
  202 +require 'HTMLPurifier/Node/Element.php';
  203 +require 'HTMLPurifier/Node/Text.php';
  204 +require 'HTMLPurifier/Strategy/Composite.php';
  205 +require 'HTMLPurifier/Strategy/Core.php';
  206 +require 'HTMLPurifier/Strategy/FixNesting.php';
  207 +require 'HTMLPurifier/Strategy/MakeWellFormed.php';
  208 +require 'HTMLPurifier/Strategy/RemoveForeignElements.php';
  209 +require 'HTMLPurifier/Strategy/ValidateAttributes.php';
  210 +require 'HTMLPurifier/TagTransform/Font.php';
  211 +require 'HTMLPurifier/TagTransform/Simple.php';
  212 +require 'HTMLPurifier/Token/Comment.php';
  213 +require 'HTMLPurifier/Token/Tag.php';
  214 +require 'HTMLPurifier/Token/Empty.php';
  215 +require 'HTMLPurifier/Token/End.php';
  216 +require 'HTMLPurifier/Token/Start.php';
  217 +require 'HTMLPurifier/Token/Text.php';
  218 +require 'HTMLPurifier/URIFilter/DisableExternal.php';
  219 +require 'HTMLPurifier/URIFilter/DisableExternalResources.php';
  220 +require 'HTMLPurifier/URIFilter/DisableResources.php';
  221 +require 'HTMLPurifier/URIFilter/HostBlacklist.php';
  222 +require 'HTMLPurifier/URIFilter/MakeAbsolute.php';
  223 +require 'HTMLPurifier/URIFilter/Munge.php';
  224 +require 'HTMLPurifier/URIFilter/SafeIframe.php';
  225 +require 'HTMLPurifier/URIScheme/data.php';
  226 +require 'HTMLPurifier/URIScheme/file.php';
  227 +require 'HTMLPurifier/URIScheme/ftp.php';
  228 +require 'HTMLPurifier/URIScheme/http.php';
  229 +require 'HTMLPurifier/URIScheme/https.php';
  230 +require 'HTMLPurifier/URIScheme/mailto.php';
  231 +require 'HTMLPurifier/URIScheme/news.php';
  232 +require 'HTMLPurifier/URIScheme/nntp.php';
  233 +require 'HTMLPurifier/URIScheme/tel.php';
  234 +require 'HTMLPurifier/VarParser/Flexible.php';
  235 +require 'HTMLPurifier/VarParser/Native.php';
  1 +<?php
  2 +
  3 +/**
  4 + * @file
  5 + * Emulation layer for code that used kses(), substituting in HTML Purifier.
  6 + */
  7 +
  8 +require_once dirname(__FILE__) . '/HTMLPurifier.auto.php';
  9 +
  10 +function kses($string, $allowed_html, $allowed_protocols = null)
  11 +{
  12 + $config = HTMLPurifier_Config::createDefault();
  13 + $allowed_elements = array();
  14 + $allowed_attributes = array();
  15 + foreach ($allowed_html as $element => $attributes) {
  16 + $allowed_elements[$element] = true;
  17 + foreach ($attributes as $attribute => $x) {
  18 + $allowed_attributes["$element.$attribute"] = true;
  19 + }
  20 + }
  21 + $config->set('HTML.AllowedElements', $allowed_elements);
  22 + $config->set('HTML.AllowedAttributes', $allowed_attributes);
  23 + if ($allowed_protocols !== null) {
  24 + $config->set('URI.AllowedSchemes', $allowed_protocols);
  25 + }
  26 + $purifier = new HTMLPurifier($config);
  27 + return $purifier->purify($string);
  28 +}
  29 +
  30 +// vim: et sw=4 sts=4
  1 +<?php
  2 +
  3 +/**
  4 + * @file
  5 + * Convenience stub file that adds HTML Purifier's library file to the path
  6 + * without any other side-effects.
  7 + */
  8 +
  9 +set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
  10 +
  11 +// vim: et sw=4 sts=4