From 899ec8a657e3ec657ac38f4ffddd27a3cdfe8bfb Mon Sep 17 00:00:00 2001 From: sunhater <sunhater@sunhater.com> Date: Wed, 12 Mar 2014 00:33:27 +0200 Subject: [PATCH] 2.54 Performance fix --- browse.php | 2 +- config.php | 2 +- core/autoload.php | 2 +- core/browser.php | 29 +++-- core/types/type_img.php | 2 +- core/types/type_mime.php | 2 +- core/uploader.php | 4 +- css.php | 2 +- doc/README | 2 +- integration/drupal.php | 2 +- js/browser/0bject.js | 2 +- js/browser/clipboard.js | 2 +- js/browser/dropUpload.js | 2 +- js/browser/files.js | 2 +- js/browser/folders.js | 2 +- js/browser/init.js | 2 +- js/browser/joiner.php | 2 +- js/browser/misc.js | 2 +- js/browser/settings.js | 2 +- js/browser/toolbar.js | 2 +- js/helper.js | 2 +- js_localize.php | 2 +- lang/en.php | 2 +- lib/class_fastImage.php | 240 ++++++++++++++++++++++++++++++++++++ lib/class_image.php | 2 +- lib/class_image_gd.php | 2 +- lib/class_image_gmagick.php | 2 +- lib/class_image_imagick.php | 2 +- lib/class_input.php | 2 +- lib/class_zipFolder.php | 2 +- lib/helper_dir.php | 2 +- lib/helper_file.php | 2 +- lib/helper_httpCache.php | 2 +- lib/helper_path.php | 2 +- lib/helper_text.php | 2 +- themes/oxygen/about.txt | 2 +- upload.php | 2 +- 37 files changed, 295 insertions(+), 46 deletions(-) create mode 100644 lib/class_fastImage.php diff --git a/browse.php b/browse.php index e15b228..f28eada 100644 --- a/browse.php +++ b/browse.php @@ -4,7 +4,7 @@ * * @desc Browser calling script * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/config.php b/config.php index d3048d8..fbe9cd1 100644 --- a/config.php +++ b/config.php @@ -4,7 +4,7 @@ * * @desc Base configuration file * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/core/autoload.php b/core/autoload.php index 550367f..23d0a8a 100644 --- a/core/autoload.php +++ b/core/autoload.php @@ -4,7 +4,7 @@ * * @desc This file is included first, before each other * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/core/browser.php b/core/browser.php index 553d5ed..4a5115d 100644 --- a/core/browser.php +++ b/core/browser.php @@ -4,7 +4,7 @@ * * @desc Browser actions class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 @@ -708,18 +708,27 @@ protected function getFiles($dir) { return $return; foreach ($files as $file) { - $size = @getimagesize($file); - if (is_array($size) && count($size)) { - $thumb_file = "$thumbDir/" . basename($file); - if (!is_file($thumb_file)) - $this->makeThumb($file, false); - $smallThumb = - ($size[0] <= $this->config['thumbWidth']) && - ($size[1] <= $this->config['thumbHeight']) && - in_array($size[2], array(IMAGETYPE_GIF, IMAGETYPE_PNG, IMAGETYPE_JPEG)); + $img = new fastImage($file); + $type = $img->getType(); + + if ($type !== false) { + $size = $img->getSize($file); + + if (is_array($size) && count($size)) { + $thumb_file = "$thumbDir/" . basename($file); + if (!is_file($thumb_file)) + $this->makeThumb($file, false); + $smallThumb = + ($size[0] <= $this->config['thumbWidth']) && + ($size[1] <= $this->config['thumbHeight']) && + in_array($type, array("gif", "jpeg", "png")); + } else + $smallThumb = false; } else $smallThumb = false; + $img->close(); + $stat = stat($file); if ($stat === false) continue; $name = basename($file); diff --git a/core/types/type_img.php b/core/types/type_img.php index cbdb651..c788cfd 100644 --- a/core/types/type_img.php +++ b/core/types/type_img.php @@ -4,7 +4,7 @@ * * @desc Image detection class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/core/types/type_mime.php b/core/types/type_mime.php index 1484031..bf22d4f 100644 --- a/core/types/type_mime.php +++ b/core/types/type_mime.php @@ -4,7 +4,7 @@ * * @desc MIME type detection class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/core/uploader.php b/core/uploader.php index c45d915..1b9f298 100644 --- a/core/uploader.php +++ b/core/uploader.php @@ -4,7 +4,7 @@ * * @desc Uploader class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 @@ -15,7 +15,7 @@ class uploader { /** Release version */ - const VERSION = "2.53"; + const VERSION = "2.54"; /** Config session-overrided settings * @var array */ diff --git a/css.php b/css.php index 4df71ba..c9a8790 100644 --- a/css.php +++ b/css.php @@ -4,7 +4,7 @@ * * @desc Base CSS definitions * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/doc/README b/doc/README index 556da26..0fed9b4 100644 --- a/doc/README +++ b/doc/README @@ -1,4 +1,4 @@ -[===========================< KCFinder 2.53 >================================] +[===========================< KCFinder 2.54 >================================] [ ] [ Copyright 2010-2014 KCFinder Project ] [ http://kcfinder.sunhater.com ] diff --git a/integration/drupal.php b/integration/drupal.php index 7f80a09..d1ade09 100644 --- a/integration/drupal.php +++ b/integration/drupal.php @@ -4,7 +4,7 @@ * * @desc CMS integration code: Drupal * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Dany Alejandro Cabrera <otello2040@gmail.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/browser/0bject.js b/js/browser/0bject.js index b66e244..29d21ad 100644 --- a/js/browser/0bject.js +++ b/js/browser/0bject.js @@ -4,7 +4,7 @@ * * @desc Base JavaScript object properties * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/browser/clipboard.js b/js/browser/clipboard.js index 20491c6..0382d79 100644 --- a/js/browser/clipboard.js +++ b/js/browser/clipboard.js @@ -4,7 +4,7 @@ * * @desc Clipboard functionality * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/browser/dropUpload.js b/js/browser/dropUpload.js index b6847cd..c8d5adc 100644 --- a/js/browser/dropUpload.js +++ b/js/browser/dropUpload.js @@ -4,7 +4,7 @@ * * @desc Upload files using drag and drop * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Forum user (updated by Pavel Tzonkov) * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/browser/files.js b/js/browser/files.js index 318fa2d..1128f4d 100644 --- a/js/browser/files.js +++ b/js/browser/files.js @@ -4,7 +4,7 @@ * * @desc File related functionality * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/browser/folders.js b/js/browser/folders.js index 299fbfc..335733e 100644 --- a/js/browser/folders.js +++ b/js/browser/folders.js @@ -4,7 +4,7 @@ * * @desc Folder related functionality * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/browser/init.js b/js/browser/init.js index 76cc67d..2a9c21b 100644 --- a/js/browser/init.js +++ b/js/browser/init.js @@ -4,7 +4,7 @@ * * @desc Object initializations * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/browser/joiner.php b/js/browser/joiner.php index 3006f8a..805fff1 100644 --- a/js/browser/joiner.php +++ b/js/browser/joiner.php @@ -4,7 +4,7 @@ * * @desc Join all JavaScript files in current directory * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/browser/misc.js b/js/browser/misc.js index 18d0848..a6e60e5 100644 --- a/js/browser/misc.js +++ b/js/browser/misc.js @@ -4,7 +4,7 @@ * * @desc Miscellaneous functionality * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/browser/settings.js b/js/browser/settings.js index 94020d0..0d4bd3d 100644 --- a/js/browser/settings.js +++ b/js/browser/settings.js @@ -4,7 +4,7 @@ * * @desc Settings panel functionality * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/browser/toolbar.js b/js/browser/toolbar.js index 4051afd..8e3dc96 100644 --- a/js/browser/toolbar.js +++ b/js/browser/toolbar.js @@ -4,7 +4,7 @@ * * @desc Toolbar functionality * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js/helper.js b/js/helper.js index 78f254a..4e6f8ee 100644 --- a/js/helper.js +++ b/js/helper.js @@ -2,7 +2,7 @@ * * @desc Helper object * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/js_localize.php b/js_localize.php index edf294c..9e214de 100644 --- a/js_localize.php +++ b/js_localize.php @@ -4,7 +4,7 @@ * * @desc Load language labels into JavaScript * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lang/en.php b/lang/en.php index ab0b79f..ba12dcf 100644 --- a/lang/en.php +++ b/lang/en.php @@ -4,7 +4,7 @@ * * @desc Default English localization * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/class_fastImage.php b/lib/class_fastImage.php new file mode 100644 index 0000000..a42093a --- /dev/null +++ b/lib/class_fastImage.php @@ -0,0 +1,240 @@ +<?php + +/** + * FastImage - Because sometimes you just want the size! + * Based on the Ruby Implementation by Steven Sykes (https://github.com/sdsykes/fastimage) + * + * Copyright (c) 2012 Tom Moor + * Tom Moor, http://tommoor.com + * + * MIT Licensed + * @version 0.1 + */ + +class fastImage +{ + private $strpos = 0; + private $str; + private $uri; + private $type; + private $handle; + + public function __construct($uri = null) + { + if ($uri) $this->load($uri); + } + + + public function load($uri) + { + if ($this->handle) $this->close(); + + $this->uri = $uri; + $this->handle = fopen($uri, 'r'); + } + + + public function close() + { + if (is_resource($this->handle)) fclose($this->handle); + } + + + public function getSize() + { + $this->strpos = 0; + if ($this->getType()) + { + return array_values($this->parseSize()); + } + + return false; + } + + + public function getType() + { + $this->strpos = 0; + + if (!$this->type) + { + switch ($this->getChars(2)) + { + case "BM": + return $this->type = 'bmp'; + case "GI": + return $this->type = 'gif'; + case chr(0xFF).chr(0xd8): + return $this->type = 'jpeg'; + case chr(0x89).'P': + return $this->type = 'png'; + default: + return false; + } + } + + return $this->type; + } + + + private function parseSize() + { + $this->strpos = 0; + + switch ($this->type) + { + case 'png': + return $this->parseSizeForPNG(); + case 'gif': + return $this->parseSizeForGIF(); + case 'bmp': + return $this->parseSizeForBMP(); + case 'jpeg': + return $this->parseSizeForJPEG(); + } + + return null; + } + + + private function parseSizeForPNG() + { + $chars = $this->getChars(25); + + return unpack("N*", substr($chars, 16, 8)); + } + + + private function parseSizeForGIF() + { + $chars = $this->getChars(11); + + return unpack("S*", substr($chars, 6, 4)); + } + + + private function parseSizeForBMP() + { + $chars = $this->getChars(29); + $chars = substr($chars, 14, 14); + $type = unpack('C', $chars); + + return (reset($type) == 40) ? unpack('L*', substr($chars, 4)) : unpack('L*', substr($chars, 4, 8)); + } + + + private function parseSizeForJPEG() + { + $state = null; + $i = 0; + + while (true) + { + switch ($state) + { + default: + $this->getChars(2); + $state = 'started'; + break; + + case 'started': + $b = $this->getByte(); + if ($b === false) return false; + + $state = $b == 0xFF ? 'sof' : 'started'; + break; + + case 'sof': + $b = $this->getByte(); + if (in_array($b, range(0xe0, 0xef))) + { + $state = 'skipframe'; + } + elseif (in_array($b, array_merge(range(0xC0,0xC3), range(0xC5,0xC7), range(0xC9,0xCB), range(0xCD,0xCF)))) + { + $state = 'readsize'; + } + elseif ($b == 0xFF) + { + $state = 'sof'; + } + else + { + $state = 'skipframe'; + } + break; + + case 'skipframe': + $skip = $this->readInt($this->getChars(2)) - 2; + $state = 'doskip'; + break; + + case 'doskip': + $this->getChars($skip); + $state = 'started'; + break; + + case 'readsize': + $c = $this->getChars(7); + + return array($this->readInt(substr($c, 5, 2)), $this->readInt(substr($c, 3, 2))); + } + } + } + + + private function getChars($n) + { + $response = null; + + // do we need more data? + if ($this->strpos + $n -1 >= strlen($this->str)) + { + $end = ($this->strpos + $n); + + while (strlen($this->str) < $end && $response !== false) + { + // read more from the file handle + $need = $end - ftell($this->handle); + + if ($response = fread($this->handle, $need)) + { + $this->str .= $response; + } + else + { + return false; + } + } + } + + $result = substr($this->str, $this->strpos, $n); + $this->strpos += $n; + + // we are dealing with bytes here, so force the encoding + return mb_convert_encoding($result, "8BIT"); + } + + + private function getByte() + { + $c = $this->getChars(1); + $b = unpack("C", $c); + + return reset($b); + } + + + private function readInt($str) + { + $size = unpack("C*", $str); + + return ($size[1] << 8) + $size[2]; + } + + + public function __destruct() + { + $this->close(); + } +} \ No newline at end of file diff --git a/lib/class_image.php b/lib/class_image.php index 75929c7..b270eab 100644 --- a/lib/class_image.php +++ b/lib/class_image.php @@ -4,7 +4,7 @@ * * @desc Abstract image driver class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/class_image_gd.php b/lib/class_image_gd.php index 6a88ff8..daf8f3f 100644 --- a/lib/class_image_gd.php +++ b/lib/class_image_gd.php @@ -4,7 +4,7 @@ * * @desc GD image driver class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/class_image_gmagick.php b/lib/class_image_gmagick.php index 13c6cce..a53b528 100644 --- a/lib/class_image_gmagick.php +++ b/lib/class_image_gmagick.php @@ -4,7 +4,7 @@ * * @desc GraphicsMagick image driver class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/class_image_imagick.php b/lib/class_image_imagick.php index 0cf02a7..4f4d7b8 100644 --- a/lib/class_image_imagick.php +++ b/lib/class_image_imagick.php @@ -4,7 +4,7 @@ * * @desc ImageMagick image driver class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/class_input.php b/lib/class_input.php index d418f31..40879c2 100644 --- a/lib/class_input.php +++ b/lib/class_input.php @@ -4,7 +4,7 @@ * * @desc Input class for GET, POST and COOKIE requests * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/class_zipFolder.php b/lib/class_zipFolder.php index fcf46f2..3885a9e 100644 --- a/lib/class_zipFolder.php +++ b/lib/class_zipFolder.php @@ -5,7 +5,7 @@ * * @desc Directory to ZIP file archivator * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/helper_dir.php b/lib/helper_dir.php index d9328e8..2ddfc54 100644 --- a/lib/helper_dir.php +++ b/lib/helper_dir.php @@ -4,7 +4,7 @@ * * @desc Directory helper class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/helper_file.php b/lib/helper_file.php index e1f860f..4221268 100644 --- a/lib/helper_file.php +++ b/lib/helper_file.php @@ -4,7 +4,7 @@ * * @desc File helper class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/helper_httpCache.php b/lib/helper_httpCache.php index ea785f9..e2c2c2c 100644 --- a/lib/helper_httpCache.php +++ b/lib/helper_httpCache.php @@ -4,7 +4,7 @@ * * @desc HTTP cache helper class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/helper_path.php b/lib/helper_path.php index 352cf25..20886ee 100644 --- a/lib/helper_path.php +++ b/lib/helper_path.php @@ -4,7 +4,7 @@ * * @desc Path helper class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/lib/helper_text.php b/lib/helper_text.php index 9c392cd..abd92d3 100644 --- a/lib/helper_text.php +++ b/lib/helper_text.php @@ -4,7 +4,7 @@ * * @desc Text processing helper class * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2 diff --git a/themes/oxygen/about.txt b/themes/oxygen/about.txt index 6e7a56a..ecebc5d 100644 --- a/themes/oxygen/about.txt +++ b/themes/oxygen/about.txt @@ -5,7 +5,7 @@ http://www.kde.org Theme Details: Project: KCFinder - http://kcfinder.sunhater.com -Version: 2.53 +Version: 2.54 Author: Pavel Tzonkov <sunhater@sunhater.com> Licenses: GPLv2 - http://www.opensource.org/licenses/gpl-2.0.php LGPLv2 - http://www.opensource.org/licenses/lgpl-2.1.php diff --git a/upload.php b/upload.php index 5eb1ab3..66b648c 100644 --- a/upload.php +++ b/upload.php @@ -4,7 +4,7 @@ * * @desc Upload calling script * @package KCFinder - * @version 2.53 + * @version 2.54 * @author Pavel Tzonkov <sunhater@sunhater.com> * @copyright 2010-2014 KCFinder Project * @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2