正在显示
58 个修改的文件
包含
4601 行增加
和
1 行删除
vendor/autoload.php
0 → 100644
vendor/composer/ClassLoader.php
0 → 100644
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 | +} |
vendor/composer/InstalledVersions.php
0 → 100644
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 | +} |
vendor/composer/LICENSE
0 → 100644
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 | + |
vendor/composer/autoload_classmap.php
0 → 100644
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 | +); |
vendor/composer/autoload_files.php
0 → 100644
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 | +); |
vendor/composer/autoload_namespaces.php
0 → 100644
vendor/composer/autoload_psr4.php
0 → 100644
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 | +); |
vendor/composer/autoload_real.php
0 → 100644
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 | +} |
vendor/composer/autoload_static.php
0 → 100644
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 | +} |
vendor/composer/installed.json
0 → 100644
此 diff 太大无法显示。
vendor/composer/installed.php
0 → 100644
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 | +); |
vendor/composer/platform_check.php
0 → 100644
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 | +<?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 | +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 | +} |
vendor/easywechat-composer/easywechat-composer/src/Laravel/Http/Controllers/DelegatesController.php
0 → 100644
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 | +} |
vendor/ezyang/htmlpurifier/CHANGELOG.md
0 → 100644
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) |
vendor/ezyang/htmlpurifier/CREDITS
0 → 100644
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 |
vendor/ezyang/htmlpurifier/LICENSE
0 → 100644
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 |
vendor/ezyang/htmlpurifier/README.md
0 → 100644
1 | +HTML Purifier [](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 |
vendor/ezyang/htmlpurifier/VERSION
0 → 100644
1 | +4.15.0 |
vendor/ezyang/htmlpurifier/composer.json
0 → 100644
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 | + * 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 | + | ||
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 |
-
请 注册 或 登录 后发表评论