Browse Source

框架扩展文件

huwhois 4 years ago
parent
commit
e8ea6bb99e
64 changed files with 3668 additions and 0 deletions
  1. 7 0
      vendor/autoload.php
  2. 445 0
      vendor/composer/ClassLoader.php
  3. 21 0
      vendor/composer/LICENSE
  4. 9 0
      vendor/composer/autoload_classmap.php
  5. 10 0
      vendor/composer/autoload_files.php
  6. 9 0
      vendor/composer/autoload_namespaces.php
  7. 12 0
      vendor/composer/autoload_psr4.php
  8. 70 0
      vendor/composer/autoload_real.php
  9. 46 0
      vendor/composer/autoload_static.php
  10. 178 0
      vendor/composer/installed.json
  11. 3 0
      vendor/topthink/think-captcha/.gitignore
  12. 32 0
      vendor/topthink/think-captcha/LICENSE
  13. 33 0
      vendor/topthink/think-captcha/README.md
  14. BIN
      vendor/topthink/think-captcha/assets/bgs/1.jpg
  15. BIN
      vendor/topthink/think-captcha/assets/bgs/2.jpg
  16. BIN
      vendor/topthink/think-captcha/assets/bgs/3.jpg
  17. BIN
      vendor/topthink/think-captcha/assets/bgs/4.jpg
  18. BIN
      vendor/topthink/think-captcha/assets/bgs/5.jpg
  19. BIN
      vendor/topthink/think-captcha/assets/bgs/6.jpg
  20. BIN
      vendor/topthink/think-captcha/assets/bgs/7.jpg
  21. BIN
      vendor/topthink/think-captcha/assets/bgs/8.jpg
  22. BIN
      vendor/topthink/think-captcha/assets/ttfs/1.ttf
  23. BIN
      vendor/topthink/think-captcha/assets/ttfs/2.ttf
  24. BIN
      vendor/topthink/think-captcha/assets/ttfs/3.ttf
  25. BIN
      vendor/topthink/think-captcha/assets/ttfs/4.ttf
  26. BIN
      vendor/topthink/think-captcha/assets/ttfs/5.ttf
  27. BIN
      vendor/topthink/think-captcha/assets/ttfs/6.ttf
  28. BIN
      vendor/topthink/think-captcha/assets/zhttfs/1.ttf
  29. 20 0
      vendor/topthink/think-captcha/composer.json
  30. 320 0
      vendor/topthink/think-captcha/src/Captcha.php
  31. 24 0
      vendor/topthink/think-captcha/src/CaptchaController.php
  32. 64 0
      vendor/topthink/think-captcha/src/helper.php
  33. 4 0
      vendor/topthink/think-image/.gitignore
  34. 22 0
      vendor/topthink/think-image/.travis.yml
  35. 201 0
      vendor/topthink/think-image/LICENSE
  36. 29 0
      vendor/topthink/think-image/README.md
  37. 26 0
      vendor/topthink/think-image/composer.json
  38. 20 0
      vendor/topthink/think-image/phpunit.xml
  39. 610 0
      vendor/topthink/think-image/src/Image.php
  40. 18 0
      vendor/topthink/think-image/src/image/Exception.php
  41. 207 0
      vendor/topthink/think-image/src/image/gif/Decoder.php
  42. 222 0
      vendor/topthink/think-image/src/image/gif/Encoder.php
  43. 88 0
      vendor/topthink/think-image/src/image/gif/Gif.php
  44. 67 0
      vendor/topthink/think-image/tests/CropTest.php
  45. 43 0
      vendor/topthink/think-image/tests/FlipTest.php
  46. 60 0
      vendor/topthink/think-image/tests/InfoTest.php
  47. 42 0
      vendor/topthink/think-image/tests/RotateTest.php
  48. 33 0
      vendor/topthink/think-image/tests/TestCase.php
  49. 58 0
      vendor/topthink/think-image/tests/TextTest.php
  50. 284 0
      vendor/topthink/think-image/tests/ThumbTest.php
  51. 58 0
      vendor/topthink/think-image/tests/WaterTest.php
  52. 15 0
      vendor/topthink/think-image/tests/autoload.php
  53. 0 0
      vendor/topthink/think-image/tests/images/test.bmp
  54. BIN
      vendor/topthink/think-image/tests/images/test.gif
  55. BIN
      vendor/topthink/think-image/tests/images/test.jpg
  56. BIN
      vendor/topthink/think-image/tests/images/test.png
  57. BIN
      vendor/topthink/think-image/tests/images/test.ttf
  58. 0 0
      vendor/topthink/think-image/tests/tmp/.gitignore
  59. 3 0
      vendor/topthink/think-installer/.gitignore
  60. 25 0
      vendor/topthink/think-installer/composer.json
  61. 26 0
      vendor/topthink/think-installer/src/Plugin.php
  62. 77 0
      vendor/topthink/think-installer/src/ThinkExtend.php
  63. 59 0
      vendor/topthink/think-installer/src/ThinkFramework.php
  64. 68 0
      vendor/topthink/think-installer/src/ThinkTesting.php

+ 7 - 0
vendor/autoload.php

@ -0,0 +1,7 @@
1
<?php
2
3
// autoload.php @generated by Composer
4
5
require_once __DIR__ . '/composer/autoload_real.php';
6
7
return ComposerAutoloaderInitfafb9a4d276f33b62b6bdfe92e796949::getLoader();

+ 445 - 0
vendor/composer/ClassLoader.php

@ -0,0 +1,445 @@
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    http://www.php-fig.org/psr/psr-0/
41
 * @see    http://www.php-fig.org/psr/psr-4/
42
 */
43
class ClassLoader
44
{
45
    // PSR-4
46
    private $prefixLengthsPsr4 = array();
47
    private $prefixDirsPsr4 = array();
48
    private $fallbackDirsPsr4 = array();
49
50
    // PSR-0
51
    private $prefixesPsr0 = array();
52
    private $fallbackDirsPsr0 = array();
53
54
    private $useIncludePath = false;
55
    private $classMap = array();
56
    private $classMapAuthoritative = false;
57
    private $missingClasses = array();
58
    private $apcuPrefix;
59
60
    public function getPrefixes()
61
    {
62
        if (!empty($this->prefixesPsr0)) {
63
            return call_user_func_array('array_merge', $this->prefixesPsr0);
64
        }
65
66
        return array();
67
    }
68
69
    public function getPrefixesPsr4()
70
    {
71
        return $this->prefixDirsPsr4;
72
    }
73
74
    public function getFallbackDirs()
75
    {
76
        return $this->fallbackDirsPsr0;
77
    }
78
79
    public function getFallbackDirsPsr4()
80
    {
81
        return $this->fallbackDirsPsr4;
82
    }
83
84
    public function getClassMap()
85
    {
86
        return $this->classMap;
87
    }
88
89
    /**
90
     * @param array $classMap Class to filename map
91
     */
92
    public function addClassMap(array $classMap)
93
    {
94
        if ($this->classMap) {
95
            $this->classMap = array_merge($this->classMap, $classMap);
96
        } else {
97
            $this->classMap = $classMap;
98
        }
99
    }
100
101
    /**
102
     * Registers a set of PSR-0 directories for a given prefix, either
103
     * appending or prepending to the ones previously set for this prefix.
104
     *
105
     * @param string       $prefix  The prefix
106
     * @param array|string $paths   The PSR-0 root directories
107
     * @param bool         $prepend Whether to prepend the directories
108
     */
109
    public function add($prefix, $paths, $prepend = false)
110
    {
111
        if (!$prefix) {
112
            if ($prepend) {
113
                $this->fallbackDirsPsr0 = array_merge(
114
                    (array) $paths,
115
                    $this->fallbackDirsPsr0
116
                );
117
            } else {
118
                $this->fallbackDirsPsr0 = array_merge(
119
                    $this->fallbackDirsPsr0,
120
                    (array) $paths
121
                );
122
            }
123
124
            return;
125
        }
126
127
        $first = $prefix[0];
128
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
129
            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130
131
            return;
132
        }
133
        if ($prepend) {
134
            $this->prefixesPsr0[$first][$prefix] = array_merge(
135
                (array) $paths,
136
                $this->prefixesPsr0[$first][$prefix]
137
            );
138
        } else {
139
            $this->prefixesPsr0[$first][$prefix] = array_merge(
140
                $this->prefixesPsr0[$first][$prefix],
141
                (array) $paths
142
            );
143
        }
144
    }
145
146
    /**
147
     * Registers a set of PSR-4 directories for a given namespace, either
148
     * appending or prepending to the ones previously set for this namespace.
149
     *
150
     * @param string       $prefix  The prefix/namespace, with trailing '\\'
151
     * @param array|string $paths   The PSR-4 base directories
152
     * @param bool         $prepend Whether to prepend the directories
153
     *
154
     * @throws \InvalidArgumentException
155
     */
156
    public function addPsr4($prefix, $paths, $prepend = false)
157
    {
158
        if (!$prefix) {
159
            // Register directories for the root namespace.
160
            if ($prepend) {
161
                $this->fallbackDirsPsr4 = array_merge(
162
                    (array) $paths,
163
                    $this->fallbackDirsPsr4
164
                );
165
            } else {
166
                $this->fallbackDirsPsr4 = array_merge(
167
                    $this->fallbackDirsPsr4,
168
                    (array) $paths
169
                );
170
            }
171
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172
            // Register directories for a new namespace.
173
            $length = strlen($prefix);
174
            if ('\\' !== $prefix[$length - 1]) {
175
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176
            }
177
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
179
        } elseif ($prepend) {
180
            // Prepend directories for an already registered namespace.
181
            $this->prefixDirsPsr4[$prefix] = array_merge(
182
                (array) $paths,
183
                $this->prefixDirsPsr4[$prefix]
184
            );
185
        } else {
186
            // Append directories for an already registered namespace.
187
            $this->prefixDirsPsr4[$prefix] = array_merge(
188
                $this->prefixDirsPsr4[$prefix],
189
                (array) $paths
190
            );
191
        }
192
    }
193
194
    /**
195
     * Registers a set of PSR-0 directories for a given prefix,
196
     * replacing any others previously set for this prefix.
197
     *
198
     * @param string       $prefix The prefix
199
     * @param array|string $paths  The PSR-0 base directories
200
     */
201
    public function set($prefix, $paths)
202
    {
203
        if (!$prefix) {
204
            $this->fallbackDirsPsr0 = (array) $paths;
205
        } else {
206
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207
        }
208
    }
209
210
    /**
211
     * Registers a set of PSR-4 directories for a given namespace,
212
     * replacing any others previously set for this namespace.
213
     *
214
     * @param string       $prefix The prefix/namespace, with trailing '\\'
215
     * @param array|string $paths  The PSR-4 base directories
216
     *
217
     * @throws \InvalidArgumentException
218
     */
219
    public function setPsr4($prefix, $paths)
220
    {
221
        if (!$prefix) {
222
            $this->fallbackDirsPsr4 = (array) $paths;
223
        } else {
224
            $length = strlen($prefix);
225
            if ('\\' !== $prefix[$length - 1]) {
226
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227
            }
228
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
230
        }
231
    }
232
233
    /**
234
     * Turns on searching the include path for class files.
235
     *
236
     * @param bool $useIncludePath
237
     */
238
    public function setUseIncludePath($useIncludePath)
239
    {
240
        $this->useIncludePath = $useIncludePath;
241
    }
242
243
    /**
244
     * Can be used to check if the autoloader uses the include path to check
245
     * for classes.
246
     *
247
     * @return bool
248
     */
249
    public function getUseIncludePath()
250
    {
251
        return $this->useIncludePath;
252
    }
253
254
    /**
255
     * Turns off searching the prefix and fallback directories for classes
256
     * that have not been registered with the class map.
257
     *
258
     * @param bool $classMapAuthoritative
259
     */
260
    public function setClassMapAuthoritative($classMapAuthoritative)
261
    {
262
        $this->classMapAuthoritative = $classMapAuthoritative;
263
    }
264
265
    /**
266
     * Should class lookup fail if not found in the current class map?
267
     *
268
     * @return bool
269
     */
270
    public function isClassMapAuthoritative()
271
    {
272
        return $this->classMapAuthoritative;
273
    }
274
275
    /**
276
     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
     *
278
     * @param string|null $apcuPrefix
279
     */
280
    public function setApcuPrefix($apcuPrefix)
281
    {
282
        $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
283
    }
284
285
    /**
286
     * The APCu prefix in use, or null if APCu caching is not enabled.
287
     *
288
     * @return string|null
289
     */
290
    public function getApcuPrefix()
291
    {
292
        return $this->apcuPrefix;
293
    }
294
295
    /**
296
     * Registers this instance as an autoloader.
297
     *
298
     * @param bool $prepend Whether to prepend the autoloader or not
299
     */
300
    public function register($prepend = false)
301
    {
302
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303
    }
304
305
    /**
306
     * Unregisters this instance as an autoloader.
307
     */
308
    public function unregister()
309
    {
310
        spl_autoload_unregister(array($this, 'loadClass'));
311
    }
312
313
    /**
314
     * Loads the given class or interface.
315
     *
316
     * @param  string    $class The name of the class
317
     * @return bool|null True if loaded, null otherwise
318
     */
319
    public function loadClass($class)
320
    {
321
        if ($file = $this->findFile($class)) {
322
            includeFile($file);
323
324
            return true;
325
        }
326
    }
327
328
    /**
329
     * Finds the path to the file where the class is defined.
330
     *
331
     * @param string $class The name of the class
332
     *
333
     * @return string|false The path if found, false otherwise
334
     */
335
    public function findFile($class)
336
    {
337
        // class map lookup
338
        if (isset($this->classMap[$class])) {
339
            return $this->classMap[$class];
340
        }
341
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342
            return false;
343
        }
344
        if (null !== $this->apcuPrefix) {
345
            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346
            if ($hit) {
347
                return $file;
348
            }
349
        }
350
351
        $file = $this->findFileWithExtension($class, '.php');
352
353
        // Search for Hack files if we are running on HHVM
354
        if (false === $file && defined('HHVM_VERSION')) {
355
            $file = $this->findFileWithExtension($class, '.hh');
356
        }
357
358
        if (null !== $this->apcuPrefix) {
359
            apcu_add($this->apcuPrefix.$class, $file);
360
        }
361
362
        if (false === $file) {
363
            // Remember that this class does not exist.
364
            $this->missingClasses[$class] = true;
365
        }
366
367
        return $file;
368
    }
369
370
    private function findFileWithExtension($class, $ext)
371
    {
372
        // PSR-4 lookup
373
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374
375
        $first = $class[0];
376
        if (isset($this->prefixLengthsPsr4[$first])) {
377
            $subPath = $class;
378
            while (false !== $lastPos = strrpos($subPath, '\\')) {
379
                $subPath = substr($subPath, 0, $lastPos);
380
                $search = $subPath.'\\';
381
                if (isset($this->prefixDirsPsr4[$search])) {
382
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
383
                        $length = $this->prefixLengthsPsr4[$first][$search];
384
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
385
                            return $file;
386
                        }
387
                    }
388
                }
389
            }
390
        }
391
392
        // PSR-4 fallback dirs
393
        foreach ($this->fallbackDirsPsr4 as $dir) {
394
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395
                return $file;
396
            }
397
        }
398
399
        // PSR-0 lookup
400
        if (false !== $pos = strrpos($class, '\\')) {
401
            // namespaced class name
402
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404
        } else {
405
            // PEAR-like class name
406
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407
        }
408
409
        if (isset($this->prefixesPsr0[$first])) {
410
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411
                if (0 === strpos($class, $prefix)) {
412
                    foreach ($dirs as $dir) {
413
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414
                            return $file;
415
                        }
416
                    }
417
                }
418
            }
419
        }
420
421
        // PSR-0 fallback dirs
422
        foreach ($this->fallbackDirsPsr0 as $dir) {
423
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424
                return $file;
425
            }
426
        }
427
428
        // PSR-0 include paths.
429
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430
            return $file;
431
        }
432
433
        return false;
434
    }
435
}
436
437
/**
438
 * Scope isolated include.
439
 *
440
 * Prevents access to $this/self from included files.
441
 */
442
function includeFile($file)
443
{
444
    include $file;
445
}

+ 21 - 0
vendor/composer/LICENSE

@ -0,0 +1,21 @@
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

+ 9 - 0
vendor/composer/autoload_classmap.php

@ -0,0 +1,9 @@
1
<?php
2
3
// autoload_classmap.php @generated by Composer
4
5
$vendorDir = dirname(dirname(__FILE__));
6
$baseDir = dirname($vendorDir);
7
8
return array(
9
);

+ 10 - 0
vendor/composer/autoload_files.php

@ -0,0 +1,10 @@
1
<?php
2
3
// autoload_files.php @generated by Composer
4
5
$vendorDir = dirname(dirname(__FILE__));
6
$baseDir = dirname($vendorDir);
7
8
return array(
9
    '1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php',
10
);

+ 9 - 0
vendor/composer/autoload_namespaces.php

@ -0,0 +1,9 @@
1
<?php
2
3
// autoload_namespaces.php @generated by Composer
4
5
$vendorDir = dirname(dirname(__FILE__));
6
$baseDir = dirname($vendorDir);
7
8
return array(
9
);

+ 12 - 0
vendor/composer/autoload_psr4.php

@ -0,0 +1,12 @@
1
<?php
2
3
// autoload_psr4.php @generated by Composer
4
5
$vendorDir = dirname(dirname(__FILE__));
6
$baseDir = dirname($vendorDir);
7
8
return array(
9
    'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'),
10
    'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
11
    'think\\' => array($baseDir . '/thinkphp/library/think', $vendorDir . '/topthink/think-image/src'),
12
);

+ 70 - 0
vendor/composer/autoload_real.php

@ -0,0 +1,70 @@
1
<?php
2
3
// autoload_real.php @generated by Composer
4
5
class ComposerAutoloaderInitfafb9a4d276f33b62b6bdfe92e796949
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
    public static function getLoader()
17
    {
18
        if (null !== self::$loader) {
19
            return self::$loader;
20
        }
21
22
        spl_autoload_register(array('ComposerAutoloaderInitfafb9a4d276f33b62b6bdfe92e796949', 'loadClassLoader'), true, true);
23
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
        spl_autoload_unregister(array('ComposerAutoloaderInitfafb9a4d276f33b62b6bdfe92e796949', 'loadClassLoader'));
25
26
        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
        if ($useStaticLoader) {
28
            require_once __DIR__ . '/autoload_static.php';
29
30
            call_user_func(\Composer\Autoload\ComposerStaticInitfafb9a4d276f33b62b6bdfe92e796949::getInitializer($loader));
31
        } else {
32
            $map = require __DIR__ . '/autoload_namespaces.php';
33
            foreach ($map as $namespace => $path) {
34
                $loader->set($namespace, $path);
35
            }
36
37
            $map = require __DIR__ . '/autoload_psr4.php';
38
            foreach ($map as $namespace => $path) {
39
                $loader->setPsr4($namespace, $path);
40
            }
41
42
            $classMap = require __DIR__ . '/autoload_classmap.php';
43
            if ($classMap) {
44
                $loader->addClassMap($classMap);
45
            }
46
        }
47
48
        $loader->register(true);
49
50
        if ($useStaticLoader) {
51
            $includeFiles = Composer\Autoload\ComposerStaticInitfafb9a4d276f33b62b6bdfe92e796949::$files;
52
        } else {
53
            $includeFiles = require __DIR__ . '/autoload_files.php';
54
        }
55
        foreach ($includeFiles as $fileIdentifier => $file) {
56
            composerRequirefafb9a4d276f33b62b6bdfe92e796949($fileIdentifier, $file);
57
        }
58
59
        return $loader;
60
    }
61
}
62
63
function composerRequirefafb9a4d276f33b62b6bdfe92e796949($fileIdentifier, $file)
64
{
65
    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
        require $file;
67
68
        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
69
    }
70
}

+ 46 - 0
vendor/composer/autoload_static.php

@ -0,0 +1,46 @@
1
<?php
2
3
// autoload_static.php @generated by Composer
4
5
namespace Composer\Autoload;
6
7
class ComposerStaticInitfafb9a4d276f33b62b6bdfe92e796949
8
{
9
    public static $files = array (
10
        '1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
11
    );
12
13
    public static $prefixLengthsPsr4 = array (
14
        't' => 
15
        array (
16
            'think\\composer\\' => 15,
17
            'think\\captcha\\' => 14,
18
            'think\\' => 6,
19
        ),
20
    );
21
22
    public static $prefixDirsPsr4 = array (
23
        'think\\composer\\' => 
24
        array (
25
            0 => __DIR__ . '/..' . '/topthink/think-installer/src',
26
        ),
27
        'think\\captcha\\' => 
28
        array (
29
            0 => __DIR__ . '/..' . '/topthink/think-captcha/src',
30
        ),
31
        'think\\' => 
32
        array (
33
            0 => __DIR__ . '/../..' . '/thinkphp/library/think',
34
            1 => __DIR__ . '/..' . '/topthink/think-image/src',
35
        ),
36
    );
37
38
    public static function getInitializer(ClassLoader $loader)
39
    {
40
        return \Closure::bind(function () use ($loader) {
41
            $loader->prefixLengthsPsr4 = ComposerStaticInitfafb9a4d276f33b62b6bdfe92e796949::$prefixLengthsPsr4;
42
            $loader->prefixDirsPsr4 = ComposerStaticInitfafb9a4d276f33b62b6bdfe92e796949::$prefixDirsPsr4;
43
44
        }, null, ClassLoader::class);
45
    }
46
}

+ 178 - 0
vendor/composer/installed.json

@ -0,0 +1,178 @@
1
[
2
    {
3
        "name": "topthink/think-installer",
4
        "version": "v1.0.12",
5
        "version_normalized": "1.0.12.0",
6
        "source": {
7
            "type": "git",
8
            "url": "https://github.com/top-think/think-installer.git",
9
            "reference": "1be326e68f63de4e95977ed50f46ae75f017556d"
10
        },
11
        "dist": {
12
            "type": "zip",
13
            "url": "https://files.phpcomposer.com/files/top-think/think-installer/1be326e68f63de4e95977ed50f46ae75f017556d.zip",
14
            "reference": "1be326e68f63de4e95977ed50f46ae75f017556d",
15
            "shasum": ""
16
        },
17
        "require": {
18
            "composer-plugin-api": "^1.0"
19
        },
20
        "require-dev": {
21
            "composer/composer": "1.0.*@dev"
22
        },
23
        "time": "2017-05-27T06:58:09+00:00",
24
        "type": "composer-plugin",
25
        "extra": {
26
            "class": "think\\composer\\Plugin"
27
        },
28
        "installation-source": "dist",
29
        "autoload": {
30
            "psr-4": {
31
                "think\\composer\\": "src"
32
            }
33
        },
34
        "notification-url": "https://packagist.org/downloads/",
35
        "license": [
36
            "Apache-2.0"
37
        ],
38
        "authors": [
39
            {
40
                "name": "yunwuxin",
41
                "email": "448901948@qq.com"
42
            }
43
        ]
44
    },
45
    {
46
        "name": "topthink/framework",
47
        "version": "v5.0.12",
48
        "version_normalized": "5.0.12.0",
49
        "source": {
50
            "type": "git",
51
            "url": "https://github.com/top-think/framework.git",
52
            "reference": "0fb51680e8d62495d27f17a0e6cf889b763a6d3c"
53
        },
54
        "dist": {
55
            "type": "zip",
56
            "url": "https://files.phpcomposer.com/files/top-think/framework/0fb51680e8d62495d27f17a0e6cf889b763a6d3c.zip",
57
            "reference": "0fb51680e8d62495d27f17a0e6cf889b763a6d3c",
58
            "shasum": ""
59
        },
60
        "require": {
61
            "php": ">=5.4.0",
62
            "topthink/think-installer": "~1.0"
63
        },
64
        "require-dev": {
65
            "johnkary/phpunit-speedtrap": "^1.0",
66
            "mikey179/vfsstream": "~1.6",
67
            "phpdocumentor/reflection-docblock": "^2.0",
68
            "phploc/phploc": "2.*",
69
            "phpunit/phpunit": "4.8.*",
70
            "sebastian/phpcpd": "2.*"
71
        },
72
        "time": "2017-11-06T01:19:03+00:00",
73
        "type": "think-framework",
74
        "installation-source": "dist",
75
        "autoload": {
76
            "psr-4": {
77
                "think\\": "library/think"
78
            }
79
        },
80
        "notification-url": "https://packagist.org/downloads/",
81
        "license": [
82
            "Apache-2.0"
83
        ],
84
        "authors": [
85
            {
86
                "name": "liu21st",
87
                "email": "liu21st@gmail.com"
88
            }
89
        ],
90
        "description": "the new thinkphp framework",
91
        "homepage": "http://thinkphp.cn/",
92
        "keywords": [
93
            "framework",
94
            "orm",
95
            "thinkphp"
96
        ]
97
    },
98
    {
99
        "name": "topthink/think-captcha",
100
        "version": "v1.0.7",
101
        "version_normalized": "1.0.7.0",
102
        "source": {
103
            "type": "git",
104
            "url": "https://github.com/top-think/think-captcha.git",
105
            "reference": "0c55455df26a1626a60d0dc35d2d89002b741d44"
106
        },
107
        "dist": {
108
            "type": "zip",
109
            "url": "https://files.phpcomposer.com/files/top-think/think-captcha/0c55455df26a1626a60d0dc35d2d89002b741d44.zip",
110
            "reference": "0c55455df26a1626a60d0dc35d2d89002b741d44",
111
            "shasum": ""
112
        },
113
        "time": "2016-07-06T01:47:11+00:00",
114
        "type": "library",
115
        "installation-source": "dist",
116
        "autoload": {
117
            "psr-4": {
118
                "think\\captcha\\": "src/"
119
            },
120
            "files": [
121
                "src/helper.php"
122
            ]
123
        },
124
        "notification-url": "https://packagist.org/downloads/",
125
        "license": [
126
            "Apache-2.0"
127
        ],
128
        "authors": [
129
            {
130
                "name": "yunwuxin",
131
                "email": "448901948@qq.com"
132
            }
133
        ],
134
        "description": "captcha package for thinkphp5"
135
    },
136
    {
137
        "name": "topthink/think-image",
138
        "version": "v1.0.7",
139
        "version_normalized": "1.0.7.0",
140
        "source": {
141
            "type": "git",
142
            "url": "https://github.com/top-think/think-image.git",
143
            "reference": "8586cf47f117481c6d415b20f7dedf62e79d5512"
144
        },
145
        "dist": {
146
            "type": "zip",
147
            "url": "https://files.phpcomposer.com/files/top-think/think-image/8586cf47f117481c6d415b20f7dedf62e79d5512.zip",
148
            "reference": "8586cf47f117481c6d415b20f7dedf62e79d5512",
149
            "shasum": ""
150
        },
151
        "require": {
152
            "ext-gd": "*"
153
        },
154
        "require-dev": {
155
            "phpunit/phpunit": "4.8.*",
156
            "topthink/framework": "^5.0"
157
        },
158
        "time": "2016-09-29T06:05:43+00:00",
159
        "type": "library",
160
        "installation-source": "dist",
161
        "autoload": {
162
            "psr-4": {
163
                "think\\": "src"
164
            }
165
        },
166
        "notification-url": "https://packagist.org/downloads/",
167
        "license": [
168
            "Apache-2.0"
169
        ],
170
        "authors": [
171
            {
172
                "name": "yunwuxin",
173
                "email": "448901948@qq.com"
174
            }
175
        ],
176
        "description": "The ThinkPHP5 Image Package"
177
    }
178
]

+ 3 - 0
vendor/topthink/think-captcha/.gitignore

@ -0,0 +1,3 @@
1
/vendor/
2
/composer.lock
3
.idea

+ 32 - 0
vendor/topthink/think-captcha/LICENSE

@ -0,0 +1,32 @@
1
2
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
3
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
4
All rights reserved。
5
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
6
7
Apache Licence是著名的非盈利开源组织Apache采用的协议。
8
该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
9
允许代码修改,再作为开源或商业软件发布。需要满足
10
的条件:
11
1. 需要给代码的用户一份Apache Licence ;
12
2. 如果你修改了代码,需要在被修改的文件中说明;
13
3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
14
带有原来代码中的协议,商标,专利声明和其他原来作者规
15
定需要包含的说明;
16
4. 如果再发布的产品中包含一个Notice文件,则在Notice文
17
件中需要带有本协议内容。你可以在Notice中增加自己的
18
许可,但不可以表现为对Apache Licence构成更改。
19
具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
20
21
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
POSSIBILITY OF SUCH DAMAGE.

+ 33 - 0
vendor/topthink/think-captcha/README.md

@ -0,0 +1,33 @@
1
# think-captcha
2
thinkphp5 验证码类库
3
4
## 安装
5
> composer require topthink/think-captcha
6
7
8
##使用
9
10
###模板里输出验证码
11
12
~~~
13
<div>{:captcha_img()}</div>
14
~~~
15
或者
16
~~~
17
<div><img src="{:captcha_src()}" alt="captcha" /></div>
18
~~~
19
> 上面两种的最终效果是一样的
20
21
### 控制器里验证
22
使用TP5的内置验证功能即可
23
~~~
24
$this->validate($data,[
25
    'captcha|验证码'=>'required|captcha'
26
]);
27
~~~
28
或者手动验证
29
~~~
30
if(!captcha_check($captcha)){
31
 //验证失败
32
};
33
~~~

BIN
vendor/topthink/think-captcha/assets/bgs/1.jpg


BIN
vendor/topthink/think-captcha/assets/bgs/2.jpg


BIN
vendor/topthink/think-captcha/assets/bgs/3.jpg


BIN
vendor/topthink/think-captcha/assets/bgs/4.jpg


BIN
vendor/topthink/think-captcha/assets/bgs/5.jpg


BIN
vendor/topthink/think-captcha/assets/bgs/6.jpg


BIN
vendor/topthink/think-captcha/assets/bgs/7.jpg


BIN
vendor/topthink/think-captcha/assets/bgs/8.jpg


BIN
vendor/topthink/think-captcha/assets/ttfs/1.ttf


BIN
vendor/topthink/think-captcha/assets/ttfs/2.ttf


BIN
vendor/topthink/think-captcha/assets/ttfs/3.ttf


BIN
vendor/topthink/think-captcha/assets/ttfs/4.ttf


BIN
vendor/topthink/think-captcha/assets/ttfs/5.ttf


BIN
vendor/topthink/think-captcha/assets/ttfs/6.ttf


BIN
vendor/topthink/think-captcha/assets/zhttfs/1.ttf


+ 20 - 0
vendor/topthink/think-captcha/composer.json

@ -0,0 +1,20 @@
1
{
2
    "name": "topthink/think-captcha",
3
    "description": "captcha package for thinkphp5",
4
    "authors": [
5
        {
6
            "name": "yunwuxin",
7
            "email": "448901948@qq.com"
8
        }
9
    ],
10
    "license": "Apache-2.0",
11
    "require": {},
12
    "autoload": {
13
        "psr-4": {
14
            "think\\captcha\\": "src/"
15
        },
16
        "files": [
17
            "src/helper.php"
18
        ]
19
    }
20
}

+ 320 - 0
vendor/topthink/think-captcha/src/Captcha.php

@ -0,0 +1,320 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
12
namespace think\captcha;
13
14
use think\Session;
15
16
class Captcha
17
{
18
    protected $config = [
19
        'seKey'    => 'ThinkPHP.CN',
20
        // 验证码加密密钥
21
        'codeSet'  => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
22
        // 验证码字符集合
23
        'expire'   => 1800,
24
        // 验证码过期时间(s)
25
        'useZh'    => false,
26
        // 使用中文验证码
27
        'zhSet'    => '们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在了不和有大这主中人上为来分生对于学下级地个用同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反体合斗路图把结第里正新开论之物从当两些还天资事队批点育重其思与间内去因件日利相由压员气业代全组数果期导平各基或月毛然如应形想制心样干都向变关问比展那它最及外没看治提五解系林者米群头意只明四道马认次文通但条较克又公孔领军流入接席位情运器并飞原油放立题质指建区验活众很教决特此常石强极土少已根共直团统式转别造切九你取西持总料连任志观调七么山程百报更见必真保热委手改管处己将修支识病象几先老光专什六型具示复安带每东增则完风回南广劳轮科北打积车计给节做务被整联步类集号列温装即毫知轴研单色坚据速防史拉世设达尔场织历花受求传口断况采精金界品判参层止边清至万确究书术状厂须离再目海交权且儿青才证低越际八试规斯近注办布门铁需走议县兵固除般引齿千胜细影济白格效置推空配刀叶率述今选养德话查差半敌始片施响收华觉备名红续均药标记难存测士身紧液派准斤角降维板许破述技消底床田势端感往神便贺村构照容非搞亚磨族火段算适讲按值美态黄易彪服早班麦削信排台声该击素张密害侯草何树肥继右属市严径螺检左页抗苏显苦英快称坏移约巴材省黑武培著河帝仅针怎植京助升王眼她抓含苗副杂普谈围食射源例致酸旧却充足短划剂宣环落首尺波承粉践府鱼随考刻靠够满夫失包住促枝局菌杆周护岩师举曲春元超负砂封换太模贫减阳扬江析亩木言球朝医校古呢稻宋听唯输滑站另卫字鼓刚写刘微略范供阿块某功套友限项余倒卷创律雨让骨远帮初皮播优占死毒圈伟季训控激找叫云互跟裂粮粒母练塞钢顶策双留误础吸阻故寸盾晚丝女散焊功株亲院冷彻弹错散商视艺灭版烈零室轻血倍缺厘泵察绝富城冲喷壤简否柱李望盘磁雄似困巩益洲脱投送奴侧润盖挥距触星松送获兴独官混纪依未突架宽冬章湿偏纹吃执阀矿寨责熟稳夺硬价努翻奇甲预职评读背协损棉侵灰虽矛厚罗泥辟告卵箱掌氧恩爱停曾溶营终纲孟钱待尽俄缩沙退陈讨奋械载胞幼哪剥迫旋征槽倒握担仍呀鲜吧卡粗介钻逐弱脚怕盐末阴丰雾冠丙街莱贝辐肠付吉渗瑞惊顿挤秒悬姆烂森糖圣凹陶词迟蚕亿矩康遵牧遭幅园腔订香肉弟屋敏恢忘编印蜂急拿扩伤飞露核缘游振操央伍域甚迅辉异序免纸夜乡久隶缸夹念兰映沟乙吗儒杀汽磷艰晶插埃燃欢铁补咱芽永瓦倾阵碳演威附牙芽永瓦斜灌欧献顺猪洋腐请透司危括脉宜笑若尾束壮暴企菜穗楚汉愈绿拖牛份染既秋遍锻玉夏疗尖殖井费州访吹荣铜沿替滚客召旱悟刺脑措贯藏敢令隙炉壳硫煤迎铸粘探临薄旬善福纵择礼愿伏残雷延烟句纯渐耕跑泽慢栽鲁赤繁境潮横掉锥希池败船假亮谓托伙哲怀割摆贡呈劲财仪沉炼麻罪祖息车穿货销齐鼠抽画饲龙库守筑房歌寒喜哥洗蚀废纳腹乎录镜妇恶脂庄擦险赞钟摇典柄辩竹谷卖乱虚桥奥伯赶垂途额壁网截野遗静谋弄挂课镇妄盛耐援扎虑键归符庆聚绕摩忙舞遇索顾胶羊湖钉仁音迹碎伸灯避泛亡答勇频皇柳哈揭甘诺概宪浓岛袭谁洪谢炮浇斑讯懂灵蛋闭孩释乳巨徒私银伊景坦累匀霉杜乐勒隔弯绩招绍胡呼痛峰零柴簧午跳居尚丁秦稍追梁折耗碱殊岗挖氏刃剧堆赫荷胸衡勤膜篇登驻案刊秧缓凸役剪川雪链渔啦脸户洛孢勃盟买杨宗焦赛旗滤硅炭股坐蒸凝竟陷枪黎救冒暗洞犯筒您宋弧爆谬涂味津臂障褐陆啊健尊豆拔莫抵桑坡缝警挑污冰柬嘴啥饭塑寄赵喊垫丹渡耳刨虎笔稀昆浪萨茶滴浅拥穴覆伦娘吨浸袖珠雌妈紫戏塔锤震岁貌洁剖牢锋疑霸闪埔猛诉刷狠忽灾闹乔唐漏闻沈熔氯荒茎男凡抢像浆旁玻亦忠唱蒙予纷捕锁尤乘乌智淡允叛畜俘摸锈扫毕璃宝芯爷鉴秘净蒋钙肩腾枯抛轨堂拌爸循诱祝励肯酒绳穷塘燥泡袋朗喂铝软渠颗惯贸粪综墙趋彼届墨碍启逆卸航衣孙龄岭骗休借',
28
        // 中文验证码字符串
29
        'useImgBg' => false,
30
        // 使用背景图片
31
        'fontSize' => 25,
32
        // 验证码字体大小(px)
33
        'useCurve' => true,
34
        // 是否画混淆曲线
35
        'useNoise' => true,
36
        // 是否添加杂点
37
        'imageH'   => 0,
38
        // 验证码图片高度
39
        'imageW'   => 0,
40
        // 验证码图片宽度
41
        'length'   => 4,
42
        // 验证码位数;默认5,2017/11/30改为4
43
        'fontttf'  => '',
44
        // 验证码字体,不设置随机获取
45
        'bg'       => [243, 251, 254],
46
        // 背景颜色
47
        'reset'    => true,
48
        // 验证成功后是否重置
49
    ];
50
51
    private $_image = null; // 验证码图片实例
52
    private $_color = null; // 验证码字体颜色
53
54
    /**
55
     * 架构方法 设置参数
56
     * @access public
57
     * @param  array $config 配置参数
58
     */
59
    public function __construct($config = [])
60
    {
61
        $this->config = array_merge($this->config, $config);
62
    }
63
64
    /**
65
     * 使用 $this->name 获取配置
66
     * @access public
67
     * @param  string $name 配置名称
68
     * @return mixed    配置值
69
     */
70
    public function __get($name)
71
    {
72
        return $this->config[$name];
73
    }
74
75
    /**
76
     * 设置验证码配置
77
     * @access public
78
     * @param  string $name  配置名称
79
     * @param  string $value 配置值
80
     * @return void
81
     */
82
    public function __set($name, $value)
83
    {
84
        if (isset($this->config[$name])) {
85
            $this->config[$name] = $value;
86
        }
87
    }
88
89
    /**
90
     * 检查配置
91
     * @access public
92
     * @param  string $name 配置名称
93
     * @return bool
94
     */
95
    public function __isset($name)
96
    {
97
        return isset($this->config[$name]);
98
    }
99
100
    /**
101
     * 验证验证码是否正确
102
     * @access public
103
     * @param string $code 用户验证码
104
     * @param string $id   验证码标识
105
     * @return bool 用户验证码是否正确
106
     */
107
    public function check($code, $id = '')
108
    {
109
        $key = $this->authcode($this->seKey) . $id;
110
        // 验证码不能为空
111
        $secode = Session::get($key, '');
112
        if (empty($code) || empty($secode)) {
113
            return false;
114
        }
115
        // session 过期
116
        if (time() - $secode['verify_time'] > $this->expire) {
117
            Session::delete($key, '');
118
            return false;
119
        }
120
121
        if ($this->authcode(strtoupper($code)) == $secode['verify_code']) {
122
            $this->reset && Session::delete($key, '');
123
            return true;
124
        }
125
126
        return false;
127
    }
128
129
    /**
130
     * 输出验证码并把验证码的值保存的session中
131
     * 验证码保存到session的格式为: array('verify_code' => '验证码值', 'verify_time' => '验证码创建时间');
132
     * @access public
133
     * @param string $id 要生成验证码的标识
134
     * @return \think\Response
135
     */
136
    public function entry($id = '')
137
    {
138
        // 图片宽(px)
139
        $this->imageW || $this->imageW = $this->length * $this->fontSize * 1.5 + $this->length * $this->fontSize / 2;
140
        // 图片高(px)
141
        $this->imageH || $this->imageH = $this->fontSize * 2.5;
142
        // 建立一幅 $this->imageW x $this->imageH 的图像
143
        $this->_image = imagecreate($this->imageW, $this->imageH);
144
        // 设置背景
145
        imagecolorallocate($this->_image, $this->bg[0], $this->bg[1], $this->bg[2]);
146
147
        // 验证码字体随机颜色
148
        $this->_color = imagecolorallocate($this->_image, mt_rand(1, 150), mt_rand(1, 150), mt_rand(1, 150));
149
        // 验证码使用随机字体
150
        $ttfPath = __DIR__ . '/../assets/' . ($this->useZh ? 'zhttfs' : 'ttfs') . '/';
151
152
        if (empty($this->fontttf)) {
153
            $dir  = dir($ttfPath);
154
            $ttfs = [];
155
            while (false !== ($file = $dir->read())) {
156
                if ('.' != $file[0] && substr($file, -4) == '.ttf') {
157
                    $ttfs[] = $file;
158
                }
159
            }
160
            $dir->close();
161
            $this->fontttf = $ttfs[array_rand($ttfs)];
162
        }
163
        $this->fontttf = $ttfPath . $this->fontttf;
164
165
        if ($this->useImgBg) {
166
            $this->_background();
167
        }
168
169
        if ($this->useNoise) {
170
            // 绘杂点
171
            $this->_writeNoise();
172
        }
173
        if ($this->useCurve) {
174
            // 绘干扰线
175
            $this->_writeCurve();
176
        }
177
178
        // 绘验证码
179
        $code   = []; // 验证码
180
        $codeNX = 0; // 验证码第N个字符的左边距
181
        if ($this->useZh) {
182
            // 中文验证码
183
            for ($i = 0; $i < $this->length; $i++) {
184
                $code[$i] = iconv_substr($this->zhSet, floor(mt_rand(0, mb_strlen($this->zhSet, 'utf-8') - 1)), 1, 'utf-8');
185
                imagettftext($this->_image, $this->fontSize, mt_rand(-40, 40), $this->fontSize * ($i + 1) * 1.5, $this->fontSize + mt_rand(10, 20), $this->_color, $this->fontttf, $code[$i]);
186
            }
187
        } else {
188
            for ($i = 0; $i < $this->length; $i++) {
189
                $code[$i] = $this->codeSet[mt_rand(0, strlen($this->codeSet) - 1)];
190
                $codeNX += mt_rand($this->fontSize * 1.2, $this->fontSize * 1.6);
191
                imagettftext($this->_image, $this->fontSize, mt_rand(-40, 40), $codeNX, $this->fontSize * 1.6, $this->_color, $this->fontttf, $code[$i]);
192
            }
193
        }
194
195
        // 保存验证码
196
        $key                   = $this->authcode($this->seKey);
197
        $code                  = $this->authcode(strtoupper(implode('', $code)));
198
        $secode                = [];
199
        $secode['verify_code'] = $code; // 把校验码保存到session
200
        $secode['verify_time'] = time(); // 验证码创建时间
201
        Session::set($key . $id, $secode, '');
202
203
        ob_start();
204
        // 输出图像
205
        imagepng($this->_image);
206
        $content = ob_get_clean();
207
        imagedestroy($this->_image);
208
209
        return response($content, 200, ['Content-Length' => strlen($content)])->contentType('image/png');
210
    }
211
212
    /**
213
     * 画一条由两条连在一起构成的随机正弦函数曲线作干扰线(你可以改成更帅的曲线函数)
214
     *
215
     *      高中的数学公式咋都忘了涅,写出来
216
     *        正弦型函数解析式:y=Asin(ωx+φ)+b
217
     *      各常数值对函数图像的影响:
218
     *        A:决定峰值(即纵向拉伸压缩的倍数)
219
     *        b:表示波形在Y轴的位置关系或纵向移动距离(上加下减)
220
     *        φ:决定波形与X轴位置关系或横向移动距离(左加右减)
221
     *        ω:决定周期(最小正周期T=2π/∣ω∣)
222
     *
223
     */
224
    private function _writeCurve()
225
    {
226
        $px = $py = 0;
227
228
        // 曲线前部分
229
        $A = mt_rand(1, $this->imageH / 2); // 振幅
230
        $b = mt_rand(-$this->imageH / 4, $this->imageH / 4); // Y轴方向偏移量
231
        $f = mt_rand(-$this->imageH / 4, $this->imageH / 4); // X轴方向偏移量
232
        $T = mt_rand($this->imageH, $this->imageW * 2); // 周期
233
        $w = (2 * M_PI) / $T;
234
235
        $px1 = 0; // 曲线横坐标起始位置
236
        $px2 = mt_rand($this->imageW / 2, $this->imageW * 0.8); // 曲线横坐标结束位置
237
238
        for ($px = $px1; $px <= $px2; $px = $px + 1) {
239
            if (0 != $w) {
240
                $py = $A * sin($w * $px + $f) + $b + $this->imageH / 2; // y = Asin(ωx+φ) + b
241
                $i  = (int)($this->fontSize / 5);
242
                while ($i > 0) {
243
                    imagesetpixel($this->_image, $px + $i, $py + $i, $this->_color); // 这里(while)循环画像素点比imagettftext和imagestring用字体大小一次画出(不用这while循环)性能要好很多
244
                    $i--;
245
                }
246
            }
247
        }
248
249
        // 曲线后部分
250
        $A   = mt_rand(1, $this->imageH / 2); // 振幅
251
        $f   = mt_rand(-$this->imageH / 4, $this->imageH / 4); // X轴方向偏移量
252
        $T   = mt_rand($this->imageH, $this->imageW * 2); // 周期
253
        $w   = (2 * M_PI) / $T;
254
        $b   = $py - $A * sin($w * $px + $f) - $this->imageH / 2;
255
        $px1 = $px2;
256
        $px2 = $this->imageW;
257
258
        for ($px = $px1; $px <= $px2; $px = $px + 1) {
259
            if (0 != $w) {
260
                $py = $A * sin($w * $px + $f) + $b + $this->imageH / 2; // y = Asin(ωx+φ) + b
261
                $i  = (int)($this->fontSize / 5);
262
                while ($i > 0) {
263
                    imagesetpixel($this->_image, $px + $i, $py + $i, $this->_color);
264
                    $i--;
265
                }
266
            }
267
        }
268
    }
269
270
    /**
271
     * 画杂点
272
     * 往图片上写不同颜色的字母或数字
273
     */
274
    private function _writeNoise()
275
    {
276
        $codeSet = '2345678abcdefhijkmnpqrstuvwxyz';
277
        for ($i = 0; $i < 10; $i++) {
278
            //杂点颜色
279
            $noiseColor = imagecolorallocate($this->_image, mt_rand(150, 225), mt_rand(150, 225), mt_rand(150, 225));
280
            for ($j = 0; $j < 5; $j++) {
281
                // 绘杂点
282
                imagestring($this->_image, 5, mt_rand(-10, $this->imageW), mt_rand(-10, $this->imageH), $codeSet[mt_rand(0, 29)], $noiseColor);
283
            }
284
        }
285
    }
286
287
    /**
288
     * 绘制背景图片
289
     * 注:如果验证码输出图片比较大,将占用比较多的系统资源
290
     */
291
    private function _background()
292
    {
293
        $path = dirname(__FILE__) . '/verify/bgs/';
294
        $dir  = dir($path);
295
296
        $bgs = [];
297
        while (false !== ($file = $dir->read())) {
298
            if ('.' != $file[0] && substr($file, -4) == '.jpg') {
299
                $bgs[] = $path . $file;
300
            }
301
        }
302
        $dir->close();
303
304
        $gb = $bgs[array_rand($bgs)];
305
306
        list($width, $height) = @getimagesize($gb);
307
        // Resample
308
        $bgImage = @imagecreatefromjpeg($gb);
309
        @imagecopyresampled($this->_image, $bgImage, 0, 0, 0, 0, $this->imageW, $this->imageH, $width, $height);
310
        @imagedestroy($bgImage);
311
    }
312
313
    /* 加密验证码 */
314
    private function authcode($str)
315
    {
316
        $key = substr(md5($this->seKey), 5, 8);
317
        $str = substr(md5($str), 8, 10);
318
        return md5($key . $str);
319
    }
320
}

+ 24 - 0
vendor/topthink/think-captcha/src/CaptchaController.php

@ -0,0 +1,24 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
12
namespace think\captcha;
13
14
use think\Config;
15
16
class CaptchaController
17
{
18
    public function index($id = "")
19
    {
20
        ob_clean();
21
        $captcha = new Captcha((array)Config::get('captcha'));
22
        return $captcha->entry($id);
23
    }
24
}

+ 64 - 0
vendor/topthink/think-captcha/src/helper.php

@ -0,0 +1,64 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
12
\think\Route::get('captcha/[:id]', "\\think\\captcha\\CaptchaController@index");
13
14
\think\Validate::extend('captcha', function ($value, $id = "") {
15
    return captcha_check($value, $id, (array)\think\Config::get('captcha'));
16
});
17
18
\think\Validate::setTypeMsg('captcha', '验证码错误!');
19
20
21
/**
22
 * @param string $id
23
 * @param array  $config
24
 * @return \think\Response
25
 */
26
function captcha($id = "", $config = [])
27
{
28
    $captcha = new \think\captcha\Captcha($config);
29
    return $captcha->entry($id);
30
}
31
32
33
/**
34
 * @param $id
35
 * @return string
36
 */
37
function captcha_src($id = "")
38
{
39
    return \think\Url::build('/captcha' . ($id ? "/{$id}" : ''));
40
}
41
42
43
/**
44
 * @param $id
45
 * @return mixed
46
 */
47
function captcha_img($id = "")
48
{
49
    return '<img src="' . captcha_src($id) . '" alt="captcha" />';
50
}
51
52
53
/**
54
 * @param        $value
55
 * @param string $id
56
 * @param array  $config
57
 * @return bool
58
 */
59
function captcha_check($value, $id = "", $config = [])
60
{
61
    $captcha = new \think\captcha\Captcha($config);
62
    return $captcha->check($value, $id);
63
}
64

+ 4 - 0
vendor/topthink/think-image/.gitignore

@ -0,0 +1,4 @@
1
/vendor/
2
/thinkphp/
3
/composer.lock
4
/.idea/

+ 22 - 0
vendor/topthink/think-image/.travis.yml

@ -0,0 +1,22 @@
1
language: php
2
3
php:
4
  - 5.4
5
  - 5.5
6
  - 5.6
7
  - 7.0
8
  - hhvm
9
10
matrix:
11
    allow_failures:
12
        - php: 7.0
13
        - php: hhvm
14
15
before_script:
16
  - composer self-update
17
  - composer install --prefer-source --no-interaction --dev
18
19
script: phpunit --coverage-clover=coverage.xml --configuration=phpunit.xml
20
21
after_success:
22
  - bash <(curl -s https://codecov.io/bash)

+ 201 - 0
vendor/topthink/think-image/LICENSE

@ -0,0 +1,201 @@
1
                                 Apache License
2
                           Version 2.0, January 2004
3
                        http://www.apache.org/licenses/
4
5
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7
   1. Definitions.
8
9
      "License" shall mean the terms and conditions for use, reproduction,
10
      and distribution as defined by Sections 1 through 9 of this document.
11
12
      "Licensor" shall mean the copyright owner or entity authorized by
13
      the copyright owner that is granting the License.
14
15
      "Legal Entity" shall mean the union of the acting entity and all
16
      other entities that control, are controlled by, or are under common
17
      control with that entity. For the purposes of this definition,
18
      "control" means (i) the power, direct or indirect, to cause the
19
      direction or management of such entity, whether by contract or
20
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
      outstanding shares, or (iii) beneficial ownership of such entity.
22
23
      "You" (or "Your") shall mean an individual or Legal Entity
24
      exercising permissions granted by this License.
25
26
      "Source" form shall mean the preferred form for making modifications,
27
      including but not limited to software source code, documentation
28
      source, and configuration files.
29
30
      "Object" form shall mean any form resulting from mechanical
31
      transformation or translation of a Source form, including but
32
      not limited to compiled object code, generated documentation,
33
      and conversions to other media types.
34
35
      "Work" shall mean the work of authorship, whether in Source or
36
      Object form, made available under the License, as indicated by a
37
      copyright notice that is included in or attached to the work
38
      (an example is provided in the Appendix below).
39
40
      "Derivative Works" shall mean any work, whether in Source or Object
41
      form, that is based on (or derived from) the Work and for which the
42
      editorial revisions, annotations, elaborations, or other modifications
43
      represent, as a whole, an original work of authorship. For the purposes
44
      of this License, Derivative Works shall not include works that remain
45
      separable from, or merely link (or bind by name) to the interfaces of,
46
      the Work and Derivative Works thereof.
47
48
      "Contribution" shall mean any work of authorship, including
49
      the original version of the Work and any modifications or additions
50
      to that Work or Derivative Works thereof, that is intentionally
51
      submitted to Licensor for inclusion in the Work by the copyright owner
52
      or by an individual or Legal Entity authorized to submit on behalf of
53
      the copyright owner. For the purposes of this definition, "submitted"
54
      means any form of electronic, verbal, or written communication sent
55
      to the Licensor or its representatives, including but not limited to
56
      communication on electronic mailing lists, source code control systems,
57
      and issue tracking systems that are managed by, or on behalf of, the
58
      Licensor for the purpose of discussing and improving the Work, but
59
      excluding communication that is conspicuously marked or otherwise
60
      designated in writing by the copyright owner as "Not a Contribution."
61
62
      "Contributor" shall mean Licensor and any individual or Legal Entity
63
      on behalf of whom a Contribution has been received by Licensor and
64
      subsequently incorporated within the Work.
65
66
   2. Grant of Copyright License. Subject to the terms and conditions of
67
      this License, each Contributor hereby grants to You a perpetual,
68
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
      copyright license to reproduce, prepare Derivative Works of,
70
      publicly display, publicly perform, sublicense, and distribute the
71
      Work and such Derivative Works in Source or Object form.
72
73
   3. Grant of Patent License. Subject to the terms and conditions of
74
      this License, each Contributor hereby grants to You a perpetual,
75
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
      (except as stated in this section) patent license to make, have made,
77
      use, offer to sell, sell, import, and otherwise transfer the Work,
78
      where such license applies only to those patent claims licensable
79
      by such Contributor that are necessarily infringed by their
80
      Contribution(s) alone or by combination of their Contribution(s)
81
      with the Work to which such Contribution(s) was submitted. If You
82
      institute patent litigation against any entity (including a
83
      cross-claim or counterclaim in a lawsuit) alleging that the Work
84
      or a Contribution incorporated within the Work constitutes direct
85
      or contributory patent infringement, then any patent licenses
86
      granted to You under this License for that Work shall terminate
87
      as of the date such litigation is filed.
88
89
   4. Redistribution. You may reproduce and distribute copies of the
90
      Work or Derivative Works thereof in any medium, with or without
91
      modifications, and in Source or Object form, provided that You
92
      meet the following conditions:
93
94
      (a) You must give any other recipients of the Work or
95
          Derivative Works a copy of this License; and
96
97
      (b) You must cause any modified files to carry prominent notices
98
          stating that You changed the files; and
99
100
      (c) You must retain, in the Source form of any Derivative Works
101
          that You distribute, all copyright, patent, trademark, and
102
          attribution notices from the Source form of the Work,
103
          excluding those notices that do not pertain to any part of
104
          the Derivative Works; and
105
106
      (d) If the Work includes a "NOTICE" text file as part of its
107
          distribution, then any Derivative Works that You distribute must
108
          include a readable copy of the attribution notices contained
109
          within such NOTICE file, excluding those notices that do not
110
          pertain to any part of the Derivative Works, in at least one
111
          of the following places: within a NOTICE text file distributed
112
          as part of the Derivative Works; within the Source form or
113
          documentation, if provided along with the Derivative Works; or,
114
          within a display generated by the Derivative Works, if and
115
          wherever such third-party notices normally appear. The contents
116
          of the NOTICE file are for informational purposes only and
117
          do not modify the License. You may add Your own attribution
118
          notices within Derivative Works that You distribute, alongside
119
          or as an addendum to the NOTICE text from the Work, provided
120
          that such additional attribution notices cannot be construed
121
          as modifying the License.
122
123
      You may add Your own copyright statement to Your modifications and
124
      may provide additional or different license terms and conditions
125
      for use, reproduction, or distribution of Your modifications, or
126
      for any such Derivative Works as a whole, provided Your use,
127
      reproduction, and distribution of the Work otherwise complies with
128
      the conditions stated in this License.
129
130
   5. Submission of Contributions. Unless You explicitly state otherwise,
131
      any Contribution intentionally submitted for inclusion in the Work
132
      by You to the Licensor shall be under the terms and conditions of
133
      this License, without any additional terms or conditions.
134
      Notwithstanding the above, nothing herein shall supersede or modify
135
      the terms of any separate license agreement you may have executed
136
      with Licensor regarding such Contributions.
137
138
   6. Trademarks. This License does not grant permission to use the trade
139
      names, trademarks, service marks, or product names of the Licensor,
140
      except as required for reasonable and customary use in describing the
141
      origin of the Work and reproducing the content of the NOTICE file.
142
143
   7. Disclaimer of Warranty. Unless required by applicable law or
144
      agreed to in writing, Licensor provides the Work (and each
145
      Contributor provides its Contributions) on an "AS IS" BASIS,
146
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
      implied, including, without limitation, any warranties or conditions
148
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
      PARTICULAR PURPOSE. You are solely responsible for determining the
150
      appropriateness of using or redistributing the Work and assume any
151
      risks associated with Your exercise of permissions under this License.
152
153
   8. Limitation of Liability. In no event and under no legal theory,
154
      whether in tort (including negligence), contract, or otherwise,
155
      unless required by applicable law (such as deliberate and grossly
156
      negligent acts) or agreed to in writing, shall any Contributor be
157
      liable to You for damages, including any direct, indirect, special,
158
      incidental, or consequential damages of any character arising as a
159
      result of this License or out of the use or inability to use the
160
      Work (including but not limited to damages for loss of goodwill,
161
      work stoppage, computer failure or malfunction, or any and all
162
      other commercial damages or losses), even if such Contributor
163
      has been advised of the possibility of such damages.
164
165
   9. Accepting Warranty or Additional Liability. While redistributing
166
      the Work or Derivative Works thereof, You may choose to offer,
167
      and charge a fee for, acceptance of support, warranty, indemnity,
168
      or other liability obligations and/or rights consistent with this
169
      License. However, in accepting such obligations, You may act only
170
      on Your own behalf and on Your sole responsibility, not on behalf
171
      of any other Contributor, and only if You agree to indemnify,
172
      defend, and hold each Contributor harmless for any liability
173
      incurred by, or claims asserted against, such Contributor by reason
174
      of your accepting any such warranty or additional liability.
175
176
   END OF TERMS AND CONDITIONS
177
178
   APPENDIX: How to apply the Apache License to your work.
179
180
      To apply the Apache License to your work, attach the following
181
      boilerplate notice, with the fields enclosed by brackets "{}"
182
      replaced with your own identifying information. (Don't include
183
      the brackets!)  The text should be enclosed in the appropriate
184
      comment syntax for the file format. We also recommend that a
185
      file or class name and description of purpose be included on the
186
      same "printed page" as the copyright notice for easier
187
      identification within third-party archives.
188
189
   Copyright {yyyy} {name of copyright owner}
190
191
   Licensed under the Apache License, Version 2.0 (the "License");
192
   you may not use this file except in compliance with the License.
193
   You may obtain a copy of the License at
194
195
       http://www.apache.org/licenses/LICENSE-2.0
196
197
   Unless required by applicable law or agreed to in writing, software
198
   distributed under the License is distributed on an "AS IS" BASIS,
199
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
   See the License for the specific language governing permissions and
201
   limitations under the License.

+ 29 - 0
vendor/topthink/think-image/README.md

@ -0,0 +1,29 @@
1
# The ThinkPHP5 Image Package
2
3
[![Build Status](https://img.shields.io/travis/top-think/think-image.svg)](https://travis-ci.org/top-think/think-image)
4
[![Coverage Status](https://img.shields.io/codecov/c/github/top-think/think-image.svg)](https://codecov.io/github/top-think/think-image)
5
[![Downloads](https://img.shields.io/github/downloads/top-think/think-image/total.svg)](https://github.com/top-think/think-image/releases)
6
[![Releases](https://img.shields.io/github/release/top-think/think-image.svg)](https://github.com/top-think/think-image/releases/latest)
7
[![Releases Downloads](https://img.shields.io/github/downloads/top-think/think-image/latest/total.svg)](https://github.com/top-think/think-image/releases/latest)
8
[![Packagist Status](https://img.shields.io/packagist/v/top-think/think-image.svg)](https://packagist.org/packages/topthink/think-image)
9
[![Packagist Downloads](https://img.shields.io/packagist/dt/top-think/think-image.svg)](https://packagist.org/packages/topthink/think-image)
10
11
## 安装
12
13
> composer require topthink/think-image
14
15
## 使用
16
17
~~~
18
$image = \think\Image::open('./image.jpg');
19
或者
20
$image = \think\Image::open(request()->file('image'));
21
22
23
$image->crop(...)
24
    ->thumb(...)
25
    ->water(...)
26
    ->text(....)
27
    ->save(..);
28
29
~~~

+ 26 - 0
vendor/topthink/think-image/composer.json

@ -0,0 +1,26 @@
1
{
2
    "name": "topthink/think-image",
3
    "description": "The ThinkPHP5 Image Package",
4
    "license": "Apache-2.0",
5
    "authors": [
6
        {
7
            "name": "yunwuxin",
8
            "email": "448901948@qq.com"
9
        }
10
    ],
11
    "require": {
12
        "ext-gd": "*"
13
    },
14
    "require-dev": {
15
        "topthink/framework": "^5.0",
16
        "phpunit/phpunit": "4.8.*"
17
    },
18
    "config": {
19
        "preferred-install": "dist"
20
    },
21
    "autoload": {
22
        "psr-4": {
23
            "think\\": "src"
24
        }
25
    }
26
}

+ 20 - 0
vendor/topthink/think-image/phpunit.xml

@ -0,0 +1,20 @@
1
<?xml version="1.0" encoding="UTF-8"?>
2
<phpunit backupGlobals="false"
3
         backupStaticAttributes="false"
4
         bootstrap="tests/autoload.php"
5
         colors="true"
6
         convertErrorsToExceptions="true"
7
         convertNoticesToExceptions="true"
8
         convertWarningsToExceptions="true"
9
         processIsolation="false"
10
         stopOnFailure="false"
11
         syntaxCheck="false">
12
    <testsuites>
13
        <testsuite name="Package Test Suite">
14
            <directory suffix=".php">./tests/</directory>
15
        </testsuite>
16
    </testsuites>
17
    <listeners>
18
        <listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener" />
19
    </listeners>
20
</phpunit>

+ 610 - 0
vendor/topthink/think-image/src/Image.php

@ -0,0 +1,610 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
12
namespace think;
13
14
use think\image\Exception as ImageException;
15
use think\image\gif\Gif;
16
17
class Image
18
{
19
20
    /* 缩略图相关常量定义 */
21
    const THUMB_SCALING   = 1; //常量,标识缩略图等比例缩放类型
22
    const THUMB_FILLED    = 2; //常量,标识缩略图缩放后填充类型
23
    const THUMB_CENTER    = 3; //常量,标识缩略图居中裁剪类型
24
    const THUMB_NORTHWEST = 4; //常量,标识缩略图左上角裁剪类型
25
    const THUMB_SOUTHEAST = 5; //常量,标识缩略图右下角裁剪类型
26
    const THUMB_FIXED     = 6; //常量,标识缩略图固定尺寸缩放类型
27
    /* 水印相关常量定义 */
28
    const WATER_NORTHWEST = 1; //常量,标识左上角水印
29
    const WATER_NORTH     = 2; //常量,标识上居中水印
30
    const WATER_NORTHEAST = 3; //常量,标识右上角水印
31
    const WATER_WEST      = 4; //常量,标识左居中水印
32
    const WATER_CENTER    = 5; //常量,标识居中水印
33
    const WATER_EAST      = 6; //常量,标识右居中水印
34
    const WATER_SOUTHWEST = 7; //常量,标识左下角水印
35
    const WATER_SOUTH     = 8; //常量,标识下居中水印
36
    const WATER_SOUTHEAST = 9; //常量,标识右下角水印
37
    /* 翻转相关常量定义 */
38
    const FLIP_X = 1; //X轴翻转
39
    const FLIP_Y = 2; //Y轴翻转
40
41
    /**
42
     * 图像资源对象
43
     *
44
     * @var resource
45
     */
46
    protected $im;
47
48
    /** @var  Gif */
49
    protected $gif;
50
51
    /**
52
     * 图像信息,包括 width, height, type, mime, size
53
     *
54
     * @var array
55
     */
56
    protected $info;
57
58
    protected function __construct(\SplFileInfo $file)
59
    {
60
        //获取图像信息
61
        $info = @getimagesize($file->getPathname());
62
63
        //检测图像合法性
64
        if (false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))) {
65
            throw new ImageException('Illegal image file');
66
        }
67
68
        //设置图像信息
69
        $this->info = [
70
            'width'  => $info[0],
71
            'height' => $info[1],
72
            'type'   => image_type_to_extension($info[2], false),
73
            'mime'   => $info['mime'],
74
        ];
75
76
        //打开图像
77
        if ('gif' == $this->info['type']) {
78
            $this->gif = new Gif($file->getPathname());
79
            $this->im  = @imagecreatefromstring($this->gif->image());
80
        } else {
81
            $fun      = "imagecreatefrom{$this->info['type']}";
82
            $this->im = @$fun($file->getPathname());
83
        }
84
85
        if (empty($this->im)) {
86
            throw new ImageException('Failed to create image resources!');
87
        }
88
89
    }
90
91
    /**
92
     * 打开一个图片文件
93
     * @param \SplFileInfo|string $file
94
     * @return Image
95
     */
96
    public static function open($file)
97
    {
98
        if (is_string($file)) {
99
            $file = new \SplFileInfo($file);
100
        }
101
        if (!$file->isFile()) {
102
            throw new ImageException('image file not exist');
103
        }
104
        return new self($file);
105
    }
106
107
    /**
108
     * 保存图像
109
     * @param string      $pathname  图像保存路径名称
110
     * @param null|string $type      图像类型
111
     * @param int         $quality   图像质量
112
     * @param bool        $interlace 是否对JPEG类型图像设置隔行扫描
113
     * @return $this
114
     */
115
    public function save($pathname, $type = null, $quality = 80, $interlace = true)
116
    {
117
        //自动获取图像类型
118
        if (is_null($type)) {
119
            $type = $this->info['type'];
120
        } else {
121
            $type = strtolower($type);
122
        }
123
        //保存图像
124
        if ('jpeg' == $type || 'jpg' == $type) {
125
            //JPEG图像设置隔行扫描
126
            imageinterlace($this->im, $interlace);
127
            imagejpeg($this->im, $pathname, $quality);
128
        } elseif ('gif' == $type && !empty($this->gif)) {
129
            $this->gif->save($pathname);
130
        } elseif ('png' == $type) {
131
            //设定保存完整的 alpha 通道信息
132
            imagesavealpha($this->im, true);
133
            //ImagePNG生成图像的质量范围从0到9的
134
            imagepng($this->im, $pathname, min((int) ($quality / 10), 9));
135
        } else {
136
            $fun = 'image' . $type;
137
            $fun($this->im, $pathname);
138
        }
139
140
        return $this;
141
    }
142
143
    /**
144
     * 返回图像宽度
145
     * @return int 图像宽度
146
     */
147
    public function width()
148
    {
149
        return $this->info['width'];
150
    }
151
152
    /**
153
     * 返回图像高度
154
     * @return int 图像高度
155
     */
156
    public function height()
157
    {
158
        return $this->info['height'];
159
    }
160
161
    /**
162
     * 返回图像类型
163
     * @return string 图像类型
164
     */
165
    public function type()
166
    {
167
        return $this->info['type'];
168
    }
169
170
    /**
171
     * 返回图像MIME类型
172
     * @return string 图像MIME类型
173
     */
174
    public function mime()
175
    {
176
        return $this->info['mime'];
177
    }
178
179
    /**
180
     * 返回图像尺寸数组 0 - 图像宽度,1 - 图像高度
181
     * @return array 图像尺寸
182
     */
183
    public function size()
184
    {
185
        return [$this->info['width'], $this->info['height']];
186
    }
187
188
    /**
189
     * 旋转图像
190
     * @param int $degrees 顺时针旋转的度数
191
     * @return $this
192
     */
193
    public function rotate($degrees = 90)
194
    {
195
        do {
196
            $img = imagerotate($this->im, -$degrees, imagecolorallocatealpha($this->im, 0, 0, 0, 127));
197
            imagedestroy($this->im);
198
            $this->im = $img;
199
        } while (!empty($this->gif) && $this->gifNext());
200
201
        $this->info['width']  = imagesx($this->im);
202
        $this->info['height'] = imagesy($this->im);
203
204
        return $this;
205
    }
206
207
    /**
208
     * 翻转图像
209
     * @param integer $direction 翻转轴,X或者Y
210
     * @return $this
211
     */
212
    public function flip($direction = self::FLIP_X)
213
    {
214
        //原图宽度和高度
215
        $w = $this->info['width'];
216
        $h = $this->info['height'];
217
218
        do {
219
220
            $img = imagecreatetruecolor($w, $h);
221
222
            switch ($direction) {
223
                case self::FLIP_X:
224
                    for ($y = 0; $y < $h; $y++) {
225
                        imagecopy($img, $this->im, 0, $h - $y - 1, 0, $y, $w, 1);
226
                    }
227
                    break;
228
                case self::FLIP_Y:
229
                    for ($x = 0; $x < $w; $x++) {
230
                        imagecopy($img, $this->im, $w - $x - 1, 0, $x, 0, 1, $h);
231
                    }
232
                    break;
233
                default:
234
                    throw new ImageException('不支持的翻转类型');
235
            }
236
237
            imagedestroy($this->im);
238
            $this->im = $img;
239
240
        } while (!empty($this->gif) && $this->gifNext());
241
242
        return $this;
243
    }
244
245
    /**
246
     * 裁剪图像
247
     *
248
     * @param  integer $w      裁剪区域宽度
249
     * @param  integer $h      裁剪区域高度
250
     * @param  integer $x      裁剪区域x坐标
251
     * @param  integer $y      裁剪区域y坐标
252
     * @param  integer $width  图像保存宽度
253
     * @param  integer $height 图像保存高度
254
     *
255
     * @return $this
256
     */
257
    public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null)
258
    {
259
        //设置保存尺寸
260
        empty($width) && $width   = $w;
261
        empty($height) && $height = $h;
262
        do {
263
            //创建新图像
264
            $img = imagecreatetruecolor($width, $height);
265
            // 调整默认颜色
266
            $color = imagecolorallocate($img, 255, 255, 255);
267
            imagefill($img, 0, 0, $color);
268
            //裁剪
269
            imagecopyresampled($img, $this->im, 0, 0, $x, $y, $width, $height, $w, $h);
270
            imagedestroy($this->im); //销毁原图
271
            //设置新图像
272
            $this->im = $img;
273
        } while (!empty($this->gif) && $this->gifNext());
274
        $this->info['width']  = (int) $width;
275
        $this->info['height'] = (int) $height;
276
        return $this;
277
    }
278
279
    /**
280
     * 生成缩略图
281
     *
282
     * @param  integer $width  缩略图最大宽度
283
     * @param  integer $height 缩略图最大高度
284
     * @param int      $type   缩略图裁剪类型
285
     *
286
     * @return $this
287
     */
288
    public function thumb($width, $height, $type = self::THUMB_SCALING)
289
    {
290
        //原图宽度和高度
291
        $w = $this->info['width'];
292
        $h = $this->info['height'];
293
        /* 计算缩略图生成的必要参数 */
294
        switch ($type) {
295
            /* 等比例缩放 */
296
            case self::THUMB_SCALING:
297
                //原图尺寸小于缩略图尺寸则不进行缩略
298
                if ($w < $width && $h < $height) {
299
                    return $this;
300
                }
301
                //计算缩放比例
302
                $scale = min($width / $w, $height / $h);
303
                //设置缩略图的坐标及宽度和高度
304
                $x      = $y      = 0;
305
                $width  = $w * $scale;
306
                $height = $h * $scale;
307
                break;
308
            /* 居中裁剪 */
309
            case self::THUMB_CENTER:
310
                //计算缩放比例
311
                $scale = max($width / $w, $height / $h);
312
                //设置缩略图的坐标及宽度和高度
313
                $w = $width / $scale;
314
                $h = $height / $scale;
315
                $x = ($this->info['width'] - $w) / 2;
316
                $y = ($this->info['height'] - $h) / 2;
317
                break;
318
            /* 左上角裁剪 */
319
            case self::THUMB_NORTHWEST:
320
                //计算缩放比例
321
                $scale = max($width / $w, $height / $h);
322
                //设置缩略图的坐标及宽度和高度
323
                $x = $y = 0;
324
                $w = $width / $scale;
325
                $h = $height / $scale;
326
                break;
327
            /* 右下角裁剪 */
328
            case self::THUMB_SOUTHEAST:
329
                //计算缩放比例
330
                $scale = max($width / $w, $height / $h);
331
                //设置缩略图的坐标及宽度和高度
332
                $w = $width / $scale;
333
                $h = $height / $scale;
334
                $x = $this->info['width'] - $w;
335
                $y = $this->info['height'] - $h;
336
                break;
337
            /* 填充 */
338
            case self::THUMB_FILLED:
339
                //计算缩放比例
340
                if ($w < $width && $h < $height) {
341
                    $scale = 1;
342
                } else {
343
                    $scale = min($width / $w, $height / $h);
344
                }
345
                //设置缩略图的坐标及宽度和高度
346
                $neww = $w * $scale;
347
                $newh = $h * $scale;
348
                $x    = $this->info['width'] - $w;
349
                $y    = $this->info['height'] - $h;
350
                $posx = ($width - $w * $scale) / 2;
351
                $posy = ($height - $h * $scale) / 2;
352
                do {
353
                    //创建新图像
354
                    $img = imagecreatetruecolor($width, $height);
355
                    // 调整默认颜色
356
                    $color = imagecolorallocate($img, 255, 255, 255);
357
                    imagefill($img, 0, 0, $color);
358
                    //裁剪
359
                    imagecopyresampled($img, $this->im, $posx, $posy, $x, $y, $neww, $newh, $w, $h);
360
                    imagedestroy($this->im); //销毁原图
361
                    $this->im = $img;
362
                } while (!empty($this->gif) && $this->gifNext());
363
                $this->info['width']  = (int) $width;
364
                $this->info['height'] = (int) $height;
365
                return $this;
366
            /* 固定 */
367
            case self::THUMB_FIXED:
368
                $x = $y = 0;
369
                break;
370
            default:
371
                throw new ImageException('不支持的缩略图裁剪类型');
372
        }
373
        /* 裁剪图像 */
374
        return $this->crop($w, $h, $x, $y, $width, $height);
375
    }
376
377
    /**
378
     * 添加水印
379
     *
380
     * @param  string $source 水印图片路径
381
     * @param int     $locate 水印位置
382
     * @param int     $alpha  透明度
383
     * @return $this
384
     */
385
    public function water($source, $locate = self::WATER_SOUTHEAST, $alpha = 100)
386
    {
387
        if (!is_file($source)) {
388
            throw new ImageException('水印图像不存在');
389
        }
390
        //获取水印图像信息
391
        $info = getimagesize($source);
392
        if (false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))) {
393
            throw new ImageException('非法水印文件');
394
        }
395
        //创建水印图像资源
396
        $fun   = 'imagecreatefrom' . image_type_to_extension($info[2], false);
397
        $water = $fun($source);
398
        //设定水印图像的混色模式
399
        imagealphablending($water, true);
400
        /* 设定水印位置 */
401
        switch ($locate) {
402
            /* 右下角水印 */
403
            case self::WATER_SOUTHEAST:
404
                $x = $this->info['width'] - $info[0];
405
                $y = $this->info['height'] - $info[1];
406
                break;
407
            /* 左下角水印 */
408
            case self::WATER_SOUTHWEST:
409
                $x = 0;
410
                $y = $this->info['height'] - $info[1];
411
                break;
412
            /* 左上角水印 */
413
            case self::WATER_NORTHWEST:
414
                $x = $y = 0;
415
                break;
416
            /* 右上角水印 */
417
            case self::WATER_NORTHEAST:
418
                $x = $this->info['width'] - $info[0];
419
                $y = 0;
420
                break;
421
            /* 居中水印 */
422
            case self::WATER_CENTER:
423
                $x = ($this->info['width'] - $info[0]) / 2;
424
                $y = ($this->info['height'] - $info[1]) / 2;
425
                break;
426
            /* 下居中水印 */
427
            case self::WATER_SOUTH:
428
                $x = ($this->info['width'] - $info[0]) / 2;
429
                $y = $this->info['height'] - $info[1];
430
                break;
431
            /* 右居中水印 */
432
            case self::WATER_EAST:
433
                $x = $this->info['width'] - $info[0];
434
                $y = ($this->info['height'] - $info[1]) / 2;
435
                break;
436
            /* 上居中水印 */
437
            case self::WATER_NORTH:
438
                $x = ($this->info['width'] - $info[0]) / 2;
439
                $y = 0;
440
                break;
441
            /* 左居中水印 */
442
            case self::WATER_WEST:
443
                $x = 0;
444
                $y = ($this->info['height'] - $info[1]) / 2;
445
                break;
446
            default:
447
                /* 自定义水印坐标 */
448
                if (is_array($locate)) {
449
                    list($x, $y) = $locate;
450
                } else {
451
                    throw new ImageException('不支持的水印位置类型');
452
                }
453
        }
454
        do {
455
            //添加水印
456
            $src = imagecreatetruecolor($info[0], $info[1]);
457
            // 调整默认颜色
458
            $color = imagecolorallocate($src, 255, 255, 255);
459
            imagefill($src, 0, 0, $color);
460
            imagecopy($src, $this->im, 0, 0, $x, $y, $info[0], $info[1]);
461
            imagecopy($src, $water, 0, 0, 0, 0, $info[0], $info[1]);
462
            imagecopymerge($this->im, $src, $x, $y, 0, 0, $info[0], $info[1], $alpha);
463
            //销毁零时图片资源
464
            imagedestroy($src);
465
        } while (!empty($this->gif) && $this->gifNext());
466
        //销毁水印资源
467
        imagedestroy($water);
468
        return $this;
469
    }
470
471
    /**
472
     * 图像添加文字
473
     *
474
     * @param  string  $text   添加的文字
475
     * @param  string  $font   字体路径
476
     * @param  integer $size   字号
477
     * @param  string  $color  文字颜色
478
     * @param int      $locate 文字写入位置
479
     * @param  integer $offset 文字相对当前位置的偏移量
480
     * @param  integer $angle  文字倾斜角度
481
     *
482
     * @return $this
483
     * @throws ImageException
484
     */
485
    public function text($text, $font, $size, $color = '#00000000',
486
        $locate = self::WATER_SOUTHEAST, $offset = 0, $angle = 0) {
487
488
        if (!is_file($font)) {
489
            throw new ImageException("不存在的字体文件:{$font}");
490
        }
491
        //获取文字信息
492
        $info = imagettfbbox($size, $angle, $font, $text);
493
        $minx = min($info[0], $info[2], $info[4], $info[6]);
494
        $maxx = max($info[0], $info[2], $info[4], $info[6]);
495
        $miny = min($info[1], $info[3], $info[5], $info[7]);
496
        $maxy = max($info[1], $info[3], $info[5], $info[7]);
497
        /* 计算文字初始坐标和尺寸 */
498
        $x = $minx;
499
        $y = abs($miny);
500
        $w = $maxx - $minx;
501
        $h = $maxy - $miny;
502
        /* 设定文字位置 */
503
        switch ($locate) {
504
            /* 右下角文字 */
505
            case self::WATER_SOUTHEAST:
506
                $x += $this->info['width'] - $w;
507
                $y += $this->info['height'] - $h;
508
                break;
509
            /* 左下角文字 */
510
            case self::WATER_SOUTHWEST:
511
                $y += $this->info['height'] - $h;
512
                break;
513
            /* 左上角文字 */
514
            case self::WATER_NORTHWEST:
515
                // 起始坐标即为左上角坐标,无需调整
516
                break;
517
            /* 右上角文字 */
518
            case self::WATER_NORTHEAST:
519
                $x += $this->info['width'] - $w;
520
                break;
521
            /* 居中文字 */
522
            case self::WATER_CENTER:
523
                $x += ($this->info['width'] - $w) / 2;
524
                $y += ($this->info['height'] - $h) / 2;
525
                break;
526
            /* 下居中文字 */
527
            case self::WATER_SOUTH:
528
                $x += ($this->info['width'] - $w) / 2;
529
                $y += $this->info['height'] - $h;
530
                break;
531
            /* 右居中文字 */
532
            case self::WATER_EAST:
533
                $x += $this->info['width'] - $w;
534
                $y += ($this->info['height'] - $h) / 2;
535
                break;
536
            /* 上居中文字 */
537
            case self::WATER_NORTH:
538
                $x += ($this->info['width'] - $w) / 2;
539
                break;
540
            /* 左居中文字 */
541
            case self::WATER_WEST:
542
                $y += ($this->info['height'] - $h) / 2;
543
                break;
544
            default:
545
                /* 自定义文字坐标 */
546
                if (is_array($locate)) {
547
                    list($posx, $posy) = $locate;
548
                    $x += $posx;
549
                    $y += $posy;
550
                } else {
551
                    throw new ImageException('不支持的文字位置类型');
552
                }
553
        }
554
        /* 设置偏移量 */
555
        if (is_array($offset)) {
556
            $offset        = array_map('intval', $offset);
557
            list($ox, $oy) = $offset;
558
        } else {
559
            $offset = intval($offset);
560
            $ox     = $oy     = $offset;
561
        }
562
        /* 设置颜色 */
563
        if (is_string($color) && 0 === strpos($color, '#')) {
564
            $color = str_split(substr($color, 1), 2);
565
            $color = array_map('hexdec', $color);
566
            if (empty($color[3]) || $color[3] > 127) {
567
                $color[3] = 0;
568
            }
569
        } elseif (!is_array($color)) {
570
            throw new ImageException('错误的颜色值');
571
        }
572
        do {
573
            /* 写入文字 */
574
            $col = imagecolorallocatealpha($this->im, $color[0], $color[1], $color[2], $color[3]);
575
            imagettftext($this->im, $size, $angle, $x + $ox, $y + $oy, $col, $font, $text);
576
        } while (!empty($this->gif) && $this->gifNext());
577
        return $this;
578
    }
579
580
    /**
581
     * 切换到GIF的下一帧并保存当前帧
582
     */
583
    protected function gifNext()
584
    {
585
        ob_start();
586
        ob_implicit_flush(0);
587
        imagegif($this->im);
588
        $img = ob_get_clean();
589
        $this->gif->image($img);
590
        $next = $this->gif->nextImage();
591
        if ($next) {
592
            imagedestroy($this->im);
593
            $this->im = imagecreatefromstring($next);
594
            return $next;
595
        } else {
596
            imagedestroy($this->im);
597
            $this->im = imagecreatefromstring($this->gif->image());
598
            return false;
599
        }
600
    }
601
602
    /**
603
     * 析构方法,用于销毁图像资源
604
     */
605
    public function __destruct()
606
    {
607
        empty($this->im) || imagedestroy($this->im);
608
    }
609
610
}

+ 18 - 0
vendor/topthink/think-image/src/image/Exception.php

@ -0,0 +1,18 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
12
namespace think\image;
13
14
15
class Exception extends \RuntimeException
16
{
17
18
}

+ 207 - 0
vendor/topthink/think-image/src/image/gif/Decoder.php

@ -0,0 +1,207 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
12
namespace think\image\gif;
13
14
15
class Decoder
16
{
17
    public $GIF_buffer = [];
18
    public $GIF_arrays = [];
19
    public $GIF_delays = [];
20
    public $GIF_stream = "";
21
    public $GIF_string = "";
22
    public $GIF_bfseek = 0;
23
    public $GIF_screen = [];
24
    public $GIF_global = [];
25
    public $GIF_sorted;
26
    public $GIF_colorS;
27
    public $GIF_colorC;
28
    public $GIF_colorF;
29
30
    /*
31
    :::::::::::::::::::::::::::::::::::::::::::::::::::
32
    ::
33
    ::    GIFDecoder ( $GIF_pointer )
34
    ::
35
     */
36
    public function __construct($GIF_pointer)
37
    {
38
        $this->GIF_stream = $GIF_pointer;
39
        $this->getByte(6); // GIF89a
40
        $this->getByte(7); // Logical Screen Descriptor
41
        $this->GIF_screen = $this->GIF_buffer;
42
        $this->GIF_colorF = $this->GIF_buffer[4] & 0x80 ? 1 : 0;
43
        $this->GIF_sorted = $this->GIF_buffer[4] & 0x08 ? 1 : 0;
44
        $this->GIF_colorC = $this->GIF_buffer[4] & 0x07;
45
        $this->GIF_colorS = 2 << $this->GIF_colorC;
46
        if (1 == $this->GIF_colorF) {
47
            $this->getByte(3 * $this->GIF_colorS);
48
            $this->GIF_global = $this->GIF_buffer;
49
        }
50
51
        for ($cycle = 1; $cycle;) {
52
            if ($this->getByte(1)) {
53
                switch ($this->GIF_buffer[0]) {
54
                    case 0x21:
55
                        $this->readExtensions();
56
                        break;
57
                    case 0x2C:
58
                        $this->readDescriptor();
59
                        break;
60
                    case 0x3B:
61
                        $cycle = 0;
62
                        break;
63
                }
64
            } else {
65
                $cycle = 0;
66
            }
67
        }
68
    }
69
70
    /*
71
    :::::::::::::::::::::::::::::::::::::::::::::::::::
72
    ::
73
    ::    GIFReadExtension ( )
74
    ::
75
     */
76
    public function readExtensions()
77
    {
78
        $this->getByte(1);
79
        for (; ;) {
80
            $this->getByte(1);
81
            if (($u = $this->GIF_buffer[0]) == 0x00) {
82
                break;
83
            }
84
            $this->getByte($u);
85
            /*
86
             * 07.05.2007.
87
             * Implemented a new line for a new function
88
             * to determine the originaly delays between
89
             * frames.
90
             *
91
             */
92
            if (4 == $u) {
93
                $this->GIF_delays[] = ($this->GIF_buffer[1] | $this->GIF_buffer[2] << 8);
94
            }
95
        }
96
    }
97
98
    /*
99
    :::::::::::::::::::::::::::::::::::::::::::::::::::
100
    ::
101
    ::    GIFReadExtension ( )
102
    ::
103
     */
104
    public function readDescriptor()
105
    {
106
        $this->getByte(9);
107
        $GIF_screen = $this->GIF_buffer;
108
        $GIF_colorF = $this->GIF_buffer[8] & 0x80 ? 1 : 0;
109
        if ($GIF_colorF) {
110
            $GIF_code = $this->GIF_buffer[8] & 0x07;
111
            $GIF_sort = $this->GIF_buffer[8] & 0x20 ? 1 : 0;
112
        } else {
113
            $GIF_code = $this->GIF_colorC;
114
            $GIF_sort = $this->GIF_sorted;
115
        }
116
        $GIF_size = 2 << $GIF_code;
117
        $this->GIF_screen[4] &= 0x70;
118
        $this->GIF_screen[4] |= 0x80;
119
        $this->GIF_screen[4] |= $GIF_code;
120
        if ($GIF_sort) {
121
            $this->GIF_screen[4] |= 0x08;
122
        }
123
        $this->GIF_string = "GIF87a";
124
        $this->putByte($this->GIF_screen);
125
        if (1 == $GIF_colorF) {
126
            $this->getByte(3 * $GIF_size);
127
            $this->putByte($this->GIF_buffer);
128
        } else {
129
            $this->putByte($this->GIF_global);
130
        }
131
        $this->GIF_string .= chr(0x2C);
132
        $GIF_screen[8] &= 0x40;
133
        $this->putByte($GIF_screen);
134
        $this->getByte(1);
135
        $this->putByte($this->GIF_buffer);
136
        for (; ;) {
137
            $this->getByte(1);
138
            $this->putByte($this->GIF_buffer);
139
            if (($u = $this->GIF_buffer[0]) == 0x00) {
140
                break;
141
            }
142
            $this->getByte($u);
143
            $this->putByte($this->GIF_buffer);
144
        }
145
        $this->GIF_string .= chr(0x3B);
146
        /*
147
        Add frames into $GIF_stream array...
148
         */
149
        $this->GIF_arrays[] = $this->GIF_string;
150
    }
151
152
    /*
153
    :::::::::::::::::::::::::::::::::::::::::::::::::::
154
    ::
155
    ::    GIFGetByte ( $len )
156
    ::
157
    */
158
    public function getByte($len)
159
    {
160
        $this->GIF_buffer = [];
161
        for ($i = 0; $i < $len; $i++) {
162
            if ($this->GIF_bfseek > strlen($this->GIF_stream)) {
163
                return 0;
164
            }
165
            $this->GIF_buffer[] = ord($this->GIF_stream{$this->GIF_bfseek++});
166
        }
167
        return 1;
168
    }
169
170
    /*
171
    :::::::::::::::::::::::::::::::::::::::::::::::::::
172
    ::
173
    ::    GIFPutByte ( $bytes )
174
    ::
175
     */
176
    public function putByte($bytes)
177
    {
178
        for ($i = 0; $i < count($bytes); $i++) {
179
            $this->GIF_string .= chr($bytes[$i]);
180
        }
181
    }
182
183
    /*
184
    :::::::::::::::::::::::::::::::::::::::::::::::::::
185
    ::
186
    ::    PUBLIC FUNCTIONS
187
    ::
188
    ::
189
    ::    GIFGetFrames ( )
190
    ::
191
     */
192
    public function getFrames()
193
    {
194
        return ($this->GIF_arrays);
195
    }
196
197
    /*
198
    :::::::::::::::::::::::::::::::::::::::::::::::::::
199
    ::
200
    ::    GIFGetDelays ( )
201
    ::
202
     */
203
    public function getDelays()
204
    {
205
        return ($this->GIF_delays);
206
    }
207
}

+ 222 - 0
vendor/topthink/think-image/src/image/gif/Encoder.php

@ -0,0 +1,222 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
namespace think\image\gif;
12
13
class Encoder
14
{
15
    public $GIF = "GIF89a"; /* GIF header 6 bytes    */
16
    public $VER = "GIFEncoder V2.05"; /* Encoder version        */
17
    public $BUF = [];
18
    public $LOP = 0;
19
    public $DIS = 2;
20
    public $COL = -1;
21
    public $IMG = -1;
22
    public $ERR = [
23
        'ERR00' => "Does not supported function for only one image!",
24
        'ERR01' => "Source is not a GIF image!",
25
        'ERR02' => "Unintelligible flag ",
26
        'ERR03' => "Does not make animation from animated GIF source",
27
    ];
28
29
    /*
30
    :::::::::::::::::::::::::::::::::::::::::::::::::::
31
    ::
32
    ::    GIFEncoder...
33
    ::
34
     */
35
    public function __construct(
36
        $GIF_src, $GIF_dly, $GIF_lop, $GIF_dis,
37
        $GIF_red, $GIF_grn, $GIF_blu, $GIF_mod
38
    )
39
    {
40
        if (!is_array($GIF_src)) {
41
            printf("%s: %s", $this->VER, $this->ERR['ERR00']);
42
            exit(0);
43
        }
44
        $this->LOP = ($GIF_lop > -1) ? $GIF_lop : 0;
45
        $this->DIS = ($GIF_dis > -1) ? (($GIF_dis < 3) ? $GIF_dis : 3) : 2;
46
        $this->COL = ($GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1) ?
47
            ($GIF_red | ($GIF_grn << 8) | ($GIF_blu << 16)) : -1;
48
        for ($i = 0; $i < count($GIF_src); $i++) {
49
            if (strtolower($GIF_mod) == "url") {
50
                $this->BUF[] = fread(fopen($GIF_src[$i], "rb"), filesize($GIF_src[$i]));
51
            } else if (strtolower($GIF_mod) == "bin") {
52
                $this->BUF[] = $GIF_src[$i];
53
            } else {
54
                printf("%s: %s ( %s )!", $this->VER, $this->ERR['ERR02'], $GIF_mod);
55
                exit(0);
56
            }
57
            if (substr($this->BUF[$i], 0, 6) != "GIF87a" && substr($this->BUF[$i], 0, 6) != "GIF89a") {
58
                printf("%s: %d %s", $this->VER, $i, $this->ERR['ERR01']);
59
                exit(0);
60
            }
61
            for ($j = (13 + 3 * (2 << (ord($this->BUF[$i]{10}) & 0x07))), $k = true; $k; $j++) {
62
                switch ($this->BUF[$i]{$j}) {
63
                    case "!":
64
                        if ((substr($this->BUF[$i], ($j + 3), 8)) == "NETSCAPE") {
65
                            printf("%s: %s ( %s source )!", $this->VER, $this->ERR['ERR03'], ($i + 1));
66
                            exit(0);
67
                        }
68
                        break;
69
                    case ";":
70
                        $k = false;
71
                        break;
72
                }
73
            }
74
        }
75
        $this->addHeader();
76
        for ($i = 0; $i < count($this->BUF); $i++) {
77
            $this->addFrames($i, $GIF_dly[$i]);
78
        }
79
        $this->addFooter();
80
    }
81
82
    /*
83
    :::::::::::::::::::::::::::::::::::::::::::::::::::
84
    ::
85
    ::    GIFAddHeader...
86
    ::
87
     */
88
    public function addHeader()
89
    {
90
        if (ord($this->BUF[0]{10}) & 0x80) {
91
            $cmap = 3 * (2 << (ord($this->BUF[0]{10}) & 0x07));
92
            $this->GIF .= substr($this->BUF[0], 6, 7);
93
            $this->GIF .= substr($this->BUF[0], 13, $cmap);
94
            $this->GIF .= "!\377\13NETSCAPE2.0\3\1" . $this->word($this->LOP) . "\0";
95
        }
96
    }
97
98
    /*
99
    :::::::::::::::::::::::::::::::::::::::::::::::::::
100
    ::
101
    ::    GIFAddFrames...
102
    ::
103
     */
104
    public function addFrames($i, $d)
105
    {
106
        $Locals_img = '';
107
        $Locals_str = 13 + 3 * (2 << (ord($this->BUF[$i]{10}) & 0x07));
108
        $Locals_end = strlen($this->BUF[$i]) - $Locals_str - 1;
109
        $Locals_tmp = substr($this->BUF[$i], $Locals_str, $Locals_end);
110
        $Global_len = 2 << (ord($this->BUF[0]{10}) & 0x07);
111
        $Locals_len = 2 << (ord($this->BUF[$i]{10}) & 0x07);
112
        $Global_rgb = substr($this->BUF[0], 13,
113
            3 * (2 << (ord($this->BUF[0]{10}) & 0x07)));
114
        $Locals_rgb = substr($this->BUF[$i], 13,
115
            3 * (2 << (ord($this->BUF[$i]{10}) & 0x07)));
116
        $Locals_ext = "!\xF9\x04" . chr(($this->DIS << 2) + 0) .
117
            chr(($d >> 0) & 0xFF) . chr(($d >> 8) & 0xFF) . "\x0\x0";
118
        if ($this->COL > -1 && ord($this->BUF[$i]{10}) & 0x80) {
119
            for ($j = 0; $j < (2 << (ord($this->BUF[$i]{10}) & 0x07)); $j++) {
120
                if (
121
                    ord($Locals_rgb{3 * $j + 0}) == (($this->COL >> 16) & 0xFF) &&
122
                    ord($Locals_rgb{3 * $j + 1}) == (($this->COL >> 8) & 0xFF) &&
123
                    ord($Locals_rgb{3 * $j + 2}) == (($this->COL >> 0) & 0xFF)
124
                ) {
125
                    $Locals_ext = "!\xF9\x04" . chr(($this->DIS << 2) + 1) .
126
                        chr(($d >> 0) & 0xFF) . chr(($d >> 8) & 0xFF) . chr($j) . "\x0";
127
                    break;
128
                }
129
            }
130
        }
131
        switch ($Locals_tmp{0}) {
132
            case "!":
133
                /**
134
                 * @var string $Locals_img ;
135
                 */
136
                $Locals_img = substr($Locals_tmp, 8, 10);
137
                $Locals_tmp = substr($Locals_tmp, 18, strlen($Locals_tmp) - 18);
138
                break;
139
            case ",":
140
                $Locals_img = substr($Locals_tmp, 0, 10);
141
                $Locals_tmp = substr($Locals_tmp, 10, strlen($Locals_tmp) - 10);
142
                break;
143
        }
144
        if (ord($this->BUF[$i]{10}) & 0x80 && $this->IMG > -1) {
145
            if ($Global_len == $Locals_len) {
146
                if ($this->blockCompare($Global_rgb, $Locals_rgb, $Global_len)) {
147
                    $this->GIF .= ($Locals_ext . $Locals_img . $Locals_tmp);
148
                } else {
149
                    $byte = ord($Locals_img{9});
150
                    $byte |= 0x80;
151
                    $byte &= 0xF8;
152
                    $byte |= (ord($this->BUF[0]{10}) & 0x07);
153
                    $Locals_img{9} = chr($byte);
154
                    $this->GIF .= ($Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp);
155
                }
156
            } else {
157
                $byte = ord($Locals_img{9});
158
                $byte |= 0x80;
159
                $byte &= 0xF8;
160
                $byte |= (ord($this->BUF[$i]{10}) & 0x07);
161
                $Locals_img{9} = chr($byte);
162
                $this->GIF .= ($Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp);
163
            }
164
        } else {
165
            $this->GIF .= ($Locals_ext . $Locals_img . $Locals_tmp);
166
        }
167
        $this->IMG = 1;
168
    }
169
170
    /*
171
    :::::::::::::::::::::::::::::::::::::::::::::::::::
172
    ::
173
    ::    GIFAddFooter...
174
    ::
175
     */
176
    public function addFooter()
177
    {
178
        $this->GIF .= ";";
179
    }
180
181
    /*
182
    :::::::::::::::::::::::::::::::::::::::::::::::::::
183
    ::
184
    ::    GIFBlockCompare...
185
    ::
186
     */
187
    public function blockCompare($GlobalBlock, $LocalBlock, $Len)
188
    {
189
        for ($i = 0; $i < $Len; $i++) {
190
            if (
191
                $GlobalBlock{3 * $i + 0} != $LocalBlock{3 * $i + 0} ||
192
                $GlobalBlock{3 * $i + 1} != $LocalBlock{3 * $i + 1} ||
193
                $GlobalBlock{3 * $i + 2} != $LocalBlock{3 * $i + 2}
194
            ) {
195
                return (0);
196
            }
197
        }
198
        return (1);
199
    }
200
201
    /*
202
    :::::::::::::::::::::::::::::::::::::::::::::::::::
203
    ::
204
    ::    GIFWord...
205
    ::
206
     */
207
    public function word($int)
208
    {
209
        return (chr($int & 0xFF) . chr(($int >> 8) & 0xFF));
210
    }
211
212
    /*
213
    :::::::::::::::::::::::::::::::::::::::::::::::::::
214
    ::
215
    ::    GetAnimation...
216
    ::
217
     */
218
    public function getAnimation()
219
    {
220
        return ($this->GIF);
221
    }
222
}

+ 88 - 0
vendor/topthink/think-image/src/image/gif/Gif.php

@ -0,0 +1,88 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
12
namespace think\image\gif;
13
14
class Gif
15
{
16
    /**
17
     * GIF帧列表
18
     *
19
     * @var array
20
     */
21
    private $frames = [];
22
    /**
23
     * 每帧等待时间列表
24
     *
25
     * @var array
26
     */
27
    private $delays = [];
28
29
    /**
30
     * 构造方法,用于解码GIF图片
31
     *
32
     * @param string $src GIF图片数据
33
     * @param string $mod 图片数据类型
34
     * @throws \Exception
35
     */
36
    public function __construct($src = null, $mod = 'url')
37
    {
38
        if (!is_null($src)) {
39
            if ('url' == $mod && is_file($src)) {
40
                $src = file_get_contents($src);
41
            }
42
            /* 解码GIF图片 */
43
            try {
44
                $de           = new Decoder($src);
45
                $this->frames = $de->getFrames();
46
                $this->delays = $de->getDelays();
47
            } catch (\Exception $e) {
48
                throw new \Exception("解码GIF图片出错");
49
            }
50
        }
51
    }
52
53
    /**
54
     * 设置或获取当前帧的数据
55
     *
56
     * @param  string $stream 二进制数据流
57
     * @return mixed        获取到的数据
58
     */
59
    public function image($stream = null)
60
    {
61
        if (is_null($stream)) {
62
            $current = current($this->frames);
63
            return false === $current ? reset($this->frames) : $current;
64
        }
65
        $this->frames[key($this->frames)] = $stream;
66
    }
67
68
    /**
69
     * 将当前帧移动到下一帧
70
     *
71
     * @return string 当前帧数据
72
     */
73
    public function nextImage()
74
    {
75
        return next($this->frames);
76
    }
77
78
    /**
79
     * 编码并保存当前GIF图片
80
     *
81
     * @param  string $pathname 图片名称
82
     */
83
    public function save($pathname)
84
    {
85
        $gif = new Encoder($this->frames, $this->delays, 0, 2, 0, 0, 0, 'bin');
86
        file_put_contents($pathname, $gif->getAnimation());
87
    }
88
}

+ 67 - 0
vendor/topthink/think-image/tests/CropTest.php

@ -0,0 +1,67 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
namespace tests;
12
13
use think\Image;
14
15
class CropTest extends TestCase
16
{
17
    public function testJpeg()
18
    {
19
        $pathname = TEST_PATH . 'tmp/crop.jpg';
20
        $image    = Image::open($this->getJpeg());
21
22
        $image->crop(200, 200, 100, 100, 300, 300)->save($pathname);
23
24
        $this->assertEquals(300, $image->width());
25
        $this->assertEquals(300, $image->height());
26
27
        $file = new \SplFileInfo($pathname);
28
29
        $this->assertTrue($file->isFile());
30
31
        @unlink($pathname);
32
    }
33
34
    public function testPng()
35
    {
36
        $pathname = TEST_PATH . 'tmp/crop.png';
37
        $image    = Image::open($this->getPng());
38
39
        $image->crop(200, 200, 100, 100, 300, 300)->save($pathname);
40
41
        $this->assertEquals(300, $image->width());
42
        $this->assertEquals(300, $image->height());
43
44
        $file = new \SplFileInfo($pathname);
45
46
        $this->assertTrue($file->isFile());
47
48
        @unlink($pathname);
49
    }
50
51
    public function testGif()
52
    {
53
        $pathname = TEST_PATH . 'tmp/crop.gif';
54
        $image    = Image::open($this->getGif());
55
56
        $image->crop(200, 200, 100, 100, 300, 300)->save($pathname);
57
58
        $this->assertEquals(300, $image->width());
59
        $this->assertEquals(300, $image->height());
60
61
        $file = new \SplFileInfo($pathname);
62
63
        $this->assertTrue($file->isFile());
64
65
        @unlink($pathname);
66
    }
67
}

+ 43 - 0
vendor/topthink/think-image/tests/FlipTest.php

@ -0,0 +1,43 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
namespace tests;
12
13
use think\Image;
14
15
class FlipTest extends TestCase
16
{
17
    public function testJpeg()
18
    {
19
        $pathname = TEST_PATH . 'tmp/flip.jpg';
20
        $image    = Image::open($this->getJpeg());
21
        $image->flip()->save($pathname);
22
23
        $file = new \SplFileInfo($pathname);
24
25
        $this->assertTrue($file->isFile());
26
27
        @unlink($pathname);
28
    }
29
30
31
    public function testGif()
32
    {
33
        $pathname = TEST_PATH . 'tmp/flip.gif';
34
        $image    = Image::open($this->getGif());
35
        $image->flip(Image::FLIP_Y)->save($pathname);
36
37
        $file = new \SplFileInfo($pathname);
38
39
        $this->assertTrue($file->isFile());
40
41
        @unlink($pathname);
42
    }
43
}

+ 60 - 0
vendor/topthink/think-image/tests/InfoTest.php

@ -0,0 +1,60 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
namespace tests;
12
13
use think\Image;
14
15
class InfoTest extends TestCase
16
{
17
18
    public function testOpen()
19
    {
20
        $this->setExpectedException("\\think\\image\\Exception");
21
        Image::open('');
22
    }
23
24
    public function testIllegal()
25
    {
26
        $this->setExpectedException("\\think\\image\\Exception", 'Illegal image file');
27
        Image::open(TEST_PATH . 'images/test.bmp');
28
    }
29
30
    public function testJpeg()
31
    {
32
        $image = Image::open($this->getJpeg());
33
        $this->assertEquals(800, $image->width());
34
        $this->assertEquals(600, $image->height());
35
        $this->assertEquals('jpeg', $image->type());
36
        $this->assertEquals('image/jpeg', $image->mime());
37
        $this->assertEquals([800, 600], $image->size());
38
    }
39
40
41
    public function testPng()
42
    {
43
        $image = Image::open($this->getPng());
44
        $this->assertEquals(800, $image->width());
45
        $this->assertEquals(600, $image->height());
46
        $this->assertEquals('png', $image->type());
47
        $this->assertEquals('image/png', $image->mime());
48
        $this->assertEquals([800, 600], $image->size());
49
    }
50
51
    public function testGif()
52
    {
53
        $image = Image::open($this->getGif());
54
        $this->assertEquals(380, $image->width());
55
        $this->assertEquals(216, $image->height());
56
        $this->assertEquals('gif', $image->type());
57
        $this->assertEquals('image/gif', $image->mime());
58
        $this->assertEquals([380, 216], $image->size());
59
    }
60
}

+ 42 - 0
vendor/topthink/think-image/tests/RotateTest.php

@ -0,0 +1,42 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
namespace tests;
12
13
use think\Image;
14
15
class RotateTest extends TestCase
16
{
17
    public function testJpeg()
18
    {
19
        $pathname = TEST_PATH . 'tmp/rotate.jpg';
20
        $image    = Image::open($this->getJpeg());
21
        $image->rotate(90)->save($pathname);
22
23
        $file = new \SplFileInfo($pathname);
24
25
        $this->assertTrue($file->isFile());
26
27
        @unlink($pathname);
28
    }
29
30
    public function testGif()
31
    {
32
        $pathname = TEST_PATH . 'tmp/rotate.gif';
33
        $image    = Image::open($this->getGif());
34
        $image->rotate(90)->save($pathname);
35
36
        $file = new \SplFileInfo($pathname);
37
38
        $this->assertTrue($file->isFile());
39
40
        @unlink($pathname);
41
    }
42
}

+ 33 - 0
vendor/topthink/think-image/tests/TestCase.php

@ -0,0 +1,33 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
12
namespace tests;
13
14
use think\File;
15
16
abstract class TestCase extends \PHPUnit_Framework_TestCase
17
{
18
19
    protected function getJpeg()
20
    {
21
        return new File(TEST_PATH . 'images/test.jpg');
22
    }
23
24
    protected function getPng()
25
    {
26
        return new File(TEST_PATH . 'images/test.png');
27
    }
28
29
    protected function getGif()
30
    {
31
        return new File(TEST_PATH . 'images/test.gif');
32
    }
33
}

+ 58 - 0
vendor/topthink/think-image/tests/TextTest.php

@ -0,0 +1,58 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
namespace tests;
12
13
use think\Image;
14
15
class TextTest extends TestCase
16
{
17
    public function testJpeg()
18
    {
19
        $pathname = TEST_PATH . 'tmp/text.jpg';
20
        $image    = Image::open($this->getJpeg());
21
22
        $image->text('test', TEST_PATH . 'images/test.ttf', 12)->save($pathname);
23
24
        $file = new \SplFileInfo($pathname);
25
26
        $this->assertTrue($file->isFile());
27
28
        @unlink($pathname);
29
    }
30
31
    public function testPng()
32
    {
33
        $pathname = TEST_PATH . 'tmp/text.png';
34
        $image    = Image::open($this->getPng());
35
36
        $image->text('test', TEST_PATH . 'images/test.ttf', 12)->save($pathname);
37
38
        $file = new \SplFileInfo($pathname);
39
40
        $this->assertTrue($file->isFile());
41
42
        @unlink($pathname);
43
    }
44
45
    public function testGif()
46
    {
47
        $pathname = TEST_PATH . 'tmp/text.gif';
48
        $image    = Image::open($this->getGif());
49
50
        $image->text('test', TEST_PATH . 'images/test.ttf', 12)->save($pathname);
51
52
        $file = new \SplFileInfo($pathname);
53
54
        $this->assertTrue($file->isFile());
55
56
        @unlink($pathname);
57
    }
58
}

+ 284 - 0
vendor/topthink/think-image/tests/ThumbTest.php

@ -0,0 +1,284 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
namespace tests;
12
13
use think\Image;
14
15
class ThumbTest extends TestCase
16
{
17
    public function testJpeg()
18
    {
19
        $pathname = TEST_PATH . 'tmp/thumb.jpg';
20
        
21
        //1
22
        $image    = Image::open($this->getJpeg());
23
24
        $image->thumb(200, 200, Image::THUMB_CENTER)->save($pathname);
25
26
        $this->assertEquals(200, $image->width());
27
        $this->assertEquals(200, $image->height());
28
29
        $file = new \SplFileInfo($pathname);
30
31
        $this->assertTrue($file->isFile());
32
33
        @unlink($pathname);
34
35
        //2
36
        $image    = Image::open($this->getJpeg());
37
38
        $image->thumb(200, 200, Image::THUMB_SCALING)->save($pathname);
39
40
        $this->assertEquals(200, $image->width());
41
        $this->assertEquals(150, $image->height());
42
43
        $file = new \SplFileInfo($pathname);
44
45
        $this->assertTrue($file->isFile());
46
47
        @unlink($pathname);
48
49
        //3
50
        $image    = Image::open($this->getJpeg());
51
52
        $image->thumb(200, 200, Image::THUMB_FILLED)->save($pathname);
53
54
        $this->assertEquals(200, $image->width());
55
        $this->assertEquals(200, $image->height());
56
57
        $file = new \SplFileInfo($pathname);
58
59
        $this->assertTrue($file->isFile());
60
61
        @unlink($pathname);
62
63
        //4
64
        $image    = Image::open($this->getJpeg());
65
66
        $image->thumb(200, 200, Image::THUMB_NORTHWEST)->save($pathname);
67
68
        $this->assertEquals(200, $image->width());
69
        $this->assertEquals(200, $image->height());
70
71
        $file = new \SplFileInfo($pathname);
72
73
        $this->assertTrue($file->isFile());
74
75
        @unlink($pathname);
76
77
        //5
78
        $image    = Image::open($this->getJpeg());
79
80
        $image->thumb(200, 200, Image::THUMB_SOUTHEAST)->save($pathname);
81
82
        $this->assertEquals(200, $image->width());
83
        $this->assertEquals(200, $image->height());
84
85
        $file = new \SplFileInfo($pathname);
86
87
        $this->assertTrue($file->isFile());
88
89
        @unlink($pathname);
90
91
        //6
92
        $image    = Image::open($this->getJpeg());
93
94
        $image->thumb(200, 200, Image::THUMB_FIXED)->save($pathname);
95
96
        $this->assertEquals(200, $image->width());
97
        $this->assertEquals(200, $image->height());
98
99
        $file = new \SplFileInfo($pathname);
100
101
        $this->assertTrue($file->isFile());
102
103
        @unlink($pathname);
104
    }
105
106
107
    public function testPng()
108
    {
109
        $pathname = TEST_PATH . 'tmp/thumb.png';
110
111
        //1
112
        $image    = Image::open($this->getPng());
113
114
        $image->thumb(200, 200, Image::THUMB_CENTER)->save($pathname);
115
116
        $this->assertEquals(200, $image->width());
117
        $this->assertEquals(200, $image->height());
118
119
        $file = new \SplFileInfo($pathname);
120
121
        $this->assertTrue($file->isFile());
122
123
        @unlink($pathname);
124
125
        //2
126
        $image    = Image::open($this->getPng());
127
128
        $image->thumb(200, 200, Image::THUMB_SCALING)->save($pathname);
129
130
        $this->assertEquals(200, $image->width());
131
        $this->assertEquals(150, $image->height());
132
133
        $file = new \SplFileInfo($pathname);
134
135
        $this->assertTrue($file->isFile());
136
137
        @unlink($pathname);
138
139
        //3
140
        $image    = Image::open($this->getPng());
141
142
        $image->thumb(200, 200, Image::THUMB_FILLED)->save($pathname);
143
144
        $this->assertEquals(200, $image->width());
145
        $this->assertEquals(200, $image->height());
146
147
        $file = new \SplFileInfo($pathname);
148
149
        $this->assertTrue($file->isFile());
150
151
        @unlink($pathname);
152
153
        //4
154
        $image    = Image::open($this->getPng());
155
156
        $image->thumb(200, 200, Image::THUMB_NORTHWEST)->save($pathname);
157
158
        $this->assertEquals(200, $image->width());
159
        $this->assertEquals(200, $image->height());
160
161
        $file = new \SplFileInfo($pathname);
162
163
        $this->assertTrue($file->isFile());
164
165
        @unlink($pathname);
166
167
        //5
168
        $image    = Image::open($this->getPng());
169
170
        $image->thumb(200, 200, Image::THUMB_SOUTHEAST)->save($pathname);
171
172
        $this->assertEquals(200, $image->width());
173
        $this->assertEquals(200, $image->height());
174
175
        $file = new \SplFileInfo($pathname);
176
177
        $this->assertTrue($file->isFile());
178
179
        @unlink($pathname);
180
181
        //6
182
        $image    = Image::open($this->getPng());
183
184
        $image->thumb(200, 200, Image::THUMB_FIXED)->save($pathname);
185
186
        $this->assertEquals(200, $image->width());
187
        $this->assertEquals(200, $image->height());
188
189
        $file = new \SplFileInfo($pathname);
190
191
        $this->assertTrue($file->isFile());
192
193
        @unlink($pathname);
194
    }
195
196
    public function testGif()
197
    {
198
        $pathname = TEST_PATH . 'tmp/thumb.gif';
199
200
        //1
201
        $image    = Image::open($this->getGif());
202
203
        $image->thumb(200, 200, Image::THUMB_CENTER)->save($pathname);
204
205
        $this->assertEquals(200, $image->width());
206
        $this->assertEquals(200, $image->height());
207
208
        $file = new \SplFileInfo($pathname);
209
210
        $this->assertTrue($file->isFile());
211
212
        @unlink($pathname);
213
214
        //2
215
        $image    = Image::open($this->getGif());
216
217
        $image->thumb(200, 200, Image::THUMB_SCALING)->save($pathname);
218
219
        $this->assertEquals(200, $image->width());
220
        $this->assertEquals(113, $image->height());
221
222
        $file = new \SplFileInfo($pathname);
223
224
        $this->assertTrue($file->isFile());
225
226
        @unlink($pathname);
227
228
        //3
229
        $image    = Image::open($this->getGif());
230
231
        $image->thumb(200, 200, Image::THUMB_FILLED)->save($pathname);
232
233
        $this->assertEquals(200, $image->width());
234
        $this->assertEquals(200, $image->height());
235
236
        $file = new \SplFileInfo($pathname);
237
238
        $this->assertTrue($file->isFile());
239
240
        @unlink($pathname);
241
242
        //4
243
        $image    = Image::open($this->getGif());
244
245
        $image->thumb(200, 200, Image::THUMB_NORTHWEST)->save($pathname);
246
247
        $this->assertEquals(200, $image->width());
248
        $this->assertEquals(200, $image->height());
249
250
        $file = new \SplFileInfo($pathname);
251
252
        $this->assertTrue($file->isFile());
253
254
        @unlink($pathname);
255
256
        //5
257
        $image    = Image::open($this->getGif());
258
259
        $image->thumb(200, 200, Image::THUMB_SOUTHEAST)->save($pathname);
260
261
        $this->assertEquals(200, $image->width());
262
        $this->assertEquals(200, $image->height());
263
264
        $file = new \SplFileInfo($pathname);
265
266
        $this->assertTrue($file->isFile());
267
268
        @unlink($pathname);
269
270
        //6
271
        $image    = Image::open($this->getGif());
272
273
        $image->thumb(200, 200, Image::THUMB_FIXED)->save($pathname);
274
275
        $this->assertEquals(200, $image->width());
276
        $this->assertEquals(200, $image->height());
277
278
        $file = new \SplFileInfo($pathname);
279
280
        $this->assertTrue($file->isFile());
281
282
        @unlink($pathname);
283
    }
284
}

+ 58 - 0
vendor/topthink/think-image/tests/WaterTest.php

@ -0,0 +1,58 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
namespace tests;
12
13
use think\Image;
14
15
class WaterTest extends TestCase
16
{
17
    public function testJpeg()
18
    {
19
        $pathname = TEST_PATH . 'tmp/water.jpg';
20
        $image    = Image::open($this->getJpeg());
21
22
        $image->water(TEST_PATH . 'images/test.gif')->save($pathname);
23
24
        $file = new \SplFileInfo($pathname);
25
26
        $this->assertTrue($file->isFile());
27
28
        @unlink($pathname);
29
    }
30
31
    public function testPng()
32
    {
33
        $pathname = TEST_PATH . 'tmp/water.png';
34
        $image    = Image::open($this->getPng());
35
36
        $image->water(TEST_PATH . 'images/test.gif')->save($pathname);
37
38
        $file = new \SplFileInfo($pathname);
39
40
        $this->assertTrue($file->isFile());
41
42
        @unlink($pathname);
43
    }
44
45
    public function testGif()
46
    {
47
        $pathname = TEST_PATH . 'tmp/water.gif';
48
        $image    = Image::open($this->getGif());
49
50
        $image->water(TEST_PATH . 'images/test.jpg')->save($pathname);
51
52
        $file = new \SplFileInfo($pathname);
53
54
        $this->assertTrue($file->isFile());
55
56
        @unlink($pathname);
57
    }
58
}

+ 15 - 0
vendor/topthink/think-image/tests/autoload.php

@ -0,0 +1,15 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
define('TEST_PATH', __DIR__ . '/');
12
// 加载框架基础文件
13
require __DIR__ . '/../thinkphp/base.php';
14
\think\Loader::addNamespace('tests', TEST_PATH);
15
\think\Loader::addNamespace('think', __DIR__ . '/../src/');

+ 0 - 0
vendor/topthink/think-image/tests/images/test.bmp


BIN
vendor/topthink/think-image/tests/images/test.gif


BIN
vendor/topthink/think-image/tests/images/test.jpg


BIN
vendor/topthink/think-image/tests/images/test.png


BIN
vendor/topthink/think-image/tests/images/test.ttf


vendor/.gitignore → vendor/topthink/think-image/tests/tmp/.gitignore


+ 3 - 0
vendor/topthink/think-installer/.gitignore

@ -0,0 +1,3 @@
1
/.idea
2
composer.lock
3
/vendor

+ 25 - 0
vendor/topthink/think-installer/composer.json

@ -0,0 +1,25 @@
1
{
2
    "name": "topthink/think-installer",
3
    "type": "composer-plugin",
4
    "require": {
5
        "composer-plugin-api": "^1.0"
6
    },
7
    "require-dev": {
8
        "composer/composer": "1.0.*@dev"
9
    },
10
    "license": "Apache-2.0",
11
    "authors": [
12
        {
13
            "name": "yunwuxin",
14
            "email": "448901948@qq.com"
15
        }
16
    ],
17
    "autoload": {
18
        "psr-4": {
19
            "think\\composer\\": "src"
20
        }
21
    },
22
    "extra": {
23
        "class": "think\\composer\\Plugin"
24
    }
25
}

+ 26 - 0
vendor/topthink/think-installer/src/Plugin.php

@ -0,0 +1,26 @@
1
<?php
2
3
namespace think\composer;
4
5
use Composer\Composer;
6
use Composer\Installer;
7
use Composer\IO\IOInterface;
8
use Composer\Plugin\PluginInterface;
9
10
class Plugin implements PluginInterface
11
{
12
    public function activate(Composer $composer, IOInterface $io)
13
    {
14
        $manager = $composer->getInstallationManager();
15
16
        //框架核心
17
        $manager->addInstaller(new ThinkFramework($io, $composer));
18
19
        //单元测试
20
        $manager->addInstaller(new ThinkTesting($io, $composer));
21
22
        //扩展
23
        $manager->addInstaller(new ThinkExtend($io, $composer));
24
25
    }
26
}

+ 77 - 0
vendor/topthink/think-installer/src/ThinkExtend.php

@ -0,0 +1,77 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
12
namespace think\composer;
13
14
use Composer\Installer\LibraryInstaller;
15
use Composer\Package\PackageInterface;
16
use Composer\Repository\InstalledRepositoryInterface;
17
18
class ThinkExtend extends LibraryInstaller
19
{
20
21
    public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22
    {
23
        parent::install($repo, $package);
24
        $this->copyExtraFiles($package);
25
    }
26
27
    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
28
    {
29
        parent::update($repo, $initial, $target);
30
        $this->copyExtraFiles($target);
31
32
    }
33
34
    protected function copyExtraFiles(PackageInterface $package)
35
    {
36
        if ($this->composer->getPackage()->getType() == 'project') {
37
38
            $extra = $package->getExtra();
39
40
            if (!empty($extra['think-config'])) {
41
42
                $composerExtra = $this->composer->getPackage()->getExtra();
43
44
                $appDir = !empty($composerExtra['app-path']) ? $composerExtra['app-path'] : 'application';
45
46
                if (is_dir($appDir)) {
47
48
                    $extraDir = $appDir . DIRECTORY_SEPARATOR . 'extra';
49
                    $this->filesystem->ensureDirectoryExists($extraDir);
50
51
                    //配置文件
52
                    foreach ((array) $extra['think-config'] as $name => $config) {
53
                        $target = $extraDir . DIRECTORY_SEPARATOR . $name . '.php';
54
                        $source = $this->getInstallPath($package) . DIRECTORY_SEPARATOR . $config;
55
56
                        if (is_file($target)) {
57
                            $this->io->write("<info>File {$target} exist!</info>");
58
                            continue;
59
                        }
60
61
                        if (!is_file($source)) {
62
                            $this->io->write("<info>File {$target} not exist!</info>");
63
                            continue;
64
                        }
65
66
                        copy($source, $target);
67
                    }
68
                }
69
            }
70
        }
71
    }
72
73
    public function supports($packageType)
74
    {
75
        return 'think-extend' === $packageType;
76
    }
77
}

+ 59 - 0
vendor/topthink/think-installer/src/ThinkFramework.php

@ -0,0 +1,59 @@
1
<?php
2
3
namespace think\composer;
4
5
use Composer\Installer\LibraryInstaller;
6
use Composer\Package\PackageInterface;
7
use Composer\Repository\InstalledRepositoryInterface;
8
9
class ThinkFramework extends LibraryInstaller
10
{
11
    public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
12
    {
13
        parent::install($repo, $package);
14
        if ($this->composer->getPackage()->getType() == 'project' && $package->getInstallationSource() != 'source') {
15
            //remove tests dir
16
            $this->filesystem->removeDirectory($this->getInstallPath($package) . DIRECTORY_SEPARATOR . 'tests');
17
        }
18
    }
19
20
    /**
21
     * {@inheritDoc}
22
     */
23
    public function getInstallPath(PackageInterface $package)
24
    {
25
        if ('topthink/framework' !== $package->getPrettyName()) {
26
            throw new \InvalidArgumentException('Unable to install this library!');
27
        }
28
29
        if ($this->composer->getPackage()->getType() !== 'project') {
30
            return parent::getInstallPath($package);
31
        }
32
33
        if ($this->composer->getPackage()) {
34
            $extra = $this->composer->getPackage()->getExtra();
35
            if (!empty($extra['think-path'])) {
36
                return $extra['think-path'];
37
            }
38
        }
39
40
        return 'thinkphp';
41
    }
42
43
    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
44
    {
45
        parent::update($repo, $initial, $target);
46
        if ($this->composer->getPackage()->getType() == 'project' && $target->getInstallationSource() != 'source') {
47
            //remove tests dir
48
            $this->filesystem->removeDirectory($this->getInstallPath($target) . DIRECTORY_SEPARATOR . 'tests');
49
        }
50
    }
51
52
    /**
53
     * {@inheritDoc}
54
     */
55
    public function supports($packageType)
56
    {
57
        return 'think-framework' === $packageType;
58
    }
59
}

+ 68 - 0
vendor/topthink/think-installer/src/ThinkTesting.php

@ -0,0 +1,68 @@
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <448901948@qq.com>
10
// +----------------------------------------------------------------------
11
12
namespace think\composer;
13
14
15
use Composer\Installer\LibraryInstaller;
16
use Composer\Package\PackageInterface;
17
use Composer\Repository\InstalledRepositoryInterface;
18
19
class ThinkTesting extends LibraryInstaller
20
{
21
    /**
22
     * {@inheritDoc}
23
     */
24
    public function getInstallPath(PackageInterface $package)
25
    {
26
        if ('topthink/think-testing' !== $package->getPrettyName()) {
27
            throw new \InvalidArgumentException('Unable to install this library!');
28
        }
29
30
        return parent::getInstallPath($package);
31
    }
32
33
    public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
34
    {
35
        parent::install($repo, $package);
36
37
        $this->copyTestDir($package);
38
39
40
    }
41
42
    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
43
    {
44
        parent::update($repo, $initial, $target);
45
46
        $this->copyTestDir($target);
47
48
    }
49
50
    private function copyTestDir(PackageInterface $package)
51
    {
52
        $appDir = dirname($this->vendorDir);
53
        $source = $this->getInstallPath($package) . DIRECTORY_SEPARATOR . 'example';
54
        if (!is_file($appDir . DIRECTORY_SEPARATOR . 'phpunit.xml')) {
55
            $this->filesystem->copyThenRemove($source, $appDir);
56
        } else {
57
            $this->filesystem->removeDirectoryPhp($source);
58
        }
59
    }
60
61
    /**
62
     * {@inheritDoc}
63
     */
64
    public function supports($packageType)
65
    {
66
        return 'think-testing' === $packageType;
67
    }
68
}