pax_global_header00006660000000000000000000000064122662050600014511gustar00rootroot0000000000000052 comment=4ada253e5b65e8b48392334dbab390dcf88c1712 spotweb-20130826+dfsg2/000077500000000000000000000000001226620506000144445ustar00rootroot00000000000000spotweb-20130826+dfsg2/.gitattributes000066400000000000000000000007441226620506000173440ustar00rootroot00000000000000# Auto detect text files and perform LF normalization #* text=auto # Custom for Visual Studio *.cs diff=csharp *.sln merge=union *.csproj merge=union *.vbproj merge=union *.fsproj merge=union *.dbproj merge=union # Standard to msysgit *.doc diff=astextplain *.DOC diff=astextplain *.docx diff=astextplain *.DOCX diff=astextplain *.dot diff=astextplain *.DOT diff=astextplain *.pdf diff=astextplain *.PDF diff=astextplain *.rtf diff=astextplain *.RTF diff=astextplain spotweb-20130826+dfsg2/.gitignore000066400000000000000000000003551226620506000164370ustar00rootroot00000000000000messages.ser nbproject nntpdb.sqlite3 nntpdb.sqlite3-journal ownsettings.php server-settings.php retrieve.sh tests/*.jpg tests/*.nzb .htaccess .htpasswd .buildpath .project .settings/ .DS_Store dbsettings.inc.php reallymyownsettings.php spotweb-20130826+dfsg2/Crypt/000077500000000000000000000000001226620506000155455ustar00rootroot00000000000000spotweb-20130826+dfsg2/Crypt/Hash.php000077500000000000000000000675601226620506000171620ustar00rootroot00000000000000 * setKey('abcdefg'); * * echo base64_encode($hash->hash('abcdefg')); * ?> * * * LICENSE: This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * @category Crypt * @package Crypt_Hash * @author Jim Wigginton * @copyright MMVII Jim Wigginton * @license http://www.gnu.org/licenses/lgpl.txt * @version $Id: Hash.php,v 1.6 2009/11/23 23:37:07 terrafrost Exp $ * @link http://phpseclib.sourceforge.net */ /**#@+ * @access private * @see Crypt_Hash::Crypt_Hash() */ /** * Toggles the internal implementation */ define('CRYPT_HASH_MODE_INTERNAL', 1); /** * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+. */ define('CRYPT_HASH_MODE_MHASH', 2); /** * Toggles the hash() implementation, which works on PHP 5.1.2+. */ define('CRYPT_HASH_MODE_HASH', 3); /**#@-*/ /** * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions. * * @author Jim Wigginton * @version 0.1.0 * @access public * @package Crypt_Hash */ class Crypt_Hash { /** * Byte-length of compression blocks / key (Internal HMAC) * * @see Crypt_Hash::setAlgorithm() * @var Integer * @access private */ var $b; /** * Byte-length of hash output (Internal HMAC) * * @see Crypt_Hash::setHash() * @var Integer * @access private */ var $l = false; /** * Hash Algorithm * * @see Crypt_Hash::setHash() * @var String * @access private */ var $hash; /** * Key * * @see Crypt_Hash::setKey() * @var String * @access private */ var $key = ''; /** * Outer XOR (Internal HMAC) * * @see Crypt_Hash::setKey() * @var String * @access private */ var $opad; /** * Inner XOR (Internal HMAC) * * @see Crypt_Hash::setKey() * @var String * @access private */ var $ipad; /** * Default Constructor. * * @param optional String $hash * @return Crypt_Hash * @access public */ function Crypt_Hash($hash = 'sha1') { if ( !defined('CRYPT_HASH_MODE') ) { switch (true) { case extension_loaded('hash'): define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH); break; case extension_loaded('mhash'): define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH); break; default: define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL); } } $this->setHash($hash); } /** * Sets the key for HMACs * * Keys can be of any length. * * @access public * @param String $key */ function setKey($key) { $this->key = $key; } /** * Sets the hash function. * * @access public * @param String $hash */ function setHash($hash) { switch ($hash) { case 'md5-96': case 'sha1-96': $this->l = 12; // 96 / 8 = 12 break; case 'md2': case 'md5': $this->l = 16; break; case 'sha1': $this->l = 20; break; case 'sha256': $this->l = 32; break; case 'sha384': $this->l = 48; break; case 'sha512': $this->l = 64; } switch ($hash) { case 'md2': $mode = CRYPT_HASH_MODE_INTERNAL; break; case 'sha384': case 'sha512': $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE; break; default: $mode = CRYPT_HASH_MODE; } switch ( $mode ) { case CRYPT_HASH_MODE_MHASH: switch ($hash) { case 'md5': case 'md5-96': $this->hash = MHASH_MD5; break; case 'sha256': $this->hash = MHASH_SHA256; break; case 'sha1': case 'sha1-96': default: $this->hash = MHASH_SHA1; } return; case CRYPT_HASH_MODE_HASH: switch ($hash) { case 'md5': case 'md5-96': $this->hash = 'md5'; return; case 'sha256': case 'sha384': case 'sha512': $this->hash = $hash; return; case 'sha1': case 'sha1-96': default: $this->hash = 'sha1'; } return; } switch ($hash) { case 'md2': $this->b = 16; $this->hash = array($this, '_md2'); break; case 'md5': case 'md5-96': $this->b = 64; $this->hash = array($this, '_md5'); break; case 'sha256': $this->b = 64; $this->hash = array($this, '_sha256'); break; case 'sha384': case 'sha512': $this->b = 128; $this->hash = array($this, '_sha512'); break; case 'sha1': case 'sha1-96': default: $this->b = 64; $this->hash = array($this, '_sha1'); } $this->ipad = str_repeat(chr(0x36), $this->b); $this->opad = str_repeat(chr(0x5C), $this->b); } /** * Compute the HMAC. * * @access public * @param String $text * @return String */ function hash($text) { $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE; if (!empty($this->key)) { switch ( $mode ) { case CRYPT_HASH_MODE_MHASH: $output = mhash($this->hash, $text, $this->key); break; case CRYPT_HASH_MODE_HASH: $output = hash_hmac($this->hash, $text, $this->key, true); break; case CRYPT_HASH_MODE_INTERNAL: /* "Applications that use keys longer than B bytes will first hash the key using H and then use the resultant L byte string as the actual key to HMAC." -- http://tools.ietf.org/html/rfc2104#section-2 */ $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key; $key = str_pad($key, $this->b, chr(0)); // step 1 $temp = $this->ipad ^ $key; // step 2 $temp .= $text; // step 3 $temp = call_user_func($this->hash, $temp); // step 4 $output = $this->opad ^ $key; // step 5 $output.= $temp; // step 6 $output = call_user_func($this->hash, $output); // step 7 } } else { switch ( $mode ) { case CRYPT_HASH_MODE_MHASH: $output = mhash($this->hash, $text); break; case CRYPT_HASH_MODE_HASH: $output = hash($this->hash, $text, true); break; case CRYPT_HASH_MODE_INTERNAL: $output = call_user_func($this->hash, $text); } } return substr($output, 0, $this->l); } /** * Returns the hash length (in bytes) * * @access private * @return Integer */ function getLength() { return $this->l; } /** * Wrapper for MD5 * * @access private * @param String $text */ function _md5($m) { return pack('H*', md5($m)); } /** * Wrapper for SHA1 * * @access private * @param String $text */ function _sha1($m) { return pack('H*', sha1($m)); } /** * Pure-PHP implementation of MD2 * * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}. * * @access private * @param String $text */ function _md2($m) { static $s = array( 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 ); // Step 1. Append Padding Bytes $pad = 16 - (strlen($m) & 0xF); $m.= str_repeat(chr($pad), $pad); $length = strlen($m); // Step 2. Append Checksum $c = str_repeat(chr(0), 16); $l = chr(0); for ($i = 0; $i < $length; $i+= 16) { for ($j = 0; $j < 16; $j++) { $c[$j] = chr($s[ord($m[$i + $j] ^ $l)]); $l = $c[$j]; } } $m.= $c; $length+= 16; // Step 3. Initialize MD Buffer $x = str_repeat(chr(0), 48); // Step 4. Process Message in 16-Byte Blocks for ($i = 0; $i < $length; $i+= 16) { for ($j = 0; $j < 16; $j++) { $x[$j + 16] = $m[$i + $j]; $x[$j + 32] = $x[$j + 16] ^ $x[$j]; } $t = chr(0); for ($j = 0; $j < 18; $j++) { for ($k = 0; $k < 48; $k++) { $x[$k] = $t = $x[$k] ^ chr($s[ord($t)]); //$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]); } $t = chr(ord($t) + $j); } } // Step 5. Output return substr($x, 0, 16); } /** * Pure-PHP implementation of SHA256 * * See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}. * * @access private * @param String $text */ function _sha256($m) { if (extension_loaded('suhosin')) { return pack('H*', sha256($m)); } // Initialize variables $hash = array( 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ); // Initialize table of round constants // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311) static $k = array( 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ); // Pre-processing $length = strlen($m); // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64 $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F)); $m[$length] = chr(0x80); // we don't support hashing strings 512MB long $m.= pack('N2', 0, $length << 3); // Process the message in successive 512-bit chunks $chunks = str_split($m, 64); foreach ($chunks as $chunk) { $w = array(); for ($i = 0; $i < 16; $i++) { extract(unpack('Ntemp', $this->_string_shift($chunk, 4))); $w[] = $temp; } // Extend the sixteen 32-bit words into sixty-four 32-bit words for ($i = 16; $i < 64; $i++) { $s0 = $this->_rightRotate($w[$i - 15], 7) ^ $this->_rightRotate($w[$i - 15], 18) ^ $this->_rightShift( $w[$i - 15], 3); $s1 = $this->_rightRotate($w[$i - 2], 17) ^ $this->_rightRotate($w[$i - 2], 19) ^ $this->_rightShift( $w[$i - 2], 10); $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1); } // Initialize hash value for this chunk list($a, $b, $c, $d, $e, $f, $g, $h) = $hash; // Main loop for ($i = 0; $i < 64; $i++) { $s0 = $this->_rightRotate($a, 2) ^ $this->_rightRotate($a, 13) ^ $this->_rightRotate($a, 22); $maj = ($a & $b) ^ ($a & $c) ^ ($b & $c); $t2 = $this->_add($s0, $maj); $s1 = $this->_rightRotate($e, 6) ^ $this->_rightRotate($e, 11) ^ $this->_rightRotate($e, 25); $ch = ($e & $f) ^ ($this->_not($e) & $g); $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]); $h = $g; $g = $f; $f = $e; $e = $this->_add($d, $t1); $d = $c; $c = $b; $b = $a; $a = $this->_add($t1, $t2); } // Add this chunk's hash to result so far $hash = array( $this->_add($hash[0], $a), $this->_add($hash[1], $b), $this->_add($hash[2], $c), $this->_add($hash[3], $d), $this->_add($hash[4], $e), $this->_add($hash[5], $f), $this->_add($hash[6], $g), $this->_add($hash[7], $h) ); } // Produce the final hash value (big-endian) return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]); } /** * Pure-PHP implementation of SHA384 and SHA512 * * @access private * @param String $text */ function _sha512($m) { if (!class_exists('Math_BigInteger')) { require_once('Math/BigInteger.php'); } static $init384, $init512, $k; if (!isset($k)) { // Initialize variables $init384 = array( // initial values for SHA384 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939', '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4' ); $init512 = array( // initial values for SHA512 '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1', '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179' ); for ($i = 0; $i < 8; $i++) { $init384[$i] = new Math_BigInteger($init384[$i], 16); $init384[$i]->setPrecision(64); $init512[$i] = new Math_BigInteger($init512[$i], 16); $init512[$i]->setPrecision(64); } // Initialize table of round constants // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409) $k = array( '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817' ); for ($i = 0; $i < 80; $i++) { $k[$i] = new Math_BigInteger($k[$i], 16); } } $hash = $this->l == 48 ? $init384 : $init512; // Pre-processing $length = strlen($m); // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128 $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F)); $m[$length] = chr(0x80); // we don't support hashing strings 512MB long $m.= pack('N4', 0, 0, 0, $length << 3); // Process the message in successive 1024-bit chunks $chunks = str_split($m, 128); foreach ($chunks as $chunk) { $w = array(); for ($i = 0; $i < 16; $i++) { $temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256); $temp->setPrecision(64); $w[] = $temp; } // Extend the sixteen 32-bit words into eighty 32-bit words for ($i = 16; $i < 80; $i++) { $temp = array( $w[$i - 15]->bitwise_rightRotate(1), $w[$i - 15]->bitwise_rightRotate(8), $w[$i - 15]->bitwise_rightShift(7) ); $s0 = $temp[0]->bitwise_xor($temp[1]); $s0 = $s0->bitwise_xor($temp[2]); $temp = array( $w[$i - 2]->bitwise_rightRotate(19), $w[$i - 2]->bitwise_rightRotate(61), $w[$i - 2]->bitwise_rightShift(6) ); $s1 = $temp[0]->bitwise_xor($temp[1]); $s1 = $s1->bitwise_xor($temp[2]); $w[$i] = $w[$i - 16]->copy(); $w[$i] = $w[$i]->add($s0); $w[$i] = $w[$i]->add($w[$i - 7]); $w[$i] = $w[$i]->add($s1); } // Initialize hash value for this chunk $a = $hash[0]->copy(); $b = $hash[1]->copy(); $c = $hash[2]->copy(); $d = $hash[3]->copy(); $e = $hash[4]->copy(); $f = $hash[5]->copy(); $g = $hash[6]->copy(); $h = $hash[7]->copy(); // Main loop for ($i = 0; $i < 80; $i++) { $temp = array( $a->bitwise_rightRotate(28), $a->bitwise_rightRotate(34), $a->bitwise_rightRotate(39) ); $s0 = $temp[0]->bitwise_xor($temp[1]); $s0 = $s0->bitwise_xor($temp[2]); $temp = array( $a->bitwise_and($b), $a->bitwise_and($c), $b->bitwise_and($c) ); $maj = $temp[0]->bitwise_xor($temp[1]); $maj = $maj->bitwise_xor($temp[2]); $t2 = $s0->add($maj); $temp = array( $e->bitwise_rightRotate(14), $e->bitwise_rightRotate(18), $e->bitwise_rightRotate(41) ); $s1 = $temp[0]->bitwise_xor($temp[1]); $s1 = $s1->bitwise_xor($temp[2]); $temp = array( $e->bitwise_and($f), $g->bitwise_and($e->bitwise_not()) ); $ch = $temp[0]->bitwise_xor($temp[1]); $t1 = $h->add($s1); $t1 = $t1->add($ch); $t1 = $t1->add($k[$i]); $t1 = $t1->add($w[$i]); $h = $g->copy(); $g = $f->copy(); $f = $e->copy(); $e = $d->add($t1); $d = $c->copy(); $c = $b->copy(); $b = $a->copy(); $a = $t1->add($t2); } // Add this chunk's hash to result so far $hash = array( $hash[0]->add($a), $hash[1]->add($b), $hash[2]->add($c), $hash[3]->add($d), $hash[4]->add($e), $hash[5]->add($f), $hash[6]->add($g), $hash[7]->add($h) ); } // Produce the final hash value (big-endian) // (Crypt_Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here) $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() . $hash[4]->toBytes() . $hash[5]->toBytes(); if ($this->l != 48) { $temp.= $hash[6]->toBytes() . $hash[7]->toBytes(); } return $temp; } /** * Right Rotate * * @access private * @param Integer $int * @param Integer $amt * @see _sha256() * @return Integer */ function _rightRotate($int, $amt) { $invamt = 32 - $amt; $mask = (1 << $invamt) - 1; return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask); } /** * Right Shift * * @access private * @param Integer $int * @param Integer $amt * @see _sha256() * @return Integer */ function _rightShift($int, $amt) { $mask = (1 << (32 - $amt)) - 1; return ($int >> $amt) & $mask; } /** * Not * * @access private * @param Integer $int * @see _sha256() * @return Integer */ function _not($int) { return ~$int & 0xFFFFFFFF; } /** * Add * * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the * possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster. * * @param String $string * @param optional Integer $index * @return String * @see _sha256() * @access private */ function _add() { static $mod; if (!isset($mod)) { $mod = pow(2, 32); } $result = 0; $arguments = func_get_args(); foreach ($arguments as $argument) { $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument; } return fmod($result, $mod); } /** * String Shift * * Inspired by array_shift * * @param String $string * @param optional Integer $index * @return String * @access private */ function _string_shift(&$string, $index = 1) { $substr = substr($string, 0, $index); $string = substr($string, $index); return $substr; } } spotweb-20130826+dfsg2/Crypt/RSA.php000077500000000000000000002142221226620506000167110ustar00rootroot00000000000000 * createKey()); * * $plaintext = 'terrafrost'; * * $rsa->loadKey($privatekey); * $ciphertext = $rsa->encrypt($plaintext); * * $rsa->loadKey($publickey); * echo $rsa->decrypt($ciphertext); * ?> * * * Here's an example of how to create signatures and verify signatures with this library: * * createKey()); * * $plaintext = 'terrafrost'; * * $rsa->loadKey($privatekey); * $signature = $rsa->sign($plaintext); * * $rsa->loadKey($publickey); * echo $rsa->verify($plaintext, $signature) ? 'verified' : 'unverified'; * ?> * * * LICENSE: This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * @category Crypt * @package Crypt_RSA * @author Jim Wigginton * @copyright MMIX Jim Wigginton * @license http://www.opensource.org/licenses/mit-license.html MIT License * @version $Id: RSA.php,v 1.19 2010/09/12 21:58:54 terrafrost Exp $ * @link http://phpseclib.sourceforge.net */ /** * Include Math_BigInteger */ require_once('Math/BigInteger.php'); /** * Include Crypt_Random */ require_once('Crypt/Random.php'); /** * Include Crypt_Hash */ require_once('Crypt/Hash.php'); /**#@+ * @access public * @see Crypt_RSA::encrypt() * @see Crypt_RSA::decrypt() */ /** * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding} * (OAEP) for encryption / decryption. * * Uses sha1 by default. * * @see Crypt_RSA::setHash() * @see Crypt_RSA::setMGFHash() */ define('CRYPT_RSA_ENCRYPTION_OAEP', 1); /** * Use PKCS#1 padding. * * Although CRYPT_RSA_ENCRYPTION_OAEP offers more security, including PKCS#1 padding is necessary for purposes of backwards * compatability with protocols (like SSH-1) written before OAEP's introduction. */ define('CRYPT_RSA_ENCRYPTION_PKCS1', 2); /**#@-*/ /**#@+ * @access public * @see Crypt_RSA::sign() * @see Crypt_RSA::verify() * @see Crypt_RSA::setHash() */ /** * Use the Probabilistic Signature Scheme for signing * * Uses sha1 by default. * * @see Crypt_RSA::setSaltLength() * @see Crypt_RSA::setMGFHash() */ define('CRYPT_RSA_SIGNATURE_PSS', 1); /** * Use the PKCS#1 scheme by default. * * Although CRYPT_RSA_SIGNATURE_PSS offers more security, including PKCS#1 signing is necessary for purposes of backwards * compatability with protocols (like SSH-2) written before PSS's introduction. */ define('CRYPT_RSA_SIGNATURE_PKCS1', 2); /**#@-*/ /**#@+ * @access private * @see Crypt_RSA::createKey() */ /** * ASN1 Integer */ define('CRYPT_RSA_ASN1_INTEGER', 2); /** * ASN1 Sequence (with the constucted bit set) */ define('CRYPT_RSA_ASN1_SEQUENCE', 48); /**#@-*/ /**#@+ * @access private * @see Crypt_RSA::Crypt_RSA() */ /** * To use the pure-PHP implementation */ define('CRYPT_RSA_MODE_INTERNAL', 1); /** * To use the OpenSSL library * * (if enabled; otherwise, the internal implementation will be used) */ define('CRYPT_RSA_MODE_OPENSSL', 2); /**#@-*/ /**#@+ * @access public * @see Crypt_RSA::createKey() * @see Crypt_RSA::setPrivateKeyFormat() */ /** * PKCS#1 formatted private key * * Used by OpenSSH */ define('CRYPT_RSA_PRIVATE_FORMAT_PKCS1', 0); /**#@-*/ /**#@+ * @access public * @see Crypt_RSA::createKey() * @see Crypt_RSA::setPublicKeyFormat() */ /** * Raw public key * * An array containing two Math_BigInteger objects. * * The exponent can be indexed with any of the following: * * 0, e, exponent, publicExponent * * The modulus can be indexed with any of the following: * * 1, n, modulo, modulus */ define('CRYPT_RSA_PUBLIC_FORMAT_RAW', 1); /** * PKCS#1 formatted public key */ define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 2); /** * OpenSSH formatted public key * * Place in $HOME/.ssh/authorized_keys */ define('CRYPT_RSA_PUBLIC_FORMAT_OPENSSH', 3); /**#@-*/ /** * Pure-PHP PKCS#1 compliant implementation of RSA. * * @author Jim Wigginton * @version 0.1.0 * @access public * @package Crypt_RSA */ class Crypt_RSA { /** * Precomputed Zero * * @var Array * @access private */ var $zero; /** * Precomputed One * * @var Array * @access private */ var $one; /** * Private Key Format * * @var Integer * @access private */ var $privateKeyFormat = CRYPT_RSA_PRIVATE_FORMAT_PKCS1; /** * Public Key Format * * @var Integer * @access public */ var $publicKeyFormat = CRYPT_RSA_PUBLIC_FORMAT_PKCS1; /** * Modulus (ie. n) * * @var Math_BigInteger * @access private */ var $modulus; /** * Modulus length * * @var Math_BigInteger * @access private */ var $k; /** * Exponent (ie. e or d) * * @var Math_BigInteger * @access private */ var $exponent; /** * Primes for Chinese Remainder Theorem (ie. p and q) * * @var Array * @access private */ var $primes; /** * Exponents for Chinese Remainder Theorem (ie. dP and dQ) * * @var Array * @access private */ var $exponents; /** * Coefficients for Chinese Remainder Theorem (ie. qInv) * * @var Array * @access private */ var $coefficients; /** * Hash name * * @var String * @access private */ var $hashName; /** * Hash function * * @var Crypt_Hash * @access private */ var $hash; /** * Length of hash function output * * @var Integer * @access private */ var $hLen; /** * Length of salt * * @var Integer * @access private */ var $sLen; /** * Hash function for the Mask Generation Function * * @var Crypt_Hash * @access private */ var $mgfHash; /** * Length of MGF hash function output * * @var Integer * @access private */ var $mgfHLen; /** * Encryption mode * * @var Integer * @access private */ var $encryptionMode = CRYPT_RSA_ENCRYPTION_OAEP; /** * Signature mode * * @var Integer * @access private */ var $signatureMode = CRYPT_RSA_SIGNATURE_PSS; /** * Public Exponent * * @var Mixed * @access private */ var $publicExponent = false; /** * Password * * @var String * @access private */ var $password = ''; /** * The constructor * * If you want to make use of the openssl extension, you'll need to set the mode manually, yourself. The reason * Crypt_RSA doesn't do it is because OpenSSL doesn't fail gracefully. openssl_pkey_new(), in particular, requires * openssl.cnf be present somewhere and, unfortunately, the only real way to find out is too late. * * @return Crypt_RSA * @access public */ function Crypt_RSA() { if ( !defined('CRYPT_RSA_MODE') ) { switch (true) { //case extension_loaded('openssl') && version_compare(PHP_VERSION, '4.2.0', '>='): // define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_OPENSSL); // break; default: define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL); } } $this->zero = new Math_BigInteger(); $this->one = new Math_BigInteger(1); $this->hash = new Crypt_Hash('sha1'); $this->hLen = $this->hash->getLength(); $this->hashName = 'sha1'; $this->mgfHash = new Crypt_Hash('sha1'); $this->mgfHLen = $this->mgfHash->getLength(); } /** * Create public / private key pair * * Returns an array with the following three elements: * - 'privatekey': The private key. * - 'publickey': The public key. * - 'partialkey': A partially computed key (if the execution time exceeded $timeout). * Will need to be passed back to Crypt_RSA::createKey() as the third parameter for further processing. * * @access public * @param optional Integer $bits * @param optional Integer $timeout * @param optional Math_BigInteger $p */ function createKey($bits = 1024, $timeout = false, $partial = array()) { if ( CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL ) { $rsa = openssl_pkey_new(array('private_key_bits' => $bits)); openssl_pkey_export($rsa, $privatekey); $publickey = openssl_pkey_get_details($rsa); $publickey = $publickey['key']; if ($this->privateKeyFormat != CRYPT_RSA_PRIVATE_FORMAT_PKCS1) { $privatekey = call_user_func_array(array($this, '_convertPrivateKey'), array_values($this->_parseKey($privatekey, CRYPT_RSA_PRIVATE_FORMAT_PKCS1))); $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, CRYPT_RSA_PUBLIC_FORMAT_PKCS1))); } return array( 'privatekey' => $privatekey, 'publickey' => $publickey, 'partialkey' => false ); } static $e; if (!isset($e)) { if (!defined('CRYPT_RSA_EXPONENT')) { // http://en.wikipedia.org/wiki/65537_%28number%29 define('CRYPT_RSA_EXPONENT', '65537'); } if (!defined('CRYPT_RSA_COMMENT')) { define('CRYPT_RSA_COMMENT', 'phpseclib-generated-key'); } // per , this number ought not result in primes smaller // than 256 bits. if (!defined('CRYPT_RSA_SMALLEST_PRIME')) { define('CRYPT_RSA_SMALLEST_PRIME', 4096); } $e = new Math_BigInteger(CRYPT_RSA_EXPONENT); } extract($this->_generateMinMax($bits)); $absoluteMin = $min; $temp = $bits >> 1; if ($temp > CRYPT_RSA_SMALLEST_PRIME) { $num_primes = floor($bits / CRYPT_RSA_SMALLEST_PRIME); $temp = CRYPT_RSA_SMALLEST_PRIME; } else { $num_primes = 2; } extract($this->_generateMinMax($temp + $bits % $temp)); $finalMax = $max; extract($this->_generateMinMax($temp)); $generator = new Math_BigInteger(); $generator->setRandomGenerator('crypt_random'); $n = $this->one->copy(); if (!empty($partial)) { extract(unserialize($partial)); } else { $exponents = $coefficients = $primes = array(); $lcm = array( 'top' => $this->one->copy(), 'bottom' => false ); } $start = time(); $i0 = count($primes) + 1; do { for ($i = $i0; $i <= $num_primes; $i++) { if ($timeout !== false) { $timeout-= time() - $start; $start = time(); if ($timeout <= 0) { return array( 'privatekey' => '', 'publickey' => '', 'partialkey' => serialize(array( 'primes' => $primes, 'coefficients' => $coefficients, 'lcm' => $lcm, 'exponents' => $exponents )) ); } } if ($i == $num_primes) { list($min, $temp) = $absoluteMin->divide($n); if (!$temp->equals($this->zero)) { $min = $min->add($this->one); // ie. ceil() } $primes[$i] = $generator->randomPrime($min, $finalMax, $timeout); } else { $primes[$i] = $generator->randomPrime($min, $max, $timeout); } if ($primes[$i] === false) { // if we've reached the timeout if (count($primes) > 1) { $partialkey = ''; } else { array_pop($primes); $partialkey = serialize(array( 'primes' => $primes, 'coefficients' => $coefficients, 'lcm' => $lcm, 'exponents' => $exponents )); } return array( 'privatekey' => '', 'publickey' => '', 'partialkey' => $partialkey ); } // the first coefficient is calculated differently from the rest // ie. instead of being $primes[1]->modInverse($primes[2]), it's $primes[2]->modInverse($primes[1]) if ($i > 2) { $coefficients[$i] = $n->modInverse($primes[$i]); } $n = $n->multiply($primes[$i]); $temp = $primes[$i]->subtract($this->one); // textbook RSA implementations use Euler's totient function instead of the least common multiple. // see http://en.wikipedia.org/wiki/Euler%27s_totient_function $lcm['top'] = $lcm['top']->multiply($temp); $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp); $exponents[$i] = $e->modInverse($temp); } list($lcm) = $lcm['top']->divide($lcm['bottom']); $gcd = $lcm->gcd($e); $i0 = 1; } while (!$gcd->equals($this->one)); $d = $e->modInverse($lcm); $coefficients[2] = $primes[2]->modInverse($primes[1]); // from : // RSAPrivateKey ::= SEQUENCE { // version Version, // modulus INTEGER, -- n // publicExponent INTEGER, -- e // privateExponent INTEGER, -- d // prime1 INTEGER, -- p // prime2 INTEGER, -- q // exponent1 INTEGER, -- d mod (p-1) // exponent2 INTEGER, -- d mod (q-1) // coefficient INTEGER, -- (inverse of q) mod p // otherPrimeInfos OtherPrimeInfos OPTIONAL // } return array( 'privatekey' => $this->_convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients), 'publickey' => $this->_convertPublicKey($n, $e), 'partialkey' => false ); } /** * Convert a private key to the appropriate format. * * @access private * @see setPrivateKeyFormat() * @param String $RSAPrivateKey * @return String */ function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients) { $num_primes = count($primes); $raw = array( 'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi 'modulus' => $n->toBytes(true), 'publicExponent' => $e->toBytes(true), 'privateExponent' => $d->toBytes(true), 'prime1' => $primes[1]->toBytes(true), 'prime2' => $primes[2]->toBytes(true), 'exponent1' => $exponents[1]->toBytes(true), 'exponent2' => $exponents[2]->toBytes(true), 'coefficient' => $coefficients[2]->toBytes(true) ); // if the format in question does not support multi-prime rsa and multi-prime rsa was used, // call _convertPublicKey() instead. switch ($this->privateKeyFormat) { default: // eg. CRYPT_RSA_PRIVATE_FORMAT_PKCS1 $components = array(); foreach ($raw as $name => $value) { $components[$name] = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($value)), $value); } $RSAPrivateKey = implode('', $components); if ($num_primes > 2) { $OtherPrimeInfos = ''; for ($i = 3; $i <= $num_primes; $i++) { // OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo // // OtherPrimeInfo ::= SEQUENCE { // prime INTEGER, -- ri // exponent INTEGER, -- di // coefficient INTEGER -- ti // } $OtherPrimeInfo = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true)); $OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true)); $OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true)); $OtherPrimeInfos.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo); } $RSAPrivateKey.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos); } $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); if (!empty($this->password)) { $iv = $this->_random(8); $symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key $symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8); if (!class_exists('Crypt_TripleDES')) { require_once('Crypt/TripleDES.php'); } $des = new Crypt_TripleDES(); $des->setKey($symkey); $des->setIV($iv); $iv = strtoupper(bin2hex($iv)); $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" . "Proc-Type: 4,ENCRYPTED\r\n" . "DEK-Info: DES-EDE3-CBC,$iv\r\n" . "\r\n" . chunk_split(base64_encode($des->encrypt($RSAPrivateKey))) . '-----END RSA PRIVATE KEY-----'; } else { $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" . chunk_split(base64_encode($RSAPrivateKey)) . '-----END RSA PRIVATE KEY-----'; } return $RSAPrivateKey; } } /** * Convert a public key to the appropriate format * * @access private * @see setPublicKeyFormat() * @param String $RSAPrivateKey * @return String */ function _convertPublicKey($n, $e) { $modulus = $n->toBytes(true); $publicExponent = $e->toBytes(true); switch ($this->publicKeyFormat) { case CRYPT_RSA_PUBLIC_FORMAT_RAW: return array('e' => $e->copy(), 'n' => $n->copy()); case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH: // from : // string "ssh-rsa" // mpint e // mpint n $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus); $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . CRYPT_RSA_COMMENT; return $RSAPublicKey; default: // eg. CRYPT_RSA_PUBLIC_FORMAT_PKCS1 // from : // RSAPublicKey ::= SEQUENCE { // modulus INTEGER, -- n // publicExponent INTEGER -- e // } $components = array( 'modulus' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($modulus)), $modulus), 'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent) ); $RSAPublicKey = pack('Ca*a*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), $components['modulus'], $components['publicExponent'] ); $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($RSAPublicKey)) . '-----END PUBLIC KEY-----'; return $RSAPublicKey; } } /** * Break a public or private key down into its constituant components * * @access private * @see _convertPublicKey() * @see _convertPrivateKey() * @param String $key * @param Integer $type * @return Array */ function _parseKey($key, $type) { switch ($type) { case CRYPT_RSA_PUBLIC_FORMAT_RAW: if (!is_array($key)) { return false; } $components = array(); switch (true) { case isset($key['e']): $components['publicExponent'] = $key['e']->copy(); break; case isset($key['exponent']): $components['publicExponent'] = $key['exponent']->copy(); break; case isset($key['publicExponent']): $components['publicExponent'] = $key['publicExponent']->copy(); break; case isset($key[0]): $components['publicExponent'] = $key[0]->copy(); } switch (true) { case isset($key['n']): $components['modulus'] = $key['n']->copy(); break; case isset($key['modulo']): $components['modulus'] = $key['modulo']->copy(); break; case isset($key['modulus']): $components['modulus'] = $key['modulus']->copy(); break; case isset($key[1]): $components['modulus'] = $key[1]->copy(); } return $components; case CRYPT_RSA_PRIVATE_FORMAT_PKCS1: case CRYPT_RSA_PUBLIC_FORMAT_PKCS1: /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is "outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here: http://tools.ietf.org/html/rfc1421#section-4.6.1.1 http://tools.ietf.org/html/rfc1421#section-4.6.1.3 DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell. DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's own implementation. ie. the implementation *is* the standard and any bugs that may exist in that implementation are part of the standard, as well. * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */ if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) { $iv = pack('H*', trim($matches[2])); $symkey = pack('H*', md5($this->password . substr($iv, 0, 8))); // symkey is short for symmetric key $symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8); $ciphertext = preg_replace('#.+(\r|\n|\r\n)\1|[\r\n]|-.+-#s', '', $key); $ciphertext = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $ciphertext) ? base64_decode($ciphertext) : false; if ($ciphertext === false) { $ciphertext = $key; } switch ($matches[1]) { case 'AES-128-CBC': if (!class_exists('Crypt_AES')) { require_once('Crypt/AES.php'); } $symkey = substr($symkey, 0, 16); break; case 'DES-EDE3-CFB': if (!class_exists('Crypt_TripleDES')) { require_once('Crypt/TripleDES.php'); } $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CFB); break; case 'DES-EDE3-CBC': if (!class_exists('Crypt_TripleDES')) { require_once('Crypt/TripleDES.php'); } $crypto = new Crypt_TripleDES(); break; case 'DES-CBC': if (!class_exists('Crypt_DES')) { require_once('Crypt/DES.php'); } $crypto = new Crypt_DES(); break; default: return false; } $crypto->setKey($symkey); $crypto->setIV($iv); $decoded = $crypto->decrypt($ciphertext); } else { $decoded = preg_replace('#-.+-|[\r\n]#', '', $key); $decoded = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $decoded) ? base64_decode($decoded) : false; } if ($decoded !== false) { $key = $decoded; } $components = array(); if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); if ($tag == CRYPT_RSA_ASN1_SEQUENCE) { /* intended for keys for which OpenSSL's asn1parse returns the following: 0:d=0 hl=4 l= 290 cons: SEQUENCE 4:d=1 hl=2 l= 13 cons: SEQUENCE 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption 17:d=2 hl=2 l= 0 prim: NULL 19:d=1 hl=4 l= 271 prim: BIT STRING */ $this->_string_shift($key, $this->_decodeLength($key)); $this->_string_shift($key); // skip over the BIT STRING tag $this->_decodeLength($key); // skip over the BIT STRING length // "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of // unused bits in teh final subsequent octet. The number shall be in the range zero to seven." // -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf (section 8.6.2.2) $this->_string_shift($key); if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); } if ($tag != CRYPT_RSA_ASN1_INTEGER) { return false; } /* We peek a little forwards, if an sequence follows the integer field, there is some additional padding we need to strip */ if (ord(substr($key, 2, 1)) == CRYPT_RSA_ASN1_SEQUENCE) { /* intended for keys for which openssl's asn1parse returns the following: 0:d=0 hl=4 l= 631 cons: SEQUENCE 4:d=1 hl=2 l= 1 prim: INTEGER :00 7:d=1 hl=2 l= 13 cons: SEQUENCE 9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption 20:d=2 hl=2 l= 0 prim: NULL 22:d=1 hl=4 l= 609 prim: OCTET STRING [HEX DUMP] */ $tag = ord($this->_string_shift($key, $this->_decodeLength($key))); /* Read the sequence with the object in it */ if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } /* skip over the rsaEncryption object and over the trailing NULL */ $encLength = $this->_decodeLength($key); $this->_string_shift($key, $encLength); if (ord($this->_string_shift($key)) != 4) { /* skip over the OCTET STRING tag */ return false; } # if $this->_decodeLength($key); // skip over the OCTET STRING length /* Inside this package we will find another ASN1 sequence and length, because at this time in the parser, it is expected to be beyond this, skip it */ $this->_string_shift($key); // skip over the sequence tag $this->_decodeLength($key); // skip over the sequence length $tag = ord($this->_string_shift($key)); } # if $length = $this->_decodeLength($key); $temp = $this->_string_shift($key, $length); if (strlen($temp) != 1 || ord($temp) > 2) { $components['modulus'] = new Math_BigInteger($temp, -256); $this->_string_shift($key); // skip over CRYPT_RSA_ASN1_INTEGER $length = $this->_decodeLength($key); $components[$type == CRYPT_RSA_PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256); return $components; } if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_INTEGER) { return false; } $length = $this->_decodeLength($key); $components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['publicExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), -256)); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['exponents'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), -256)); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($key, $length), -256)); if (!empty($key)) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } $this->_decodeLength($key); while (!empty($key)) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } $this->_decodeLength($key); $key = substr($key, 1); $length = $this->_decodeLength($key); $components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['coefficients'][] = new Math_BigInteger($this->_string_shift($key, $length), -256); } } return $components; case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH: $key = base64_decode(preg_replace('#^ssh-rsa | .+$#', '', $key)); if ($key === false) { return false; } $cleanup = substr($key, 0, 11) == "\0\0\0\7ssh-rsa"; extract(unpack('Nlength', $this->_string_shift($key, 4))); $publicExponent = new Math_BigInteger($this->_string_shift($key, $length), -256); extract(unpack('Nlength', $this->_string_shift($key, 4))); $modulus = new Math_BigInteger($this->_string_shift($key, $length), -256); if ($cleanup && strlen($key)) { extract(unpack('Nlength', $this->_string_shift($key, 4))); return array( 'modulus' => new Math_BigInteger($this->_string_shift($key, $length), -256), 'publicExponent' => $modulus ); } else { return array( 'modulus' => $modulus, 'publicExponent' => $publicExponent ); } } } /** * Loads a public or private key * * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed) * * @access public * @param String $key * @param Integer $type optional */ function loadKey($key, $type = CRYPT_RSA_PRIVATE_FORMAT_PKCS1) { $components = $this->_parseKey($key, $type); if ($components === false) { return false; } $this->modulus = $components['modulus']; $this->k = strlen($this->modulus->toBytes()); $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent']; if (isset($components['primes'])) { $this->primes = $components['primes']; $this->exponents = $components['exponents']; $this->coefficients = $components['coefficients']; $this->publicExponent = $components['publicExponent']; } else { $this->primes = array(); $this->exponents = array(); $this->coefficients = array(); $this->publicExponent = false; } return true; } /** * Sets the password * * Private keys can be encrypted with a password. To unset the password, pass in the empty string or false. * Or rather, pass in $password such that empty($password) is true. * * @see createKey() * @see loadKey() * @access public * @param String $password */ function setPassword($password) { $this->password = $password; } /** * Defines the public key * * Some private key formats define the public exponent and some don't. Those that don't define it are problematic when * used in certain contexts. For example, in SSH-2, RSA authentication works by sending the public key along with a * message signed by the private key to the server. The SSH-2 server looks the public key up in an index of public keys * and if it's present then proceeds to verify the signature. Problem is, if your private key doesn't include the public * exponent this won't work unless you manually add the public exponent. * * Do note that when a new key is loaded the index will be cleared. * * Returns true on success, false on failure * * @see getPublicKey() * @access public * @param String $key * @param Integer $type optional * @return Boolean */ function setPublicKey($key, $type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1) { $components = $this->_parseKey($key, $type); if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) { user_error('Trying to load a public key? Use loadKey() instead. It\'s called loadKey() and not loadPrivateKey() for a reason.', E_USER_NOTICE); return false; } $this->publicExponent = $components['publicExponent']; return true; } /** * Returns the public key * * The public key is only returned under two circumstances - if the private key had the public key embedded within it * or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this * function won't return it since this library, for the most part, doesn't distinguish between public and private keys. * * @see getPublicKey() * @access public * @param String $key * @param Integer $type optional */ function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1) { if (empty($this->modulus) || empty($this->publicExponent)) { return false; } $oldFormat = $this->publicKeyFormat; $this->publicKeyFormat = $type; $temp = $this->_convertPublicKey($this->modulus, $this->publicExponent); $this->publicKeyFormat = $oldFormat; return $temp; } /** * Generates the smallest and largest numbers requiring $bits bits * * @access private * @param Integer $bits * @return Array */ function _generateMinMax($bits) { $bytes = $bits >> 3; $min = str_repeat(chr(0), $bytes); $max = str_repeat(chr(0xFF), $bytes); $msb = $bits & 7; if ($msb) { $min = chr(1 << ($msb - 1)) . $min; $max = chr((1 << $msb) - 1) . $max; } else { $min[0] = chr(0x80); } return array( 'min' => new Math_BigInteger($min, 256), 'max' => new Math_BigInteger($max, 256) ); } /** * DER-decode the length * * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 § 8.1.3} for more information. * * @access private * @param String $string * @return Integer */ function _decodeLength(&$string) { $length = ord($this->_string_shift($string)); if ( $length & 0x80 ) { // definite length, long form $length&= 0x7F; $temp = $this->_string_shift($string, $length); list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)); } return $length; } /** * DER-encode the length * * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 § 8.1.3} for more information. * * @access private * @param Integer $length * @return String */ function _encodeLength($length) { if ($length <= 0x7F) { return chr($length); } $temp = ltrim(pack('N', $length), chr(0)); return pack('Ca*', 0x80 | strlen($temp), $temp); } /** * String Shift * * Inspired by array_shift * * @param String $string * @param optional Integer $index * @return String * @access private */ function _string_shift(&$string, $index = 1) { $substr = substr($string, 0, $index); $string = substr($string, $index); return $substr; } /** * Determines the private key format * * @see createKey() * @access public * @param Integer $format */ function setPrivateKeyFormat($format) { $this->privateKeyFormat = $format; } /** * Determines the public key format * * @see createKey() * @access public * @param Integer $format */ function setPublicKeyFormat($format) { $this->publicKeyFormat = $format; } /** * Determines which hashing function should be used * * Used with signature production / verification and (if the encryption mode is CRYPT_RSA_ENCRYPTION_OAEP) encryption and * decryption. If $hash isn't supported, sha1 is used. * * @access public * @param String $hash */ function setHash($hash) { // Crypt_Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example. switch ($hash) { case 'md2': case 'md5': case 'sha1': case 'sha256': case 'sha384': case 'sha512': $this->hash = new Crypt_Hash($hash); $this->hashName = $hash; break; default: $this->hash = new Crypt_Hash('sha1'); $this->hashName = 'sha1'; } $this->hLen = $this->hash->getLength(); } /** * Determines which hashing function should be used for the mask generation function * * The mask generation function is used by CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_SIGNATURE_PSS and although it's * best if Hash and MGFHash are set to the same thing this is not a requirement. * * @access public * @param String $hash */ function setMGFHash($hash) { // Crypt_Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example. switch ($hash) { case 'md2': case 'md5': case 'sha1': case 'sha256': case 'sha384': case 'sha512': $this->mgfHash = new Crypt_Hash($hash); break; default: $this->mgfHash = new Crypt_Hash('sha1'); } $this->mgfHLen = $this->mgfHash->getLength(); } /** * Determines the salt length * * To quote from {@link http://tools.ietf.org/html/rfc3447#page-38 RFC3447#page-38}: * * Typical salt lengths in octets are hLen (the length of the output * of the hash function Hash) and 0. * * @access public * @param Integer $format */ function setSaltLength($sLen) { $this->sLen = $sLen; } /** * Generates a random string x bytes long * * @access public * @param Integer $bytes * @param optional Integer $nonzero * @return String */ function _random($bytes, $nonzero = false) { $temp = ''; if ($nonzero) { for ($i = 0; $i < $bytes; $i++) { $temp.= chr(crypt_random(1, 255)); } } else { $ints = ($bytes + 1) >> 2; for ($i = 0; $i < $ints; $i++) { $temp.= pack('N', crypt_random()); } $temp = substr($temp, 0, $bytes); } return $temp; } /** * Integer-to-Octet-String primitive * * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}. * * @access private * @param Math_BigInteger $x * @param Integer $xLen * @return String */ function _i2osp($x, $xLen) { $x = $x->toBytes(); if (strlen($x) > $xLen) { user_error('Integer too large', E_USER_NOTICE); return false; } return str_pad($x, $xLen, chr(0), STR_PAD_LEFT); } /** * Octet-String-to-Integer primitive * * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}. * * @access private * @param String $x * @return Math_BigInteger */ function _os2ip($x) { return new Math_BigInteger($x, 256); } /** * Exponentiate with or without Chinese Remainder Theorem * * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.2}. * * @access private * @param Math_BigInteger $x * @return Math_BigInteger */ function _exponentiate($x) { if (empty($this->primes) || empty($this->coefficients) || empty($this->exponents)) { return $x->modPow($this->exponent, $this->modulus); } $num_primes = count($this->primes); if (defined('CRYPT_RSA_DISABLE_BLINDING')) { $m_i = array( 1 => $x->modPow($this->exponents[1], $this->primes[1]), 2 => $x->modPow($this->exponents[2], $this->primes[2]) ); $h = $m_i[1]->subtract($m_i[2]); $h = $h->multiply($this->coefficients[2]); list(, $h) = $h->divide($this->primes[1]); $m = $m_i[2]->add($h->multiply($this->primes[2])); $r = $this->primes[1]; for ($i = 3; $i <= $num_primes; $i++) { $m_i = $x->modPow($this->exponents[$i], $this->primes[$i]); $r = $r->multiply($this->primes[$i - 1]); $h = $m_i->subtract($m); $h = $h->multiply($this->coefficients[$i]); list(, $h) = $h->divide($this->primes[$i]); $m = $m->add($r->multiply($h)); } } else { $smallest = $this->primes[1]; for ($i = 2; $i <= $num_primes; $i++) { if ($smallest->compare($this->primes[$i]) > 0) { $smallest = $this->primes[$i]; } } $one = new Math_BigInteger(1); $one->setRandomGenerator('crypt_random'); $r = $one->random($one, $smallest->subtract($one)); $m_i = array( 1 => $this->_blind($x, $r, 1), 2 => $this->_blind($x, $r, 2) ); $h = $m_i[1]->subtract($m_i[2]); $h = $h->multiply($this->coefficients[2]); list(, $h) = $h->divide($this->primes[1]); $m = $m_i[2]->add($h->multiply($this->primes[2])); $r = $this->primes[1]; for ($i = 3; $i <= $num_primes; $i++) { $m_i = $this->_blind($x, $r, $i); $r = $r->multiply($this->primes[$i - 1]); $h = $m_i->subtract($m); $h = $h->multiply($this->coefficients[$i]); list(, $h) = $h->divide($this->primes[$i]); $m = $m->add($r->multiply($h)); } } return $m; } /** * Performs RSA Blinding * * Protects against timing attacks by employing RSA Blinding. * Returns $x->modPow($this->exponents[$i], $this->primes[$i]) * * @access private * @param Math_BigInteger $x * @param Math_BigInteger $r * @param Integer $i * @return Math_BigInteger */ function _blind($x, $r, $i) { $x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i])); $x = $x->modPow($this->exponents[$i], $this->primes[$i]); $r = $r->modInverse($this->primes[$i]); $x = $x->multiply($r); list(, $x) = $x->divide($this->primes[$i]); return $x; } /** * RSAEP * * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.1}. * * @access private * @param Math_BigInteger $m * @return Math_BigInteger */ function _rsaep($m) { if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) { user_error('Message representative out of range', E_USER_NOTICE); return false; } return $this->_exponentiate($m); } /** * RSADP * * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.2 RFC3447#section-5.1.2}. * * @access private * @param Math_BigInteger $c * @return Math_BigInteger */ function _rsadp($c) { if ($c->compare($this->zero) < 0 || $c->compare($this->modulus) > 0) { user_error('Ciphertext representative out of range', E_USER_NOTICE); return false; } return $this->_exponentiate($c); } /** * RSASP1 * * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.1 RFC3447#section-5.2.1}. * * @access private * @param Math_BigInteger $m * @return Math_BigInteger */ function _rsasp1($m) { if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) { user_error('Message representative out of range', E_USER_NOTICE); return false; } return $this->_exponentiate($m); } /** * RSAVP1 * * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}. * * @access private * @param Math_BigInteger $s * @return Math_BigInteger */ function _rsavp1($s) { if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) { user_error('Signature representative out of range', E_USER_NOTICE); return false; } return $this->_exponentiate($s); } /** * MGF1 * * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}. * * @access private * @param String $mgfSeed * @param Integer $mgfLen * @return String */ function _mgf1($mgfSeed, $maskLen) { // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output. $t = ''; $count = ceil($maskLen / $this->mgfHLen); for ($i = 0; $i < $count; $i++) { $c = pack('N', $i); $t.= $this->mgfHash->hash($mgfSeed . $c); } return substr($t, 0, $maskLen); } /** * RSAES-OAEP-ENCRYPT * * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.1 RFC3447#section-7.1.1} and * {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}. * * @access private * @param String $m * @param String $l * @return String */ function _rsaes_oaep_encrypt($m, $l = '') { $mLen = strlen($m); // Length checking // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error // be output. if ($mLen > $this->k - 2 * $this->hLen - 2) { user_error('Message too long', E_USER_NOTICE); return false; } // EME-OAEP encoding $lHash = $this->hash->hash($l); $ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2); $db = $lHash . $ps . chr(1) . $m; $seed = $this->_random($this->hLen); $dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1); $maskedDB = $db ^ $dbMask; $seedMask = $this->_mgf1($maskedDB, $this->hLen); $maskedSeed = $seed ^ $seedMask; $em = chr(0) . $maskedSeed . $maskedDB; // RSA encryption $m = $this->_os2ip($em); $c = $this->_rsaep($m); $c = $this->_i2osp($c, $this->k); // Output the ciphertext C return $c; } /** * RSAES-OAEP-DECRYPT * * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.2 RFC3447#section-7.1.2}. The fact that the error * messages aren't distinguishable from one another hinders debugging, but, to quote from RFC3447#section-7.1.2: * * Note. Care must be taken to ensure that an opponent cannot * distinguish the different error conditions in Step 3.g, whether by * error message or timing, or, more generally, learn partial * information about the encoded message EM. Otherwise an opponent may * be able to obtain useful information about the decryption of the * ciphertext C, leading to a chosen-ciphertext attack such as the one * observed by Manger [36]. * * As for $l... to quote from {@link http://tools.ietf.org/html/rfc3447#page-17 RFC3447#page-17}: * * Both the encryption and the decryption operations of RSAES-OAEP take * the value of a label L as input. In this version of PKCS #1, L is * the empty string; other uses of the label are outside the scope of * this document. * * @access private * @param String $c * @param String $l * @return String */ function _rsaes_oaep_decrypt($c, $l = '') { // Length checking // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error // be output. if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) { user_error('Decryption error', E_USER_NOTICE); return false; } // RSA decryption $c = $this->_os2ip($c); $m = $this->_rsadp($c); if ($m === false) { user_error('Decryption error', E_USER_NOTICE); return false; } $em = $this->_i2osp($m, $this->k); // EME-OAEP decoding $lHash = $this->hash->hash($l); $y = ord($em[0]); $maskedSeed = substr($em, 1, $this->hLen); $maskedDB = substr($em, $this->hLen + 1); $seedMask = $this->_mgf1($maskedDB, $this->hLen); $seed = $maskedSeed ^ $seedMask; $dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1); $db = $maskedDB ^ $dbMask; $lHash2 = substr($db, 0, $this->hLen); $m = substr($db, $this->hLen); if ($lHash != $lHash2) { user_error('Decryption error', E_USER_NOTICE); return false; } $m = ltrim($m, chr(0)); if (ord($m[0]) != 1) { user_error('Decryption error', E_USER_NOTICE); return false; } // Output the message M return substr($m, 1); } /** * RSAES-PKCS1-V1_5-ENCRYPT * * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}. * * @access private * @param String $m * @return String */ function _rsaes_pkcs1_v1_5_encrypt($m) { $mLen = strlen($m); // Length checking if ($mLen > $this->k - 11) { user_error('Message too long', E_USER_NOTICE); return false; } // EME-PKCS1-v1_5 encoding $ps = $this->_random($this->k - $mLen - 3, true); $em = chr(0) . chr(2) . $ps . chr(0) . $m; // RSA encryption $m = $this->_os2ip($em); $c = $this->_rsaep($m); $c = $this->_i2osp($c, $this->k); // Output the ciphertext C return $c; } /** * RSAES-PKCS1-V1_5-DECRYPT * * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.2 RFC3447#section-7.2.2}. * * For compatability purposes, this function departs slightly from the description given in RFC3447. * The reason being that RFC2313#section-8.1 (PKCS#1 v1.5) states that ciphertext's encrypted by the * private key should have the second byte set to either 0 or 1 and that ciphertext's encrypted by the * public key should have the second byte set to 2. In RFC3447 (PKCS#1 v2.1), the second byte is supposed * to be 2 regardless of which key is used. for compatability purposes, we'll just check to make sure the * second byte is 2 or less. If it is, we'll accept the decrypted string as valid. * * As a consequence of this, a private key encrypted ciphertext produced with Crypt_RSA may not decrypt * with a strictly PKCS#1 v1.5 compliant RSA implementation. Public key encrypted ciphertext's should but * not private key encrypted ciphertext's. * * @access private * @param String $c * @return String */ function _rsaes_pkcs1_v1_5_decrypt($c) { // Length checking if (strlen($c) != $this->k) { // or if k < 11 user_error('Decryption error', E_USER_NOTICE); return false; } // RSA decryption $c = $this->_os2ip($c); $m = $this->_rsadp($c); if ($m === false) { user_error('Decryption error', E_USER_NOTICE); return false; } $em = $this->_i2osp($m, $this->k); // EME-PKCS1-v1_5 decoding if (ord($em[0]) != 0 || ord($em[1]) > 2) { user_error('Decryption error', E_USER_NOTICE); return false; } $ps = substr($em, 2, strpos($em, chr(0), 2) - 2); $m = substr($em, strlen($ps) + 3); if (strlen($ps) < 8) { user_error('Decryption error', E_USER_NOTICE); return false; } // Output M return $m; } /** * EMSA-PSS-ENCODE * * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}. * * @access private * @param String $m * @param Integer $emBits */ function _emsa_pss_encode($m, $emBits) { // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error // be output. $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8) $sLen = $this->sLen == false ? $this->hLen : $this->sLen; $mHash = $this->hash->hash($m); if ($emLen < $this->hLen + $sLen + 2) { user_error('Encoding error', E_USER_NOTICE); return false; } $salt = $this->_random($sLen); $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt; $h = $this->hash->hash($m2); $ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2); $db = $ps . chr(1) . $salt; $dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1); $maskedDB = $db ^ $dbMask; $maskedDB[0] = ~chr(0xFF << ($emBits & 7)) & $maskedDB[0]; $em = $maskedDB . $h . chr(0xBC); return $em; } /** * EMSA-PSS-VERIFY * * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}. * * @access private * @param String $m * @param String $em * @param Integer $emBits * @return String */ function _emsa_pss_verify($m, $em, $emBits) { // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error // be output. $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8); $sLen = $this->sLen == false ? $this->hLen : $this->sLen; $mHash = $this->hash->hash($m); if ($emLen < $this->hLen + $sLen + 2) { return false; } if ($em[strlen($em) - 1] != chr(0xBC)) { return false; } $maskedDB = substr($em, 0, $em - $this->hLen - 1); $h = substr($em, $em - $this->hLen - 1, $this->hLen); $temp = chr(0xFF << ($emBits & 7)); if ((~$maskedDB[0] & $temp) != $temp) { return false; } $dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1); $db = $maskedDB ^ $dbMask; $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0]; $temp = $emLen - $this->hLen - $sLen - 2; if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) { return false; } $salt = substr($db, $temp + 1); // should be $sLen long $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt; $h2 = $this->hash->hash($m2); return $h == $h2; } /** * RSASSA-PSS-SIGN * * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}. * * @access private * @param String $m * @return String */ function _rsassa_pss_sign($m) { // EMSA-PSS encoding $em = $this->_emsa_pss_encode($m, 8 * $this->k - 1); // RSA signature $m = $this->_os2ip($em); $s = $this->_rsasp1($m); $s = $this->_i2osp($s, $this->k); // Output the signature S return $s; } /** * RSASSA-PSS-VERIFY * * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}. * * @access private * @param String $m * @param String $s * @return String */ function _rsassa_pss_verify($m, $s) { // Length checking if (strlen($s) != $this->k) { user_error('Invalid signature', E_USER_NOTICE); return false; } // RSA verification $modBits = 8 * $this->k; $s2 = $this->_os2ip($s); $m2 = $this->_rsavp1($s2); if ($m2 === false) { user_error('Invalid signature', E_USER_NOTICE); return false; } $em = $this->_i2osp($m2, $modBits >> 3); if ($em === false) { user_error('Invalid signature', E_USER_NOTICE); return false; } // EMSA-PSS verification return $this->_emsa_pss_verify($m, $em, $modBits - 1); } /** * EMSA-PKCS1-V1_5-ENCODE * * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}. * * @access private * @param String $m * @param Integer $emLen * @return String */ function _emsa_pkcs1_v1_5_encode($m, $emLen) { $h = $this->hash->hash($m); if ($h === false) { return false; } // see http://tools.ietf.org/html/rfc3447#page-43 switch ($this->hashName) { case 'md2': $t = pack('H*', '3020300c06082a864886f70d020205000410'); break; case 'md5': $t = pack('H*', '3020300c06082a864886f70d020505000410'); break; case 'sha1': $t = pack('H*', '3021300906052b0e03021a05000414'); break; case 'sha256': $t = pack('H*', '3031300d060960864801650304020105000420'); break; case 'sha384': $t = pack('H*', '3041300d060960864801650304020205000430'); break; case 'sha512': $t = pack('H*', '3051300d060960864801650304020305000440'); } $t.= $h; $tLen = strlen($t); if ($emLen < $tLen + 11) { user_error('Intended encoded message length too short', E_USER_NOTICE); return false; } $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3); $em = "\0\1$ps\0$t"; return $em; } /** * RSASSA-PKCS1-V1_5-SIGN * * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}. * * @access private * @param String $m * @return String */ function _rsassa_pkcs1_v1_5_sign($m) { // EMSA-PKCS1-v1_5 encoding $em = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); if ($em === false) { user_error('RSA modulus too short', E_USER_NOTICE); return false; } // RSA signature $m = $this->_os2ip($em); $s = $this->_rsasp1($m); $s = $this->_i2osp($s, $this->k); // Output the signature S return $s; } /** * RSASSA-PKCS1-V1_5-VERIFY * * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}. * * @access private * @param String $m * @return String */ function _rsassa_pkcs1_v1_5_verify($m, $s) { // Length checking if (strlen($s) != $this->k) { user_error('Invalid signature', E_USER_NOTICE); return false; } // RSA verification $s = $this->_os2ip($s); $m2 = $this->_rsavp1($s); if ($m2 === false) { user_error('Invalid signature', E_USER_NOTICE); return false; } $em = $this->_i2osp($m2, $this->k); if ($em === false) { user_error('Invalid signature', E_USER_NOTICE); return false; } // EMSA-PKCS1-v1_5 encoding $em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); if ($em2 === false) { user_error('RSA modulus too short', E_USER_NOTICE); return false; } // Compare return $em === $em2; } /** * Set Encryption Mode * * Valid values include CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_ENCRYPTION_PKCS1. * * @access public * @param Integer $mode */ function setEncryptionMode($mode) { $this->encryptionMode = $mode; } /** * Set Signature Mode * * Valid values include CRYPT_RSA_SIGNATURE_PSS and CRYPT_RSA_SIGNATURE_PKCS1 * * @access public * @param Integer $mode */ function setSignatureMode($mode) { $this->signatureMode = $mode; } /** * Encryption * * Both CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_ENCRYPTION_PKCS1 both place limits on how long $plaintext can be. * If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will * be concatenated together. * * @see decrypt() * @access public * @param String $plaintext * @return String */ function encrypt($plaintext) { switch ($this->encryptionMode) { case CRYPT_RSA_ENCRYPTION_PKCS1: $length = $this->k - 11; if ($length <= 0) { return false; } $plaintext = str_split($plaintext, $length); $ciphertext = ''; foreach ($plaintext as $m) { $ciphertext.= $this->_rsaes_pkcs1_v1_5_encrypt($m); } return $ciphertext; //case CRYPT_RSA_ENCRYPTION_OAEP: default: $length = $this->k - 2 * $this->hLen - 2; if ($length <= 0) { return false; } $plaintext = str_split($plaintext, $length); $ciphertext = ''; foreach ($plaintext as $m) { $ciphertext.= $this->_rsaes_oaep_encrypt($m); } return $ciphertext; } } /** * Decryption * * @see encrypt() * @access public * @param String $plaintext * @return String */ function decrypt($ciphertext) { if ($this->k <= 0) { return false; } $ciphertext = str_split($ciphertext, $this->k); $plaintext = ''; switch ($this->encryptionMode) { case CRYPT_RSA_ENCRYPTION_PKCS1: $decrypt = '_rsaes_pkcs1_v1_5_decrypt'; break; //case CRYPT_RSA_ENCRYPTION_OAEP: default: $decrypt = '_rsaes_oaep_decrypt'; } foreach ($ciphertext as $c) { $temp = $this->$decrypt($c); if ($temp === false) { return false; } $plaintext.= $temp; } return $plaintext; } /** * Create a signature * * @see verify() * @access public * @param String $message * @return String */ function sign($message) { if (empty($this->modulus) || empty($this->exponent)) { return false; } switch ($this->signatureMode) { case CRYPT_RSA_SIGNATURE_PKCS1: return $this->_rsassa_pkcs1_v1_5_sign($message); //case CRYPT_RSA_SIGNATURE_PSS: default: return $this->_rsassa_pss_sign($message); } } /** * Verifies a signature * * @see sign() * @access public * @param String $message * @param String $signature * @return Boolean */ function verify($message, $signature) { if (empty($this->modulus) || empty($this->exponent)) { return false; } switch ($this->signatureMode) { case CRYPT_RSA_SIGNATURE_PKCS1: return $this->_rsassa_pkcs1_v1_5_verify($message, $signature); //case CRYPT_RSA_SIGNATURE_PSS: default: return $this->_rsassa_pss_verify($message, $signature); } } }spotweb-20130826+dfsg2/Crypt/Random.php000077500000000000000000000111651226620506000175050ustar00rootroot00000000000000 * * * * LICENSE: This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * @category Crypt * @package Crypt_Random * @author Jim Wigginton * @copyright MMVII Jim Wigginton * @license http://www.gnu.org/licenses/lgpl.txt * @version $Id: Random.php,v 1.9 2010/04/24 06:40:48 terrafrost Exp $ * @link http://phpseclib.sourceforge.net */ /** * Generate a random value. * * On 32-bit machines, the largest distance that can exist between $min and $max is 2**31. * If $min and $max are farther apart than that then the last ($max - range) numbers. * * Depending on how this is being used, it may be worth while to write a replacement. For example, * a PHP-based web app that stores its data in an SQL database can collect more entropy than this function * can. * * @param optional Integer $min * @param optional Integer $max * @return Integer * @access public */ function crypt_random($min = 0, $max = 0x7FFFFFFF) { if ($min == $max) { return $min; } // see http://en.wikipedia.org/wiki//dev/random // if open_basedir is enabled file_exists() will ouput an "open_basedir restriction in effect" warning, // so we suppress it. if (@file_exists('/dev/urandom')) { static $fp; if (!$fp) { $fp = fopen('/dev/urandom', 'rb'); } extract(unpack('Nrandom', fread($fp, 4))); // say $min = 0 and $max = 3. if we didn't do abs() then we could have stuff like this: // -4 % 3 + 0 = -1, even though -1 < $min return abs($random) % ($max - $min) + $min; } /* Prior to PHP 4.2.0, mt_srand() had to be called before mt_rand() could be called. Prior to PHP 5.2.6, mt_rand()'s automatic seeding was subpar, as elaborated here: http://www.suspekt.org/2008/08/17/mt_srand-and-not-so-random-numbers/ The seeding routine is pretty much ripped from PHP's own internal GENERATE_SEED() macro: http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3_2/ext/standard/php_rand.h?view=markup */ if (version_compare(PHP_VERSION, '5.2.5', '<=')) { static $seeded; if (!isset($seeded)) { $seeded = true; mt_srand(fmod(time() * getmypid(), 0x7FFFFFFF) ^ fmod(1000000 * lcg_value(), 0x7FFFFFFF)); } } static $crypto; // The CSPRNG's Yarrow and Fortuna periodically reseed. This function can be reseeded by hitting F5 // in the browser and reloading the page. if (!isset($crypto)) { $key = $iv = ''; for ($i = 0; $i < 8; $i++) { $key.= pack('n', mt_rand(0, 0xFFFF)); $iv .= pack('n', mt_rand(0, 0xFFFF)); } switch (true) { case class_exists('Crypt_AES'): $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR); break; case class_exists('Crypt_TripleDES'): $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); break; case class_exists('Crypt_DES'): $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR); break; case class_exists('Crypt_RC4'): $crypto = new Crypt_RC4(); break; default: extract(unpack('Nrandom', pack('H*', sha1(mt_rand(0, 0x7FFFFFFF))))); return abs($random) % ($max - $min) + $min; } $crypto->setKey($key); $crypto->setIV($iv); $crypto->enableContinuousBuffer(); } extract(unpack('Nrandom', $crypto->encrypt("\0\0\0\0"))); return abs($random) % ($max - $min) + $min; } ?>spotweb-20130826+dfsg2/INSTALL000077500000000000000000000025731226620506000155070ustar00rootroot00000000000000== Installation requirements == Spotweb has been regulary tested on several different systems. Spotweb is mostly used on: * Unix-based (Linux, FreeBSD) operating systems or small NAS systems like Synology and Qnap * Apache Webserver * PHP v5.3 or higher (modules required: ctyle, curl, DOM, gettext, mbstring, xml, zip, zlib, gd, openssl) * MySQL webserver. Spotweb also supports PostgreSQL and SQLite where SQLite is the least supported and tested database engine. Please run 'testinstall.php' from within your browser before attempting anything further with Spotweb and make sure all items are checked 'OK'. == Installation instructions == 1. Ensure you have an database server installed (either MySQL or PostgreSQL) 2. Create an empty 'spotweb' database 3. Ensure you have a webserver running and PHP is configured for this webserver 3. Download Spotweb 4. Unpack Spotweb to a directory of your choosing 5. Run 'install.php' from your browser until everything is 'OK'. Fix the parts which aren't OK. 6. Follow the wizard and perform the instructions as given by the wizard. == Troubleshooting == When a white page appears instead of your Spotweb installation, this usually indicates an typing error in either your ownsettings.php, dbsettings.inc.php or a configuration error in your webserver. Please consult your Apache's errorlog for the exact error and fix it. spotweb-20130826+dfsg2/LICENSE000077500000000000000000000027201226620506000154550ustar00rootroot00000000000000Copyright (c) 2011, Spotweb All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Spotweb team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. spotweb-20130826+dfsg2/Math/000077500000000000000000000000001226620506000153355ustar00rootroot00000000000000spotweb-20130826+dfsg2/Math/BigInteger.php000077500000000000000000003552761226620506000201120ustar00rootroot00000000000000> and << cannot be used, nor can the modulo operator %, * which only supports integers. Although this fact will slow this library down, the fact that such a high * base is being used should more than compensate. * * When PHP version 6 is officially released, we'll be able to use 64-bit integers. This should, once again, * allow bitwise operators, and will increase the maximum possible base to 2**31 (or 2**62 for addition / * subtraction). * * Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format. ie. * (new Math_BigInteger(pow(2, 26)))->value = array(0, 1) * * Useful resources are as follows: * * - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)} * - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)} * - Java's BigInteger classes. See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip * * Here's an example of how to use this library: * * add($b); * * echo $c->toString(); // outputs 5 * ?> * * * LICENSE: This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * @category Math * @package Math_BigInteger * @author Jim Wigginton * @copyright MMVI Jim Wigginton * @license http://www.gnu.org/licenses/lgpl.txt * @version $Id: BigInteger.php,v 1.33 2010/03/22 22:32:03 terrafrost Exp $ * @link http://pear.php.net/package/Math_BigInteger */ /**#@+ * Reduction constants * * @access private * @see Math_BigInteger::_reduce() */ /** * @see Math_BigInteger::_montgomery() * @see Math_BigInteger::_prepMontgomery() */ define('MATH_BIGINTEGER_MONTGOMERY', 0); /** * @see Math_BigInteger::_barrett() */ define('MATH_BIGINTEGER_BARRETT', 1); /** * @see Math_BigInteger::_mod2() */ define('MATH_BIGINTEGER_POWEROF2', 2); /** * @see Math_BigInteger::_remainder() */ define('MATH_BIGINTEGER_CLASSIC', 3); /** * @see Math_BigInteger::__clone() */ define('MATH_BIGINTEGER_NONE', 4); /**#@-*/ /**#@+ * Array constants * * Rather than create a thousands and thousands of new Math_BigInteger objects in repeated function calls to add() and * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them. * * @access private */ /** * $result[MATH_BIGINTEGER_VALUE] contains the value. */ define('MATH_BIGINTEGER_VALUE', 0); /** * $result[MATH_BIGINTEGER_SIGN] contains the sign. */ define('MATH_BIGINTEGER_SIGN', 1); /**#@-*/ /**#@+ * @access private * @see Math_BigInteger::_montgomery() * @see Math_BigInteger::_barrett() */ /** * Cache constants * * $cache[MATH_BIGINTEGER_VARIABLE] tells us whether or not the cached data is still valid. */ define('MATH_BIGINTEGER_VARIABLE', 0); /** * $cache[MATH_BIGINTEGER_DATA] contains the cached data. */ define('MATH_BIGINTEGER_DATA', 1); /**#@-*/ /**#@+ * Mode constants. * * @access private * @see Math_BigInteger::Math_BigInteger() */ /** * To use the pure-PHP implementation */ define('MATH_BIGINTEGER_MODE_INTERNAL', 1); /** * To use the BCMath library * * (if enabled; otherwise, the internal implementation will be used) */ define('MATH_BIGINTEGER_MODE_BCMATH', 2); /** * To use the GMP library * * (if present; otherwise, either the BCMath or the internal implementation will be used) */ define('MATH_BIGINTEGER_MODE_GMP', 3); /**#@-*/ /** * The largest digit that may be used in addition / subtraction * * (we do pow(2, 52) instead of using 4503599627370496, directly, because some PHP installations * will truncate 4503599627370496) * * @access private */ define('MATH_BIGINTEGER_MAX_DIGIT52', pow(2, 52)); /** * Karatsuba Cutoff * * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication? * * @access private */ define('MATH_BIGINTEGER_KARATSUBA_CUTOFF', 25); /** * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256 * numbers. * * @author Jim Wigginton * @version 1.0.0RC4 * @access public * @package Math_BigInteger */ class Math_BigInteger { /** * Holds the BigInteger's value. * * @var Array * @access private */ var $value; /** * Holds the BigInteger's magnitude. * * @var Boolean * @access private */ var $is_negative = false; /** * Random number generator function * * @see setRandomGenerator() * @access private */ var $generator = 'mt_rand'; /** * Precision * * @see setPrecision() * @access private */ var $precision = -1; /** * Precision Bitmask * * @see setPrecision() * @access private */ var $bitmask = false; /** * Mode independant value used for serialization. * * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for * a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value, * however, $this->hex is only calculated when $this->__sleep() is called. * * @see __sleep() * @see __wakeup() * @var String * @access private */ var $hex; /** * Converts base-2, base-10, base-16, and binary strings (eg. base-256) to BigIntegers. * * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using * two's compliment. The sole exception to this is -10, which is treated the same as 10 is. * * Here's an example: * * toString(); // outputs 50 * ?> * * * @param optional $x base-10 number or base-$base number if $base set. * @param optional integer $base * @return Math_BigInteger * @access public */ function Math_BigInteger($x = 0, $base = 10) { if ( !defined('MATH_BIGINTEGER_MODE') ) { switch (true) { case extension_loaded('gmp'): define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP); break; case extension_loaded('bcmath'): define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_BCMATH); break; default: define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_INTERNAL); } } switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: if (is_resource($x) && get_resource_type($x) == 'GMP integer') { $this->value = $x; return; } $this->value = gmp_init(0); break; case MATH_BIGINTEGER_MODE_BCMATH: $this->value = '0'; break; default: $this->value = array(); } if (empty($x)) { return; } switch ($base) { case -256: if (ord($x[0]) & 0x80) { $x = ~$x; $this->is_negative = true; } case 256: switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $sign = $this->is_negative ? '-' : ''; $this->value = gmp_init($sign . '0x' . bin2hex($x)); break; case MATH_BIGINTEGER_MODE_BCMATH: // round $len to the nearest 4 (thanks, DavidMJ!) $len = (strlen($x) + 3) & 0xFFFFFFFC; $x = str_pad($x, $len, chr(0), STR_PAD_LEFT); for ($i = 0; $i < $len; $i+= 4) { $this->value = bcmul($this->value, '4294967296', 0); // 4294967296 == 2**32 $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])), 0); } if ($this->is_negative) { $this->value = '-' . $this->value; } break; // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb) default: while (strlen($x)) { $this->value[] = $this->_bytes2int($this->_base256_rshift($x, 26)); } } if ($this->is_negative) { if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) { $this->is_negative = false; } $temp = $this->add(new Math_BigInteger('-1')); $this->value = $temp->value; } break; case 16: case -16: if ($base > 0 && $x[0] == '-') { $this->is_negative = true; $x = substr($x, 1); } $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x); $is_negative = false; if ($base < 0 && hexdec($x[0]) >= 8) { $this->is_negative = $is_negative = true; $x = bin2hex(~pack('H*', $x)); } switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $temp = $this->is_negative ? '-0x' . $x : '0x' . $x; $this->value = gmp_init($temp); $this->is_negative = false; break; case MATH_BIGINTEGER_MODE_BCMATH: $x = ( strlen($x) & 1 ) ? '0' . $x : $x; $temp = new Math_BigInteger(pack('H*', $x), 256); $this->value = $this->is_negative ? '-' . $temp->value : $temp->value; $this->is_negative = false; break; default: $x = ( strlen($x) & 1 ) ? '0' . $x : $x; $temp = new Math_BigInteger(pack('H*', $x), 256); $this->value = $temp->value; } if ($is_negative) { $temp = $this->add(new Math_BigInteger('-1')); $this->value = $temp->value; } break; case 10: case -10: $x = preg_replace('#^(-?[0-9]*).*#', '$1', $x); switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $this->value = gmp_init($x); break; case MATH_BIGINTEGER_MODE_BCMATH: // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different // results then doing it on '-1' does (modInverse does $x[0]) $this->value = (string) $x; break; default: $temp = new Math_BigInteger(); // array(10000000) is 10**7 in base-2**26. 10**7 is the closest to 2**26 we can get without passing it. $multiplier = new Math_BigInteger(); $multiplier->value = array(10000000); if ($x[0] == '-') { $this->is_negative = true; $x = substr($x, 1); } $x = str_pad($x, strlen($x) + (6 * strlen($x)) % 7, 0, STR_PAD_LEFT); while (strlen($x)) { $temp = $temp->multiply($multiplier); $temp = $temp->add(new Math_BigInteger($this->_int2bytes(substr($x, 0, 7)), 256)); $x = substr($x, 7); } $this->value = $temp->value; } break; case 2: // base-2 support originally implemented by Lluis Pamies - thanks! case -2: if ($base > 0 && $x[0] == '-') { $this->is_negative = true; $x = substr($x, 1); } $x = preg_replace('#^([01]*).*#', '$1', $x); $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT); $str = '0x'; while (strlen($x)) { $part = substr($x, 0, 4); $str.= dechex(bindec($part)); $x = substr($x, 4); } if ($this->is_negative) { $str = '-' . $str; } $temp = new Math_BigInteger($str, 8 * $base); // ie. either -16 or +16 $this->value = $temp->value; $this->is_negative = $temp->is_negative; break; default: // base not supported, so we'll let $this == 0 } } /** * Converts a BigInteger to a byte string (eg. base-256). * * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're * saved as two's compliment. * * Here's an example: * * toBytes(); // outputs chr(65) * ?> * * * @param Boolean $twos_compliment * @return String * @access public * @internal Converts a base-2**26 number to base-2**8 */ function toBytes($twos_compliment = false) { if ($twos_compliment) { $comparison = $this->compare(new Math_BigInteger()); if ($comparison == 0) { return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } $temp = $comparison < 0 ? $this->add(new Math_BigInteger(1)) : $this->copy(); $bytes = $temp->toBytes(); if (empty($bytes)) { // eg. if the number we're trying to convert is -1 $bytes = chr(0); } if (ord($bytes[0]) & 0x80) { $bytes = chr(0) . $bytes; } return $comparison < 0 ? ~$bytes : $bytes; } switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: if (gmp_cmp($this->value, gmp_init(0)) == 0) { return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } $temp = gmp_strval(gmp_abs($this->value), 16); $temp = ( strlen($temp) & 1 ) ? '0' . $temp : $temp; $temp = pack('H*', $temp); return $this->precision > 0 ? substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : ltrim($temp, chr(0)); case MATH_BIGINTEGER_MODE_BCMATH: if ($this->value === '0') { return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } $value = ''; $current = $this->value; if ($current[0] == '-') { $current = substr($current, 1); } while (bccomp($current, '0', 0) > 0) { $temp = bcmod($current, '16777216'); $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value; $current = bcdiv($current, '16777216', 0); } return $this->precision > 0 ? substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : ltrim($value, chr(0)); } if (!count($this->value)) { return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } $result = $this->_int2bytes($this->value[count($this->value) - 1]); $temp = $this->copy(); for ($i = count($temp->value) - 2; $i >= 0; --$i) { $temp->_base256_lshift($result, 26); $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT); } return $this->precision > 0 ? str_pad(substr($result, -(($this->precision + 7) >> 3)), ($this->precision + 7) >> 3, chr(0), STR_PAD_LEFT) : $result; } /** * Converts a BigInteger to a hex string (eg. base-16)). * * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're * saved as two's compliment. * * Here's an example: * * toHex(); // outputs '41' * ?> * * * @param Boolean $twos_compliment * @return String * @access public * @internal Converts a base-2**26 number to base-2**8 */ function toHex($twos_compliment = false) { return bin2hex($this->toBytes($twos_compliment)); } /** * Converts a BigInteger to a bit string (eg. base-2). * * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're * saved as two's compliment. * * Here's an example: * * toBits(); // outputs '1000001' * ?> * * * @param Boolean $twos_compliment * @return String * @access public * @internal Converts a base-2**26 number to base-2**2 */ function toBits($twos_compliment = false) { $hex = $this->toHex($twos_compliment); $bits = ''; for ($i = 0; $i < strlen($hex); $i+=8) { $bits.= str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT); } return $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0'); } /** * Converts a BigInteger to a base-10 number. * * Here's an example: * * toString(); // outputs 50 * ?> * * * @return String * @access public * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10) */ function toString() { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: return gmp_strval($this->value); case MATH_BIGINTEGER_MODE_BCMATH: if ($this->value === '0') { return '0'; } return ltrim($this->value, '0'); } if (!count($this->value)) { return '0'; } $temp = $this->copy(); $temp->is_negative = false; $divisor = new Math_BigInteger(); $divisor->value = array(10000000); // eg. 10**7 $result = ''; while (count($temp->value)) { list($temp, $mod) = $temp->divide($divisor); $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', 7, '0', STR_PAD_LEFT) . $result; } $result = ltrim($result, '0'); if (empty($result)) { $result = '0'; } if ($this->is_negative) { $result = '-' . $result; } return $result; } /** * Copy an object * * PHP5 passes objects by reference while PHP4 passes by value. As such, we need a function to guarantee * that all objects are passed by value, when appropriate. More information can be found here: * * {@link http://php.net/language.oop5.basic#51624} * * @access public * @see __clone() * @return Math_BigInteger */ function copy() { $temp = new Math_BigInteger(); $temp->value = $this->value; $temp->is_negative = $this->is_negative; $temp->generator = $this->generator; $temp->precision = $this->precision; $temp->bitmask = $this->bitmask; return $temp; } /** * __toString() magic method * * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call * toString(). * * @access public * @internal Implemented per a suggestion by Techie-Michael - thanks! */ function __toString() { return $this->toString(); } /** * __clone() magic method * * Although you can call Math_BigInteger::__toString() directly in PHP5, you cannot call Math_BigInteger::__clone() * directly in PHP5. You can in PHP4 since it's not a magic method, but in PHP5, you have to call it by using the PHP5 * only syntax of $y = clone $x. As such, if you're trying to write an application that works on both PHP4 and PHP5, * call Math_BigInteger::copy(), instead. * * @access public * @see copy() * @return Math_BigInteger */ function __clone() { return $this->copy(); } /** * __sleep() magic method * * Will be called, automatically, when serialize() is called on a Math_BigInteger object. * * @see __wakeup() * @access public */ function __sleep() { $this->hex = $this->toHex(true); $vars = array('hex'); if ($this->generator != 'mt_rand') { $vars[] = 'generator'; } if ($this->precision > 0) { $vars[] = 'precision'; } return $vars; } /** * __wakeup() magic method * * Will be called, automatically, when unserialize() is called on a Math_BigInteger object. * * @see __sleep() * @access public */ function __wakeup() { $temp = new Math_BigInteger($this->hex, -16); $this->value = $temp->value; $this->is_negative = $temp->is_negative; $this->setRandomGenerator($this->generator); if ($this->precision > 0) { // recalculate $this->bitmask $this->setPrecision($this->precision); } } /** * Adds two BigIntegers. * * Here's an example: * * add($b); * * echo $c->toString(); // outputs 30 * ?> * * * @param Math_BigInteger $y * @return Math_BigInteger * @access public * @internal Performs base-2**52 addition */ function add($y) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_add($this->value, $y->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $temp = new Math_BigInteger(); $temp->value = bcadd($this->value, $y->value, 0); return $this->_normalize($temp); } $temp = $this->_add($this->value, $this->is_negative, $y->value, $y->is_negative); $result = new Math_BigInteger(); $result->value = $temp[MATH_BIGINTEGER_VALUE]; $result->is_negative = $temp[MATH_BIGINTEGER_SIGN]; return $this->_normalize($result); } /** * Performs addition. * * @param Array $x_value * @param Boolean $x_negative * @param Array $y_value * @param Boolean $y_negative * @return Array * @access private */ function _add($x_value, $x_negative, $y_value, $y_negative) { $x_size = count($x_value); $y_size = count($y_value); if ($x_size == 0) { return array( MATH_BIGINTEGER_VALUE => $y_value, MATH_BIGINTEGER_SIGN => $y_negative ); } else if ($y_size == 0) { return array( MATH_BIGINTEGER_VALUE => $x_value, MATH_BIGINTEGER_SIGN => $x_negative ); } // subtract, if appropriate if ( $x_negative != $y_negative ) { if ( $x_value == $y_value ) { return array( MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_SIGN => false ); } $temp = $this->_subtract($x_value, false, $y_value, false); $temp[MATH_BIGINTEGER_SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ? $x_negative : $y_negative; return $temp; } if ($x_size < $y_size) { $size = $x_size; $value = $y_value; } else { $size = $y_size; $value = $x_value; } $value[] = 0; // just in case the carry adds an extra digit $carry = 0; for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) { $sum = $x_value[$j] * 0x4000000 + $x_value[$i] + $y_value[$j] * 0x4000000 + $y_value[$i] + $carry; $carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT52; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1 $sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT52 : $sum; $temp = (int) ($sum / 0x4000000); $value[$i] = (int) ($sum - 0x4000000 * $temp); // eg. a faster alternative to fmod($sum, 0x4000000) $value[$j] = $temp; } if ($j == $size) { // ie. if $y_size is odd $sum = $x_value[$i] + $y_value[$i] + $carry; $carry = $sum >= 0x4000000; $value[$i] = $carry ? $sum - 0x4000000 : $sum; ++$i; // ie. let $i = $j since we've just done $value[$i] } if ($carry) { for (; $value[$i] == 0x3FFFFFF; ++$i) { $value[$i] = 0; } ++$value[$i]; } return array( MATH_BIGINTEGER_VALUE => $this->_trim($value), MATH_BIGINTEGER_SIGN => $x_negative ); } /** * Subtracts two BigIntegers. * * Here's an example: * * subtract($b); * * echo $c->toString(); // outputs -10 * ?> * * * @param Math_BigInteger $y * @return Math_BigInteger * @access public * @internal Performs base-2**52 subtraction */ function subtract($y) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_sub($this->value, $y->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $temp = new Math_BigInteger(); $temp->value = bcsub($this->value, $y->value, 0); return $this->_normalize($temp); } $temp = $this->_subtract($this->value, $this->is_negative, $y->value, $y->is_negative); $result = new Math_BigInteger(); $result->value = $temp[MATH_BIGINTEGER_VALUE]; $result->is_negative = $temp[MATH_BIGINTEGER_SIGN]; return $this->_normalize($result); } /** * Performs subtraction. * * @param Array $x_value * @param Boolean $x_negative * @param Array $y_value * @param Boolean $y_negative * @return Array * @access private */ function _subtract($x_value, $x_negative, $y_value, $y_negative) { $x_size = count($x_value); $y_size = count($y_value); if ($x_size == 0) { return array( MATH_BIGINTEGER_VALUE => $y_value, MATH_BIGINTEGER_SIGN => !$y_negative ); } else if ($y_size == 0) { return array( MATH_BIGINTEGER_VALUE => $x_value, MATH_BIGINTEGER_SIGN => $x_negative ); } // add, if appropriate (ie. -$x - +$y or +$x - -$y) if ( $x_negative != $y_negative ) { $temp = $this->_add($x_value, false, $y_value, false); $temp[MATH_BIGINTEGER_SIGN] = $x_negative; return $temp; } $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative); if ( !$diff ) { return array( MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_SIGN => false ); } // switch $x and $y around, if appropriate. if ( (!$x_negative && $diff < 0) || ($x_negative && $diff > 0) ) { $temp = $x_value; $x_value = $y_value; $y_value = $temp; $x_negative = !$x_negative; $x_size = count($x_value); $y_size = count($y_value); } // at this point, $x_value should be at least as big as - if not bigger than - $y_value $carry = 0; for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) { $sum = $x_value[$j] * 0x4000000 + $x_value[$i] - $y_value[$j] * 0x4000000 - $y_value[$i] - $carry; $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1 $sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT52 : $sum; $temp = (int) ($sum / 0x4000000); $x_value[$i] = (int) ($sum - 0x4000000 * $temp); $x_value[$j] = $temp; } if ($j == $y_size) { // ie. if $y_size is odd $sum = $x_value[$i] - $y_value[$i] - $carry; $carry = $sum < 0; $x_value[$i] = $carry ? $sum + 0x4000000 : $sum; ++$i; } if ($carry) { for (; !$x_value[$i]; ++$i) { $x_value[$i] = 0x3FFFFFF; } --$x_value[$i]; } return array( MATH_BIGINTEGER_VALUE => $this->_trim($x_value), MATH_BIGINTEGER_SIGN => $x_negative ); } /** * Multiplies two BigIntegers * * Here's an example: * * multiply($b); * * echo $c->toString(); // outputs 200 * ?> * * * @param Math_BigInteger $x * @return Math_BigInteger * @access public */ function multiply($x) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_mul($this->value, $x->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $temp = new Math_BigInteger(); $temp->value = bcmul($this->value, $x->value, 0); return $this->_normalize($temp); } $temp = $this->_multiply($this->value, $this->is_negative, $x->value, $x->is_negative); $product = new Math_BigInteger(); $product->value = $temp[MATH_BIGINTEGER_VALUE]; $product->is_negative = $temp[MATH_BIGINTEGER_SIGN]; return $this->_normalize($product); } /** * Performs multiplication. * * @param Array $x_value * @param Boolean $x_negative * @param Array $y_value * @param Boolean $y_negative * @return Array * @access private */ function _multiply($x_value, $x_negative, $y_value, $y_negative) { //if ( $x_value == $y_value ) { // return array( // MATH_BIGINTEGER_VALUE => $this->_square($x_value), // MATH_BIGINTEGER_SIGN => $x_sign != $y_value // ); //} $x_length = count($x_value); $y_length = count($y_value); if ( !$x_length || !$y_length ) { // a 0 is being multiplied return array( MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_SIGN => false ); } return array( MATH_BIGINTEGER_VALUE => min($x_length, $y_length) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ? $this->_trim($this->_regularMultiply($x_value, $y_value)) : $this->_trim($this->_karatsuba($x_value, $y_value)), MATH_BIGINTEGER_SIGN => $x_negative != $y_negative ); } /** * Performs long multiplication on two BigIntegers * * Modeled after 'multiply' in MutableBigInteger.java. * * @param Array $x_value * @param Array $y_value * @return Array * @access private */ function _regularMultiply($x_value, $y_value) { $x_length = count($x_value); $y_length = count($y_value); if ( !$x_length || !$y_length ) { // a 0 is being multiplied return array(); } if ( $x_length < $y_length ) { $temp = $x_value; $x_value = $y_value; $y_value = $temp; $x_length = count($x_value); $y_length = count($y_value); } $product_value = $this->_array_repeat(0, $x_length + $y_length); // the following for loop could be removed if the for loop following it // (the one with nested for loops) initially set $i to 0, but // doing so would also make the result in one set of unnecessary adds, // since on the outermost loops first pass, $product->value[$k] is going // to always be 0 $carry = 0; for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0 $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0 $carry = (int) ($temp / 0x4000000); $product_value[$j] = (int) ($temp - 0x4000000 * $carry); } $product_value[$j] = $carry; // the above for loop is what the previous comment was talking about. the // following for loop is the "one with nested for loops" for ($i = 1; $i < $y_length; ++$i) { $carry = 0; for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) { $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; $carry = (int) ($temp / 0x4000000); $product_value[$k] = (int) ($temp - 0x4000000 * $carry); } $product_value[$k] = $carry; } return $product_value; } /** * Performs Karatsuba multiplication on two BigIntegers * * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}. * * @param Array $x_value * @param Array $y_value * @return Array * @access private */ function _karatsuba($x_value, $y_value) { $m = min(count($x_value) >> 1, count($y_value) >> 1); if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) { return $this->_regularMultiply($x_value, $y_value); } $x1 = array_slice($x_value, $m); $x0 = array_slice($x_value, 0, $m); $y1 = array_slice($y_value, $m); $y0 = array_slice($y_value, 0, $m); $z2 = $this->_karatsuba($x1, $y1); $z0 = $this->_karatsuba($x0, $y0); $z1 = $this->_add($x1, false, $x0, false); $temp = $this->_add($y1, false, $y0, false); $z1 = $this->_karatsuba($z1[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_VALUE]); $temp = $this->_add($z2, false, $z0, false); $z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false); $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); $z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]); $xy = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]); $xy = $this->_add($xy[MATH_BIGINTEGER_VALUE], $xy[MATH_BIGINTEGER_SIGN], $z0, false); return $xy[MATH_BIGINTEGER_VALUE]; } /** * Performs squaring * * @param Array $x * @return Array * @access private */ function _square($x = false) { return count($x) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ? $this->_trim($this->_baseSquare($x)) : $this->_trim($this->_karatsubaSquare($x)); } /** * Performs traditional squaring on two BigIntegers * * Squaring can be done faster than multiplying a number by itself can be. See * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} / * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information. * * @param Array $value * @return Array * @access private */ function _baseSquare($value) { if ( empty($value) ) { return array(); } $square_value = $this->_array_repeat(0, 2 * count($value)); for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) { $i2 = $i << 1; $temp = $square_value[$i2] + $value[$i] * $value[$i]; $carry = (int) ($temp / 0x4000000); $square_value[$i2] = (int) ($temp - 0x4000000 * $carry); // note how we start from $i+1 instead of 0 as we do in multiplication. for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) { $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry; $carry = (int) ($temp / 0x4000000); $square_value[$k] = (int) ($temp - 0x4000000 * $carry); } // the following line can yield values larger 2**15. at this point, PHP should switch // over to floats. $square_value[$i + $max_index + 1] = $carry; } return $square_value; } /** * Performs Karatsuba "squaring" on two BigIntegers * * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}. * * @param Array $value * @return Array * @access private */ function _karatsubaSquare($value) { $m = count($value) >> 1; if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) { return $this->_baseSquare($value); } $x1 = array_slice($value, $m); $x0 = array_slice($value, 0, $m); $z2 = $this->_karatsubaSquare($x1); $z0 = $this->_karatsubaSquare($x0); $z1 = $this->_add($x1, false, $x0, false); $z1 = $this->_karatsubaSquare($z1[MATH_BIGINTEGER_VALUE]); $temp = $this->_add($z2, false, $z0, false); $z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false); $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); $z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]); $xx = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]); $xx = $this->_add($xx[MATH_BIGINTEGER_VALUE], $xx[MATH_BIGINTEGER_SIGN], $z0, false); return $xx[MATH_BIGINTEGER_VALUE]; } /** * Divides two BigIntegers. * * Returns an array whose first element contains the quotient and whose second element contains the * "common residue". If the remainder would be positive, the "common residue" and the remainder are the * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder * and the divisor (basically, the "common residue" is the first positive modulo). * * Here's an example: * * divide($b); * * echo $quotient->toString(); // outputs 0 * echo "\r\n"; * echo $remainder->toString(); // outputs 10 * ?> * * * @param Math_BigInteger $y * @return Array * @access public * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}. */ function divide($y) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $quotient = new Math_BigInteger(); $remainder = new Math_BigInteger(); list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value); if (gmp_sign($remainder->value) < 0) { $remainder->value = gmp_add($remainder->value, gmp_abs($y->value)); } return array($this->_normalize($quotient), $this->_normalize($remainder)); case MATH_BIGINTEGER_MODE_BCMATH: $quotient = new Math_BigInteger(); $remainder = new Math_BigInteger(); $quotient->value = bcdiv($this->value, $y->value, 0); $remainder->value = bcmod($this->value, $y->value); if ($remainder->value[0] == '-') { $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0); } return array($this->_normalize($quotient), $this->_normalize($remainder)); } if (count($y->value) == 1) { list($q, $r) = $this->_divide_digit($this->value, $y->value[0]); $quotient = new Math_BigInteger(); $remainder = new Math_BigInteger(); $quotient->value = $q; $remainder->value = array($r); $quotient->is_negative = $this->is_negative != $y->is_negative; return array($this->_normalize($quotient), $this->_normalize($remainder)); } static $zero; if ( !isset($zero) ) { $zero = new Math_BigInteger(); } $x = $this->copy(); $y = $y->copy(); $x_sign = $x->is_negative; $y_sign = $y->is_negative; $x->is_negative = $y->is_negative = false; $diff = $x->compare($y); if ( !$diff ) { $temp = new Math_BigInteger(); $temp->value = array(1); $temp->is_negative = $x_sign != $y_sign; return array($this->_normalize($temp), $this->_normalize(new Math_BigInteger())); } if ( $diff < 0 ) { // if $x is negative, "add" $y. if ( $x_sign ) { $x = $y->subtract($x); } return array($this->_normalize(new Math_BigInteger()), $this->_normalize($x)); } // normalize $x and $y as described in HAC 14.23 / 14.24 $msb = $y->value[count($y->value) - 1]; for ($shift = 0; !($msb & 0x2000000); ++$shift) { $msb <<= 1; } $x->_lshift($shift); $y->_lshift($shift); $y_value = &$y->value; $x_max = count($x->value) - 1; $y_max = count($y->value) - 1; $quotient = new Math_BigInteger(); $quotient_value = &$quotient->value; $quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1); static $temp, $lhs, $rhs; if (!isset($temp)) { $temp = new Math_BigInteger(); $lhs = new Math_BigInteger(); $rhs = new Math_BigInteger(); } $temp_value = &$temp->value; $rhs_value = &$rhs->value; // $temp = $y << ($x_max - $y_max-1) in base 2**26 $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value); while ( $x->compare($temp) >= 0 ) { // calculate the "common residue" ++$quotient_value[$x_max - $y_max]; $x = $x->subtract($temp); $x_max = count($x->value) - 1; } for ($i = $x_max; $i >= $y_max + 1; --$i) { $x_value = &$x->value; $x_window = array( isset($x_value[$i]) ? $x_value[$i] : 0, isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0, isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0 ); $y_window = array( $y_value[$y_max], ( $y_max > 0 ) ? $y_value[$y_max - 1] : 0 ); $q_index = $i - $y_max - 1; if ($x_window[0] == $y_window[0]) { $quotient_value[$q_index] = 0x3FFFFFF; } else { $quotient_value[$q_index] = (int) ( ($x_window[0] * 0x4000000 + $x_window[1]) / $y_window[0] ); } $temp_value = array($y_window[1], $y_window[0]); $lhs->value = array($quotient_value[$q_index]); $lhs = $lhs->multiply($temp); $rhs_value = array($x_window[2], $x_window[1], $x_window[0]); while ( $lhs->compare($rhs) > 0 ) { --$quotient_value[$q_index]; $lhs->value = array($quotient_value[$q_index]); $lhs = $lhs->multiply($temp); } $adjust = $this->_array_repeat(0, $q_index); $temp_value = array($quotient_value[$q_index]); $temp = $temp->multiply($y); $temp_value = &$temp->value; $temp_value = array_merge($adjust, $temp_value); $x = $x->subtract($temp); if ($x->compare($zero) < 0) { $temp_value = array_merge($adjust, $y_value); $x = $x->add($temp); --$quotient_value[$q_index]; } $x_max = count($x_value) - 1; } // unnormalize the remainder $x->_rshift($shift); $quotient->is_negative = $x_sign != $y_sign; // calculate the "common residue", if appropriate if ( $x_sign ) { $y->_rshift($shift); $x = $y->subtract($x); } return array($this->_normalize($quotient), $this->_normalize($x)); } /** * Divides a BigInteger by a regular integer * * abc / x = a00 / x + b0 / x + c / x * * @param Array $dividend * @param Array $divisor * @return Array * @access private */ function _divide_digit($dividend, $divisor) { $carry = 0; $result = array(); for ($i = count($dividend) - 1; $i >= 0; --$i) { $temp = 0x4000000 * $carry + $dividend[$i]; $result[$i] = (int) ($temp / $divisor); $carry = (int) ($temp - $divisor * $result[$i]); } return array($result, $carry); } /** * Performs modular exponentiation. * * Here's an example: * * modPow($b, $c); * * echo $c->toString(); // outputs 10 * ?> * * * @param Math_BigInteger $e * @param Math_BigInteger $n * @return Math_BigInteger * @access public * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and * and although the approach involving repeated squaring does vastly better, it, too, is impractical * for our purposes. The reason being that division - by far the most complicated and time-consuming * of the basic operations (eg. +,-,*,/) - occurs multiple times within it. * * Modular reductions resolve this issue. Although an individual modular reduction takes more time * then an individual division, when performed in succession (with the same modulo), they're a lot faster. * * The two most commonly used modular reductions are Barrett and Montgomery reduction. Montgomery reduction, * although faster, only works when the gcd of the modulo and of the base being used is 1. In RSA, when the * base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because * the product of two odd numbers is odd), but what about when RSA isn't used? * * In contrast, Barrett reduction has no such constraint. As such, some bigint implementations perform a * Barrett reduction after every operation in the modpow function. Others perform Barrett reductions when the * modulo is even and Montgomery reductions when the modulo is odd. BigInteger.java's modPow method, however, * uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and * the other, a power of two - and recombine them, later. This is the method that this modPow function uses. * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates. */ function modPow($e, $n) { $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs(); if ($e->compare(new Math_BigInteger()) < 0) { $e = $e->abs(); $temp = $this->modInverse($n); if ($temp === false) { return false; } return $this->_normalize($temp->modPow($e, $n)); } switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_powm($this->value, $e->value, $n->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $temp = new Math_BigInteger(); $temp->value = bcpowmod($this->value, $e->value, $n->value, 0); return $this->_normalize($temp); } if ( empty($e->value) ) { $temp = new Math_BigInteger(); $temp->value = array(1); return $this->_normalize($temp); } if ( $e->value == array(1) ) { list(, $temp) = $this->divide($n); return $this->_normalize($temp); } if ( $e->value == array(2) ) { $temp = new Math_BigInteger(); $temp->value = $this->_square($this->value); list(, $temp) = $temp->divide($n); return $this->_normalize($temp); } return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_BARRETT)); // is the modulo odd? if ( $n->value[0] & 1 ) { return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY)); } // if it's not, it's even // find the lowest set bit (eg. the max pow of 2 that divides $n) for ($i = 0; $i < count($n->value); ++$i) { if ( $n->value[$i] ) { $temp = decbin($n->value[$i]); $j = strlen($temp) - strrpos($temp, '1') - 1; $j+= 26 * $i; break; } } // at this point, 2^$j * $n/(2^$j) == $n $mod1 = $n->copy(); $mod1->_rshift($j); $mod2 = new Math_BigInteger(); $mod2->value = array(1); $mod2->_lshift($j); $part1 = ( $mod1->value != array(1) ) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new Math_BigInteger(); $part2 = $this->_slidingWindow($e, $mod2, MATH_BIGINTEGER_POWEROF2); $y1 = $mod2->modInverse($mod1); $y2 = $mod1->modInverse($mod2); $result = $part1->multiply($mod2); $result = $result->multiply($y1); $temp = $part2->multiply($mod1); $temp = $temp->multiply($y2); $result = $result->add($temp); list(, $result) = $result->divide($n); return $this->_normalize($result); } /** * Performs modular exponentiation. * * Alias for Math_BigInteger::modPow() * * @param Math_BigInteger $e * @param Math_BigInteger $n * @return Math_BigInteger * @access public */ function powMod($e, $n) { return $this->modPow($e, $n); } /** * Sliding Window k-ary Modular Exponentiation * * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} / * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}. In a departure from those algorithims, * however, this function performs a modular reduction after every multiplication and squaring operation. * As such, this function has the same preconditions that the reductions being used do. * * @param Math_BigInteger $e * @param Math_BigInteger $n * @param Integer $mode * @return Math_BigInteger * @access private */ function _slidingWindow($e, $n, $mode) { static $window_ranges = array(7, 25, 81, 241, 673, 1793); // from BigInteger.java's oddModPow function //static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1 $e_value = $e->value; $e_length = count($e_value) - 1; $e_bits = decbin($e_value[$e_length]); for ($i = $e_length - 1; $i >= 0; --$i) { $e_bits.= str_pad(decbin($e_value[$i]), 26, '0', STR_PAD_LEFT); } $e_length = strlen($e_bits); // calculate the appropriate window size. // $window_size == 3 if $window_ranges is between 25 and 81, for example. for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); ++$window_size, ++$i); $n_value = $n->value; // precompute $this^0 through $this^$window_size $powers = array(); $powers[1] = $this->_prepareReduce($this->value, $n_value, $mode); $powers[2] = $this->_squareReduce($powers[1], $n_value, $mode); // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end // in a 1. ie. it's supposed to be odd. $temp = 1 << ($window_size - 1); for ($i = 1; $i < $temp; ++$i) { $i2 = $i << 1; $powers[$i2 + 1] = $this->_multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $mode); } $result = array(1); $result = $this->_prepareReduce($result, $n_value, $mode); for ($i = 0; $i < $e_length; ) { if ( !$e_bits[$i] ) { $result = $this->_squareReduce($result, $n_value, $mode); ++$i; } else { for ($j = $window_size - 1; $j > 0; --$j) { if ( !empty($e_bits[$i + $j]) ) { break; } } for ($k = 0; $k <= $j; ++$k) {// eg. the length of substr($e_bits, $i, $j+1) $result = $this->_squareReduce($result, $n_value, $mode); } $result = $this->_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode); $i+=$j + 1; } } $temp = new Math_BigInteger(); $temp->value = $this->_reduce($result, $n_value, $mode); return $temp; } /** * Modular reduction * * For most $modes this will return the remainder. * * @see _slidingWindow() * @access private * @param Array $x * @param Array $n * @param Integer $mode * @return Array */ function _reduce($x, $n, $mode) { switch ($mode) { case MATH_BIGINTEGER_MONTGOMERY: return $this->_montgomery($x, $n); case MATH_BIGINTEGER_BARRETT: return $this->_barrett($x, $n); case MATH_BIGINTEGER_POWEROF2: $lhs = new Math_BigInteger(); $lhs->value = $x; $rhs = new Math_BigInteger(); $rhs->value = $n; return $x->_mod2($n); case MATH_BIGINTEGER_CLASSIC: $lhs = new Math_BigInteger(); $lhs->value = $x; $rhs = new Math_BigInteger(); $rhs->value = $n; list(, $temp) = $lhs->divide($rhs); return $temp->value; case MATH_BIGINTEGER_NONE: return $x; default: // an invalid $mode was provided } } /** * Modular reduction preperation * * @see _slidingWindow() * @access private * @param Array $x * @param Array $n * @param Integer $mode * @return Array */ function _prepareReduce($x, $n, $mode) { if ($mode == MATH_BIGINTEGER_MONTGOMERY) { return $this->_prepMontgomery($x, $n); } return $this->_reduce($x, $n, $mode); } /** * Modular multiply * * @see _slidingWindow() * @access private * @param Array $x * @param Array $y * @param Array $n * @param Integer $mode * @return Array */ function _multiplyReduce($x, $y, $n, $mode) { if ($mode == MATH_BIGINTEGER_MONTGOMERY) { return $this->_montgomeryMultiply($x, $y, $n); } $temp = $this->_multiply($x, false, $y, false); return $this->_reduce($temp[MATH_BIGINTEGER_VALUE], $n, $mode); } /** * Modular square * * @see _slidingWindow() * @access private * @param Array $x * @param Array $n * @param Integer $mode * @return Array */ function _squareReduce($x, $n, $mode) { if ($mode == MATH_BIGINTEGER_MONTGOMERY) { return $this->_montgomeryMultiply($x, $x, $n); } return $this->_reduce($this->_square($x), $n, $mode); } /** * Modulos for Powers of Two * * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1), * we'll just use this function as a wrapper for doing that. * * @see _slidingWindow() * @access private * @param Math_BigInteger * @return Math_BigInteger */ function _mod2($n) { $temp = new Math_BigInteger(); $temp->value = array(1); return $this->bitwise_and($n->subtract($temp)); } /** * Barrett Modular Reduction * * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} / * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly, * so as not to require negative numbers (initially, this script didn't support negative numbers). * * Employs "folding", as described at * {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}. To quote from * it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x." * * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that * usable on account of (1) its not using reasonable radix points as discussed in * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable * radix points, it only works when there are an even number of digits in the denominator. The reason for (2) is that * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line * comments for details. * * @see _slidingWindow() * @access private * @param Array $n * @param Array $m * @return Array */ function _barrett($n, $m) { static $cache = array( MATH_BIGINTEGER_VARIABLE => array(), MATH_BIGINTEGER_DATA => array() ); $m_length = count($m); // if ($this->_compare($n, $this->_square($m)) >= 0) { if (count($n) > 2 * $m_length) { $lhs = new Math_BigInteger(); $rhs = new Math_BigInteger(); $lhs->value = $n; $rhs->value = $m; list(, $temp) = $lhs->divide($rhs); return $temp->value; } // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced if ($m_length < 5) { return $this->_regularBarrett($n, $m); } // n = 2 * m.length if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) { $key = count($cache[MATH_BIGINTEGER_VARIABLE]); $cache[MATH_BIGINTEGER_VARIABLE][] = $m; $lhs = new Math_BigInteger(); $lhs_value = &$lhs->value; $lhs_value = $this->_array_repeat(0, $m_length + ($m_length >> 1)); $lhs_value[] = 1; $rhs = new Math_BigInteger(); $rhs->value = $m; list($u, $m1) = $lhs->divide($rhs); $u = $u->value; $m1 = $m1->value; $cache[MATH_BIGINTEGER_DATA][] = array( 'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1) 'm1'=> $m1 // m.length ); } else { extract($cache[MATH_BIGINTEGER_DATA][$key]); } $cutoff = $m_length + ($m_length >> 1); $lsd = array_slice($n, 0, $cutoff); // m.length + (m.length >> 1) $msd = array_slice($n, $cutoff); // m.length >> 1 $lsd = $this->_trim($lsd); $temp = $this->_multiply($msd, false, $m1, false); $n = $this->_add($lsd, false, $temp[MATH_BIGINTEGER_VALUE], false); // m.length + (m.length >> 1) + 1 if ($m_length & 1) { return $this->_regularBarrett($n[MATH_BIGINTEGER_VALUE], $m); } // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2 $temp = array_slice($n[MATH_BIGINTEGER_VALUE], $m_length - 1); // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2 // if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1 $temp = $this->_multiply($temp, false, $u, false); // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1 // if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) $temp = array_slice($temp[MATH_BIGINTEGER_VALUE], ($m_length >> 1) + 1); // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1 // if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1) $temp = $this->_multiply($temp, false, $m, false); // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit // number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop // following this comment would loop a lot (hence our calling _regularBarrett() in that situation). $result = $this->_subtract($n[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false); while ($this->_compare($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $m, false) >= 0) { $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $m, false); } return $result[MATH_BIGINTEGER_VALUE]; } /** * (Regular) Barrett Modular Reduction * * For numbers with more than four digits Math_BigInteger::_barrett() is faster. The difference between that and this * is that this function does not fold the denominator into a smaller form. * * @see _slidingWindow() * @access private * @param Array $x * @param Array $n * @return Array */ function _regularBarrett($x, $n) { static $cache = array( MATH_BIGINTEGER_VARIABLE => array(), MATH_BIGINTEGER_DATA => array() ); $n_length = count($n); if (count($x) > 2 * $n_length) { $lhs = new Math_BigInteger(); $rhs = new Math_BigInteger(); $lhs->value = $x; $rhs->value = $n; list(, $temp) = $lhs->divide($rhs); return $temp->value; } if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) { $key = count($cache[MATH_BIGINTEGER_VARIABLE]); $cache[MATH_BIGINTEGER_VARIABLE][] = $n; $lhs = new Math_BigInteger(); $lhs_value = &$lhs->value; $lhs_value = $this->_array_repeat(0, 2 * $n_length); $lhs_value[] = 1; $rhs = new Math_BigInteger(); $rhs->value = $n; list($temp, ) = $lhs->divide($rhs); // m.length $cache[MATH_BIGINTEGER_DATA][] = $temp->value; } // 2 * m.length - (m.length - 1) = m.length + 1 $temp = array_slice($x, $n_length - 1); // (m.length + 1) + m.length = 2 * m.length + 1 $temp = $this->_multiply($temp, false, $cache[MATH_BIGINTEGER_DATA][$key], false); // (2 * m.length + 1) - (m.length - 1) = m.length + 2 $temp = array_slice($temp[MATH_BIGINTEGER_VALUE], $n_length + 1); // m.length + 1 $result = array_slice($x, 0, $n_length + 1); // m.length + 1 $temp = $this->_multiplyLower($temp, false, $n, false, $n_length + 1); // $temp == array_slice($temp->_multiply($temp, false, $n, false)->value, 0, $n_length + 1) if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) { $corrector_value = $this->_array_repeat(0, $n_length + 1); $corrector_value[] = 1; $result = $this->_add($result, false, $corrector, false); $result = $result[MATH_BIGINTEGER_VALUE]; } // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits $result = $this->_subtract($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]); while ($this->_compare($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $n, false) > 0) { $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $n, false); } return $result[MATH_BIGINTEGER_VALUE]; } /** * Performs long multiplication up to $stop digits * * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved. * * @see _regularBarrett() * @param Array $x_value * @param Boolean $x_negative * @param Array $y_value * @param Boolean $y_negative * @return Array * @access private */ function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop) { $x_length = count($x_value); $y_length = count($y_value); if ( !$x_length || !$y_length ) { // a 0 is being multiplied return array( MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_SIGN => false ); } if ( $x_length < $y_length ) { $temp = $x_value; $x_value = $y_value; $y_value = $temp; $x_length = count($x_value); $y_length = count($y_value); } $product_value = $this->_array_repeat(0, $x_length + $y_length); // the following for loop could be removed if the for loop following it // (the one with nested for loops) initially set $i to 0, but // doing so would also make the result in one set of unnecessary adds, // since on the outermost loops first pass, $product->value[$k] is going // to always be 0 $carry = 0; for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0 $carry = (int) ($temp / 0x4000000); $product_value[$j] = (int) ($temp - 0x4000000 * $carry); } if ($j < $stop) { $product_value[$j] = $carry; } // the above for loop is what the previous comment was talking about. the // following for loop is the "one with nested for loops" for ($i = 1; $i < $y_length; ++$i) { $carry = 0; for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) { $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; $carry = (int) ($temp / 0x4000000); $product_value[$k] = (int) ($temp - 0x4000000 * $carry); } if ($k < $stop) { $product_value[$k] = $carry; } } return array( MATH_BIGINTEGER_VALUE => $this->_trim($product_value), MATH_BIGINTEGER_SIGN => $x_negative != $y_negative ); } /** * Montgomery Modular Reduction * * ($x->_prepMontgomery($n))->_montgomery($n) yields $x % $n. * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function * to work correctly. * * @see _prepMontgomery() * @see _slidingWindow() * @access private * @param Array $x * @param Array $n * @return Array */ function _montgomery($x, $n) { static $cache = array( MATH_BIGINTEGER_VARIABLE => array(), MATH_BIGINTEGER_DATA => array() ); if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) { $key = count($cache[MATH_BIGINTEGER_VARIABLE]); $cache[MATH_BIGINTEGER_VARIABLE][] = $x; $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($n); } $k = count($n); $result = array(MATH_BIGINTEGER_VALUE => $x); for ($i = 0; $i < $k; ++$i) { $temp = $result[MATH_BIGINTEGER_VALUE][$i] * $cache[MATH_BIGINTEGER_DATA][$key]; $temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000))); $temp = $this->_regularMultiply(array($temp), $n); $temp = array_merge($this->_array_repeat(0, $i), $temp); $result = $this->_add($result[MATH_BIGINTEGER_VALUE], false, $temp, false); } $result[MATH_BIGINTEGER_VALUE] = array_slice($result[MATH_BIGINTEGER_VALUE], $k); if ($this->_compare($result, false, $n, false) >= 0) { $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], false, $n, false); } return $result[MATH_BIGINTEGER_VALUE]; } /** * Montgomery Multiply * * Interleaves the montgomery reduction and long multiplication algorithms together as described in * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36} * * @see _prepMontgomery() * @see _montgomery() * @access private * @param Array $x * @param Array $y * @param Array $m * @return Array */ function _montgomeryMultiply($x, $y, $m) { $temp = $this->_multiply($x, false, $y, false); return $this->_montgomery($temp[MATH_BIGINTEGER_VALUE], $m); static $cache = array( MATH_BIGINTEGER_VARIABLE => array(), MATH_BIGINTEGER_DATA => array() ); if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) { $key = count($cache[MATH_BIGINTEGER_VARIABLE]); $cache[MATH_BIGINTEGER_VARIABLE][] = $m; $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($m); } $n = max(count($x), count($y), count($m)); $x = array_pad($x, $n, 0); $y = array_pad($y, $n, 0); $m = array_pad($m, $n, 0); $a = array(MATH_BIGINTEGER_VALUE => $this->_array_repeat(0, $n + 1)); for ($i = 0; $i < $n; ++$i) { $temp = $a[MATH_BIGINTEGER_VALUE][0] + $x[$i] * $y[0]; $temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000))); $temp = $temp * $cache[MATH_BIGINTEGER_DATA][$key]; $temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000))); $temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false); $a = $this->_add($a[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false); $a[MATH_BIGINTEGER_VALUE] = array_slice($a[MATH_BIGINTEGER_VALUE], 1); } if ($this->_compare($a[MATH_BIGINTEGER_VALUE], false, $m, false) >= 0) { $a = $this->_subtract($a[MATH_BIGINTEGER_VALUE], false, $m, false); } return $a[MATH_BIGINTEGER_VALUE]; } /** * Prepare a number for use in Montgomery Modular Reductions * * @see _montgomery() * @see _slidingWindow() * @access private * @param Array $x * @param Array $n * @return Array */ function _prepMontgomery($x, $n) { $lhs = new Math_BigInteger(); $lhs->value = array_merge($this->_array_repeat(0, count($n)), $x); $rhs = new Math_BigInteger(); $rhs->value = $n; list(, $temp) = $lhs->divide($rhs); return $temp->value; } /** * Modular Inverse of a number mod 2**26 (eg. 67108864) * * Based off of the bnpInvDigit function implemented and justified in the following URL: * * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js} * * The following URL provides more info: * * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85} * * As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields * int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't * auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that * the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the * maximum possible $x is 26 bits and the maximum $result is 16 bits. Thus, we have to be able to handle up to * 40 bits, which only 64-bit floating points will support. * * Thanks to Pedro Gimeno Fortea for input! * * @see _montgomery() * @access private * @param Array $x * @return Integer */ function _modInverse67108864($x) // 2**26 == 67108864 { $x = -$x[0]; $result = $x & 0x3; // x**-1 mod 2**2 $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4 $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8 $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16 $result = fmod($result * (2 - fmod($x * $result, 0x4000000)), 0x4000000); // x**-1 mod 2**26 return $result & 0x3FFFFFF; } /** * Calculates modular inverses. * * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. * * Here's an example: * * modInverse($b); * echo $c->toString(); // outputs 4 * * echo "\r\n"; * * $d = $a->multiply($c); * list(, $d) = $d->divide($b); * echo $d; // outputs 1 (as per the definition of modular inverse) * ?> * * * @param Math_BigInteger $n * @return mixed false, if no modular inverse exists, Math_BigInteger, otherwise. * @access public * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information. */ function modInverse($n) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_invert($this->value, $n->value); return ( $temp->value === false ) ? false : $this->_normalize($temp); } static $zero, $one; if (!isset($zero)) { $zero = new Math_BigInteger(); $one = new Math_BigInteger(1); } // $x mod $n == $x mod -$n. $n = $n->abs(); if ($this->compare($zero) < 0) { $temp = $this->abs(); $temp = $temp->modInverse($n); return $negated === false ? false : $this->_normalize($n->subtract($temp)); } extract($this->extendedGCD($n)); if (!$gcd->equals($one)) { return false; } $x = $x->compare($zero) < 0 ? $x->add($n) : $x; return $this->compare($zero) < 0 ? $this->_normalize($n->subtract($x)) : $this->_normalize($x); } /** * Calculates the greatest common divisor and Bézout's identity. * * Say you have 693 and 609. The GCD is 21. Bézout's identity states that there exist integers x and y such that * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which * combination is returned is dependant upon which mode is in use. See * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bézout's identity - Wikipedia} for more information. * * Here's an example: * * extendedGCD($b)); * * echo $gcd->toString() . "\r\n"; // outputs 21 * echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21 * ?> * * * @param Math_BigInteger $n * @return Math_BigInteger * @access public * @internal Calculates the GCD using the binary xGCD algorithim described in * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}. As the text above 14.61 notes, * the more traditional algorithim requires "relatively costly multiple-precision divisions". */ function extendedGCD($n) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: extract(gmp_gcdext($this->value, $n->value)); return array( 'gcd' => $this->_normalize(new Math_BigInteger($g)), 'x' => $this->_normalize(new Math_BigInteger($s)), 'y' => $this->_normalize(new Math_BigInteger($t)) ); case MATH_BIGINTEGER_MODE_BCMATH: // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway. as is, // the basic extended euclidean algorithim is what we're using. $u = $this->value; $v = $n->value; $a = '1'; $b = '0'; $c = '0'; $d = '1'; while (bccomp($v, '0', 0) != 0) { $q = bcdiv($u, $v, 0); $temp = $u; $u = $v; $v = bcsub($temp, bcmul($v, $q, 0), 0); $temp = $a; $a = $c; $c = bcsub($temp, bcmul($a, $q, 0), 0); $temp = $b; $b = $d; $d = bcsub($temp, bcmul($b, $q, 0), 0); } return array( 'gcd' => $this->_normalize(new Math_BigInteger($u)), 'x' => $this->_normalize(new Math_BigInteger($a)), 'y' => $this->_normalize(new Math_BigInteger($b)) ); } $y = $n->copy(); $x = $this->copy(); $g = new Math_BigInteger(); $g->value = array(1); while ( !(($x->value[0] & 1)|| ($y->value[0] & 1)) ) { $x->_rshift(1); $y->_rshift(1); $g->_lshift(1); } $u = $x->copy(); $v = $y->copy(); $a = new Math_BigInteger(); $b = new Math_BigInteger(); $c = new Math_BigInteger(); $d = new Math_BigInteger(); $a->value = $d->value = $g->value = array(1); $b->value = $c->value = array(); while ( !empty($u->value) ) { while ( !($u->value[0] & 1) ) { $u->_rshift(1); if ( (!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1)) ) { $a = $a->add($y); $b = $b->subtract($x); } $a->_rshift(1); $b->_rshift(1); } while ( !($v->value[0] & 1) ) { $v->_rshift(1); if ( (!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1)) ) { $c = $c->add($y); $d = $d->subtract($x); } $c->_rshift(1); $d->_rshift(1); } if ($u->compare($v) >= 0) { $u = $u->subtract($v); $a = $a->subtract($c); $b = $b->subtract($d); } else { $v = $v->subtract($u); $c = $c->subtract($a); $d = $d->subtract($b); } } return array( 'gcd' => $this->_normalize($g->multiply($v)), 'x' => $this->_normalize($c), 'y' => $this->_normalize($d) ); } /** * Calculates the greatest common divisor * * Say you have 693 and 609. The GCD is 21. * * Here's an example: * * extendedGCD($b); * * echo $gcd->toString() . "\r\n"; // outputs 21 * ?> * * * @param Math_BigInteger $n * @return Math_BigInteger * @access public */ function gcd($n) { extract($this->extendedGCD($n)); return $gcd; } /** * Absolute value. * * @return Math_BigInteger * @access public */ function abs() { $temp = new Math_BigInteger(); switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $temp->value = gmp_abs($this->value); break; case MATH_BIGINTEGER_MODE_BCMATH: $temp->value = (bccomp($this->value, '0', 0) < 0) ? substr($this->value, 1) : $this->value; break; default: $temp->value = $this->value; } return $temp; } /** * Compares two numbers. * * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this is * demonstrated thusly: * * $x > $y: $x->compare($y) > 0 * $x < $y: $x->compare($y) < 0 * $x == $y: $x->compare($y) == 0 * * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). * * @param Math_BigInteger $x * @return Integer < 0 if $this is less than $x; > 0 if $this is greater than $x, and 0 if they are equal. * @access public * @see equals() * @internal Could return $this->subtract($x), but that's not as fast as what we do do. */ function compare($y) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: return gmp_cmp($this->value, $y->value); case MATH_BIGINTEGER_MODE_BCMATH: return bccomp($this->value, $y->value, 0); } return $this->_compare($this->value, $this->is_negative, $y->value, $y->is_negative); } /** * Compares two numbers. * * @param Array $x_value * @param Boolean $x_negative * @param Array $y_value * @param Boolean $y_negative * @return Integer * @see compare() * @access private */ function _compare($x_value, $x_negative, $y_value, $y_negative) { if ( $x_negative != $y_negative ) { return ( !$x_negative && $y_negative ) ? 1 : -1; } $result = $x_negative ? -1 : 1; if ( count($x_value) != count($y_value) ) { return ( count($x_value) > count($y_value) ) ? $result : -$result; } $size = max(count($x_value), count($y_value)); $x_value = array_pad($x_value, $size, 0); $y_value = array_pad($y_value, $size, 0); for ($i = count($x_value) - 1; $i >= 0; --$i) { if ($x_value[$i] != $y_value[$i]) { return ( $x_value[$i] > $y_value[$i] ) ? $result : -$result; } } return 0; } /** * Tests the equality of two numbers. * * If you need to see if one number is greater than or less than another number, use Math_BigInteger::compare() * * @param Math_BigInteger $x * @return Boolean * @access public * @see compare() */ function equals($x) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: return gmp_cmp($this->value, $x->value) == 0; default: return $this->value === $x->value && $this->is_negative == $x->is_negative; } } /** * Set Precision * * Some bitwise operations give different results depending on the precision being used. Examples include left * shift, not, and rotates. * * @param Math_BigInteger $x * @access public * @return Math_BigInteger */ function setPrecision($bits) { $this->precision = $bits; if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ) { $this->bitmask = new Math_BigInteger(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256); } else { $this->bitmask = new Math_BigInteger(bcpow('2', $bits, 0)); } $temp = $this->_normalize($this); $this->value = $temp->value; } /** * Logical And * * @param Math_BigInteger $x * @access public * @internal Implemented per a request by Lluis Pamies i Juarez * @return Math_BigInteger */ function bitwise_and($x) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_and($this->value, $x->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $left = $this->toBytes(); $right = $x->toBytes(); $length = max(strlen($left), strlen($right)); $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); return $this->_normalize(new Math_BigInteger($left & $right, 256)); } $result = $this->copy(); $length = min(count($x->value), count($this->value)); $result->value = array_slice($result->value, 0, $length); for ($i = 0; $i < $length; ++$i) { $result->value[$i] = $result->value[$i] & $x->value[$i]; } return $this->_normalize($result); } /** * Logical Or * * @param Math_BigInteger $x * @access public * @internal Implemented per a request by Lluis Pamies i Juarez * @return Math_BigInteger */ function bitwise_or($x) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_or($this->value, $x->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $left = $this->toBytes(); $right = $x->toBytes(); $length = max(strlen($left), strlen($right)); $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); return $this->_normalize(new Math_BigInteger($left | $right, 256)); } $length = max(count($this->value), count($x->value)); $result = $this->copy(); $result->value = array_pad($result->value, 0, $length); $x->value = array_pad($x->value, 0, $length); for ($i = 0; $i < $length; ++$i) { $result->value[$i] = $this->value[$i] | $x->value[$i]; } return $this->_normalize($result); } /** * Logical Exclusive-Or * * @param Math_BigInteger $x * @access public * @internal Implemented per a request by Lluis Pamies i Juarez * @return Math_BigInteger */ function bitwise_xor($x) { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_xor($this->value, $x->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $left = $this->toBytes(); $right = $x->toBytes(); $length = max(strlen($left), strlen($right)); $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); return $this->_normalize(new Math_BigInteger($left ^ $right, 256)); } $length = max(count($this->value), count($x->value)); $result = $this->copy(); $result->value = array_pad($result->value, 0, $length); $x->value = array_pad($x->value, 0, $length); for ($i = 0; $i < $length; ++$i) { $result->value[$i] = $this->value[$i] ^ $x->value[$i]; } return $this->_normalize($result); } /** * Logical Not * * @access public * @internal Implemented per a request by Lluis Pamies i Juarez * @return Math_BigInteger */ function bitwise_not() { // calculuate "not" without regard to $this->precision // (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0) $temp = $this->toBytes(); $pre_msb = decbin(ord($temp[0])); $temp = ~$temp; $msb = decbin(ord($temp[0])); if (strlen($msb) == 8) { $msb = substr($msb, strpos($msb, '0')); } $temp[0] = chr(bindec($msb)); // see if we need to add extra leading 1's $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8; $new_bits = $this->precision - $current_bits; if ($new_bits <= 0) { return $this->_normalize(new Math_BigInteger($temp, 256)); } // generate as many leading 1's as we need to. $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3); $this->_base256_lshift($leading_ones, $current_bits); $temp = str_pad($temp, ceil($this->bits / 8), chr(0), STR_PAD_LEFT); return $this->_normalize(new Math_BigInteger($leading_ones | $temp, 256)); } /** * Logical Right Shift * * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift. * * @param Integer $shift * @return Math_BigInteger * @access public * @internal The only version that yields any speed increases is the internal version. */ function bitwise_rightShift($shift) { $temp = new Math_BigInteger(); switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: static $two; if (!isset($two)) { $two = gmp_init('2'); } $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift)); break; case MATH_BIGINTEGER_MODE_BCMATH: $temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0); break; default: // could just replace _lshift with this, but then all _lshift() calls would need to be rewritten // and I don't want to do that... $temp->value = $this->value; $temp->_rshift($shift); } return $this->_normalize($temp); } /** * Logical Left Shift * * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. * * @param Integer $shift * @return Math_BigInteger * @access public * @internal The only version that yields any speed increases is the internal version. */ function bitwise_leftShift($shift) { $temp = new Math_BigInteger(); switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: static $two; if (!isset($two)) { $two = gmp_init('2'); } $temp->value = gmp_mul($this->value, gmp_pow($two, $shift)); break; case MATH_BIGINTEGER_MODE_BCMATH: $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0); break; default: // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten // and I don't want to do that... $temp->value = $this->value; $temp->_lshift($shift); } return $this->_normalize($temp); } /** * Logical Left Rotate * * Instead of the top x bits being dropped they're appended to the shifted bit string. * * @param Integer $shift * @return Math_BigInteger * @access public */ function bitwise_leftRotate($shift) { $bits = $this->toBytes(); if ($this->precision > 0) { $precision = $this->precision; if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) { $mask = $this->bitmask->subtract(new Math_BigInteger(1)); $mask = $mask->toBytes(); } else { $mask = $this->bitmask->toBytes(); } } else { $temp = ord($bits[0]); for ($i = 0; $temp >> $i; ++$i); $precision = 8 * strlen($bits) - 8 + $i; $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3); } if ($shift < 0) { $shift+= $precision; } $shift%= $precision; if (!$shift) { return $this->copy(); } $left = $this->bitwise_leftShift($shift); $left = $left->bitwise_and(new Math_BigInteger($mask, 256)); $right = $this->bitwise_rightShift($precision - $shift); $result = MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right); return $this->_normalize($result); } /** * Logical Right Rotate * * Instead of the bottom x bits being dropped they're prepended to the shifted bit string. * * @param Integer $shift * @return Math_BigInteger * @access public */ function bitwise_rightRotate($shift) { return $this->bitwise_leftRotate(-$shift); } /** * Set random number generator function * * $generator should be the name of a random generating function whose first parameter is the minimum * value and whose second parameter is the maximum value. If this function needs to be seeded, it should * be seeded prior to calling Math_BigInteger::random() or Math_BigInteger::randomPrime() * * If the random generating function is not explicitly set, it'll be assumed to be mt_rand(). * * @see random() * @see randomPrime() * @param optional String $generator * @access public */ function setRandomGenerator($generator) { $this->generator = $generator; } /** * Generate a random number * * @param optional Integer $min * @param optional Integer $max * @return Math_BigInteger * @access public */ function random($min = false, $max = false) { if ($min === false) { $min = new Math_BigInteger(0); } if ($max === false) { $max = new Math_BigInteger(0x7FFFFFFF); } $compare = $max->compare($min); if (!$compare) { return $this->_normalize($min); } else if ($compare < 0) { // if $min is bigger then $max, swap $min and $max $temp = $max; $max = $min; $min = $temp; } $generator = $this->generator; $max = $max->subtract($min); $max = ltrim($max->toBytes(), chr(0)); $size = strlen($max) - 1; $random = ''; $bytes = $size & 1; for ($i = 0; $i < $bytes; ++$i) { $random.= chr($generator(0, 255)); } $blocks = $size >> 1; for ($i = 0; $i < $blocks; ++$i) { // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems $random.= pack('n', $generator(0, 0xFFFF)); } $temp = new Math_BigInteger($random, 256); if ($temp->compare(new Math_BigInteger(substr($max, 1), 256)) > 0) { $random = chr($generator(0, ord($max[0]) - 1)) . $random; } else { $random = chr($generator(0, ord($max[0]) )) . $random; } $random = new Math_BigInteger($random, 256); return $this->_normalize($random->add($min)); } /** * Generate a random prime number. * * If there's not a prime within the given range, false will be returned. If more than $timeout seconds have elapsed, * give up and return false. * * @param optional Integer $min * @param optional Integer $max * @param optional Integer $timeout * @return Math_BigInteger * @access public * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}. */ function randomPrime($min = false, $max = false, $timeout = false) { $compare = $max->compare($min); if (!$compare) { return $min; } else if ($compare < 0) { // if $min is bigger then $max, swap $min and $max $temp = $max; $max = $min; $min = $temp; } // gmp_nextprime() requires PHP 5 >= 5.2.0 per . if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) { // we don't rely on Math_BigInteger::random()'s min / max when gmp_nextprime() is being used since this function // does its own checks on $max / $min when gmp_nextprime() is used. When gmp_nextprime() is not used, however, // the same $max / $min checks are not performed. if ($min === false) { $min = new Math_BigInteger(0); } if ($max === false) { $max = new Math_BigInteger(0x7FFFFFFF); } $x = $this->random($min, $max); $x->value = gmp_nextprime($x->value); if ($x->compare($max) <= 0) { return $x; } $x->value = gmp_nextprime($min->value); if ($x->compare($max) <= 0) { return $x; } return false; } static $one, $two; if (!isset($one)) { $one = new Math_BigInteger(1); $two = new Math_BigInteger(2); } $start = time(); $x = $this->random($min, $max); if ($x->equals($two)) { return $x; } $x->_make_odd(); if ($x->compare($max) > 0) { // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range if ($min->equals($max)) { return false; } $x = $min->copy(); $x->_make_odd(); } $initial_x = $x->copy(); while (true) { if ($timeout !== false && time() - $start > $timeout) { return false; } if ($x->isPrime()) { return $x; } $x = $x->add($two); if ($x->compare($max) > 0) { $x = $min->copy(); if ($x->equals($two)) { return $x; } $x->_make_odd(); } if ($x->equals($initial_x)) { return false; } } } /** * Make the current number odd * * If the current number is odd it'll be unchanged. If it's even, one will be added to it. * * @see randomPrime() * @access private */ function _make_odd() { switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: gmp_setbit($this->value, 0); break; case MATH_BIGINTEGER_MODE_BCMATH: if ($this->value[strlen($this->value) - 1] % 2 == 0) { $this->value = bcadd($this->value, '1'); } break; default: $this->value[0] |= 1; } } /** * Checks a numer to see if it's prime * * Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the * $t parameter is distributability. Math_BigInteger::randomPrime() can be distributed accross multiple pageloads * on a website instead of just one. * * @param optional Integer $t * @return Boolean * @access public * @internal Uses the * {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24}. */ function isPrime($t = false) { $length = strlen($this->toBytes()); if (!$t) { // see HAC 4.49 "Note (controlling the error probability)" if ($length >= 163) { $t = 2; } // floor(1300 / 8) else if ($length >= 106) { $t = 3; } // floor( 850 / 8) else if ($length >= 81 ) { $t = 4; } // floor( 650 / 8) else if ($length >= 68 ) { $t = 5; } // floor( 550 / 8) else if ($length >= 56 ) { $t = 6; } // floor( 450 / 8) else if ($length >= 50 ) { $t = 7; } // floor( 400 / 8) else if ($length >= 43 ) { $t = 8; } // floor( 350 / 8) else if ($length >= 37 ) { $t = 9; } // floor( 300 / 8) else if ($length >= 31 ) { $t = 12; } // floor( 250 / 8) else if ($length >= 25 ) { $t = 15; } // floor( 200 / 8) else if ($length >= 18 ) { $t = 18; } // floor( 150 / 8) else { $t = 27; } } // ie. gmp_testbit($this, 0) // ie. isEven() or !isOdd() switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: return gmp_prob_prime($this->value, $t) != 0; case MATH_BIGINTEGER_MODE_BCMATH: if ($this->value === '2') { return true; } if ($this->value[strlen($this->value) - 1] % 2 == 0) { return false; } break; default: if ($this->value == array(2)) { return true; } if (~$this->value[0] & 1) { return false; } } static $primes, $zero, $one, $two; if (!isset($primes)) { $primes = array( 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 ); if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL ) { for ($i = 0; $i < count($primes); ++$i) { $primes[$i] = new Math_BigInteger($primes[$i]); } } $zero = new Math_BigInteger(); $one = new Math_BigInteger(1); $two = new Math_BigInteger(2); } if ($this->equals($one)) { return false; } // see HAC 4.4.1 "Random search for probable primes" if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL ) { foreach ($primes as $prime) { list(, $r) = $this->divide($prime); if ($r->equals($zero)) { return $this->equals($prime); } } } else { $value = $this->value; foreach ($primes as $prime) { list(, $r) = $this->_divide_digit($value, $prime); if (!$r) { return count($value) == 1 && $value[0] == $prime; } } } $n = $this->copy(); $n_1 = $n->subtract($one); $n_2 = $n->subtract($two); $r = $n_1->copy(); $r_value = $r->value; // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) { $s = 0; // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier while ($r->value[strlen($r->value) - 1] % 2 == 0) { $r->value = bcdiv($r->value, '2', 0); ++$s; } } else { for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) { $temp = ~$r_value[$i] & 0xFFFFFF; for ($j = 1; ($temp >> $j) & 1; ++$j); if ($j != 25) { break; } } $s = 26 * $i + $j - 1; $r->_rshift($s); } for ($i = 0; $i < $t; ++$i) { $a = $this->random($two, $n_2); $y = $a->modPow($r, $n); if (!$y->equals($one) && !$y->equals($n_1)) { for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) { $y = $y->modPow($two, $n); if ($y->equals($one)) { return false; } } if (!$y->equals($n_1)) { return false; } } } return true; } /** * Logical Left Shift * * Shifts BigInteger's by $shift bits. * * @param Integer $shift * @access private */ function _lshift($shift) { if ( $shift == 0 ) { return; } $num_digits = (int) ($shift / 26); $shift %= 26; $shift = 1 << $shift; $carry = 0; for ($i = 0; $i < count($this->value); ++$i) { $temp = $this->value[$i] * $shift + $carry; $carry = (int) ($temp / 0x4000000); $this->value[$i] = (int) ($temp - $carry * 0x4000000); } if ( $carry ) { $this->value[] = $carry; } while ($num_digits--) { array_unshift($this->value, 0); } } /** * Logical Right Shift * * Shifts BigInteger's by $shift bits. * * @param Integer $shift * @access private */ function _rshift($shift) { if ($shift == 0) { return; } $num_digits = (int) ($shift / 26); $shift %= 26; $carry_shift = 26 - $shift; $carry_mask = (1 << $shift) - 1; if ( $num_digits ) { $this->value = array_slice($this->value, $num_digits); } $carry = 0; for ($i = count($this->value) - 1; $i >= 0; --$i) { $temp = $this->value[$i] >> $shift | $carry; $carry = ($this->value[$i] & $carry_mask) << $carry_shift; $this->value[$i] = $temp; } $this->value = $this->_trim($this->value); } /** * Normalize * * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision * * @param Math_BigInteger * @return Math_BigInteger * @see _trim() * @access private */ function _normalize($result) { $result->precision = $this->precision; $result->bitmask = $this->bitmask; switch ( MATH_BIGINTEGER_MODE ) { case MATH_BIGINTEGER_MODE_GMP: if (!empty($result->bitmask->value)) { $result->value = gmp_and($result->value, $result->bitmask->value); } return $result; case MATH_BIGINTEGER_MODE_BCMATH: if (!empty($result->bitmask->value)) { $result->value = bcmod($result->value, $result->bitmask->value); } return $result; } $value = &$result->value; if ( !count($value) ) { return $result; } $value = $this->_trim($value); if (!empty($result->bitmask->value)) { $length = min(count($value), count($this->bitmask->value)); $value = array_slice($value, 0, $length); for ($i = 0; $i < $length; ++$i) { $value[$i] = $value[$i] & $this->bitmask->value[$i]; } } return $result; } /** * Trim * * Removes leading zeros * * @return Math_BigInteger * @access private */ function _trim($value) { for ($i = count($value) - 1; $i >= 0; --$i) { if ( $value[$i] ) { break; } unset($value[$i]); } return $value; } /** * Array Repeat * * @param $input Array * @param $multiplier mixed * @return Array * @access private */ function _array_repeat($input, $multiplier) { return ($multiplier) ? array_fill(0, $multiplier, $input) : array(); } /** * Logical Left Shift * * Shifts binary strings $shift bits, essentially multiplying by 2**$shift. * * @param $x String * @param $shift Integer * @return String * @access private */ function _base256_lshift(&$x, $shift) { if ($shift == 0) { return; } $num_bytes = $shift >> 3; // eg. floor($shift/8) $shift &= 7; // eg. $shift % 8 $carry = 0; for ($i = strlen($x) - 1; $i >= 0; --$i) { $temp = ord($x[$i]) << $shift | $carry; $x[$i] = chr($temp); $carry = $temp >> 8; } $carry = ($carry != 0) ? chr($carry) : ''; $x = $carry . $x . str_repeat(chr(0), $num_bytes); } /** * Logical Right Shift * * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder. * * @param $x String * @param $shift Integer * @return String * @access private */ function _base256_rshift(&$x, $shift) { if ($shift == 0) { $x = ltrim($x, chr(0)); return ''; } $num_bytes = $shift >> 3; // eg. floor($shift/8) $shift &= 7; // eg. $shift % 8 $remainder = ''; if ($num_bytes) { $start = $num_bytes > strlen($x) ? -strlen($x) : -$num_bytes; $remainder = substr($x, $start); $x = substr($x, 0, -$num_bytes); } $carry = 0; $carry_shift = 8 - $shift; for ($i = 0; $i < strlen($x); ++$i) { $temp = (ord($x[$i]) >> $shift) | $carry; $carry = (ord($x[$i]) << $carry_shift) & 0xFF; $x[$i] = chr($temp); } $x = ltrim($x, chr(0)); $remainder = chr($carry >> $carry_shift) . $remainder; return ltrim($remainder, chr(0)); } // one quirk about how the following functions are implemented is that PHP defines N to be an unsigned long // at 32-bits, while java's longs are 64-bits. /** * Converts 32-bit integers to bytes. * * @param Integer $x * @return String * @access private */ function _int2bytes($x) { return ltrim(pack('N', $x), chr(0)); } /** * Converts bytes to 32-bit integers * * @param String $x * @return Integer * @access private */ function _bytes2int($x) { $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT)); return $temp['int']; } }spotweb-20130826+dfsg2/Mobile_Detect.php000066400000000000000000000344171226620506000176650ustar00rootroot00000000000000isMobile() or $detect->isTablet() * * For more specific usage see the documentation navigate to: * http://code.google.com/p/php-mobile-detect/wiki/Mobile_Detect * * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ class Mobile_Detect { protected $detectionRules; protected $userAgent = null; protected $accept = null; // Assume the visitor has a desktop environment. protected $isMobile = false; protected $isTablet = false; protected $phoneDeviceName = null; protected $tabletDevicename = null; protected $operatingSystemName = null; protected $userAgentName = null; // List of mobile devices (phones) protected $phoneDevices = array( 'iPhone' => '(iPhone.*Mobile|iPod|iTunes)', 'BlackBerry' => 'BlackBerry|rim[0-9]+', 'HTC' => 'HTC|HTC.*(6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT', 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus', 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35', 'Motorola' => '\bDroid\b.*Build|DROIDX|HRI39|MOT\-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT909|XT910|XT912|XT928', 'Samsung' => 'Samsung|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9300 |GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-P6810|GT-P7100|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100', 'Sony' => 'E10i|SonyEricsson|SonyEricssonLT15iv', 'Asus' => 'Asus.*Galaxy', 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ; @todo - complete the regex. 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;) 'GenericPhone' => '(mmp|pocket|psp|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|wap|nokia|Series40|Series60|S60|SonyEricsson|N900|PPC;|MAUI.*WAP.*Browser|LG-P500)' ); // List of tablet devices. protected $tabletDevices = array( 'BlackBerryTablet' => 'PlayBook|RIM Tablet', 'iPad' => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic. 'Kindle' => 'Kindle|Silk.*Accelerated', 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|GT-P1000|GT-P1010|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P1000|GT-P3100|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7300|GT-P7320|GT-P7500|GT-P7510|GT-P7511', 'HTCtablet' => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200', 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617', 'AsusTablet' => 'Transformer|TF101', 'NookTablet' => 'NookColor|nook browser|BNTV250A|LogicPD Zoom2', 'AcerTablet' => 'Android.*\b(A100|A101|A200|A500|A501|A510|W500|W500P|W501|W501P)\b', 'YarvikTablet' => 'Android.*(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468)', 'GenericTablet' => 'Tablet(?!.*PC)|ViewPad7|LG-V909|MID7015|BNTV250A|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b', ); // List of mobile Operating Systems. protected $operatingSystems = array( 'AndroidOS' => '(android.*mobile|android(?!.*mobile))', 'BlackBerryOS' => '(blackberry|rim tablet os)', 'PalmOS' => '(avantgo|blazer|elaine|hiptop|palm|plucker|xiino)', 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|\bS60\b', 'WindowsMobileOS' => 'IEMobile|Windows Phone|Windows CE.*(PPC|Smartphone)|MSIEMobile|Window Mobile|XBLWP7', 'iOS' => '(iphone|ipod|ipad)', 'FlashLiteOS' => '', 'JavaOS' => '', 'NokiaOS' => '', 'webOS' => '', 'badaOS' => '\bBada\b', 'BREWOS' => '', ); // List of mobile User Agents. protected $userAgents = array( 'Chrome' => '\bCrMo\b|Chrome\/[.0-9]* Mobile', 'Dolfin' => '\bDolfin\b', 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera', 'Skyfire' => 'skyfire', 'IE' => 'IEMobile|MSIEMobile', 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile', 'Bolt' => 'bolt', 'TeaShark' => 'teashark', 'Blazer' => 'Blazer', 'Safari' => 'Mobile.*Safari|Safari.*Mobile', 'Midori' => 'midori', 'GenericBrowser' => 'NokiaBrowser|OviBrowser|SEMC.*Browser' ); function __construct(){ // Merge all rules together. $this->detectionRules = array_merge( $this->phoneDevices, $this->tabletDevices, $this->operatingSystems, $this->userAgents ); $this->userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null; $this->accept = isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : null; if ( isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_X_WAP_CLIENTID']) || isset($_SERVER['HTTP_WAP_CONNECTION']) || isset($_SERVER['HTTP_PROFILE']) || isset($_SERVER['HTTP_X_OPERAMINI_PHONE_UA']) || // Reported by Nokia devices (eg. C3) isset($_SERVER['HTTP_X_NOKIA_IPADDRESS']) || isset($_SERVER['HTTP_X_NOKIA_GATEWAY_ID']) || isset($_SERVER['HTTP_X_ORANGE_ID']) || isset($_SERVER['HTTP_X_VODAFONE_3GPDPCONTEXT']) || isset($_SERVER['HTTP_X_HUAWEI_USERID']) || isset($_SERVER['HTTP_UA_OS']) || // Reported by Windows Smartphones (isset($_SERVER['HTTP_UA_CPU']) && $_SERVER['HTTP_UA_CPU'] == 'ARM') // Seen this on a HTC ) { $this->isMobile = true; } elseif (!empty($this->accept) && (strpos($this->accept, 'text/vnd.wap.wml') !== false || strpos($this->accept, 'application/vnd.wap.xhtml+xml') !== false)) { $this->isMobile = true; } else { $this->_detect(); } } public function getRules() { return $this->detectionRules; } /** * Magic overloading method. * * @method boolean is[...]() * @param string $name * @param array $arguments * @return mixed */ public function __call($name, $arguments) { $key = substr($name, 2); return $this->_detect($key); } /** * Private method that does the detection of the * mobile devices. * * @param string $key * @return boolean|null */ private function _detect($key='') { if(empty($key)){ // Begin general search. foreach($this->detectionRules as $_regex){ if(empty($_regex)){ continue; } if(preg_match('/'.$_regex.'/is', $this->userAgent)){ $this->isMobile = true; return true; } } return false; } else { // Search for a certain key. // Make the keys lowecase so we can match: isIphone(), isiPhone(), isiphone(), etc. $key = strtolower($key); $_rules = array_change_key_case($this->detectionRules); if(array_key_exists($key, $_rules)){ if(empty($_rules[$key])){ return null; } if(preg_match('/'.$_rules[$key].'/is', $this->userAgent)){ $this->isMobile = true; return true; } else { return false; } } else { trigger_error("Method $key is not defined", E_USER_WARNING); } return false; } } /** * Check if the device is mobile. * Returns true if any type of mobile device detected, including special ones * @return bool */ public function isMobile() { return $this->isMobile; } /** * Check if the device is a tablet. * Return true if any type of tablet device is detected. * @return boolean */ public function isTablet() { foreach($this->tabletDevices as $_regex){ if(preg_match('/'.$_regex.'/is', $this->userAgent)){ $this->isTablet = true; return true; } } return false; } }spotweb-20130826+dfsg2/README.md000077500000000000000000000036251226620506000157340ustar00rootroot00000000000000#SpotWeb Spotweb is a webbased usenet binary resource indexer based on the protocol and development done by Spotnet (http://github.com/spotnet). Spotweb requires an operational webserver with PHP5 installed, it uses either an MySQL or an PostgreSQL database to store it's contents in. ## Features Spotweb is one of the most-featured Spotnet clients currently available, featuring among other things: * Fast * Customizable filter system from within the system * Posting of comments and spots * Showing and filtering on new spots since the last view * Watchlist * Easy to download multiple files * Runs on NAS devices like Synology and qnap * Rating of spots * Integration with [Sick beard](http://www.sickbeard.com) and [CouchPotato](http://couchpotatoapp.com/) as a 'newznab' provider * Platform independent (reported to work on Linux, *BSD and Windows) * Both central as user-specific blacklist support built-in * Spam reporting * Easy layout customization by providing custom CSS * Boxcar/Growl/Notify My Android/Notify/Prowl and Twitter integration (*) * Spot statistics on your system * Sabnzbd and nzbget(*) integration * Multi-language (*) * Multiple-user ready (*) * Opensource and open development model (*) (*) Unique feature among all known Spotnet clients ## Installation Installation is the toughest part of Spotweb. Depending on your platform you should look at the different tutorials available on the [Spotweb wiki](https://github.com/spotweb/spotweb/wiki), but the basic steps are: 1. Ensure you have an database server installed (either MySQL or PostgreSQL) 2. Create an empty 'spotweb' database 3. Ensure you have a webserver running and PHP is configured for this webserver 3. Download Spotweb 4. Unpack Spotweb to a directory of your choosing 5. Open 'install.php' in your browser until everything is 'OK'. Fix the parts which aren't OK. 6. Follow the wizard and perform the instructions as given by the wizard. spotweb-20130826+dfsg2/favicon.ico000077700000000000000000000000001226620506000221462images/favicon.icoustar00rootroot00000000000000spotweb-20130826+dfsg2/images/000077500000000000000000000000001226620506000157115ustar00rootroot00000000000000spotweb-20130826+dfsg2/images/favicon.ico000077500000000000000000000025761226620506000200470ustar00rootroot00000000000000h( eăæ¿000ÿÿÿiüÿiơÿhị̈[Û̃fêí]́đÄÄÄ¡ưÿmùü°                         ÿÿÿ€ÀÀÀààđøøüü₫spotweb-20130826+dfsg2/images/refresh.png000077500000000000000000000070421226620506000200630ustar00rootroot00000000000000‰PNG  IHDRóÿa OiCCPPhotoshop ICC profilexÚSgTSé=÷̃ôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆ€ŒQ, Øä!¢ƒ£ˆÊûá{£kÖ¼÷æÍ₫µ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sư#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zB¦@F€˜&S `ËcbăP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™F̣W<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aa@.Ây™24àó̀ ‘àƒóưxήÎÎ6¶_-ê¿ÿ"bbă₫åÏ«p@át~Ñ₫,/³€;€m₫¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷̣»oÁÔ(€hƒáÏwÿï?ưG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púaÁ(¼ AÈa!ÚˆbX#™…ø!ÁH‹$ ɈQ"K‘5H1RT UḤ=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Đdt1 ›Đr´=Œ6¡çĐ«hÚ>CÇ0Àè3Äl0.ÆĂB±8, “c˱"¬ «Æ°V¬»‰ơcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤T̉̉F̉nR#é,©›4H#“ÉÚdk²9”, +È…ääĂä3ää!̣[ b@q¤øSâ(RÊjJåå4åe˜2AU£RƯ¨¡T5ZB­¡¶R¯Q‡¨4u9̓IK¥­¢•Óhh÷i¯ètºƯ•N—ĐW̉ËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ª̃ª UóUËT©^S}®FU3Să© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yư‰YĂLĂOC¤Q ±_ă¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ư»‹=ª©¡9C3J3W³Ró”f?ă˜qøœtN ç(§—ó~̃ï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSƯ§ §M=:ơ®.ªk¥¡»Dw¿n§î˜¾^€Lo§̃y½çú}/ưTưmú§ơG X³ $Û Î<Å5qo</ÇÛñQC]Ă@C¥a•a—á„‘¹Ñ<£ƠFFŒiÆ\ă$ămÆmÆ£&&!&KMêMîRM¹¦)¦;L;LÇÍ̀Í¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«Ögðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ă“}º}ư= ‡Ù«Z~s´r:V:̃Μî?}Åô–é/gXÏÏØ3ă¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆƯȽäJtơq]áz̉ơ›³›Âí¨Û¯î6îiî‡ÜŸ̀4Ÿ)Y3sĐĂÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸă>ă<7̃2̃Y_̀7À·È·ËOĂo_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈ́­!÷ç˜Î‘Îi…P~èÖĐaæa‹Ă~ '…‡…W†?pˆXÑ1—5wÑÜCsßDúD–D̃›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fỲƠXXIlK9.*®6nl¾ßüíó‡ââ ă{˜/È]py¡ÎÂô…§©.,:–@LˆN8”đA*¨Œ%̣w% yÂÂg"/Ñ6шØC\*ṆH*Mz’́‘¼5y$Å3¥,幄'©¼L LƯ›:v m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²₫Ån‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«+Íí̀³ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏf̉féæ̃-[–ª—æ—n ÙÚ´ ßV´íơöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6î̉Ưµa×ønÑî{¼ö4́ƠÛ[¼÷ư>ɾÛUUMƠfƠeûIû³÷?®‰ªéø–ûm]­NmqíÇ̉ư#¶×¹ÔỞ=TRÖ+ëGǾ₫ïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jḄF›Sû[b[ºÒ>ÑÖễzüGÛœ499â?rưéü§CÏdÏ&₫¢₫Ë®/~øƠë×Îјѡ—̣—“¿m|¥ưêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±ơSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  œtIMEÛ "OĂ9‡TIDAT8Ëu‘mhUuÇ?ÿsÎ=÷œƯ‡Ư{wœ»sî:«æ\3†’¢Ø$©H&”/Ú$P2ö"Ö‹‘Œ²©‘o$RÑ”P $\™"nf‘ ›³áƯƒ3[íñ>߇^x úÀ—ß|¿o¾P tư‡<¦¡ƠYốn±6'PêÛ¡¤åñ½´i? |ă^ÆÜƠ»–ÖÔ>½ÏđV릩ÈÙ́̀p|ôâÈù=Ü#sđÅÎĂ¥a_›pWKr¨™­·„"‹»…¢bÛ6Ū:Đ4'¡b'ÙÔ,ɹDçƯ»÷NƠ­¨:]½$(w´¬mózjÚç~ŸÎcÖM‡äèÏ©¬¦k-±̣¨Çé̉ zUB'n‡”‹=×¹Ó{à 뀆·†÷ZF4á÷ëŸùü¾û3ÆÂ?tnÊm/u¼²}ăÚNŸ;R««Ù–$O2ga– •¬éP³f­®«û—Ç¢×ea OïË0aß¹Ăí]Ï߸1ø.¶%I؉Œ‰-¤\Ît¨ª£ÿ»®-‡Ê…¯V•G{O·fæ{>`yÓæªªÊđKgÁD¤ó¦iË€­¬j¨Îܺ=̃-Ùư&–Œ¢«B®{%eAaÛö×s·Goùg&yô§̃ß0,’$Mü9ơ3đ°ÆígûW¿°rU‘bár*ạ̈ÿểÑË'vîâX±íĐƒCcß(BéĂÆ“ÓIz.₫ºặ‰'Ÿ4Ô¿}J«]V^̣{•©™ùè¥̃¾÷K<®3 dIP\$ƒUU( û7î8¶-²®Ăÿ( à-‘ Ó®»79Ư8øGü“p$på#Kp*²pk2–¥ñ÷lÊVDº÷L O,>rs|d¨;>4à™̣ù7˲2đEú¯ơ5(€ĐTU¾?ñà¯ÏO~aëk6Íç¤Eé h•e±Xe°´́ƠT&ƒe»He|øÖ±ÙkŸö¹b뀳îơWçîœoèị̂euks*=‘§V;]~,2™4‰Éøh~f´+~åËs`¤±­”ĐüRvfÔ–d§×2s@@ª°W Üvr ¸]ø@0ÄÚ‘ ’ °° ² €â@è1ˆ‡0IEND®B`‚spotweb-20130826+dfsg2/images/spotnet.gif000077500000000000000000000441261226620506000201060ustar00rootroot00000000000000GIF89aÜ÷ÿÿÿ₫ú₫úöúêèù̃̃úúú₫̣̣öáäúïñ₫~†ªŒ”´àäơơöús}¢ƒ¯‘›¸̃âîØ̃ë5O¡¬ẴâêÖÚâ.J~?X†‹–ªª¶̀Ú̃åbw—¥»“­ºÆÚ›¥µÖáóåîưMeTm’ƒ–²huˆ‹œ•¥̉ÚæÚâîâǽPj]mƒ£°¾ÑÎÖáëị̂ IyKe…Vr–r¶z¦p~x‡™DLV½ËÜÏƯî»ÆÔÆÎØ(Jp8Y}.FbDf‹JjRr–UvPnNjVr’[v•Rh€n‹ªk†¤‰¢¾ƒ–«‹³¤¶Ë´ÆÛ³½ÈÂÉÑ)Ou0X/Ty9]‚=b‡EjCe†Kn’Nr•A]z]„¬c‰±Rr’]£Vv–\|œ`z”d~™sªjƒœ}—²tŒ¤|”¬„œ´‘¦¼| ®ÂYdo¬¼̀ĂÔå´Ẳª¶ÂÊÓÜ̃æîÚâêÖ̃æǽ̣JnJj‰Ec€Rv–Ondƒ¡\uŒm¥v’­p‡}’¥Œ£¸•ª¾²Å‹œ¬„”£“¤´£µÅ«¸£°¼ÑÚâV{„­­½½ÊƠ9YrVw‘¥¿Ó¦ºÊ‹¦È×â¶ĂÍị̂ơFk†„£¸Œ¬Â¬»ÅÚë÷̉̃æÚæîÖâêêơưÑØƯMy–\ˆ¤f‘­p–­¨Ău›³{ ¸“´É›ºÎ«ÇسÍ̃¼ÔăÅÛé“£­ËàíZ„œNq…dŒ¢l’§{›®–ªµÑåñÖẹ̀àđùV•u”¤ÄØåơữæêäê톣Œ£­j¶Ó̃Ö̃áƠâæÜăåq”µ»­ÅËc†́úư’²·æúữëíÚçéz¡¤ÆƠÖ·ÏĐậ̣æơơú₫₫öúụ́ööâææêííĐàßQzw¥Â¿²ªŒ¥›wëúó¼ªj‘xâñç¹ÏÀÎâÔÖèÛäëæÛîàÅÙÉñọ̈ị́îú₫ú”³“…¥ƒ¯Ê¨ê÷æĂÚ¹ÓăËöúôâíÙóù́ûươ₫₫úöọ̣̣̈ñ₫úúúöö₫₫₫úúúöööÿÿÿ!ùÿ,Üÿÿ H° Áƒ*\Ȱ¡Ă‡#JœH±¢Å‹3jÜȱ£Ç CI²¤É“(Sª\Ă²¥Ê—0CÚ°ÓäC…l)Ú´)¢… µ¨I´(ÄÀlºa£„Q7N(z$§˜ƠOX‹½xEÑ«† =;¶ Z̀¸ÅIdh&M² )fµ“ƯNV¯>{V¬“œqQj ®á”6öL©r‡ d̉,±-áô0CJ–êÚÍËÙ*ÏÏ|Íy¶ˆ‡%¯B‡Z^íÑF+Sb[aTk’œP–:0­̀z %Ÿđvîüé³q:¡ç8s6‡Î¢G›-Ü»zEÊ@¬h·RÅJ2ˆ^øÿª¥-‹¬ =̣Åyï³ÏX#wï«~}å¿~ÙqVço[”„•ˆu:dCV¡ ‚Ú]Á‡9¨ ‰0ơY7(̉‰.8á¡ OäđÂ'ö¹GŸhs 8‡rÎägÇ‹vüR‡ik`8d qÅwdq…Cü1É „EM]H%;°‘ÆJđ‘„K,¡ !näPI1¾,—¢+.—ß™h¾Ă%0üBÁ €½RHR9æhƒ>₫D|jÁ§Z(¡Æ$9ÈEº9ù̉!„üqRDjE 4!H–[NâA%Ÿ´ˆæ§gÂ(ª0¬yÉ©vh GW¯ÜXgu®ưÿxE}j!„C !„Z ¡„ .Èg"&Ø€^J&4±DRPá¬X¬Ñ”`Pˆ¥Zj’p¼QÇúŘæ¨j–j®©×\Ó&1‹‡!kÔ‚µ–ª¡‰¶Üæ€Â¤–*ê¹ç*̣©¤Ë0P€[`…4"–¼O٠ƽøâk¿aäÆ_äüjÀÁCyƒÔ‚ |4ǘB%Öµj¨1H*Ûº ±/vŒ ²©#‹l@ÉéZS€5ê3´"ÁS̀DÉ\k¾ụ̂«óÎ|Ôm÷̣ˆ"E{ÿÔ‚B( ©M3tÅRÂF*ªHâå's¬y]{ vº˜_Ă€5œWSÀ5¿EtÁ¬Í¶J2ój«Íü227̃vó¡Ä́Uá‚%Ådˆ^.……?„!”"ˆlBˆ*NXưBä3€ù噟l=çœP ?[£B‰s:b6äË:Î:Ăn7í~ø‘Dûƒ́À¤H»g!8c¼LÑœj2ˆ̣̀“„ 6E;{̉‹̃ơ°‡½8ĐƠ M˜n|%™ Î÷ºØÑN íKBÈ@?¤Á  –ÁM¡ ú»È €Ñ¿ÿyÈ |Â"`‡kˆ­ làÿXímO‚ €".ˆÁ‘Øà7ë Ù'Â’áW$Ä&Lp¬" Up! Nđ‘&¢‡p!<$‰6ê°¿¸D?X€~ ‘ˆüÈc‘8Á0±‰29úv¦>ÙQQ„$üƒ"97` o¹Àà¬J.&*#)mØÆ¾¡=Œ ¹§G~ 1c;™xđG@~Äs£ÛAè>+^Q‘h@Ăá†@r"7Ä”&››œägL#"p(‰U¬"D(Èø8ÊT^ƒMâÚø\)Xú,v†œ]-IxË?ä f0Cœ0D,#k¦bCO ´ †(9c0ÁÿD¸Á™OQ%R`đ£̉Ăæ/æ@:Ô›Ø&7Abƒ1đ œ́g"q‰Ît¦³ŸkøåC₫–*Đ³ SBXR¼}:¢y h%怪_¨€t¨Ă"^ 9<"^•‰EgB[.̣œMƒR t±"»ăClªĐ*xa¥d9Ä+lᄘêÍÑ)OåÀƒGáRG„(9àAYw‡ÇÿºaN P'ûÊ2̉¨™M']• AWƒpÄR(„AA;  W —46¨­ nëD´jå-E}[T̀S®Ânq{<6b´ iÄ î Y]†DI Ñ"Á v¹ë]ĐB ‚Ø­x[–©éå,{£&564‹I–²'{e¿#±Ñ6Áƒ T€F@¡„Cl‘ƒVx Àl8°q•ªàwÄ€@äFÏ«Ùá¦a½Æ¥đ †¬†À!&D&êơ§,hÁ˜%^‡(„BXÖ(  Èá4rj%A^¡ĂÄ8j‚h‚RÍĐˆÛ˜ÿ#86/z#LÜ GmÈcC‘l¨Á A’êÀ帬°„*`Œ,gÙÆØ̣–O æÿ$.xìæ4 —d@ƒ›ß¼‘8ǵ£›•p+¼ÆI¸Á en`†¬a‚ệu„Bc'€B‰!íhI;̉[VM)À.V]ÓVê§uYB% A¢¤nÍ n9g{öxy&"&ájXĂa;pBÖPk…´€ dÈ­l†{bd†TB4Đh,o¹ßZ¦€ |AHKHÙÊÎ D÷Ÿ`@Û¹ÄâüP¥14"ÛƯ¼éüăăU8yË,· j»ƒGä‚ÿ­B ï,  7ăƒ½)bˆ¼BQ@̉£ÿl‚7̉zÂÏ”R©àËxƒÎ0ñ*ña a8B0ñ?ôXƠ‰¹D>rt›Ơ§ƒ¨A»Ậ$èa0T D!åDXâÊw´¿%d_½à?“„>•¢ç#oxĂ ́ơ#€Á `/ƠA’ת7Èánơ«G~î’Ç–=eC h}&°ÁCˆ%~ƠÎ&´€Á^4NńGïT}·é̃û 4ѾMOƒÎÀ /Gơâ7̉x¯:Üă9ÉÍ*Û¾`n@ç RˆA(Ág<û‚·rC¼ úv4ÿ² >tÛ›‹M!ƒÁ‹^*ÚÓ^O‚O„;à!;eĐđCR|¥?yâæ0yË÷²…y²uic÷’4x…ÄÛGzÑ'đU¶ü&iv§ĺ·5í§~}W*Z%C9$x.}GoapöXPƒV€‰ |û—yÅßvgl uÊWỳ‡€/đ|(àƒpcOƒ‡Q7aư¥o÷z#‚Z‚·w _ó5^ø…—@{ùP† i^Pƒj¨†$À x;ØLyA€Cèu—ç|HèPç~àNÿàgOøA~àkX<#&P.Z؈&ÿx*æR‚ç†ébùP2₫đw}—gèÙ±†X`wđYl` :‡aLuÊræV€±¥‡…E‹Èà€-p`†Ô>í3s÷„zq°¡°&¦eÊ–…\22•³‚ax —x ₫àéâÖ`ë /à NP `à„§ˆa 8­Hnxn&×|rP Ï·´XŸVvP‚0kÀ‚@K—5-§—à &– ¹oưwØŒ\ƒ~ç÷…`X*—ø…IƠØ÷oà j h|đ]ÉSèøJ·†®ø%²hµh‹s !¥‚ÿ"îCBˆ”$&Ƹ )w8{˸&b(‘”X×P†eø5ƠèĐưđ <à­ f ’khà¡<â¦瘒a,‡Pn.iVy(,{ˆ4¹w¤r p V4Bf ¹oX&”D‰eÈ–lA‚æ̣5•h‰O‰‰QÙ”e¸÷p ‹€jlđ: \¹†iĐ,9 bI–­“Y$gỵx„2é–đáR* đI U ´I›ÆˆŒÂe}éow…¯÷ ’x{À”₫@‘ĂYÀ÷à` ƒà‚0 ®đ``áˆÿrå–ƒÙyu–pàfÿe€FX÷h‹Wè"s `i@;PµYŒ…&Ö́— ¹ilù›ù!˜‘˜ —•Ơ8œŒyÙÀ„ …fÀ¢đ\# â6n¯kn0–Ư)´&䉀ôh´˜éɈ$3•;Đeô)”Ç(pY#2ê§pBœ’ø`˜ëP†RÉ‘U)n êäq¦O n¡8âÆu#—¡ê&Cæl©X§™ªi¢„i €‚bbA™{yŒs÷ (H‘©pÀ¹5_¨‘Q)₫P›5@iĐS¤ƒ:À—iƒd nJypđ¥anÿ`|ÀJ`AĂç‰5©Y2'ă¥v` ]F¦»ÙŸE•Öc–茧2 RÉÖđ –P€0eß–f|:™:FJJyèö’ I'àÀA eĐV£Vú-Aç"ø…›Ê9PlÀ–` ¢Ê›<‡lé…₫°9Ad ú…È™ ‡0«´ đZy†® d¨X€ƒ̣đÈ|?U¬‘tn@|2@Åm¥»ä<@á’…$£©BdJˆp~)i¾)i¿Yt—@TY²TTÉ@ Pc@«µ ¯Lw@aàÿ6d“ ®0jFàO¢éuZ ;‡k €¯y+đ€xđê|`B„ †„=Ö`G$AÀi eÛŸ'{³ç~(Ø£&ÛëÀpb³đ*³3+¯|:d. oÀ##9nP[(@i Øv´ Ñy}ĐN Ry;0f@WBpđ(¸9æ*6{0đI *đ—[¶6Z{6‰k’×Đ0PqĐ÷gЬsK·gP5°x&5à:đX#I€+´x¥²«¡kÇê¨Ypb&đ; D600!n0dÿ dhAŸ+Aàa@7²B—p‚y£̉˜ İ M0qgp^hP1;·»»»¼Ûx6dl àÖ yĐÁ:åiXÈ`¸ a0  Ô;÷ÔQ@”@`= `*P‘kíă«;0æKMÔ„|Đ¹¿̣{{¬{ fĂ·[g Kç„$P̀t¼[¾›\ó ’Jăù¡Wª€u *°λ¡6̀ ]t` ¶° ‹bC6&s=' Àđd`lđ(¦$Ă`f`¶|WthÛ&ràÿPcBH<Äf€i`ÄH̀»K̀ÄLĐ儈Åfà l.P„åy‡5<`´|q@~€]dàbPGP/`ml &¼¹ư`¿° L~€ƒàk̃̀»èÄxªTMÿ@ÎJŒ˜œÎéü?·®pZhp€²x%º&0l¸Đ‹i Óë$7° ƒP2ĐXĐ{`c­Öut®v`°„đ»Äp@—€Dt n Ÿe[{r pË̉-ử0KâLÓ‚Àæ̀LÜ™̀…„O9PÆ»†UĐ=UÔø˜lÔz*  ÄZ¬6@°É:ƳlP2pƠxP©]¬­ÚE@\‰°Æ`¨DœC•ÚSp *đpđœV?‹PPv Ź ù¡$0Gđ²0[«\·MÄt¥fÇÓ9ÉĐƯsÿˆ́yÙ5h¼ÀS¦‰Å¶—&X2§ ]¼x6´dđ@ÆaÆnp§Ơ­ưßE°­½ƠG‡` `Û…²%‹¾fđN½K. —pJ̉®Gp|Ư¬}MƯC,Óy§Æ5dÚØƯƯ2-ăL[@̃Å[.p„ÏW|˜wjâ…鉯°ÊÊŸp1ß0yÚ à¬-àNNM¾D €ĐP°¿ ^²à¹ytúpáÇ¥[´cĐƯÑ» FƯ5pNéÜyª§B6ˆƯƯƯ­§gÔP, ¼†y W:“¯×̃˜<ÿ FđNúÏ:9À°¨íÚîä.åDÀé¾RËÍ¿ĐÅ(+ÖcÍ9¿đœ€g`[mbàá>;së€â¹ÄƯr¾§x„MĐ×B́zÚ‡đÎdàă­†[( “ùÈ̃HÉê–à2Px fèØfƠ>à$¤­x€Ú«Íä îœîéDĐîî>åà×`Ṕ€ÛØh Ơđ#ëFĐƯâäÍu;Ľ̃Ư₫—8‰³É-£çzî: cđâă=̃[uÙv—&øºƠà ¡Xƒ}ßÙfdđT'° hpéL>àêÿ̃éíÎîínFpóFË$p$0Đ́À9́ ÆP§FP™É8đGĐ,N~@đƠx.ç _ÀSßúzzM€ à DPñ_“ĐPë­Ï(È₫đ`à˜Đ4X&?Y3áN\„̣W`Ç‚Áû½¯˜>àQ.åênó à°ó~:4VjS~$&”$đïh̃µî‹QdPŸÎOÓwfÀ1¶ÉưdaÇîơ.àØd_ñ2°ëÍñ— Ñ—` gÀ5˜ƠxÀèh,Á€ ÜÀ ̀Đ7p_4‘!“ ̣1?øéîß+0ư#0¹Ä‹ å;Ÿ3/ÿ‹Qfàe°.äoă»ß;¿ø›¯¿œÄçD£ïYX„ €âæÈîơ‡à n¶ä!HpË‘*Tüúek‹©R Œx4âÙ́ßG!E$ỶäI”)U‚,aĂ²dÜj1ºbH–2Jbô1… E„Ư³§£{ŒŒAck“¥;,AqƒˆC‚ L€3 Ÿ0|ø(«ÄlÙ4cˆa;†­BÆôYËVŒŸ3yḱEÓ ̉ n"HÍ ÄƒØ,&ÄÆ!Ȉ&9jrÈrNƒ̀³å ……v.1€a V.^²1ÈVΦ]ÛvÿJ% q“†lVlZÑBÆBKMd * œ bÚ#æL°dÏÀ[·NƯ:_;&`U°ă"?cÍú1«„=™&bêq[&“Gtí“÷ ¾üB£̉h¢°AÔ8l1!k %sÄ2̃àÄ ¤Û¢ ~­GŒ¨Â,XËÈ5<‚8c“ÛZtñÅ’JĐm“háĂ*lâ ¯(î‚ Ø€®¹=dØÂ$“L²ö£Œ½ü‹‰Kă°ÄcÈ"ƒpü‰CNüØÿŒ³8ú‡Ó¨°¨ÄƠN܈0˜€qSNkk©K¢™dmêñ,R-.ˆ N# "ÙÅn’‰‰™`QFL0Á¢Iđh °¦€jP–Dx@…Đp=3«äŒ#èÓvŒ4Øp¡Œºø›ód¢t $±Åq¤AB"Œw’I$s@ĐAŒE *â‘MÊq̉J-Åc/ŒXêNvx$lø o¬bGQUU !„đ# ‚£"̣Àƒ‰h¦Ùn;jZÆm¤éF×Hđ(±=¹DY~øéÇjªydƒ#vEö¦ơ# ?à+ƒ?úÊ4êµÿk[@P0ÁÖEŒ ?ßuPĐéuAäÀå=úÍC#¨HRÖ°xm£ 0ÁˆaøaÀ9-á†8´‰&-„Ă8Ơ…Đcˆ!ÀP"‰("ºF´±fjréåó^rá„\pñä™r¸F×=nƒø¡̉€K.±Æœµ„2¦M‚i?̀h"ê2·N88XkÛ₫ü LÏ&øôPÆÈ¦wĐĐ~¡N® ÔT£#»[ËÛ0Pøˆ@âüưÛl`ÁKŒ‘#“,L½‚q-8ṿ!0" aùƒÎÀ‡<ˆAÖ5z P„·¸,, WdĐpÜè4„±ÿ_aư¨.8ä;ØÀ‘ˆ?˜‰ dh̉À„1O‡Lʵ¯\çJWô¾ö'±!Be›xđ‚,à„ÜFáˆR6k ˆ`„#̀ c4‚ ?4®$7”ˆÂ/¢‘†üAcYè_Ç@đ bA”P†gXẰÅ/hÁ ºâ ­hÅ0†Q ™uđƒX°~QØA!*đ…^Đ€ "h¨á É„k1'ÅK!v₫è° YK×`Ô6wÁ+^dƒÅ(¢€ à„®(ºQ vCØ ÄF0́­ Kc5!VJÿÈÁf¨É₫§‡;2"aøÂŇ?AÈPÙ#hÈC&2ƒŒt$+VÁ v£ÁƒÍđkÀ€ ƒê@:t‰ ‡h„)g˜3B‡€Ä¦&ˆ¸x³,Ă˜ '¯µ P’—d ä‚'FquPÁ"t°43™%º[ÂM0ªÏg5}úÜ| êàÁºùMp€äü9$̣̃ùöêöưhIô[¨ø7h †ZơF^ ñpª[bêØÀÔÎj3¤úƒhÄ«ùRƒ3br¨Á‘ѽÇđzÊnÈw€,H¡Ø-o¹€đPhF̀4đ ¼m1zç|Óù²ísO½Iƒ|À×ê‘ÏeúC¡o7L.¨„ƠéÿUE22ßOđú¾S|üdHCùÉÈD)¾ÀT°!홨>hÜă'[³Œ¸€ÔP§¾0áƠjđÀ#ô"PŒƯÁ"ä€I唯ˆ¼à0ß»Ăç;ÿù̀Ú›#HŸœRŸ38=ÔS (ĐkH­Ts£°¥S sº CµV’:Ưc88(†«ë… ̉:ác…âƒ´ă‹´ä‹†hh…J¨„a†IÈXn iˆÓA°x£—zq˜ùƒ=y5¿¿n©ƒ8ÈÂ8è 98ȱ&0)?$¡¿Ê ƒà„Ê’ 3K3#1r¦ô©6ơaÿ[H@Ú`€ ˜ƒI -È=Ó£ ¼°Ú#ˆS53„Cd8·‡«Ë…Ư1á#>Œ´~K>i¸§VØ*¯j…76Hr ¬]àGpƒzY¢xi€>˜‹28‰ó«&(—¾hñk'¨8¼¡8#Dp4ȃ,œ‚)X.¬?28·Áÿ0#À4œ+À#(„D€CÜCK°ƒ:`ƒ/ £! ÀÙS7 ̀@40‰'´A;D…û´”¹:NØ­à+A¯“DUH…äK1Kü-M„…OÈVHiˆ™YĐ…]Èp 6à€ ` hÅWLGh„ÿ; 4¨7¡AH?»%Dp„1°/*(Fb|’ù;Æ%70é(‚gT#@˜5,°4>@@md‰ù±¨A`¤ƒ­>ôsDµ¾PG¦$Äw„G·û´Èmϱ*{tÄ®®°K'HUđÇap…[¸*àĂ…\8tˆm˜„Xàƒ&Ø5ÇpG@ Gp€>ÈK$ t4‹ü‹‹ÅFø+9P5p„ï“*¼”ôbTÉcl9BØ·9Ăÿó‚@Ÿ0Z36œ́I’ŸØ:à¡Ô‚q”= CJSRʾTG=!w4Äx”Ê{«üœË Gl…­”Äÿd˜„°”„aÀ…Đᄲ4$´…e0‡tІb„X º¬ËAàQÚØK4 ùÅZJƒаó ¸Ú‚è“$ÆÇ,ÆÈ̀‘±‚'+ú2Ü,# ÆḥLkDL@ ;G¨ƒ0FĐ‚<:ʦËÀT‹M¿©&:DDµă1@‡EÔ-àûÍà”„~L±VÈFܪK„…²ä„\pNj m0mØ…YHƒ́ÜN^8½ÜË4`Ê 9—ô Û)hÏ,|ÏÇ4Æc,• xƒ\„+̣?¾Ù2Pœ,À ÀFÑüˆÄópƒ?=@·t»ÀÿלP¦¬PÂHAp¨ŒÊGÈĂ19đPzÑƠJ .å[…'8QNxVà*W`Q\à„^X†e°s ‡gø8˜…]0 ^”Âi ûN$8ƒ -Bh‚ôk°9/ú¢‚ÈÂ&E’']IÊË¢D9·‘2ô¼½)Îä̀œ[³2@°D‚è€ÈB È ‹ÖŒP ¥P=IƒLØQ5pƒ…»M<Ơ1«( >í夠x̣ÍEëºh ÈV@KXĐDßZÔFơH]†jˆmđ_„)Ố$`=@‚>8¼ mB0̀4¡2@„akUW=IÇ„L.,•ÿ,²2Đưr™´)Ï3‚"£ÎÔ¹5[³Đ́ÉŸ̀Aàƒq,G6EÇ¥”M=©V^TAp…‹ÊmƠS`"p¥G ̣SàS¤EËrè-WE……¬sé‡q€p˜×j€‡tđ…_xZ¨…Œ£ÅF$Ø¢èƒ 5ºl@ÈV•6p%đWm̉'úú´ ,H} 3Π9¾‰F4\3j$Ù’uC”½Gp$hÙ5]¤TÊ7Ö¨Ùídƒ ÅMn….`‚+@m×q Z¡Ơº̃ªm€W«¢ ̉¹Ư„Zx€‡z¨‡Í¡Wz¸WcÈZHƒc<ñ ÿO Xïd1©3FÉ“"ƒ0‚¹Fc”Ơ¼UÁ‚AX€IÎØU›2³+Üơ‘1(„Đ2PE€ƒaº—…8¼cÊiƯQĂ°Ù¯PÛÖÍƠ•B¶ªƒĐ¥Ç̉™ ̉ZD̉s  Ïv†ØÚØƯz˜ ™y ƒ_H†­ÅH­)—X‚Íˉ4,Àæ=ÎK&ûc)3ˆá(g¹9gƠ€0Œđ5p'p¨¬-@@ËÜ&‚’#^3ñ=Me7H@tS÷)Vne]b,“åü­b[¾b ÀW8‡s †rĐ!ẵèfiP0ăepN‚ ^X‡‘.é’®Úrp+AØÚîJ³È ±Í=̃ă~J^#pƒb³‚)ˆXỏ–³‚ ê ø6X‚$Đ7èƒ- ­<€„Í̀BŸLƒ’­j¶8₫áI„öEbu1è>—ÿơ"jzy³öÜ*Öc8nlHn·vël0†¸®ëºn†f€nx8´À–ƯÙ́Á‡tƒPˆÄ^lY*¦Îf¶Ø²bC„0ˆ.ä?¼D¶‚+xaŒƒ%XFøX¶:’<…H@@ÑÜØædù8‚xCÑdD„¾¤\Vîmß2à&:eh¸ªb ă>ncHnå^îlHñsˆkénè̃èŒE¼Ê1₫ëînïFfv¨yذ„]̣óÖ–2`¤»Ø2)hø>à.6éÅ‘‚ xa,¸‚$àj=ȰR0êÈKÖÆ¬3“jM&ÿHØä `‚̣…C(B€Ó°>èꉗߦ—w4Køµ¸ qb qä6ñå>‡/ôu(tpqêñ- t°JϹhOă'i6†K°„F 4È!æ¡ÓÎ$ƒ=XL+p+p̉'ïé»Í‘‹¸ïẻ‚Ú̉T¶Ij“Ñæ>xj„Q3ÀM®‹libíɘ„U¶\ );n©ËôLßhđóôt/ôlèuȇr(‡C ŒFQn]Ư*H×hpHăb®t{¨l@†{9́Zma‹²L$%•5 ƒ&Oơ&ơfVßlÅYdü‚$àƒ,ĐŒÿm$(ÿÄ”×¶j1Đgù(S˜5Xâ>ñ’j/‡öhÊ(à?ñ@ÇvB×ömçö|ÀtH¹cr/wsïÍ7@gpQ¥çd÷yp÷ø…W€[ØÚ§Ù’ÛÓ¶ ö<Dp̉T_L‚/xfû†°+`„/‚+ÈWÀUƠ„8[^/©ÎøÑøN^3@ÈÆ0ư‡h ±N¬ö‚7•_yPû4 c€y?ñ™7t›ÏuxüyȆt@‡Hßå.&׬̣-V¨ÊÑ)zçTf5vwk€vàGà!×ä’„ Hoq‘'È) Æ*˜‚®÷æ'‘̣ƒOgÿ+ ̀‚+x‚7ƒ-€HXEσđχ¶5ƒí`¢YóWÈ{½çD0yÉàđ{ |¨ˆÁoù<ôÄdžsø¯ùîÈÇW|xÿyÀ‡tz$ÑD¢'{’zg¹rQµ̀µz çͳçđ¡½{÷ hŒĂ¡]»Êéx$R$#F6°Ø‚DL™>=™‰1奕)Tf̉œé£•*8đä$È A²d¹rʼn@[̣lYºTĈ+¬AäH˜²Ù°¡k“`ÿÆ’-kö,Ú´jÓ–ÀàÑ$7råBqaéîƯzñÂăïßhräĂfØđ¹s¿~ÿekÜxäuù&«S‡C†öÊ¥—«§[¢oÁ*íêt«VĂX±Z%IR9Ϲ@´V sCˆï9dp °&MvṆ̃#̣¸H/$M¢̀C‘̀—/kRÇ™³JOŸ?}±ä n4]*CƠE ®¸Ê5LV1^(yµö>₫üjM̀uăÂî]pX¢×|‚  ƒ‡%vcE6Y>•Y†n»eC:œäi¦¡¦Új®I¢J*ÉĐ3MµPM5éoö @p0¡ÑÈáWơảeäÁ†RH7…ÔÑt“9a‘P?MySTaÔ‚ Dç‘ÿzE¨·VÁg„ctTC"úÉ9çZ6Ḷ^pÀA  ø×` 21‰-Ƙ„QXá…ÊøoäÈ#P.!æJjĂ”h"©h <.¾X ;3̉hO=÷„Â;ÀÈ.Ḉ̣#A±‡C"1†Mü¡ä’U8I…PîDåOW`ñSU0)²YÜÄzëUEĘê0RGn²ùƠ(B'¹å₫Ă!zîÉç*(è Ä£ÂbF&ef‘Dư–ó9·Tzi¦¬­Âi§d’‰9ơ,3*Œ¤ª=ü 9̃œ±Æ²Öäc²Él,ù’³NëC”QRyÿE²U2‹̉b! " ×TéUe„\m0†c§¹IçÇÂ!ëöùg đ2¸ˆ¼Äh`Œ½RX™£™éÖ/Ø÷ÔóN<®p‚ ‰¬µf≩xª0*¥d=G\ÍC Q è7eˆ0»`̣˜xàA„Kâ†Z. İ+·L¥̀Úq‡9‹ ƒ TéLUU9_ ´Ha|ƠæF”´̉±«Å‚!p´ XÔ/ ºỢjpµ1Æür/¾v¿aKi:ï”s .®¨}0Ânk÷)¥Œ"H=öÜ1?Ëï?€‚9̃YFáDàQ„âñ¯0d˜¡¥³̉ [ÿ“Äk¼ƒ¬íàaZA B­Vp© ‡Lë‰Ê¶ ’¯°ÉMG8ƒ#d§Á´ÜÀ Êî¦Ö;«¯„†™P¾.ƒäAJy3º<ÂQ6ѬmªHöJAQˆ‚©ú? Ä! ñF È=¼Ñ¦1´/~“ĐHØ€:¹"Lḍ$ÿ ijdvÀ  +˜ Ù•lEu9Â,Ø[l°e±"¢&‡đ‘w‹¨1êPàϾP½²±µ ­đkÊ«‘©"BwDĂ·hÅÁ^sCëib ™@Eöh1‹X0¢‡?„Q‰8Dß, ¹8‡7ú 1nÿ˜À&0A³(ö¡~Œ`̉uœ•₫­́&Ư™Rv`¶Íư¤V@ ‚X•Ms»̣•1„Å̃,#öÈÇø‘jƒ$¤1 I¯C ¯2×hdn)¾Ḥë2Fiª÷6O‚²¢$e,HÉ xH$•ªäÛƒÀĂ¹¢å.đ°Ë‰ †H0£¤&i‘‹–;æ‹"”,Œ‘ŒgœA4£ ÁœAĐÙ<‚57 †#ẫô& Àƒr.B¿+!Ô¹Îl *–id ]HOƯÄs’ä`,ZqC̣3”³#Đ«Ö"óˆ* €€,`0đP=€±‡>ô¡pºÿœ(̣€…¨¡;-Ó¨wˆ¹²0;?¹đ0”)ü½0#ô ‚n”`LgZdÜÔ´Û Y:/¨‡\gQ³1!¯%U©KuÈ 5svÄ#­€Å*Üö¶…ơS”XƠj,F1 Zđv<Ȇ=ô! ` €~á \ä¢7(ÂZq¸Æµ Ïvî+X½ _¸̀,œ¶¼@+# ‹¥HˆđX‘xd È`eëxĐ¡¿t @P ÚDá«B₫è‡=J%Ï~Ö©m$9X«V¼ámp«íUI‰Ûݶµø°’Áƒ },†ÿ ́av¼VÅ'1lg<ëb«»¥ŸÓÿ 5zÉ(¡7[j#L2PÆ1¼`+ú ~°BPz‚é+lÚUđ4ûÚ“ŸdaÔĐ$¬„à…ÅÑ H3X5}aM”¡ È ®íˆ„F¼¿v°/!̣1“9Ùư@đ‚Ù¡̣4?;µ—yyC"üfH‚8EI)nÇ‚¦…‡ư,ˆA.ç~Äë WÀb̃0O-=ưo1Â(FÉË´×ë$J N&Á‹À"Ÿ×})•o{!´0D|g¸/%2~S¬!—¶È/ác›\åac‡DT.x–·<3/?<>ÔÁpP;ªXE&üÉá;‹"«̃̃sŸÿLôÿAƯĐ8 ,èA¿= ¾‰¾`ơ«ó$'W°B1¹é¯|°b'c4Ñ[„hâÉR~)•‘w¹WÖ.0€È÷~le÷Ăïư<ôW>£Â3C‡·̃²?l´£á8!&qÉ—rçƠí·?,n@Ư GÆ 0eÉtĐx }€1x‹E…1T(«o½wüÛ^WË “_ –`9“bÍ|¬Z¬aÓ¬5#ñaY Â%0À50B4à ôœ5°ĐC4ij©›%̃eXö½ B(1|C;tC)h!”åínùÜníBæ #„Ÿ [%¤†+Œƒ7@¼ÿ›áøX#…ÿY]]G]Ñ́ œ̀œ` Ab)V©¡ïêÈÔÀ!$‚ \ ®±€ØA(›ßñCøÊ\?àÆÉ9X Vâ¹  ¢̃¨C ^2Đ 7* -ˆÂÎáÙå[ˆŸhJ+¸‚<‡ư Ă1 ₫)ÜPaQ\]”đÛÖE×å[TÉÜâŒ]î¡T$G4¹Đœ8Bºá6@5Ø!2’à‘`f”B¬ÙËYÆ N#5R#4‚8´ƒ7Œ)dÂ,Db@ù %öÙ¸\¸&®†¦ Ă.¼A BdÁ)¢¢*²ÿ¢ÔYGyGP³ÜÁ $ î=\ ”z©ZÑBØB0 㮑Âô=#C™U42D5v$!Æ F²1TY ˆƒ;xCne.đœÏaбß9ˆÚ°‚+ÄS|â.øˆAdhA=RaPXAää£+̣£PÖO”×O€ab$ T|ơâ!ØB 8$ñ± ÀùTC€Ê!„XúCF bjy$ZºàY®C6C`€ °Á¬IºĂU•B)ŒR,üœ‡Uâ# k C9(:a$|W#(ÁOeQ¬"₫t>î#̀È̀´0eÙ-ÉW ¨ÿÁ!\%V^`Z?„åX’%F â:(̃<¤¥G®Đ:¨€„D%ÄA"t€!ÜÀ•ÙÀ ¨Á8‚8˜ä1p£äÍ‚ĐV"Ư$H/P+¤n¼‚ùÂè›A3{̣<¦¢Á́Ñ^ẃÚí6'´CÚ€"H¤AYƒ đ€"4!î ‚-`D;£1%Ë3%ß³=7B!4ö₫pr3ëÿAtî’ẁ•®B×´®2"£1^́À`@6ÿC ´À6A Ô@ q Đs ˆt2ă³pho(Uûs=…8ªA#²M‡µCv@5èôN£’2À/¼€p@ 2Ü@B23ơOqT´pØ›U_5 AVkdÔ>~5M‹5bc`¨̉NOä1̣ƒ5À@<‚" ² ·.‚ü0IÿTB‚øA_[uàhQTA±¶ArbǶÜB6Tc'£À%ü‚8@ n ]×3IëóHƒö!ü,÷UëAy~ÁuXÁ0l˶ucYCÛöm;vđ€^HtØÀe›^ƒö h7,·{‡ÁOVaL”A °̣uçwññÀAÑmßÍ‹đC\ƒ ¼À$‚!ạ̀?à€ ·-GhÂ!¤$…'Á_ÇwQèu ²~‡ø™ ô·ÿwÄ|%©\ƒ,‚«~€ ´̣X´K8FLx…[øçvl*¬ˆ‹¸Ç"”‰ÿĂˆ?© đl Àơ9sÀ‚–“Á_A|€§¹˜' Dä‘÷÷YOôCTĂ%T9-‚%ky7Âd¹l,_˜ ơ˜ºœ˜À%œù™§y÷€Ă`,‚lBüv+—€ÿÁklxâ(øÁŒA :¨«$‰¹¡ŸµwGŒ¢W6  Æ$¤ÁÜ€  ¥›4¦;·ÿ œŒ‡:°§ ,övÛ¡¡;4¢«x?hÀ=‚B ü*sù)¸@¬A°w;ZÜÀ/˜ơv;’7¶’óƒÈÁŸ¼ú$ü$Aÿî)^At^B{{°z?ˆ{±O›x’Cô«†_8Âwr®Cś(8¾w{{¿W¼©362öBTÀÀ{;s®ŸâüĂ" ÁD|Ä›@¸[¼Åºwk|5dƒE¡‚üÆ₫ä ơÁ ¼·º1Qª³üN¹we?CÔXBU#<¦g<Â!@! û¼ ³·ù÷=Ñ_¼N£’̀/"ø5| Aœ%́ ”â½cư˜›@m@ÀWÖ=×wưc³¼D–;XC(,ˆœ4k¬ ÁDâó€x:܇:(BøWV>̃ĂHƯwư×ÿÿû-hà×|á¾_(¾âCÁîă¹Ö@å·¾ëÓư’c~ƯW<̃=È<½’6ÂŒ>é—~vê‡x Àå¿>̣W¾WÚ=ƯÏ~cß}óÏ>\ƒ¸_ó~Çÿ¾n  ¿˜ă@̣ÿëg>2"?̃€₫àsr AǼâ[‚ ‚÷y„œœëD¿~4xđ`€ÖDÈÏ_(ø( ƒ†G(9rxtä% (™ ư3yeJ•+Y¶tùfL™3iÖ´YÓ ~ ̣tˆ¨AvÖˆ2˜P@…Jø|ù“qăFÙ2qkV­[¹vơºÿ‡"~ ‹ö#ʳ́Ñ ÍuÛ°`¿ Q(‰¢1ªT–25ióp`Áƒ »d€[Åmß]kAdÏ₫¬ gÇ&¨y£zT“¦daÑ£I—†yCYÊ«WĂ-ÀàdÉ”X+ WN(Ưœ9z …(M“¦‰7G"ÖÔ^ÎĐÚ5é̉eGf}™wçr ¤Icèxxñăe²àÁÏ:äÉÏY_3``züêé!cÏîQN”L q÷ÿß¿~ym¾êˆZ2 ¸„Á÷̃‹:À‹7üxPĂ ¿ÜCÓÂ"°À„lAM¼ÄAø ”Í(”ª78$C:¼GÁJàÿDE,ñÄ Q|ÂØ¬¹¤Â©ä`#Cr|J­Lø%ºañK`€AÈ.S,’̣’QID̀häª(Ơ\¦°|S¶·œsÎ.…ü’º_dŒ¿MÎd‚Í@M©9 ’Èøä„ÁFí “N;½„ÈœJFK̀0ƒA=ô`›¾÷dÔÑT…RIO|PL·Û! 4éïÓ\¡lC‘KƯ2Ơ_„öUUeuK-]mP"LóËB₫̉•ZKˆâ—9´C…n½%vXcSE¶N; SVù£‘áª}—CCêđ–̃z¿W\GÉạ̊NKe„ŒFœ„—àÿQÁÿ—„í]Übóư•Ü ˆUÉ È`ↂ5¯(T ä„}YØ̃†^5b-ù”#2Đoă˜3$”9@¾™‚‘I®×ä‡÷½Äßí ø£†Ne>Ú´C( ç›EÖygv8_V/©?KĐ CZ¤½Í(æ ƒ́¦q†:ê_¤&Ög:íè-?3öëºkA¥É̃Û́œºÛ}¦`ª4’`ÂF»÷Ê„ö~üñ¾ÿ|m|…¡Yuwwñεê˜:ê€<̣¾ư¦|êc —Ñ%IÓóØoºáÑmt¾Í™̣ÊĂm4”(ä@Ä`–ù™løàöÛs/½éÉÇ—ÿp96ñăŒă“ß₫¥, ½ùæŸ/;z̃Q/v,!Ă&på~–hŸ₫ñ™–íñ…‡₫P‚ t‹ßObƒCÔ ¤_ư‡¿üñlQ0!@Đ{L`;‚Ú.tăĂẤE4hØYx9 `‹Øà?è<îNz*ƒ øPƒŒ±ˆˆáe8CÖPtös  *à>œ¡@”bˆHD#‰J4ÛÇÁ?hO D _PÆ*шHLbqö T$ï #Åđˆ:”ÑŒU¼¢Ơ¨E=1%s¢ ÎÀƒ:,y´âƠˆ;̉©hÿC)ÅŒµCA"_pÆ=Ö¡}ä[̀†¬°’,´Ê †Gx‘‰<#i(J " gøa*¥h\²„ƒèb‰GO2̣ƒtđáØñr¾Ẳ‡E “Çœá)à„0”a Ч4Ï0ˆWR–Úܦí(à‚0đ!â”§4Ç`†Iđ–ÆÔ#2Mh‘@Ê ÿđ¥ ' s“úܧyà‡I&. •& aMl*̉uà†pTF¤¾,C ئ3†(˜ˆñQ¾ô7( ̉à†Ú2¥uØô „]¾¨()LÏ 8¼à¤P‚3ñÓ >µ€€̀?  …êVỦ”¬€Xç¸ZÖ“°­fUëZÙÚÖÂ;spotweb-20130826+dfsg2/images/startup.png000077500000000000000000002235151226620506000201340ustar00rootroot00000000000000‰PNG  IHDR@̀+€æ^tEXtSoftwareAdobe ImageReadyqÉe<&ïIDATxÚ́½÷—$×u&̃e¤Ï,_]ƠƠ]í»ah8 AOj%Q3svuvÿ­ùewΜ³ç̀jæÈŒ8’H‰’B´A{SƠå}¥Ï {ï}/"³Iˆ") Rq»º*++222ó}ïúï B&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&™d’I&Ÿ‡ˆÙ[I&Ÿ³Èb– ¦K²ÇAQô{A໓8“L›H’,IR,0#QUÓ sröH©\…Û†eạ̊%]×dY²í‚](„ad˜¦. ¸×ë¶[ƯN»y°w¸·s¸·Û8Ø‹ă8p&™ü&°*)*ˆfÙMדªḉ¼•³ Ó¨Ö't3g˜V¥>fX9CÓr–aXf.—×UPÂ¥k9Ó¸Q$ÄB†ă~ßét{­Ngïàpk}ucmeăá̉Êư;{;€3ÉäWĐ²,ƒ­ 8”’Ê´66zT3Œb¹¿jK;oJV.gYF¥R7-@%ü]xëb›¦¡k¦©[†¦È²ª©ºªi _΀̃!QiÇBE¾ç÷]ï°ƠÙÜ=XÛ̃][ß\ºwûêïܽñi»y˜8“L•£¦)@́Xøhܼ,ËÎËp'h̀ruLÑ4Ó0‹¥’$+º®ÂmÓ0ry+ÊV%,”¨p3¸„J²®+đt«,ƒ$xN@+è[qˆX!3›!Q‚@²ăNwukomsomcăÊÇï½ơ£¿ÙXY†G±c”́ƒ̀äß‹_*Kºn‚F‰¢d€YQ”‹•J©R/Vj9ÛÖÁC×̀ …êØ˜$  *Aʪ Æ/*VUtê* "ø±ª"ƒRUYËhPHèùi5¼D±Ùé4÷ÿî/ÿôïÿןf&t&_Đ“ªé³óÇÏ<15{´\«Ûv₫™€OYMĂH¯¢Ê9K· „†®LKZB|œ `@f… «ƒ½èC¢é ú6b4ÂĂ("¥S*N!Ñ” æ¸I,%@Rô>ŒJÅîdXO¬fx^T¬ˆ̃ ̣"*¸¾± pë†K\33­Áe€êâ _º~ùĂ À™|}Úñ©™‹/~ùø©'ªµJ½^«VJ…"hV° F/è[³¯*Ø·YT_ày’™:—€#´8…8 Ó“Ơ,¢WS̀‰£ 3…hr÷PEé‰Ù)RGà›|G‘+2#;¢øóϼ"–{ ,^C#€Ñû+:t<„,¸À€^×EWØ C„6FÈÔúÄä¹§ŸÍœÉK Ăœ:²đåoưá±Sgf&Ǧ§ÆK¥‚¦¢÷+ÚEÉí\Ï÷ĂÍà¡ Ÿ¤¨W9̃†¢h%ȇ’o"#@NQ™Â7˜‚X¤ºÉcNlizf‘íà®'î2åˆàÑ>÷q»e®ÅcdbĐ́d‡T0|sÉbö‚ h! *‘ {!<"iñô¹ À™|¤Xª<ơü+/½ö¹¹™ăÇçÆêẹ'1 đÄû!†E´â#ëđ>BẀ5,âœBÇ‚8jû ü!9@â–âY1=DÀ\ÀRB¡í¦øwŒÑg0Ë1Ô%E V½Hˆ%$À₫ 7º̀ ¡‹Î5œ„N.‹rđ _̀ZΠ‡Q'Ăm GÓêăà Höá‰jă€3ù¢Hulâå¯ữó¯|ơøÂ‘cÇèh!‡Ob]Xơ,̃;SáQ¸>¢W…QUHíă!Îù}ˆ8£cTÀ'?JÄbfÑÂÂæ(–đO` `˜3 W«‹ BX¢Z—Ü×ƯZŒ^K·Áz`&=ÖLÆ·đ>;¨cM–,S6$ b±•ß±¸2<…¥Ñ„& ç ƯÊœÉBjăS¯~óû̉—/œ=1?7 +¾ÄTe² ®”x”ÿ‡ù™4<´ƒBD̉؉*E¥?"ܨœ€ĂSF¬Œ4Dí‡dỌ̈Ø’? üÈơ@Ƙ˜m‹yg*Ơªñà8b:VN¤’%Ïwb ¡«+$î7ø’"+ 8ª„:pwû¡# ªÏO;Bèá³h?ûF³B®‡=/4}àL¿Ø…̉‹_ù ÷‰ó§æ§=̣đ̉Œ̀h|(Áê02,±_bÚÅ &Tp%¥ËÜf„©@|I³* – `Œ0GLïúuCô&}T˜ ]1+0Çî”Â)"́@•K0ơ/ÏZ*]@×Á¯Xf…xªcįÈ~‰ƯA0èû¾ăzđÏ/?èvú½XÖ+÷¶7Üày=Ư4e•oÜS3 ÇggÏTU7á9DIeÅéBr˜=„,B×C%Œ– Æ¥áUy¡¯ª€3ỳ2uäèSϽ|rqáèÜ4–cÊñÊÚt*6Nơ-ê(<œCªŒ°>@o4Dö°/±‘ßÄ ™è®bü(FÇÀ´1&Q| ! 13„D¯@‰Bßu–>•4‡n¿aXØo·pºA¯×n5³¨ÁOÆ÷gɿȭ—²½±öƒ?ûo»[ëßưÿ—¬¨ÓSGÀ+UAÓ4Ÿ–HQÏóÏhÑQù ¡W ûăŸ¾9¿p¢/óEK͆åx˜>%¨Ø# Oˆë*˜8“Ç&®OÏNLÔ-ËXÛj.o4¶vÛ­^¿Ưî6:ưF»ZĐOÍVTIt=·Û:tú}X¸Ưv³Ư<́´ÛhA»ƒVăÀs]Đ™€Z0¾Ñ¬TSÀ MIÄÖB‘3Z Ø!°ÂVwQ r„EHD{€P*ääàôÂA€^ñg/)ÓÀ™<>ñ=wok= A)ŵJ€}³²8BŒ}x‡=̀£ØùâØä̀ʃ;åRÁ˜9̣µßÿOO?yqq₫ÈÔdƯ0û„¡µ]Pû±˜X1g“X[ï.fMD=‹CLÖVEƯH¢(‡àÙJ‚ª˜£Z¹ kj³Û7‘‰úgEÎLèL§́ûÛ›k¾ïÅ¡W-å+…üa» fóh lƇưC¶eNÎÎ?[9ûüÓÏ}í»ÿáèÑypzëƠ2¶û>•‰ö àG!,f3nj߃À#Ằ:«đw,ÿTº,,ÛĐM{XVç€J)̉Ùñ£¼e^ßÙ–Q¥‘2yœ^pÜ<Ø%œ/ƠuƯ«÷̃ÄÀ¨$±Đwü¾ë—,£6>)c­ƠçZ;U­_zơë_₫ÖïÏÖ*'ÎÚù#‘O¨yˆMµh„E¤B‰uC¤Ûb(pöŸ ŒÉƉ†˜X³ ¤È´$‘̉F®¢¦ˆOÔ4µ^-Å÷>;{g“2y¼̉ĺo®,Ï-^P±ËɲÖr:V5ưÔ…§¾úïñ­sÿIæ¤ »²́Tkc`A¸÷›wzó_|ơ+ß₫ƒ¹é™S ³ơz{úü€́Û˜ÑëE £}fu Ú²Œ­È©¶®@i^öÚàâQ­È»¢8/.˜Í Z7ö÷®W)Á0)ØæÎAĂ4´Ÿ/DËœÉć.:<…°TÈ©ª̉s<‘W ø,y†}'p½È6­úø”¢(H4ơđ´/½üµ/½öŹ#Gg§ TÜL"Á“¨9&Jh‰îA·–ó̀’•°|C¤<Ÿl&đ@5§Iñ´¨Ñ‰–E]W×½|kù₫f³R©«²”·Í‚mí́₫|ÿœ,p&Ư >́w›ÎÀ©—óvÎjvú©6¢™  ²¤:^hÊôÜB._Ä́ñoF.~ékß¹ø̀ ó3ă s3¶m1²I‰BO¬>ƒR¾Äq)A4§º“’z –ÙeI¥”n^ ².‰ñÜ&ƒ—˜%Ê9æµ\J«Ó÷Ú½k÷75ͨ•qØ7ĐEÛ₫ù*Ú2 œÉă–^§Ơn6úƯ^©\™¬—¶÷›°¶‰Y`¥"ƒ÷<¿iS3s…Rå7à§åÅ×¾yêÄ™Åù™ÙéqM•=ÇSVä0™aa“Qcr\Q ¼.ƒQđ‰HK±ÄH¤))a:•4ÅÀ¬Ëyy}ûÍïî4ú"Fb6€Á4ôbÁẤÑÙ'e”1µ¹ºôo›L̉ ăů~çÙ¿rêø±ăó³ơZEFbçMb¢’Æ03ázØÜ4‰ç‡,̣l~·È¿Iv˜©æd€(gä!-.’:¨*º†̀ï·—¶̃º|o·Ñ1tœ¨!%2ßZ´-EE¢i€±ÀÆ:$uă€3yü²µ±ê:=ß v.Ÿ3Ú>ú–³ a©bÅÿÀC&JM‰Á¾yåƒp0ø·zö|¡ôÚïưÇKÏ¿|̣øüÜôd¹RDÀ>9 +ƒî”1ú¬ˆTäHÎ9æzc™a)Xœ*fờpDHé`QJ¼Û́y9C•“ơ Q»?ósqCœæ {,—K¶ Æ€nA¹¼3,°5Ơ€Ư|9f/&qÛ—$0 á“ÓQ,X»†iânFÍÁÂ5 €°aº0Öh×F7µ1xià]å¬\±`Éi˜q>àSăPhT. w=Ïkwúf«Ưêî́îï.Ư»¹¶|wgsơquÛöw·<¯ï»ƒ±J9o鮢 ”¤˜ ¤AÚ>ÎïŒ5E 8ü58îrváÂ3/¼ö?ªU+gÎÏ̀ŒĂ₫H%‚¡ §+càŒ'sFª!$J”v^)錄8o::ø4‰DḈI©FµàĂ2tm÷ yơ₫æÇ·Vá5Á%}Ä:’Èđf-LX=¸°ÛªT+—¨ơ_å ÀŸ¯À*µ‰“ç.?}._,ÂdLHđz€˜LZ&f…̉2€Q×@}¦hp$êă(>NØÀÙ °äĐơ‚îÀƒÏÜ |ª’P/Øo úë{‘Àư3^>ÊV©]ªÖÆÆa=ô:½ƒĂĂSgÏnmnm®­l®-ß»uµ±¿¦ơç à8“¶’̣جnÙµ̣̉æ>VÿSè–ÜLDN óBËVËƠ1x'öv~¥gØ_zåk/¼úéñêâÜ‘z­,c‚*Veú,pœ¡0œ‚ÈK§b$¾øe°Î‘‚̀"K1¯”.«">@4NăÓô€;ƒÿ–V×ôöƠ•½l¶¥ó#h1Î,D¸äå!WiëpÓ EQ« đñ#wÇ£ÎüĐ®ÇN^xñkß<²8c` É¹œ)ˆ8Æ?’X S ±;6ØÇ ùµ±$ ¢¸Ù‹x*Ôq1)Øw<GH‹^àă¢À‰²N³ëhÙĐ pƒYÖQ¡q#|\ủ7#²U^•Ky«Z̀×Êù©ÙÙ#G¦{ÇvvNîíí}ểÖÚÊîÖÚîö:X×Ưnûó ‰m¿₫đ₫ü‰ °ÜËÅÂÚNƒ5Ê“ăbôÇGÅ.Ăä̀Ü/`xưó‹§¿üÿí́ù§&k•Ó§ó9?ô0́¤ªÊ:"tY™ÍÍ€‰ó*&\é ™E—½,Æ#®23³‡ô^àÍ‚u…¾×ï-ưí?]¹³²™³lS»IUp80=Ùå12è•’"&¢Ø‚́SÇø¼ d₫|…h»ñ3ÚïzƯ}·×uœ›…!F¡ÙZ4ZGwáGæÓ¨ßØ «GÓTø€1FEÖ›ñw¢€Ú•¯z[&Ú4¬2H¢&,AP ¯’öà́ûÍÎ̃aG^AĂŒ+ù\±>>13}ú́™ƒƒĂÍÍÍíí͵ơƠ¥­µePư^ç7îr}°¢Cß…«µ &TY*–ÓÓàO7€7  krv₫úå~I èÜÓÏ}ù›pâø‰ăsÓ³3“¦‰„é9 ±äÈùç")NREd´L©KˆUNÅÉûÉZÿès‹’§ä ¬Ÿ—«Y·ø9¾wơöß¿uơ°ăäL>ŸN§ŸB>oS]îÅÆÀWàôb́; #®Ö,́f§§e>đç, [6Ö—V—–û«ƯµC>¬äEV0Ôo¨cĐƒN!¢4“üa²$eÀŒẼ[Êêx$¢?äU¸<‚‡8K kmKça‹¬¨^â5÷„đ0 ·{¶ª)EÛª́bm¬R«_\l·Û‡ơƠƠ奻7ÀÀîwÛ~àÇ¿$ĂîĐnö:Beª >‚Âk¢ÉF¥Bâ´Që\­O€ûêăè _$v¡xáâ‹/ư»gÍM׈êUĐĐ¿†÷Ÿ%uéü˜·b­È$IXMµ«„>/k0(G¬ˆ™̉²’”s°â"~¸híĐN No¯;øá[½}ù^¯çå,]S¶¡÷}Đóùœ ¾Ÿ̉fx’vç0€{p,°çr9đ¢j•âƯ•ơœhŒFïä `ŸƒtZM°–ŒƠ§ªyÛDw+–刀æ›®Éđ©†ªăœvƠÀøÚub̉Đ"&»9K* —¢”$YÆ3ÊÓ’Ú=~Oî8æ.˜´±±#a@«,9ÇóÚƯA»ïza¬jz¾P(—KfPÍGÏ€̉Ï“sÍù̃¿9ŒM+73¿XŸœy·Ñđ£y–¹!-RN¶61gH":gmù~·Óú'¬M¾̣ßÿÊ7~ï̀ââ©Åù©é1•"c:ƠKP 9Nˆè”8Á'˜`TF4₫ d Ư‹9b|H›-½û²È†u#™,ƯUV@&Ëđ ¹¶¹ÿ×?₫đ½kÏ·s&r¸S.X¦ê,6ăff”ȳǬU h8̀4b¡O»ºµû`eƒˆ¥ÅL¾QÖ8ºúáÛ»›kóÇNMMŸñD­éDƯ@tĂ8D¶J4}ó>Ø0ñl"O ÙIY}O§¹ ¦@’((S‰8’ÿ†ø†Ơ¹i 'ˆăă:ßhöLC³sFÎ.ÍcÎ`lb|ñÔ¹N·ÛØßY_y°rÿ|o·ÿfÛ\»Ù톾g[–e½§P)§¿@M¥„—kKÅru{cơŸ;ÛÂɳ_úêwx̣™Å£GN,̀ 9–X¦đ.ơD1ª:?ä^ kâíwâ&¶³÷IJ(ëD1‰ 2̣HRå48‘•9ăĐ®·î¬~ÿ?XÚØ5 #gè́³”Xƒ0½(́vˆ‚v·…ól›³F£ƈLWă¹8ˆœJ1l%€áDg´²Ÿ#†7×—áË´́Éé¹£‹g'¦æÆËm/n¹Â€¶櫦 MP'"nE)M¢&kI´YàúX=>i’Á¸0ỔC½Lé4ă¨;p:˜Ö†¦‚oª«z¡”Cn›ññÚÄä̀ü±æÁ>xíá}p’›ư^§ưë½3€±Æ₫ÓïÂú-b̀UM1Ä;n‰oÊ …0Äb&¸Ă´~&w ÖèK_ÿ½ç_zmvzzafjr¼j­ÛéŸk̀ + 䢑wÓ[Oê•4j$²ÏÙø‰S¥9"ÎLG& }jª*7[Ư|÷ê[ßq¼Đ2Àª¦ât8BÊI±Èº@;@L%X¸E9»K>Ÿ·,“˜¢ù¾ïÑ\Bx®’mĂß:Ư¨«i)Pæ?}  yowskưá }P0µZ>—KÜ2ǸfdI!1̀RLJ >¥4̉3¢£y“0Ô®Çe|\§§mn<¨5'tÑØÂpÎ@,$*›cOSæ¦ÛyÍÊå¥êøÄÜñÓçœA·y¸t÷úỂƯÍƠåvóÍ×_.™|¸·Ưí4ƒ0PiŸë†2C.×Ă"ă–̣£X‰…±©Ù\¾Đ<ܧd»vêÂŧ_xơÔ‰³'LOÔaÉKÈq‰I‰ḅ’ÈY¥4/#¨)iD½œºJŒ$²]á= åu5‚N7á—¤P³””î“´³È̉Ăơ½¼uåÓ;kº¢+ ¥¦Ø€†„ȃWe±€6ÛQ’rkÜPd P÷ú=Àm1Ÿ×u2Ă!Ûă8äX9Ưæå31`û;đuÛ0g?ºxzj₫„e•:¡æ"y €5­¡–8 Å´¹\x”~%ư5f´0IđJ’̉Ó ?7¹cø=yLjŒ3M Xû²"jº¡à¸ĐüÀí–](×Ï=ơâá₫öĂû·V—>è¶[¿D«F¸çrEË4´NߡٻÔœ¤À:\P±TCöPø¯~ëÏ]|~~ræøÑ™©±ªÉÍÉvÆ=hbª’S0³ña(ZyY.ö>QQ( DR¦°+„JŒ¾1‚¶cøê•½}m}¿U©”àÑëđ"$²ŒcỀ ̀“g½Nô9¤î7g×!Zi4§]'Ă|.o:l~è»nPÈÛ…|N–eÖÏÏ.9đH\gđàî§—nMNÍ>ÿ èä|®âÄÊ DFalGăñË¡ñÈR¼‰?ÔRµ,¤©¥´’(A:Q”§¤̀17³ÓˆÚh-æGPÑRŒ9ËXS#gUå,Ư^oĐí÷5»8>sô‰K/ïn­ܹ̉¾»µ₫ r?đ ́tÊƠº†UJTANK’²ÚÊP`%ŒÂÄỐ̃ÖÆ7¾÷Çç/<=;1àÿœ"p·^Rj*±`ŒxôBmơ‹Ô7H5qXĦ°Q‚,ƒÇzæ‰gÀH^]¾·µ±º±ºô™á®ÆÁëạ̀Ëaéߤ+)ÉĐP…|;y₫é£'Î:yö̀âüx½bè:h¼§rç =Vfa*ÆÓŒFD#Ë*¥kè㵪V1 ú16¹$w— ˆKô6ZƯ7>¾óÓOîyaœĂÖ{ ¡¨Hjk¡¸0`zWˆ¸9Mû¥–‰?€íg‹Ùe‚KÜô½ÀË™VTÁz½ZR5%DiưOà/n km|ÈSW?u~fîxµ6 µ©Á8Mư2¥G‘&$}p©6MªóyƠ_̉' ~Æ‹?–Ní÷ä ,=M‘°8Ï£\¥¦Z,cP$Û´Æk¶ăU:=g÷ µwØjµ́ñ|µ:5vĐÛÛ^Û^_yxÿ68±Ưn;- ]yÁ 7(æMMU1ÂjÎR:u đ,B069=]«Ÿ›«•†*ż®”X«DÆéxŒî§aÄÊy‹<¥è0³B(*¡!d!—ÀEfï‚$5iºª,¯ï¼ñ₫íO—¶àÉrº’ĐnđøM_ˆ`cÓt-ÏsXˆñÀ!l<£E¤•J¸bªiWp7pÎÁ₫á̀ä$¼á•’3ŒAω“ ” À_p÷8\{xwcơA¾X>yö©¹c§ëÓ ¨º‚Ä EHx7ùH‰'/Ñ$Ă “”˜Ñ<  £ó:FơöÏ›åI TÀ‰¡J†V³Äë‰ÅtCAl8Ê6VcÙR•|µ0]+tú›û̓f{ï %ö{Svmfñü© Ḯl¬<¸ópé8Éà7no¬u;MPÂ…B¡hi®£¨ £€cIZb N(Œå´é‰ñc³S¥R‘½ ́ Ö!‰«%y—!Ơjø¾G^4f•d̃4$’f³1±µ¹ÂLÅÄÔA¬’„sPŸŸ̃yøúû·W¶†®é†¤g“¨uŒ4Z´Ñ!+-X†¦ù>x³N¬v“HxÅ1ßrÁM’éjY5,}Nªªöú}×uáyófLô½”6K#ưvèâ8v>x«Ëw{ ™ªÅ¼’WäY‰¡á̀²¦¼ˆ8IY “ORú˜¤öcÔnyû%†'åuùè¿ †ªX°d5иŒÑ\d¡F A¢̀˜YeªlS«ä'k¥‰ZÀ)«º/(²+Ơ&Nœ›œ9R®Ô¨]N©ONÒƠŒœïơ[}Ô;C;?F¿…¸b©gfN,̀[–a, tb̀B¨t_`€º¾ç.|× |Đ„A2®‹PˆxYe‰æ Ùô-âư ü#`ŸÚ FỠÿôîß½}}m·i`k}`ñ®d\(‹ơ‘kÍ>Fd´ÔT£}˜Ë¨YŸuM²În®æi7‘(ÜM¶n%åR±\,‚Irí΃­½joÊ4đo•€êh5ö;­Ăí•£ÇÏ,œ<_˜T ` ˜z³Oñ₫¬MÍF.‰h3cÅ/Ö8&1VúÇÂC’˜Dh9ĂïÄU ½3´‚m̀WúîÔ^£³ßèlíî4«sg&æO^¸ô²ÓëÂéCßo†®`†ÂèeeÔ½đmªd^8:>3= póiJ:¥!$Ä÷(°* ¦{iœ§s+ÊïÆÉơ%Å“‚˜Đ¤oËÜJIŒ@¢ p¤kjßñß½rûïv{~̃2˜rf­Zđ:eÏDâ4wTËZ‹°#A]ç¬B€»‰ƒÑfÚ*6& 9´Àbq²!ÍE“1|Á³Ă±!QªƠR~4»iàß>m<èw·7W·6v›‡rè 5Ö[#ŧ=…aû‘$IVh ƠªÄJ„´G)Ñ´#E!́rk¬ ¤ÚFV{ ó|ê5`u±R:jD’FkCx[•%Û̉ÇÊö‘ÉêÜd}¬VtJư@CÑÀ4—‹åXư₫éd đø±¥‰'&K§ÇÇkaÄCJRà’ø/’˜ÜͿ؋!Æa4øRäÛ`›©́c•>oÄ>™¥ÅZƒ‡%Đ¼0 /ÁQHj¤E·蔹¯›t+².+dyIdy$³'“Ưé.$ÆS'%@-}”ǾDåÄl}aº^¯–½ApĐr@Ñ…‘à̀J„¸dHgæê§æ&Á cn'+^ùÉ…!z%$‘‚΢’Ä´x ûI-^¢‚EøJÉ/à/ L¢Z O¸¹´₫Wo\¾·ºÏjP7q̀dW¿%V8H§@QSá4 ÍÆ÷ŒoÓ45¤ơÁ†pf0ËÔƒEơw,"索¨cƠ*<ºƠí\¹u? CÆ€ËíjÏmî-ß»µ³µ*†^)géè_ ¤‘WSÀS¥$Êôx!Oˆ©îNXØä6I„!-iDó’`ÁTG¯Ä₫ÓĐ ërN’„t¿elL!‡¡ï‡pLÑ6ÍÔA»Y˜©” noms·Ùî ¼8ŒÆ Ƴ'¦Î-Îaf¥)­ÑøÙĐa…¡ư›$¾%^[nfRƠÑ ₫q8*ñ¥à6_¾ưđõ¸¼¹×ÄÁ›̀₫îŒSRL ³$càL³̀TA¾$¤ËĂư! öa4YAƒÑ¡QÙU@´¸]²î ¦´áÿx­ËY½₫àÓ;ËíǹLÿî(äN«±|ïæ̃î¦,DÅ|NÇ=<¢E©HœÏB‰F¥„ä¦rv€tHR¬+±FÜ¡²ÂƠ–ØÇ¤ÊĤ¤8Ї\A\''uG ư2ß#ÄÚ##æM0píù!<)oÎOWÏ.LŸ˜›+åáÎN¿OUcj‹à/’0đË¡σ‰Ï?„‡wvíÚøæ?wnüđÍ«Ÿ̃ß×Ä 2$q¸Hœ·(yÓ„a€Üú u±Œm…ª$9ĐTf¥&’<²Å ™m†®ză/¦hçJåxHk[»7ï?„K*ˆL~×\)×́ï`»âöú²s¢m9­—ĤĂ'm¸M¢]¢0ĐUdÖ́&D–IŸÈäÇ ¬&‘YÈüOC(ÑD³ù́WRª¤ƒ]G™×)svȈ*!P‘i=U½xzîä‘ñ¢mn´¯ÜÛ¼romuç¬ä-øbf*‹‘%q<̃̀ &fc僷ă³ÈTÎåỹ•[K?xăêên˶p{¨ÂQJóä|zÈ-t(¡˜ºĂp‘íÈb̉[(s.3UsÄ 4 s¥”|d›F;“y™ĐE¬Tºª” Öâ‘ñWŸ>qîøTÎ4·Úï\øá­‡[ûmV(¥œ™·tF¸‘đb¤µ’ÄW’åbÉ4Bo,X¦Öéö^ÿàú̃¹uØqlK“YƠD̀ßÖ Á^¯œ¼c<Nyv`aO‚ȃh<#GẸ̀̉îtZG|N¢Dqf]KYe›Ïé–¡›†Ëå¶ön?xè8XÊVù¿q½Íµå­•NëPŒC1 ¥8RTÂP¬À)1§Ó1ÅJưZbH³ ³§”&6³œ„oI¹pÄ̉ư2c÷:¨[⌃sd=ˉŸB¼”R°^B .1Ó¡œ·N$›ó#áÎêî'wÖ>½¿q{e§ƠsÀ´Î™vƠS¶6¥ÿd́Vlåϱ̃* " ³ÓÆö̃áß¿ùÓ+¼0²©NC¤6Cæñă`¤$ĐÇö´Ô fï …ÆF̉?™RG̣p«8ÿ$O°Ó[æœi6ŸrFxŒ¥i•8Xù&kÛîöº7î=lw» ÍG̀äߌĂë+÷A!‡đUyÍÆ};n2’·(³8׳” S–̉đ³4,‹$×sIÿAŸEö …ÿν̃Ñe1G(ië‚$%U‰Cc›çªÙt^væ±r₫Âñé'Ò>}êˆeê›û­ËwÖÆÛ-8\°‚L™‘Ö ³³ÜrCxEpÈưƠ;uùĂ+đ‡œ¥w4‰{IÛtê-Èô¶$N¾̀ú(³ ±v£ú%vMmæŒÀI;{³È́çæ4%#³4/́V¶¡ço`l §¿èº°¾zë̃~£¥Q€+“_â¹Nópïáư›;›kî [*‘8‚%°¿Ơ3H<̃Cê7­²J}Z9Q¼Bâï ¼Zƒ›«<¹*¥Â¢ÍI§[y˜GàáˆƠØÎ)™ocHÆe¢ À1«äfêg¦N×á̃›{Wïomî6ß=X° L“ÇI73V-"‰>(IU•®Ư]ưá?}rsyGƠ48pè] » cêTd¿“Ñ/+efEĐr2‹USâ 8uẠœŒåaîE³bÂ1åöË,èZ ¬q]V`sËÆ{KÛ{R¦ÿ=«Û­Ă‡÷oŒăÀÇíæzP¼V³ÊÆ|%i`2†eî÷ÊŒç†ñTs0ó¤±Ä ri˜F ü Ă½#sCÓ^_á§4®Ăèç¢&²…Ïâ/Àôi>g™¨F^;UæLRt§¿`·*Ó̀{Ü p-ªØ–ˆÛ̃Ÿä¡(KEÓ’)Ŭª Û€L9SaààLàç³mÜà¼rÏ {7Än§4ºn°ßêAØwpRŒëv¿×sÁA04e~²27^±1P₫àêưÿùï¯î4àu6o™fĵyQ8¯Óyü\–¬ âĐc—x!§HLwØ¥Àª¹z•X' È«Áő۬U pÁÉ™ÚX±@mĂ(¦¦‚!}gyưÏôAµ\¨WbI¸răN»ƯËú3yD h6àkíá½{7¯NLÏÍίÔ'K•jµZË‹6,%X́ è†Eç'éFyÓ0T5¦²Al‹í¬2Ö“D*¶́`Ơ•ëjê¸Øo`Æï4²ÀơPVư ËƯ4Ô Œû}GÑåNÏTAGjºÜĐV"‹ư¾«éZà”Àd»ç‚% ¿t5CîuƯNß5 ÅơBæ½t-UŸ¬&ëù‚­´ü¯Ÿ|üöÇ7û®/ÓÀèB ly„”¼Cĺw — øX}Ö Œ‘g‘ñ½ă‰™ 73€*S¸É!pO˜yÎ÷’Pưª±íHX¿ièêµ;Ëÿù¿ÿưÆ~û™'ÎÀéÊy»˜·†[€3ùlqÁỂøº~åưZ}bf₫øøäl®PªOLØHwj‚êIJ%Iœ››¥xçá¬a⨀PS×A÷ÅX“(w©«46,°tû†s°́)ÖUÉCöÔđv‹}àº"»!À—A«¬"±₫ưÀg{†ªø%2¶Ư ´4 û!l°;Dh +R€“ĐØt¾×é:GgÊ‚,üă;Wß¹zGÀÖÎâTWçº"Á†®‰#ÅTb"cºŒ*X!In ¬×_ätD‹DÎ6ê“ÆÆÊ0°äcv°ă…P`6§ä¢t4¯Aå̀q)Ÿ+ÚăÀµ-.éGo_₫?|gs¿]«á̃Ü9ƒ6ñ*²OgÎäWs· _kK°âjăÓ'Î\˜8èx·Ú­A8LÖ-]‹aEGơÁ K®€ƠZ5̀ù™©ñ±*É~#éAĐKuQ‚mj~(©°A/ü] c{ƒ©k!Në[-c#®ăĐ Uæµdƒ1VúA«kçŒ+wA‡µA?×ëƠ¯>ûôµ»¶aGĐ5]’̣"̉xqƒ̉ªÆg/ª`¥•Œö“‘볈2̃¡ LvÚˆƠN 2KVyÆ,r™ú-Q3‡k]m]Èi•b…ËlÛ œ¿zưĂ¿~ọ́A«_¯h¸¸¹{`¢X*Øṽ03g̣«¼`iÚ©óŸ¹x)ŒµåÍM×ơ»íñ¢ĐÛ¹sgeÙ¼N«1è÷4]?ºxvñ́Ó “cÏ?yná蔆=4Tw8qåĐh^̀Á„Œ—ST‰Dg…͉ÄrÁÁÚ´É\B9¤q^'­úcº̣̀‡¹QT¯”/ï¯l<\Û ƒ* s¢Tø̣³OÜ^^½µ¼êzJ‰ï˜ØuÄ„ÑÆs@‡¦º%O¬ÿx,Eg†aV¿–tRĐ›Đɹù“Ôøl*>üñnH£4°s8@T¥hW̃6Ưî÷ÿ₫½¿|ưcYÑÆ«e ăQÛ$8 {ûÍG'…¼fh€3ùuäØÉ Ͻôj±Z];è´z‡û]SöEwÿơø₫Æê2öH̉© ÏNÏ?·¸đüÓgggÆ(ô12[ G1s²I¹• ”ñAªÙ$–uIf%³Ø’”PĐ ©+Xo0zÏT¦.'ø´‡­ö»×î}xơ~ÜoRÑ}Ç«Î<6Q­|zyc?ˆd0 2?Ê IØ[ßï /0MĂ0´„!¦pÙ®7N+1ˆ9€Æ|+¬#"ÛµW±SíïáJCWGÓ½Z°4Ê ÖA³ưÿ~ÿŸ¼¼…œeF¼y {ÁMßÚ;<±0×_.Ø€3ù•¥R?÷ÔsçÏíyñN³Ùhàá£cÂÇo¿“¢7_,?ưÂW.½ôÚÓçOzÇÆÊ°zAϰÖ{)™á§ ™Z€…Q>L®H™ÂÅ( Ĩ4(¶Ë¦÷̣dA¥`¸aă¯q¸B4Ä;qµá§¥G¦íå₫æŸ._¹»F]ª™ÀíöÖïúA¥ m¦^¹t₫T5_øäÎưN¿oH“eU*˜ëB‹ÚUŒl’82‚æ4đ̀Rb;PÙ Ña‹¬W—q÷ÑU‡¦ÀdÚ”¸¥ảH.ئă±́½Ëw₫́GïƯZÚ̉  ~¯ÈG±±¢ï8v'pBr½\Μɯ&s 'Ÿxæ¥'.œ½±rØvÛ[]KKVôáå÷zƯ¶¢¨ÇNùëđ̀SO¼tñ<9½f>eT†˜’qªµ˜`•´ –d`\–æ–È’øÈ`ÔD(†s®Ă0NGº¥ƯylĐedøTßf·óÑơ¥¿~ưăûL«T&PWŒ đ¾;đƒ:œy¬TX<:cÛÆƠ»K»M¸ Ø3«,'ÄĂ„¶0¸Êê 2Ÿ̀Ç\A–ÀKSÚªAåO†’Âç¯HeÛzÁÔM$’~ü₫µ?û»÷ö;°I€:f&ÆÈè9|làî4ư0°-Ư´² V&¿˜Vîâó¯=éRct{;{ƯĐ›¶n}̣úệ=8àüÅ¿ưÿiñØÂÙG åb£Ó÷Z¬Èß÷O ˰ԃ“™8œùÀ!Íá¦e­«ZH.,üÅó}đ)}ßw\Ÿ“§K2́`¤j>+‰h¤D]Óá×s#A†çZÛÚưñ»ŸzuP†L÷,¬‘âÁÀÙÚÚƠê{8±a¼V~9îæ½•ûë[~àS`+É*¤s†Ñ¢îđ¤5JDqÿö/б4!… @‹Ó^êíÅÑk4ôŒ IeŒ‚²m• ¹ëư¾ư·o_u=ߢΈ‘Ä|€,£ÚcÛ­vÿ Ñ]˜-Á3g̣KÛÎ’t₫âKÏ^z®T­x{Íñ¼å{{“EÁíl]ûøXÑ•Úø+_ÿîË/]êơÜ×?º€yJÚ€i^]Ű0'BÀü) bú‡¢Àí»¡*œúB˜ù G€íJSÅø»óDIƠj³U@ Ç̉Yà0ÏÀơÀŒïº‘;5? 'hM>i+nŒ=ÆÂó6Í5 z®;Y+=ûÄÉz¥x÷áÆn³³Y{½˜ vă Q‚ç{Ö†¦©n™3€‰læéâS‹!›’FTAÈâ‘î…½L*æsåbÎÎé‡Í8½ï\¾o‰©i™)é0ÈxdƼ%‡íN£Ó‘å̉Dæg̣ËËÄôÜ ¯~ăôÙÓ÷7›ÇƯÜhI33^úÁŸư°q°+̣™_;îÜ ¾ÿæåN·Ï̉* “|?ˆÄåÜ(?$zA¨)pÄŒaTÑ2’Zcz‰́m¸–Q‘*Ăxơ k¢\ÅúMbcW°¾åZ¨N}Ôb̃¬TJ•bn}÷PL–ÓđT2‚H £ ÑnÁî ¹ïxSµ̉ѹ©©±ê'7ï¯lî©_H\Q!’®Á ?0ƠdÀ 4Tä+bñwæÑÇQœŒ:cldh^SVdZ¥”+ås;{‡úwï¼ùÉmØŒÀTHg³'?â‘H;•j‰b¯çt»ư^O˜¨gÎä—MÓ/½̣Í“'Nö}áîú,¥‡vZ´ïƯüpé̃M8àÔùgyá•#Gfü̃µÍƯs‰Gđ‘f̀SY0waeú„$ÿJ¥ÄqÈ`I­9”ăM¦"°™fŒă–Ú±S suÈå ( ‘¶.ÖˆÚéá8ÏJ!7?5¶»ßlt{ª¼Ô#©Â¡€»ĐAqÁ’8n³ÛŸŸ¨¿̣́…ÛK+Ÿ̃[é;®JmJiKHX‡Ø̀'@“ĐŒ39¥´âŒĐ±IœRññà”3ô‰Z1o`çÿ×?ÿñ'·Wr9 6£‘@a:ªç“S^û~«Óêơ]?ë#p&¿”ñ|æÉKO>ưüÄÔÄÇw7`IƯ¿·WΉÔ}ç'Amḷ…/çܹ3ÛÍOn,klÈKr‡s‰c̃²Ă˜¸$›6™e ‰¼ÎOG‹YT -ë˜:œˆ6J$: ́~bƒG9 .ѱc+¥m„,ê̓V­˜›˜¨—Ü̉Ú.7”Rœđ 6àSPdgà6–ëƯï¸áüdơÂÉ…é±Ê?}x48\: CHÆ,³‰h‰¯ ¾z·çÀïØ“(§c.x9Èmh{W‹…œyó₫ÚưŸ¯¯íÚy ^Ö(z“[|̉RªÁ81T©ÛwZ­́‰ ÈVg&ÿ¢ å _:¶0×uc¤§q‚íƠ½SG­wßøÏàø=ÿê·N9U«×̃üè&’*Ë# £ÑVt~¢Ø¤"§LF*\¥ƒyÁ¦j 8m@~rD1j¤ăÁ¬aKëơG†’Ss¢xĐêńwƠ:~d²ZÈ¡oNñå¤Y ñÚ’‰i^­ßï7öÛíöưµí{{ăơê}ă…'Oσ¿ 6uV œ9§D_§"V m¶Ú É#Ú˜D>™?„Êấ\‚ùÖÇ7ÿï?ÿû¥Í=M7¤”’[y§âÑ!N Ôè›û‡`ºëZ¦3ù—đyêÂ3gÎ_(VÊo^¾+èέSGsÛK·®}ËnáĹ³9¾0óÁú½‡[yÛ`ù¡QƯ§UB̉q éœvh, «±*DmÚ¸àƯÂ-k’¬U± —ơ b¤È̉đ8ü;”Ă£ÈÈD$å{̃æ~³V²§&k¶m¬ï†A,iœ™Q»Â™T,a üËưưưb±§́9îñ©ú«Ï\+?øôn»çƠN˜\s7ÍíơØkr°(*g áÓF…ÉzÙÔå7̃ÿôO~đV³ë ¢Ø$œ'BÚÀ(¦yÁ5Y/†ª6Ú½vw`ç¬ À™üBăY'§çŸ{ùk'/,m´z½®+^5/₫à/~èû^©Réµï‚rcùͯ«rZđ8T¼ñèé̉b$^ùœè(.ÁÚ„+i\_QG¥\*À#°·ISÛî mĐˆëûqHá(™3ƯÄRRb!÷«¥f{Đ–¥ñ’½0-ƒWÜx¦¦̣ÂFi8\;Ÿ·á´‡î#Qñ¦ëĂS\82;QưøÖ̉Ơ›cCÅèwú*Řs‰0.‰`ºÇ¡‡¦¥Ê‚NUYâd½¤©̣_½₫ÁŸÿèPå…¼ÍJ$Å‘q:¥˜½?#o]jÀK¥x›J8p&¿HÊƠ±/}ơ»çÎë‡̣̉æ®ç{[cÓê½›ïom¬j~êü3ÇŸ›ÿäöĂưĂf>—{„™ëÔGÖ"«Nlåá0NdƯEÛĐ+EÛ̉Ô¼aÔJE¤k°14#¬Ør)W*åjµ₫Â…\>ÿ“>juåb{¼CÇ|è},đe`Ü ÀEK5̣¦Y-ÚƠJ¾^/”+89™«˜&ú©.è2/8^«ƯßÛo/­́|ôñƒ×{×á|cơâñcGçë3̉:=·Ùó°ÈІ½b<w°‡ÎáP ôÔœ¹¾{+\ơ*pˆ|8S*çºn³Ưq<¯Vü¾·0Uưö+O|ó₫̣ú>¨AËÔø˜d1yÅœ|¯T0w÷ß½rëƯkKªÙ¶•QÇÉP¦„đ.鯢0½[‘(¤¡xÿ®Sm¶úđ¨ À™|¶ËƠ³O^:}úd(ªË[Ă₫ÁÖᑺºñđƽ[×à€# §^₫Êׯêµ+wVW6vÁ&üL'é̉mº€+Çơ…H°uc¼Zœª•§§*€@P§ù(W8U-–=h¬óưQ¸̃áAwcçđẠ́îƯûÛŸ̃X}ç½;vΨÛ33ÅZƯ.çµVÇmwùØ5)Éd^ăEAÉ2¦ê•n°s؈8deȡaÁ.¢©ưÁ`{w·T* oœœ«ă…§n…k‹w¤$aô–(<{°RÇ«…G&ǸM›Ÿ˜.&ÜxAèGđź÷‘[NÆ!åDfA‚RB§6>Y˜*?ùÄB·çlo5î/m_¿µ¶üpok³mÛ* ¹R±j­Æ'¸°e°&&!íRäă{£x¿Ù³ µZ̀ëºvpØê»øă°‹¤!¸ù@”b.7đ¼f³í¹~ï82₫ä©£•‚}siưô¾ï#;Ç æ¨`OYYÛyưƒk;ûMÔí’ñöˆŸ ±=âb$^q̀ĂbÔ/)̉¼oĐ¿ đmC;¿x´R̀ƒQ8“Ï]>wñĉƒ`·ÑÚXoE3;“»ö̃å­uëϼúå×¾"«úƠ;7:ưiiÀ™kŸam&½źøüĉ£ăÓă•rɶmLÈ´z½f»—3tđ -C3T*7(ID‘éHˆƒ}å0Œ|jÓG$ÓŒ3æ&Vª¹g*Ç.œŸÛ̃ĩ½¿yëöÆ̉ưƒ‡̉áØ¤=6ËØó¶ë„IØü–ÓÍÖé;’r̃¯€¹Üs¢ˆ‘iđB*́OÀ" Ë÷<Çuèáf§lf́›“µ[Ë7—705¥`‡†Câk·—>¾~û }²„L@‚<,‹z¾|S6H§¾1e‘BÆ3µK•‹ÓăỠÀÁñ£ÙbÍäçåôϽüÊ—ÜX̃Ø;ØÛïo®57—®̃¼ö1üơÜS/<}éùé©©k÷Ö×¶Éæå«‘Œ"É áŒ/Yª¬J%o[F«×o- ƯF»Î-ʰÜË»p¹0]¯Ô+…™±J¥”gËéiÅ(à´ˆ́(Œ)OL=LØ¸Äæ µz¾P>¾xḅáĂư[·ÖW×ö÷vºµq³T1 §’8¡D$ºÍª±–ZP¹ï }p‰+¥¢©ë€L?DÅ‹ƒB™UK#NuCWÁœvÜv«OZw¯Ù}bqö♣đÚ®ƯYí Üœ¦ú~pẵ̉•Û«½¾«ax ©m%1Jí’8U¸4S<©´Æåù^#²"‡b;‡¡iÓăµÿŸ½÷~²ëºïϹù̃—_'t72ˆ@ ‚$À$Y"5 .ĂÎÖ̀ú‡­­­­Ú?djgggÆăơØ3»[²å±lZ T¢$‰$H‘H»ÑñơË7ư†sîkHY¯×Êư/ơưoú×q·úĂJeȱsûÛ¾C·>óĐ½û^{b́ÚƠÍéºåË­¯|û«ƒ~zăcÇï9qü¶•Nḯù‹8¦âYns®7B3BC2¨\ïöWÖ;5!qÅq2§9‹r ¯Z›8ĂçÔ*ál«¾oqæĐî¹cíßícư™¤HÈD‘á0'Á8LÆ9Å5éFU«ÁẃÙ·ê½wW_ặơëj6+6*¹Ze!YOg@4Ao4¸µN? ½F%˜¶­ ˆá¬`á*<† ÈÂ#»ÁÑx<hW¼đÆÅóíưó3ÇoÙû̃µån·ûÂÙ·^ç &ÎSJ[.íªA.Z(6¡Q´ö:$Ï̃8‰Â`ºÁ7Œ¡̣dơBi˜]RĐzÛóá›G£ h,«Óu‡ăf-ªøî·_~ëåóSTÀu´n—̉B–LÅ03y“Äv(£OË.im¬‹Ú5ƠZ˜†OCÅÍËNïÜnºƯÿè“}đÉùƯ{Î^¸:%.,/4å`í ßür&3s‹<ñÑ<ñÈÅë민ù>²i™)ÅDB ₫1ag)̣3Çiƒq ư¤J¯fG ϯ¹QƯ ño>¨ÔÜ $ #²~lEº«»½Ñû×W_÷ʹ‹×Ï_Z‚Hö]›´©Pt¾!ËtÆL–Ø(ÑAĂŸÔó™]µ……6ĂÊRoЉKŸç81CR>D2ôáB‡°"U+ϲ8- ÑNƠC(¼O·§É6̀Ă\́×̣}#ʱÍ:„ƯVw0NRă±(´G#¿×¬*¤Ê‰ëÙ¯Pÿ:ài0Få´@Ïù™©V½gùëï]®DÁN ½sÛ6•²Ù®Ô꯽s}§W®läĂÁî½áŸ~á+I<†ƠŒª5dÄúÛĐđ PöT}Oc„^ä™ÈR5f£>Úy2Îú½x8J_¿pí͋׿ưê…ƒ‹Ó÷̃~è®ĂûöÎOƠDE/éH¢×+nŒ•̉u5½ưĐ½ç₫C3s×_»²|m#¨jËQp á¢j5 C×ơ¨­V¬\U@œzÍj´;̣V7{£$—mw•±?*0Ç’ÏŒ—&ɵµa¥’g ¡9x©¡ßŒ¸ŸƠ>,•AŒĂ6äß ¦YÑÆ̉*²B¥ă¸YQlayŸïÛ5½À;·m£b¥̃xơ…ƒÇç•)Ëöß¿´V÷$ z[đ¥½̃÷àc·Ưvø¯¾₫Êf·çRß@‡x¼T@̀ Ç1\ˆ®ç̀M7í›;|h×î…öôtëIå:9êÛ *w!}¦ÇẸ́s4\̃́À'ËÉrI˜f —i¿;^_ll G#œư~ïƯko_Yyîµ ÷Üvà‰SǵJ·?¢PcA, ]\:qfT„±hïªn¾pnùíó×7ă¤̉ÂÔ˜&£µ¡ăíV+ªTxRU{FÉ8ÉƠ ]à”ÁÁV^X8ỎTD¸óĐ÷ơđÍ·–¿øÜk3íæ/?ù°kÛ14à̃>˜WLñG¥+K–₫KBm3.¤µ¯RZƒ&ϤGo3ê 6TơƯ₫›Ùvc§„̃¹ƯtëvÖ[íÙ¹ùEáúƒÁøâ¥ÍC{§U¯,_ûÈ'₫»èƒW×¶}霜ô rîVoñÖjFw8ø±ƯûË=óøCwÜr`O»5e‰À³#Ë Uáå¹›¥p‰Ûªđ±-"G„ơ°ÙçA³ mjµ"]Wy®†^£QªÍLU£răÁ5]ȵ­̃¯][Ư¬†̃®fbdœ²̃®â5ít{œaQ>fS3Ơj-l;ëCÛ'ÑNew»]x !PC|!­o(»1§Jº•JĐ®„™đ-íÄ­ĐEª×οû—̃Zéô«•ê/=qÏFoø*œ1ëĐ;XFñ½\¡em{ï ²tb7ltvÑøqDÁ¿|×kÔªđĐ›ưÁÖp eÈѹé9çüƒ {~‘›£àÓ±[®\í¾pvơ¡Óù~øÈcOøµêW¿ôÆXcÛ”:W8\êfxmbTàH¶ịư¥ßMk•" rÏ/»^ĐjD óÍ^o¼r£»´̉ƯèŒài¼}y åÔу§î«UKĂ,ÑLD,§ơtº@UiHÎo¡:­™èĽ.œ»~cyC†© Ù`0//-÷º½v»]A2í~¨ơ…'6†—̉ÉÛU¦] ă­qœ2‚g™¦¯^¸töÜÅ1Ô×^ЬWkµđo₫Ëë+.₫¬%uXO¼ &mÚîê¼,&ăpưoÅ¢<Ü¡²VƠ߃ª€<Ơ4¡&¾Èw2đNèÚn¹íÁ|âîû»ëô½w¾{zaW–ĂV¸A„̃˯^[œo>ôĐ½·:ø̣›_륖\dĐîBôîÙ=óß̣‘_ûÄCÇŒs±5ÂZØ–Œă,â!DyFCÄ̉À(³ơ„4“S¢ñ'NÅûËqgSôûv:Æñ«ç¦vÜF-Ú5Ó\\h„ yâ(Ṃ«kË›]¨®áX Ñ gÑœ ÅRÑʲ‚Ú6Ea«Ö !ÅơÖÇh5ä(Zf[P‹÷z½A¿† œiưC d1LàtP­z5¤áQœ¤/½~̃“\Ø®ï'i~lßÜüLûéo¼ p'ă8f ù;üjíég^€ ƒË÷½è9˜äƯ~ÿ¶c{₫§öä‡ÎÜÅåz/†f =¸đzcè@Óœ'Ä‚ D³"Y­âÀ‰b×èƯUTÀÛèAÔ‹^Wô{¤;Û‚0Nº™¹ƠJ¸0ר5Ó€œ‰=³₫`1¼±Ơwm«ú”ä¹ö¤qN‚ïÇ1ªÛÂĂU›‘k»ƒn'±²ṛ'GĂh4††ÏÂg‚ dig’ñQđz“\A¶ßê^ü̃Ûß»pÅrà`ñy›ûÁÓ·åJ|á¹7gÛơ$†´m¯V«×ÆkV̉úx<—º„.Èg%>,jn‘¤.*÷9. éƠîĐAéÎÛÏiôZÓ³ ä—ï~à¡Ûï=ºÿ襵₫7_¼ôÆÛ«KËư­A¶5Ä467U #ï½K›íVÍ œ —VZ–h·Ƚ½ÁđÎÛ÷ÿ¯ÿâ£w>°9GcéĂ÷Ù6\¼₫₫f-F\(¶>QDHå$¯tè2àî;pœabøqÔph§‰ƒ:­NjY±ýz¥²~j~¶Á¸¹5£'iA‘htH¸₫Z:£TL cÁ>Ă\[ĂÇu½x™¹Q’zTVüÇư~?Ë2×u^·Ùf°2qñêï¼ö6jÜÚ9/ˆJà=qßmđ½r₫r³‰,Ç\ªXå¼̉±fVèœ,Ë!s¹é~QͰj¡%MPBÈAÇslC̣¬;Lvøç´ăƯ½ïĐcO₫̉‰{î¾ưîCƠ©ú‹/_ùÚ·..Ưèå)ú¢à²ƒÈ§Àsg§káo\=|`J¹̃ÚfÇ!5HÁ`xû±=ÿó?̣Ö½»W£4·‘U+ H¼[}„"Z˜O$íhơ†VñÂÖ”…eGqY®—„XÂk₫‡æà(´sûyºy~p˱;ùĐÇï<}̣ÎûvÇÙ_üÍ÷^}s 2n%@§›³-迆ªm×t}4N—¯o=¸+¬«ë[½Fô«Ÿxø;oí ă¢@„cVä½á¸?‹\ëKQx¨\a¸l&°G¡“1fBtưbWP¡ăÿAB-ô_0=p uæ†#Ơ!¯‰¼®₫ ̃`¥Y+aΧóơ7“4C¤L M±³Fú9ºùAtâäư§üб‡î¸û–åơ₫Ÿá÷.¯…G:‹ÄzA¿L„đª.a?.já‰Û¿ǜ¹ï~÷Ư<|±nuûƯü₫SÇ SNs¤AU<§}”³)Hpƒcÿ—ë2YĐnVèöWÑWÉP0'Dù¨Ü*ÂHƠC'̣ƒĂ{ª£8Ç=‡pg‹C©LAEÊ[z?/zi ưq£Q OŸ80Ó®~û́{——7olơĐ*±U‡<Œ°X27!ꃒº÷Né˜ñªn«=Ơi/E<‰Àq] ¥Í½+5%É••<Ëö,Î׫x×úqê X#đf§ê+›ÿ³Z ÚZiˤ|)µF4##YNlÂ'd‹°W,`"ộHmwG†7ÂCBH>†Cn8Ú àŸ—›ëù'ï{äî38|Û¾»N¾±1ü³¿~ơâ•N„Æ–KŸrKÊ8x!‘@9\âĐæfLïÜƠcGwMµê­fåÑ3·Cào Çöàê‚Kj4Jˆ£+™%D£)*’)±æẓ¬SŸ©g1‚3ÎÏBàúJª™–l†º^[aèKÂJŸP m…ă{–ă(HBIª|·éêÖµ~¿ăÙ3đƠăgµç_ÿÜûKË­BªÙjÍ·-z,2QĂ6Xä4zâA?) c¸Ùlç›Y/ÙJĐ Æ ‚ Ôƒú«ôơuxƒ æBos«/éi×ëQ½{ư27®ˆ ÂÊĂ(uÎÛÄqÄD8Œ3s¡‰—6sÛ¬²c¹₫Æ‚{”ô!ˆ+̉w-•©úç%zï¼ç‘“§¿ư®Ă÷>¶´>ø“¿:{ñêfrœ¯µÑñ¢Dª [—XÅ0¹sá%­ñ̀Lưâåơx=<ûø#w90Ÿe¶¢‰)„joâDđ¬b„ªS.’óÉܨ0-̃ç`BÑ₫*äÙ&4¸N……̣q>$¬8+rg&p†•#Ổ~%¬6ªQ%tka ĂfÿÆ`8đƯjäíf´o×[ưaœB(¸R9·áª…óB*º·(‹C…sR$EáFÇuy“KÇÖùĐŒFăM¤+dPûÂ3<~Ëâ]S/¼ñ₫ÆṼRÓôgÚ¡TŃÂ~älk„ÿÉĐ“cié‹$N­èBϼ¨Ü†s·₫9¨œưàÎ{½çÁÜyêØ©û-¯ >ûW¯¾wi½ýbSµ̀Ë1¬£×|†^jU?ª/½rû‘Ù>zî˜}‰â4ëǹvNض(¢lGødS+ë¸ÅüKqKU IØsD/‰ư¡§ˆDÆ%xáÂŒ$Ïñ\›MÈCX‘Ñ b-/ªUj[ƒ¥NĂu"Ï  ̃=Û‚—·̉AO$xIĐP«Ü,¢ù áy8çaaÎK@²· khV„=°Mv)Æû£ ^́foŒ{2i%™zøäx'¾ùÊ;đư¾ÇÍɲ̉m͸b4›&!£ê-ÔP±³̣Óª©€×î̃̀‚`-̃*Áï”Đ?ă· ¬Üûà‡ßuÿ=§Ÿ¼÷È…‹kŸùü+W—;ơjˆV˜TØñ¬Æ¶¹ï¥˜WѶ‘G̉ưûÚ¯œ ̣ºSŸd[%SGcT]ƠÑ«'E\6¹ù'Ç ¬ĐĂ-NÈĐ‚f…-©:dH»?F¶‚&rŒÀs›• Y9¶₫£„´FpÑ| BV«Ú¾íÀï/¿}}ư)˨¸ÎCÇA¤¿xîâÖ(¶«vhË"¡†œ3Ù'éC‡Ă„oĂjµ™4×zël‡Ăl>Vfëy6/Ă+a°83ỡ̉ú0NàH„È­†Af‰A2Úf#X´RÙvÆ¢éÛµ¨T—FNV”ÚDĐlrÆ»bö¶ØÉÀ?ă•ó™GŸ¼ă‡~ô®;î¾åÜ{kô—/]]êÔ+ÑÑyÚlIÍ¢”GĂQ,îÇg£áKŸF+zô£ûgÂ!Î9ä"ƠC²¶|:P1Í1́IGˆ HfĂQ3ŸfέZá{²³å¹¥ƯË Y‹¢™V£U­@ôRÂÆØ'½;|X)½Ö¦ÊBÂsƒÙZ+ƒ̃pĂ’¾(ÜĐwf›µqœ^[ï¤YæùsÈS6À¥Ï}F ?/½,ă4Ή²èh£×l“SÙÖ ÇÙ0Φ[ûNú̃…kWnlxäoLa†â]lÔFËwí ¥„¶<“<'Ô-pÁ/E sHYTV[†2"$û›[–URÿñŒƯ¹ÊVoaT¹ÿÑ¿û̃Ç?uèÈo½|ñ/Ÿyc½3l5B›wd¿åđ?ȸ#W*ä­¥‹r¨ 9¿«qâö=4ÑL«‹cdơ*®K3Œœ6Ey¡¼ºg„F^˜¡Ñd+›¥HW¨¢×“I"<(Ÿ3ø_>5U]œnÁU=7ûƒAœÀSñËwD`Û®*ôY %бÙ¾^¸}¥ó₫zgÉ{#1ûȇ ??e¥3µ¢Àvílœ”“¦â8s#`IALÏ\¦ç4ªíaåE< ‡A(´å˜Âê—ú[hƯç§đ̃Øè–¸*Ù̀•¶b,´‰ŒĐbÏJk–`ưn,Ù¾0qBâi—̉óg£ƒ«]“n©Æ₫™Ư÷>øÄ'OƯwÿ#ŸÚw`áó_}ăó_}=Ịz-tl¡;W TNB«0ÓñN¥´%ơV ƒ®ºĐsö/L‡(µ^Ô«A#úŸôb(Ÿ‹B*mLÅ¡^á¿yR¥KëœZ”LsNÆ"Mz *tÙï#ÙU¡îœjW¢…é–kÙ7Ö»Cˆ 6 ,°óƠóq,l\ k#RºÄ3T½ æÛ‡\ûƯÍ­•8n«"jWĂ'î<wûÖ•¥%A`§Ö(Δ^Oó4Z˜:Z“o™úQĐ7W²y…ôƯA…ß%@ˆÀ¬ôº‡÷̀v éo HúFd¸†́~‹‰Ñ gÍ’÷ ’ ¦sœ[¼g£G)ôÙr‰+̣ ü³x«7Ú§}ê3ưÂ/Ü73?ó¹/½̣ùg̃€’¸Ư Ñ>›̣*•ɤfEcÔ`¦a´m}¶ÅXŵjDïT£UhcÚgbúl̉‚o›È¢ö“Z6èùSˆ̉ˆaÉ…dêÔµñH¦)ÔÀ(tçg[®ă,¯nmlơ±¼·üqÈX9ÊI"qÜÂq”ëB†¦kÿ¸ü'C*½;Ơ8d[—WVV́lqk ZµđĂ'Åizqi ^W%t$Rsö‚áó…W5¹9ÀYÍH¤µJ£Ă!2ŒéæV*ƒđ\àÑá'=ÏÙ»0ưîµÍáj~ÈL&VĂ’wn€-^Aë$,Ié¶ÆÊp›̀Xi×ZĐ¥¤ø3ĂÏ^ô6Û}à“wßwßÇ?₫Øôlóỵ̈»ù̀ë®cת>É9Y­¡kcv<¡àÅÆ’ºZɽ1D…kÛ3íêÁ…é p‘Ư#D³¶ưp׉ٓ z´9ˆĐÊl’ªGBtáˆđÍ%jº åHeå<“'̉Lâ ¥ǽÙv½]‹†ă´ÓXx²à9Sp%  ơ BWà(¦u1F²ô-áçp&Hwºv È“ơÍ•"@‚cè±·l †kƯ[¯„?!á -Â#ôZXiÎæ¾TëMƠ§†pÀ(1<­#„±fƒŸoƠ£V­reùƯ<×rđy! »ö$g Í+d¿5RÈă’e"mGq¬̀¨¹”î`»•+Ă_³pÇàûgç}ë̃Gáăÿü‡₫ä'oM5>óù—₫æëo@6뵸¸+¯-qQ °…¾›8>±p;q‹_rخڂܲo¾}xïlº(%CßøG#—½ W´1EÍÁ Èb0ă¾?oaăí̉C¡o…<´únàyQè¶Üy8†ï%™;úXHh¾ç„ARTàTđ¦P®ZxScfÏ¥ уŸ†NºPÖlóP»é’Ơ,+ºƒÑl­rúđ>¸«-h= 1œfy>j³’ÎƠX¢e%¾_­GƠ9 ̉ÜÈ‹ |8Ộ=smx́÷—×KèrA)•¯áS̉Xÿʲü¥X‚çR¶cMn-c§b\ͬ‰áµ Z̃â»ƯÉÀ?#7Çq=qÿc=vÛÑÿ“½ úƯÏ=÷̀óç!Bj®mç$Ôô—û]̃Hè$Œ 1¢¯ßÙ;×̃½«…s¬à®Øu±®6aÔŒ­-Jï²ñăÍ ÖÛL§¡<„U`-¸keSĐJ‰Æ‘ï…‡r±Yë’¨ Rù‘›ÖB†Ơ<‡ØÎ<×¶ôu¬\Àù ô´â/†Î¤jo®u`4:¿Ơ½a‹¶m‹íÆí»g¿ûîT­ĂA2JÛŒ…tWLPGƯjPˆvmº7́ÁSÇăØ÷£0DsẸ̀–Ø¿8Óé»ư±Đ w Ë2ÛÑ•¦– H±m—Äág1©ZnsqT7µ"ª„e™Ú›“´éQvøg%÷î¿åöÓ|ôäƯ'>öÔC¹°>ơgß₫Êóo¹®U‡è¥ ™ 7¸úï‡ÁGµ3ÛzÁ5.ä̃…é&”4©F("ü̉2un²TÖ{M¼.sX4á%¦eö•$%ƒ'XP£ù—b—#»«\'§y*äXåûKˆEx¢À.±̃àºq¹±Ö|Åx[9‚d&`!m“ä˜Ç•ù™ƒưÑkMy•¼HÎL/mö®ntÏ©ƠƒÑjœâRÛ¢˜Đ^M?ÄÈeiäWêQ½3èæEÇcGC²Â`qvêÚêÖpZHûw₫äÙg?)´”îl ·²©„f¬¤l‡°V\ÙJ^‹"Ï+¾{`azqº‰—Z5£µ0]£7B–2'F)C¬‘`椪dª °êSĂÆúœN G’¶üAå.¤h…p+— 6)¶ú® !́¹đ± <[9©Gsúµø(¼Â(~P9MCiáÊi\™ï6÷ÎíSÖúVo0CÏ,nÙ5U \(ª-ߪUƒs&Ïèy«1»æ|oëäÏCoËEÿË%7C₫¸˜oák¶ĐèúÄÂçư³Oq뺶߆m°‡^£ ¿3pE‰®bHΙ ¸åMvj‚KTxcHtµp÷̃]Óq¾1çqœT]woºƠOă°FÄ ¢;X:‹á]:œYTk˜&–í5¢dàá1¾ù®}hï,Tö—®¯¹®m\)´µ ¼£Đl7Ûë7LWÔF„Rh¹#€§ƠzĂ6´Ư æPë²f§„₫)̃Ûî„1´ç ³íÍ₫hckÇ¥FĂư’»ƒ±…¢!¶î0¤vÖ&Å)ù­–ùJF{©(ϱ úø3¡¡$ŒæÚ àŸÚ›„½'O?₫ȃwÿâÇ]ZïAî}ơí«½P‹Z¶4h+l<µ´„Å8IZ›j¦ef¢ïú¾»gWk¶]£îN’R“y_Œ³R‹½=©Û,á|í§’./´ÿ̃¤‰£K7&Ti[ÔV–Ù[2ÎĐ²sÏg̃<íh=Đ #¾ßÑĐASaêD„§….M…¶Dü;¢—oxƯKåD^»µ. Ï[2@¨U.§¢Jg<e±ëÁyaÇö̉°sBií®¢€N8đưjXét{i’GÉÔ|½Q¯½ú̃*-laω!%'©äĂÆÈÖéV¹àÙyœ̉ÔŒ_t M£‹ Â'o¾đ.¢Đc¢´sû黹ëgîyđƒùà¿üñ'–Öÿæ¾röü5^¸È«¸*Á̀6owém”7èÛj_Ø‹3­éfTÔ¡1øqèÄx-Au¸MªŒw¦\̣̣ج<è²d»=î·m&"Đ‹VG¸=‚v{`,QªZ]á{ê¶£L TB#¢“%óÜ2Z<R˜Tl{o_º–;T>N(Ư÷̀î©Gb¥s5Ë,hæ¡§nøa⺶Rñ°Ư-…¹(ƯLü3Fƒ'U kđj³<Çq£Z ƒpiu >ăXr"‚Cc*—^\B—'Œ!K9‘Ùá3ÂÀ6LÏ«_ˆ2æÁBGSM“4ÏN0üæ̃£÷₫Çñ©Ç>đè=¯¾{ư·₫ø«ï\Y«E˜{™jʤ" Ø k=Î¥¶^&Ñ́ câö(‰w®]wI†¢_Đj•œ’Ểơ¥ơZ†ă×]°+v.ŒÏ( ¤•˜$Ii€ˆÄKO ËN=›ÖaĐ!Û™¡Xׂ=•¤gÄ++†Nj–l¡Çº7µ¿ÛàO´=•*)̣zm~ßÜî¥s½qºù,Ë*¶³ƯTƠZĐí¡´%›D¥Đ¨ÄldĂ,¯yxD¢ùS–D¡ßÄ«›]h=4S" ~¶£¹Gósè¬ở¶|”–¤4$î4J¾°I½¢äúofmΡ¾À?m}¯œ8ơđC}ø?úØCgîü̉‹ç₫ĂŸ~}u½×ªU\×Öư,›5&P3.æy’ÅÔœœ"mu¶]Ÿ®Cº£ÚUđĐ˜8†¼Ọ̈ÅX^Bÿ—g´ÊÈ5óMÓi†¤ÿ"WNbá„Ê2ƒ{陬­W\zSÏIq_lqØÓ¥»}9+ ³„•sζ`:€‰á ¯Fmí¸aQ–µ9œó3û›—̃^ﮄî¬RH¸lg'¡ïƠªÁ`8ÎÉU¬0l”¼đ6ˆÇU/ªá`4‚¸̣=÷êÆ`8‚Ÿuèukº†¤µ²0­®°ÊăÄÿ–Ä2Œ Îû†B(hcṾ›Âhsm¾ÓÿtƯ¨zâÔ#ø…§~ơ“ºóø‘§Ÿ}ơ·>ûơñ8nƠ,Ưß*yERÏœ%ÉëTlsp fA?[‚ÅÙ{å`C.†Lqø |IBYíFi½È¡¤ÈA84â¸R¢#YĂz¤Á†º|T8>sÙùâ—FW®S³́ tßľÙà™!Ÿr”L‰¡\”¼\̀ÏĂ¢ơ¯ØĂ“rZc‰=»Ø‹j¸wazn³mœT°`È3OYựsV­î†3xE¼@bö­̉§i’ ß z=¬œëë«ĐS+MØ äPœ»¡ÅÛ˜ ÄaTÜ›¨(ÍLR ¶¨qV̉Ü?p(IÍzÚ àŸÛ́ücwœyđáÇư×>zäĐ̃?úâw÷éo%YÖ¨G.̉H±Mµè?7®ZN”.•L—H£`×*¸Æ¥u‘Í«[¡UÉYaƒëUj†%í%q&]Á\«NShE+&öëƠ‘¦(ñ‚£Ûi±§PyZi!Bvªf#ăd¶¯:đơơhë̉/£–èA”dí Oe÷̣ÂÊQ9t¨¹Á1”ëSËOrZj(:¦¸ä£₫Ú̉?§=÷ÀbL›\cy~¥]ß½0Ó}½3’Êe©.(F‡q\«†ç Qéèư†¬É† ÏÇYQ«T¦§›o^éAB a·څ ’•F‹k„‘íG­Ë«v,`”\ơ$W¡CyÁu¡¿,¤Y‡JB„Øfº¦å+ÑZAsæYö<¸I€5/2…–ߣ-HY²v è·s‡¤/¤C34ử̀»€"v,Ë„5‰®Ü- ¨´7¨„Î4'«5¸×w1}dÿÔÙ7/' .¿̣X9.¤Í¬`¯7CYa:ạ̀øŒ³"k47:TÉs¥É8èt­›cÑ£¸8Ím©í4†LèV¯|éw§J†RÄư&áwÉcjî —Ê@·₫ÉŒ^ÛÙwđÖÿØé{N₫ú¯>™Jë7ÿđ‹_z₫Í0t‘`„£XŒJGÏpÉúĂæÏ°RäI²mx@¶,0Z§›ƠÀu ,} ơ!µ<±eY¡q ö6‡mÚWŒûÜŒă°o¡Ö°¡!Ó(eµ˜»åNRxk…YẠ́•¬,›“%w«Ù@ă¿àJó¼yqâ‰KÓ+îZu¶fÆíœù‡‰^©GVˆfU¼fK$¬4XƯ´PÚ àŸ¸›ă¸ûn¹í¾‡Ÿ1Ÿ g·B{ö–}µ —Ö­ÄEnÅÀ.4äµÏ†ü&U4¥¾F'ÿ›Ư¡ÍŒÖĐe»Rb̉₫Ăѧç C ä˜x XWA‰{"™Ët³£ñµ­—Û|„0{P3cÓv2đOØÍu½[n=yß#O>xú®_ưÄG™úwŸụ̀7_y»Q¢ÀB‚Á«hskO#ƒ»à,* ×@)iM÷ßjTÜd]$ÁÁP 6s:z­›¬̣t?,¬Ạ̀†™5‚±׈HHÜ®].˜¹ÀÈb-=U”9˾çtS(m“£a/|vG©º¦îUµÈÆU¥ªˆÅMIưÄKœieR·¤$EU·¾<̣ÊÅxŒQâÙT² »uhï´%—Sä8«<ƶßƒÊØµHEÈ̉@Ê2B•h7«²¸ƠP¬đ§¤Â í¥b£cCŒSư$å¶ån©2kfå–èo”–gúa™W¨¹üzÏN.Çø€;ütóüàđ­'OƯÿÁG¼÷Ÿ~́±₫ø?}îÙï¾y©YĂè•z(¥ñÉ´ø•zÅkiz 9¿Súä8´Ù0Ej$•Tơjت‡l5­ơ9ôàZÈ XZ–²²úP(ÁË”‹m<(wzăQB?TEE”P~Un:tâ-åƯ•¶D*0ï’ͯØr3pAc™RE}m5'é‰CªYUЦ…O³° 6IN„¤xJËÇĐPăIÖI-I,-@êqÉqeḮ\«~ni9…â&KE†2w‹₫iNo0̉«Y³b”e³Áw Ç13©Ø°ôĘfdÊTЧÀCá«’@¨ç̣8"cT·e´ iP¥}&ˆm„^,äb>©ÏËά1Eï”Đ?1·0ª;qßƯgÿĐc÷øƒœ¿´ú©§¿qñÚzzç²€=Ỷ ˰äÙu‡©?zZ¥Khjƒy«DrMW•Àw´`cÖFÜ7ëIµĐÙ–É –'KưUäÓç\$×DwGưÀ m+*”!)ĂྱĐ̃9ÛEÊÆHJ[«p¸Ră4‹“°¢êúâơd0ÕŔƯeç¹̣̀@H«$mÓ¨?8ˆ¾ß$²L xFø¾Böc&2(•…ת·÷́ª¾ó₫jà‡đ´’8c₫ c£#)nk ‹kíF¥º5ˆáéZØ”,¬Ek ܨĂưĂkÆU £¢Ñ—T2gC.y~m¦èǤÊ#I~¦É̀rGú'ăV­7Ÿ|đ₫‡>ø¡Çï{è₫»_xặ~ú›ë^½8†×k$5t;j• ÜYz”¬-¨vt?L»Ó(đ‰7ƒ8ÍP²“(¶a6”̃Ü’¡RŸdçđUiĐ‚p°Ô³h}ÔƯzXS*Ô×v8…6+#́N*˜~ÙÓ/æb`a÷›'y†%4ª^äd 1<ÚèŒOoƯ×®-UD¹²äMX«m±û}±]n•PV ‡jăÙ)ỤV\äăTƠƒÚÂ\C©¥$…Â;‡ C§̣|§ĐÅÉBFư*ß‹ÂÀߌ‘wAC…²Ô5.¾´o#ÜU:ʤQ‘-Uí”u¥FöY3‚¶àÑư± "₫æ„jÈ‹¨₫ñßêÍ©§¹ÿá'>ùÔcwÜ~Ë×^zû3_x±ÓAǻL6@–&*XT¤'Æ%gP;-àđÉÑÚ’]Ï}à˵Jèg],‘Îk^3åâ®U.‘••ynH;€X¼3±›AukÜßtC¯b[. Ó3iˆÈµN1"Ê ¶ØÆ`5¶I´È̉ÛVQ3×÷̣Jÿúzï«[Ü:>´kƵưÚÚÂ?@!ü;ÙíHåƒÆgn%J¤vaç ̣y1H²Fà5ê‘çÉ$É ¼Ñ&Íe%´Íe¿ábĐ‹ÊÚ){̃`­gkƠRß¾ÈZy:q8}áÎॹ¦ñQämjñ̀`2¯"…;ÉÚ¸Û̉lÉ"¤éUÙ’”…qœíđùÖlÍÜqïc§îècO=vüÖĂ_|îÍ?úâ‹pcî-‰»º5ZWCê×€4[Y*(m³ÂÑÄ}ÔoE¹œjäAeHø-ƠíØFijiiB$b¯k+dË̃M·Í´>tx^;ª_¬lùë­½–±¾•:.yĂă+2RÉ lƒÿNy iƯºóŒÊèLo•²”\È\GvûÉW_º₫æÅơÇîZ¼ ‚¸̃ṕ0SĐ ØVé¦ûwÅ0$ÿ8Vư^nàb”f±O yª©á8+v½Voă!.œñ@Érǵ£e Δ† ÓE5àƒ₫`lo­IR²-wÑ Ÿ"đ´Œ¯ç9đR[cÁ(+ÆmVA *[&0[æX±—ßJ«ÛÑ÷Ø4pÇY«^Ư àçmzváøƯºç̀ÇŸzüØáưŸûÚKŸöµ4-jaÀ$^=L̉t¢’/íÉØY›̀ZZâY§lSr[ÚZÖ ‚I®¦¤Nä×™g$,SV£j‡¤Đµ-#œ#Kn“f&0¸wºÚèÇ£µÍÍÀq}×/̣ qvq¦[°ĐkN₫a¥…N¿ÜñR9M)7O0c$ó:%Áøœ>ÆÅ#๟»¼ñÖåµc{¯|àîƒ÷™¯EÏÂ5M¾í›5íđz‡{!Ø̣Á8î§ư8=Ô¬·Ø¥ î6QEœYøƠÛB7³‚¶Z8 4›ÈáĐJ\ơj˜äp‡‰mOœ=Qƒ$;'/Z%\#N—Ŭ[oe cr†â²„hç  †sm¸SÛï²YàQ4Ưï9¾w'€|Ñ;·x̣ôî:yß'zäÈ‘_xîơÏ}í,üZ!÷ZåJÖâ—đReèÚºơåOqƒjÛe$ VÔá ç²I% ({+Mí§¢ÛÖË¡̉¬Ùz¶,lGók©¶LcZ§]kÅ2Íw¼Ư­™Îỡzs®åæÊƒûApA¿Üñ í$Sơœåœ„1ƯÂÇI–Q´rÖ!­³´ÂPO ¨¤lV¼nøƯóËß{oí®[æ»sßíûf¦›5ÏñÈÉ4¿ ÊË|Đ϶†I÷Æ}xdÏsI⣰áÔP–Fq*ÏFeL‹Gâ(Y@N \‰àPʈæå”îkACXjËï¨g¤åjIT*Ü C•‘σmđđAÚÎjûœMi±  Ú®Dy[‹ṢL+ÍóÙFxêÄÁµ«ḯđç653êßyש?ơè¾½ ñơW¾đÜpW|—V¸ŒÎ½̀¤®¥•9X·q:fđDö ÜÜâh~ñ¨•å¹,M)5ÆĂØ ™z›̣­ÀæNWêQ²Ù©“G‚O²hDƠƯÍÙ‹›—}oµúY>Í .×¶FñÈJâ68Sd_‘™bñœ̉Fƒ˜ZäœZđå47ñ\đ¤:÷\gƇf[½yqíÊî|»ºoWsß\s¦YA¡i ơµà‰æ™5eĂq:H JÎàM}ŸƠr$9e¹p¸ Îra™Q/6Ăt̉%«3=œƒVÖs}ßíÇ)|Å¥_BAºKæ¸ăÊ8×|ÀZ%@á4fabâ^1aZf°ä™A;4*KêA¾÷y¦ (™›®Ưuëkï¼öÿñßïđ¥r^¼çÁÜsßé}äÑÙ]ÓOăƠ/½đ&üzª‘ï0úFKØH_ñ¦lkâK†CNNŶԓ'©ÇÑY.~hTƒƒÁуÖyEÄü¤r zm₫AAŒCUrwÙ̃à)¹Ös`F‡@Tî팺76ÖưÙåYĂuñ́€ ‚f–bÑ¢(¡â8¥†3§K•ôj­[9¦>‚™ÆèZDå²ïØƠ›Æµîp³?~ûÊF5t…yB¥¥Q#ؾëV|̀±LÇÏàebv”)>ªä “¬…6rª„‘\¦ø¡ƯŒä/iQ+Ós×ûărÔ,5k›ç kîQ GRBDgăĐÿUl̀@9X™ĐƠ?˜öyAei?6XB ËL#:yl÷̉ûç?ưÛÿnuùúNÿ¨o»ö~äcwœ¼ó©?̉nî+/}í¥·áB¯†Åª6x¡ĐÖ×Ö{Z#Å;$7éèµy¶dKCBĐxGÎĂˆQ–ÊsœJè’ §*áT́É@K#TIöñflf©ábÇ.&KˆrˆÅ_­ƒŒĐ‡Ă³»_¹2\ÚXÛ3íæ¹£ëç¤i6AÍ3ÁP ŒO*ÍL†ÜL§©ûåÊ™¾”éMSÁ.µÄ$nÑï[’G̀̉¨ñA¬I<9&µ¯/ưeS±]¸–™©áïƒ8MíÉ€Kă\ ÆDs´ é„Ă,DivÁØnl ̉…™ÆGæW¯½ó{¿ơ¯!zw9~Ä7¹¸÷Đ=~øÔ©SO₫ÂĂ^₫é—¾óÂ÷̃ƒ‹ r/«‚ÿ>ƒ²0UnIÊד´¶œtÂëO”]91a€«!ô]Ÿêg2c–äjáà^—ơå˜À ̉e™‰³Á>“‘ẹ6w…bq½É„đ¬WªÇvxñư³Ëị̂tU&ùB Đ~{£8%INU(VÅTÔ›·È ª2ă¬c:7dCExA2Z˜¥£,ʵ$¼Br¯ƒµđ–z¤\€?’`Ú~¹OxXiFØb̀®Ù0÷‡cβüvÀÉ— _’*W=ü`dă@̀sĂÉ–XBz7ͺö´>Æwê‹™Fu0¡;K™ŸơiPL¸G%NƒÅÚ™"Á«^º#\³ùüLư®c K—.|ê7ÿƠúÊ2;ü#ºAºÜ³ïÈ}ôÖÛ}äĂÛ^đ¹g^zùüåÈ÷*‘gܪ …¡Ư—3aé®=Û,p„Û¦‹Ơ~ ͺT|³í»D¿(¡ÎÓü$ f(đ KkñØF5¶ĐHHîÀu&·J^¾ÅW*öèxÙ¢BƠ`¿¹æÔ¡™½¯\y=‰gùfo¡TàEÙc„AR°&9ê<«²2.ô& #Ws8€)’0ßṢ̉ŒB…6 Ó‚ÑÆˆ$'Í7R–DL–ßÔ„':KHM¤R«½Aw3z›ø]]qŒMùÛü '©ÊÖTđdª0)L9,̀›‚ ?É 8ÂǼÎO’øŒÆ_AH£ ¿ºŒ¶Âđ&9¿ xûá¼H²|ï®Ö‡̃ëƠOÿö¿él¬—èÎ₫QÜlÛÙ½ÿđé‡?vûí·~øCç–óÏ|çw¯Ă•]ñ}-̣&'@É7¬UJ¤^rKºÇ¥˜9‚ëj[o’xúTÆ90® m<% {AĂ2ơ(…ơhY¹đVi&  5‘“#+½µ Ÿ8:hk8<ư_ơ‡ •°æÙv5  ïí†h]H ²¯Ơä~ỦúslP±Ư-RÔỂ»%LÖ6¤¿1kP¥”ùKQÍŒª–¨²đ‹Ï“­‘T)‚N,BŒe[½Ñ8ó,ơE<­b2År;á+E 3ÏÓ¸lóÚ…éƒ-³›†_Gœ¥Ă8•JËgSư/•ÚnWjsæÑ æUI^xí{¦Ç÷µß|ùÛŸư½ßÙêl”n£;ü£¸!EáØƯw~â¶Û<úÈé~’ñ¯^¸´\ Đ̉ZO€mY"%IÄB+i”ÊÉl³ qB×ÇôWé!f20óuKϱCÏqm%mèuqßhMt̃2óêIˆRF+yÀ̉ÈÓ”®e¥4ŒU ĂXöo[î©ư·%irị̂›'xPĐnöd³‚ˆàV5‚Nµ;iÍGL³1X¸”ŶSÑ”µĐĂ-\*QAM.&ÉR}µ¬Hsv ¢ÉqQH#LG ŸB”uÇ$ÖĂZ—#×V6ăq†.|‡ơ7´™ ă›Å¥±7†îw̉©]lÚYÛTÛ±âƠ5±¡ç]g”&>5Ê,H ·»8©̉Øè/#Mñ@[œm84÷­/?ư…?ÿăÑhø}W×NÿĐsï¡#wœ~ä#·Ưvô₫3'7ûă/<÷Æ̣ZM9\G²B% ÔyȈà`˪­´b{)3ië -ƒ(ím@:ˆQúvX®ShoÅ"àï4ĂÛ¾…ÖgŸ}æé¿₫³?Jâñ^`;üĂœYI¹çÀÑ»O?qlj[OŸ¾{­7üâs¯__Ûª†¾g;4²JQ i™TL€*iè~de$˾Øá[ÄË¢u$€aûn‡Ơ9\è¤dØÄeRÂ6x™¬s,ça6Hb¦/gx€K«©á»¿\¨².µŒ đ ²Đ:ẓ«oÆo\¾tû;đ̣¥ÍÆt½ùÎl³1¹¾Ơƒ+[•¬† ‡̉́î©A[‚ÉĂB²(—­Zh«”óGom5•B“ "$céMDefH%…ʸ˜¢êçư₫Ö»—×]Ç)¤ <jÈÁµQ§>°·a»BWFºÑ-°&$iw2-ƒ'lœ¤Z»‹êmDHŦO%5ƒà„£´hV¯öîjܺ§ù•¿₫́Ÿ₫Ó4I₫Îkl'€ˆ·Z½uøÖ»>rçÉă½8ùêwÏ/¯÷jQˆ+YÁ³Ó̉PA'^-kd$™ƒê3VÀRzÍ«7MẨ£iIr¥‹«ôÑ…Hö]ƯæJ}'€aVͶܶ®@—°'W§œT×–N²ä9E'm»Å'$ñÉ'©‡ƠGo=ừkùÛW̃?º'­{n¬¥µ(j×Ư¹V ¾ưÆzwˆ“iPi¶RfüysK+•̉°K˜ÚÓ@”Nz,O£4€v¶MX¢øàäêæT‰‘Ä]0ªâ¦ï¿·¼t£_ukđ=^äBĂ³¿±²¥…˜·Å/Û¥Iî» WTí :F™ki: ¿ ‘á]Y¥˜—i,¡¥dƠÄüơ P÷=÷¶ƒ»§ư/₫Ùï?ûå¿ù¯E¯ø¯đ7vnÿH+ßÅ»÷:tË~ÇóÏ¿²¼ºụ̀ Đ5Óvµ‰ ñÑ‘DÄÉ·i-Ä̉çôÇ|•›^b ̉P²5̉“®ë„¾ú̉÷Ñ{ Kđ“®­5<¢û‹²‰³9œµä:—ë6·¹ôm‚ç̃e.6¢Ñ̉*¥P…dû‘¢t0``̀{i3ª¹Pf¥ ¯Sœg…t8­¯½}%ÓaêȨm3æëë}˶nvWbv‚Œ°GĐ»qăCQV,–6BÅF½X釛µúˆ¼˜8ƒoµÍsT?T"gßz`æÀlô·Ÿư½g¿ôß̃ üĂ½Ơ›Óíé©é™ÖZ§wei".,¦¡GV¼ƒµs(:zÅ ¨‰.¬ÖˆÓ<~ƒÙ€FNbó†°'a—ItưAÔ»mØØ̀°y#<É©•ÛiKk<ɒ߯‹?‹ĂlP¶M•!~1xs÷À8ª©zó‘c÷~íơüƠwßÛ¿«;ƯܽºYïôªsͨQ …lB=»¾90m°–ËJi¥ThµªŸ·QàKS5ƯÿNضڬ“èz<Ï̉̃g|ƒĐ•£-¥ªù•¥³o^¤ßƠÂj3²”½¶Ú“(rƠösB‹yxO\›…BÛûn“¿á̀û#Ú´Imæ‹€Êápè8ö4Ú6ºB<&-Qÿ6Íàt?qxa±|öwÿĂ‹Ï~5Ë̉ÿö5¶À?´Å/záºĐUÁ¯{ccg™ëÚz5¡•Ë[ Ñ0u5™̀÷B1<áÙ¶K&ÍÀ™à: Ă2† l ¿ºÙ¸¸\iV+3 ÿ ̣{¥µÎ`œ2÷¿`ÅÚâR\hÓ’»¸'«u\±W¶Øë <`&ÆF´΄•(úaxi™­È.̉Ơo~çỤ̈̉¨ê„®ïÔQè9£~²²̃#O«Üµ¢YnÑå\»Ö¬Ư¸°-y³6×6™+ ¬̉­1ü²ÊéæXR9wV¬T$¸·îŸ]l…OæS/~óÿ=zwø‡xƒvÊv\¨[àXFÇèl*'~‚Œ¯°m£DǾÀ¡oW—diöËs­ƒ¥ÙÂl`«7Ç„Ê`ù¦rƯÉñ̀zqSV7b2ÙÖ¤8áê|đØ]íjó[ç^8wåư½³­ù©ö̉jxạ́ ]¯M7ÂĂ{fë•àỆ…qZpEMâ‹Æv†Xj[ó ƒueMLJ%ÆÏ…öÁB¥O©WÓfª¢»uơù—ßîof~ưº5Ăj%t²ëË[’¸“¬¦“zd¦UÛ¿kz¶]ơ<—Ô›µh;¢¦ Í:(;¢J½:†ߪƠ0 FzîǘTb¹ÇE%̣Õºo¶éüɧ~ëÅo~ Ơ₫{ÊHû!Ưà\o´¦fvOÏδ§«~g.TƠN° ăMŒhXeÛË‹"GËÆÚLøE’w¹2đ́ °|—GT:²égyÿ¤1˜œy×ñ½`.ƠÛØÅ*đz8eO4·,Qjs£C9¹@ËÄ:Á@iđâMµtYN›¤ƒ•0¼ê]­™Vuj½;º´rƯq†³MUäÙƠµx¥ƒÎf5l×£ï*œ%ưaœ¦)ëµ6·¬̉EÇ~zhˆZ“€^„²½Ä sËă{È…¨Fr®̉ÿÚóßùîË×¼̀­4ÂÚLujº&sûâŵµ¾ç¢›ÎL5k‡÷ÎÚ=Ó¨G±?H ÑŒs\³ræak›go‚+lÖ‚×~5£ ‘Œ̣¶T¥Ơ*qZD¾wê¶½»̃ïÿο}éÛßøûTÎ;ü£¸Aï3=»Pk´÷́Y'Ôf®Ă•±DQhrµ¬Ơœq4m,Ë8–Ù±†®ïx¾åh¾>w-W§q‡ê|$~ÏD°Áp™8·̀’È*‡j’ V„ÖÙ@ Ơ¶¨TÈ¢ÔÑ7µn7  öTi×ëçöf¹uqi­;\o7’Z({ưøÚúhis¤ô­ALÆÖ6C=i€ N2RĂ‘,ˆ]¯†ưÑ8ItŸ¡™ŸvlÆÜ›UCÿÔí{½¼÷éß₫?̃8ûÿOÑ»À?Ü[’Œ«ƠFµ>=·k¶Ñ¨¯w6 đ CmâÖËR’®Sî8iS¤ºø½¸r¥­ÛX‡ÁJ†FsáMé¿%ô]ïT ßJ„Ûdi`$r›«™¦,Lˆü¥¨©‘65•V3ÍËpUâæpÖ£₫7 ™ójîßµ»Nmơów¯_ẃ₫âtQ ÓÑ(YÚ]ßHz£3\Ùơ0¨x¦Ic̉W b—A6éUØÚÏEPQăJ/(üXêYÎÑk‘Ú×HÏ{ù¯ù̃`¥¨FasWmzW½ê‡W.ũ»´Z`|zíFåÀî™#ûç§j£Ü¸"áN×s]¨Đ»su0?¶$4NĐÉóôL¨P¯¡ŒÖh4æâ½ )ư&y¿Ó3ẃ́øÿ₫÷ỵ̈Ưó¯3Èt'€RnôkÔSµFk~~µ”F±ëbí¬†f/đÊ×Ѭ OÜñúTËvè!-̃Ñ 2ÍêvRj°a ëê‘i .KRÚ¥ ´fX¥.ñmĐSnf¥¥ ¾ï !&6"ÛBUªm5ódÄ¥¾ÿçi¬•¥đĐóS³G÷Û́ˆs—nt†(͵zy:Yí¤+Ưdk”A ED- + Qßx5 Ăư@sD: ·̀ ¤J?^ l|ˆ^×íªr{Ï¿öâÓ_>;ZQµJ¥½Đœ«ùùưÎ¥k¾ằM×÷̀µnÙ37Ó¨ÚÄ€(Û UÏó €·#yß® Ë8Msø3©=H.+N³$IY”ß„8Ïkapïíûáú§~ă_^¹ønQÿ€kl'€¸·xŒèóf{±ƯnMµ›Ư~Œj—+cé6’ki“x1CÏ }‡”$pȬE°4=I»1”»úu 3*ËfïÏw]G;ÿjÅ,³̉æ¿riÁp“ b—A§Êºy{B¾)Ó₫`ôN83ÊŒ¶ô–“³Rßt}º¿i¯w³Ëkë[ƒNà'ÓƠ´ƯH™Åi²9̀à K H¬®ç¸¾ø>Êܣ꼉çăûV:!TÁD¯åú̉v ̀Ẹ́\(›‹º7’é̉—¿ó—¿~^Ăv«9µØhMU‹̀¾zi³³5jƠĂ}s­ÅÙf³w¬Ô9M¿²¹)\\Ù¹đ{„l¹-~u¶HZ*è̉Ơ€f-“!œƯÔA §y³^¹çÖƯYùwó»~ơ’úEïNÿ(n½îfT©×›Óó»wÙÛï¨/hn8h´°„†œiG¾‰»eæ$đÀF Ë)î©„6|B³@æm”‘æ°$zü8,V©©4ù‘Ö„J¸- —DÛ›Ja5ÉĂ wRTúp)M’Æ“ºŒçïÛ:ñ÷ÊÂâ,…́tú–jxªƯÙLW»½Î¸“ƯF”´*Y-̀|Q"I§H…¥,·°ál ,?t‚Èqá ldz_X® „9¼Ï…öAÔ¢ CµycéƯ§¿öÂk¯®5íö̀|«½Đ¨„A:Tk#((g‹ÓzùBômM$Y?¬Œ°+¶ùe#lÆó¡Ị̂ÂhÉWæq }å´9IóZ„‚d̃ȵqè<ŒÓjä?pç₫ÑÆƠOÿÖ¿¾±tí½;k¤Å-Mâó¯¿xđè‰Ù«s»́ëơ†(f;FGRpcŒJNĐ²:’åW¸c Úë03́{=úâÖË60 ZiÈu¶‘~±É[Ú2/º¬*EƠ&‰CN‰j[ơ«₫κY–ñ¬¡”ˆÖÍƠ·íâÇè!¬qÜïl­Ï´ǽÂߨXớ̃æpíÆújà®×Cw*¤]Í‹R~!½\y…đ!Œ•r‰€ÁZ"øVùDWV ́ÀÏ}k,̣a2ܺ¶¹vî½+o\ÜPă`ÿÜêT„<éäPeÖt-ªEÔ]\X¡· +ià Z¥XÛ˜·¶Mj̀u‰p_’¬màM6!5:8x¶â ê)Tç¦9̃T-75==3733ƠX]ïX6KG „+Û¤ÊÀ·măcÅØI»´,+%cYV̉L‰51ĐR¶v$¤Âï¶tôFш²V¶·̀ eäN¿ƒqsè2¹gÛƠ6Ù-Émtú²V–rû…ùưy~µ`¥c}ăÍsïwûăjµVoƒ^eÊĩ²çØë/öâµÎV§gÇ…èø‘™̀qCø¯”бV È…NYÉ 26G7ú½µ̃µµÍëqyû¦ö7ëU”É„ ËÑô;đ,?rhbg±ó Ÿ=‹Ô+4= æ- A„yđ81@/ -ÁnYCÇ̀ø€ÍO$in TÆ’bß\û®ĂsƯÍ¥OưŸÿûÆÚÊÿÿKk'€$ăèxü̃Û¯-î=|èÈ-I-Ç –¸íáxÙaµ4<ËÙÏCVXåÊD{£ø3¡œ ³…—•egk2Œ² ă—- I²íJqI Äן)C‘W'€ 6̣¦øS“è5® †–åJ˜ oSb‹̉t“̉µë@¯à&‰º|}éëß~ùü[çá´i´ë³ó‹µv¸ƠÍạ̈ÈâÁƠé8“|Ô¬t[›½‘}Ûî¹äh@CL¼ Ó¨–Ü'㤋₫8ÏR(~£ƯSó¨æ:4CO•ʶ¸¶bÀ9á½´₫W^ä’˜¾<%F„ˆ%Y¨N ø Ë—D=,]çLÆWFQÍôi­ä é4ß5Ơ€ÏÍOƠNÙµ|ù­?üO¿¹±văå̉Ú àÑm}uù¹³ûn¶Ú[[]¬™=ÇƠ¡«%24z̉2¨ÁU¥Ÿ¨]0°Ù…ơrŒ" ôHpÊÙ®WâZF<ƒy¿¼7R7Ă›Íè´Üè~ß^W}`̣æAV¾Û¿ –̀¡kÛ^œd×—7ßzç̉³ßüÎ÷^{ơW¾¥I­ñ¿4Ú3µz%eK7zóóQ%Ùªµ¦ª³Id*³¸7́ŒÓq·?€vxœ¢ÊpĐ-2D}ĂiæØ>!¸-¯RoF¡ë¡đRă¥4¡ˆ§Íö¶ñúdr`Á %­bæ+ !h§%("â8iÎRR—Àä}ÄTêzâPZ‰éfơø₫éKoư“OÿÇܻ͌À?ê¥̉ơ+ï^8÷z³Ưº½ÑhÔ+h±m™­ˆÑyƠ­V)à̀DQ"·H±Ù́uợSỤ̂j”9G¼pâ03}-ai5?˜N7öVÆxúFP7ͶØëƒ<oJÍß·FÂû¢¦ĐĂá±ÇÙ¥k«o¿wåƠ×οđÂso¿₫̣;ç_Í‘æá½ọ̈ {÷OÏÏ×QçFgاêQ·×Ẹ̈^CdûWƒzE©=³ˆ›‡Æ(Ép8ØÜè,¯­Ú¨êÙƯÁY /èËi‚+YLù\rđt`ŒR» SăNÙUiu<ó¦ÚYS¡èí¢ú''½¡é†$­Œ>W+iüƯ₫ö̃,H́®άÊZzW·¤–4̉Œ¤Ù{ß)½±¹U­”»{¨z~€,Øs¯NŸ;tøøÁ#GFFG‡†l«uz†öç°›hPÀ=đûd-+¬fûÚAï¨ư5 % ³ö(¢9£¼q;̣úxµVÔ–hj”Ú`Ûsd?nbÅ¡ë ߥ´[à«™lnm}ë̀́µ©Ë×&&§O½ùÆ•Kço߸º¾¶¬,ÎüƯ›g̃xelï~@xh¬ư~iuesd P©ÔnOITv”¢ï›ñXT¨‚ùCÛ³gá₫ưå•åj­f×¹¸_&jçé¯@Ц3VVJظA2cC¹8hJ3‹„’’‰»’|äRY„@ˆ®µ“BX0GP4{h°¯R«Œí»6Óđ;vÔjUßuôñưÆûûr̃@HÎR¸Td²¬¨7:+lŒÂ)¿~ч042¬eT¦ \ZQí«(Cж£ Æ°ågsFoƒ+Ù ¡9Êb±Œsú~Dü7¤#d‹ÅûS`µ“³·nÜ9wú‡“çOƯ½=·±¶’äl›8wâècÓƯWƯ¬Íß[Ư³·Ø×WØXßr²6›µ£@^¤iú? Á9?’³́‡†\.W‚ª̉¾”‰j©GNî¨@X¶/¨?,2e DƯÛ(ÍËö[aÖ•ƒö»®Ë«‡ ©¯B°¤àĐÙvđ{3ºn.̀µA‹ JØÍÈîø6nß¼:3u₫ÀC 8¸7ïd¡FRXUÅÈ„­O8[8úO~fófœl¤BS4?…[†µ<¸à{d) ÛD©î"$’¬ÄT'Đ̃Ẩ§nÔ»¸Q0Uø%ƒö¢[Y§îZK÷×/NÎN\½67q₫äÄ™7î/̃ÛX_5¯̀›× H}üÉ₫ÁÁÁá¾»ëëkk¥‘½{ÊyÇ£ä€ 3*́'æq$I†èQ&(77<<84¶gl¿_ß¡0Ïqѹ°kQ†[1¨2 ÆKu«‚¶ƒ¡ÄmQMXÎÅ!‹t˜&µ2̣íOM‘RVÈaƯƱs-×̣iHQ0–Çe˜© PÀ™¨a¼?g³\_¿?}eîÍ“¯L_™º8=qjyq¾\̃L¹8SỌ¹‘=£ắ*­®–VVJ͵êÙ\!́lÏ.è½Hæ%›A;aÜxhpplÏèÖÖÖÊÚ tăjĐ£Øç†>"ëa/‰È¹åRá;ª)+ß/dI› ªd{Q½+Êl°(s‹×#ó˜´b íü^hƒk‹¹b!ïV½¡‘HZ8=¿ƒÇ̉⽫Óç÷̃hß@±Ø?˜ [·¶â€ ­°qY6̣*]C)Ù›n{Ù°ØÙ™©£a›e“è́É0*ùJ¸v-«9êÂáàȦ,Ê¥ÏÚß[7·QÚºu÷̃Ô•¹Ó§.Î^»vezbúü[‹ó·­° –si₫©zøØđÈđĐđ€[­/.Ü©Ô6Á‹ñ~§BÎÉç±(K‡Ǵ\zRÑ>ßä7‰p@É‹gdp0́ùëÖK¥­JƠoz¤½Wư₫0AƠxªaå‡Jeœ ‚ëQ¦í†ÅbƯpư|†M)Ÿ.ô}á ăÆ­¹!d)‰ÜÁ®WÈ;Ă}~5ËÎú\®àw¼= ¬éÀCÇöêóc̣£đÉ0Ê"ĂE3²6ÇJUÚ¡­™ZéPÍ÷¨u ơKvD ^p‚\;lº~B¶ËĐ´­&„Û®'‹?z^“_7*=‘ñºÓZ©|mîÆÔågÏOLOOÍL^¼ë ïÉäĂª~…BÔăB¡8:2­onnkǺar²]¡²~T*4—ơSܺŌµ’ô%zŸÉGQ1a¡̀à-˜>ˆÈøèà9?#܇ưk«÷/óĐá£Ăcc#Ă}}Å|.´¤ "Ÿ)NĂσ%¾J~¦P¬Sdœ0ÂĂº+pÄe˜@C…TíHèmf»^sJo<é+·Ô¯™ù¤À´í½kå«×æ¦/Ͻ8}éÂùÙ˯NŸ[]^ÚæÊ”·6ÏŸ|ơ‰gŸ2Çöî+WJ}ưƒkk+¥ơƠjµR)—ƒp :CC³_È (Åóy¿Û#̃;A>€Ëåú³«́ëp²N±¯èäÀ¢ C#ưƒùBà-ôđt́îQ°óxŸĂ¶ø%yư"d¸ÆÚX]»ee×7eW-ȶ¢~₫¤²é ¼BÆđc¡³åZ¹88D…€ßñăǼä́•Kcă0öô÷÷ ç|Ï•¾Ë’rä< *I‡~&ß¶L½Đ§–xf¨!PTù†Ă›ô^·9Bƒ«œ†"bXÑÑ^̃Đ. 9µÏ¯mT.^¹8umrzö™“³W&ñ,s]}e®]9óÆ+ƒĂĂưƒNÑ}́Éç‡G÷áÉJëë1*• }³´ˆl¬¯–·¶–æïx¾§}‚4>ÇAù]_[4„@² 2¨„< â!Tû¾.¿jBÁ¯¶Ñ7€‡^+‡̣…b±¯?ëĂàÏ%(ç¸æ±§ŸÜûåǻĐ•lWëƠ $Ów-Ù¿₫ïT«åL}3ï§’eËåÊPÿ`>ŸÇ {~Ç0“é‹'~äñ;BGÈe“Z¹>†OO © a·E~#ªçªj(ưYÑÏ¥˜åFÄc¢Đˆ¦9Àâ9>CÉ[åúI³®LAX8{ẹüWWW–º»2P¯^xü¹÷ï;p`ttï#?|htcë8Å@újơ:ÄŒR©T,äÖ76ñü¥̉fÖÉl•JNy«́ÖjkëË´Ÿ…æ¹¾º\÷êË ÷€ĂƠ•ûĐ¢Jy³†mÀƠåÍʦo¯ÇZÖª• ƠcJgÛ¸̉g̣®ûñÿÉû¯?g;ù€¼ú"‹?7O¨o°ïœ̣üدº9?7™ơ>œÏ9¸¬Đ7سB¿{ÆƯÛ×/OƯ¿ÏØè¡â‘{ê~Ip/ô$… ‘¬ !5zŸµØ mHvß%Ù°ëa7‘0 ß ₫£Î#^³Ï—´×¨æL5sÜP &÷®oÜÉât®®•.N]Ÿ¸tuæêơKÎ\™ˆÈ®ś΅cƯ­ûW -ÓĐÚ{*•ª_*|àö•€ÿrđZơ¸ÿ]';a{xx æKÔ®ßa¼î‚cCPߨ̣Kˆ”6ËÀüÜüzĐÄÉ«u33øc³ùDm­BÇ®­Rû NÙ×”!_́½Ñ½pÊ€ßæ.9{å±GŸÛ»wïư#ưûFªA=qª§è[›³M9‚+Îf³aLQà'̣ưÿs9—Đ_¡Bg­°ĐyS•çÂÄ´ à/Nv}mëæíÅKÓ×NŸ™˜ö¡{uú,¸nÀĐ½^»Ø×?ºwÿ#‡XQ5yw­gLđ§”Æ\2€‚÷vĐ9Ü b!ư•È9¾s½/o{VT9È͹AËoÈä[[•Ơµ ää Äo¶†ûBvwlo PÜ3§Ô¸Íruq}fmØ÷cG"ôÚê7äC-₫è Ï|â¹ÿ\|dlßHGÍ­ỐÁÁá^(å»jl¬­^ºđæøáGæöÙ72TÈùÊLÈŸªÍùvæ,§.PÜP$%{Kê·ùŒ́ WXÈÂ\n4â51±°à\!ïû[VJ›³Ó7ÁuÏœ½8=557;5;}~q₫Î\ Ÿä€’ơ ¢­Pđ,~6|=*9¯ó±ª̣ÑEag&ëX}…œ780:2$/ß_]^Ư Vf¸"H0²ëµ*i*~̣¶ÆuAXkA è(3Ä c¨ƒÿ Äïîé}ÇÜïf²¥Á-ïĐ¾‘åƠơĂ/û*å­®À¸àƯÀ„ë7f§f&Ï í›Ư;vpÿGÆǴZTgĂ èP®³‚†^nÔªĂ%cUÂ2BUÖ úûrɰ’á̉9vƒ³åƒ€ŒåµÍ™™Ùó—®\¸xyââ…ë—/^¿ÚH÷{óîë,äÄÉŒbli(O`àd8¶=Xÿ,îĐ 9È̉^̀çúû‹Å¾ƠùÅû3UЧÅô—˯Vi×jxrÁñ‹]QqYZtÊL¤U Ïññ¡bfa₫/ÿ¸^_Ö₫Ä ̃™ŸúăŸgùß¿º8·àwÉØÜܘ™:ûđ±'nŒÎßă[«ÔÜ0e?l›Qw^/TG˜®Û0.Sm~ïGˆƠ¡­0x̉ÿ³“óÏëêÚæ™ WÏM̀LOÍ?{êÚƠK·®_Y^¼÷v-…¯…:YÑ]ÛnîÜhl‹×f+wú2¥¹±e$yA&„¶Dñ²t„;°o´P,ܾ3Åñ»FñäÔNÛ/‹k¹}Å”d2!ºa¦´My Đ€ =wü >®Ö\J·„8ơág/­ŒƯ˜_{é3ÿχÿăß₫å̉¶1Ü++»k0\Z/ö Œ́Ùk9…}{÷¦†ƠN–[d‚ /¡€lUbüªN‘Í„ŕƯ0₫8H* ›ûÙA—H­öƯÎ@±ok«zấåo}ï­—đæËßÿ̃ëÿñï“çßœ»:µµ¹ñ6®ĂĐÈèǴÓïyêø̃Ñ‘ˆOr–.')Gk"ˆ‡)øÑg`Ù²w¯Í1¢Á„wˆlfX4H%ư}EºÍMßh—Êî÷öç³´ºyki³¢¨¸ç;ºÜ|X=̣̀#ăµ€“ÓÀ ‡ú ù‚³¸VƯ7|f̣¢ÔƠăÀï‚¥hzâÔÁĂG‡ÆöN]ÛÿĐ¾={Gúªµ:¥%P µz£@dà%ĐˆÑT!Ăq¨¢<œ¼ä:5Ͻmrêú©³Ó3Wo\<{ù̉™ù;7ô$û·ep&¥"÷J&Üx#5b~ßè¹M}TU 3붘 7“߀́Öóyç¡CûƯ……e×·fgBW/„íŒ !ߦ¼ËÀh˜Ÿ3ÔÏøđ¾¡gîÏP:ƠÎóÉgomyƒgd 8¿\}êÙ̃<ô½ëW§z~—Œù»7®]¾¸ÿàĂW¯;²oÏàá¼ăD|$`ªnèr½È˜LÑTAaT70̀ørœËâuàEÊÚ¸>¯ºîưÅƠ‹—fO™º~ăÆ•© ÓNƯ»3G1‰»dúú|‹Ÿf¤›…À̀đSĐØ´eîsQÎ́y¶¬.Ú“3 :{h|,›±çîc‰ü¾ A-í¬í/ø]§¶|K^:gêu¯Xp>ºßÈ 4d;ÅS/Ñ #"¾kÙNÿđèø¡‡°ån¯°û»f\™>øèă#ûÇÏOÍ?8†sV…{0Xâù¬Q?’!Œr&pi \̃ÏU¬Tjwç—¯̀Ü:{ṿÊồ́̀¥Ë“§—îƯ©Ơ*Û9=;"‰TÊå­­¬“µ?) Ùû“‚đHṇ@±=¯;JÜ8ê4`ƠX蜓;8¾ »°¸T̀ ̉Å‚̀°B̃÷'Y™¨ Ÿ́yüđ¹£ƒX̀°O1ExD•‚Å₫ £gÄzå¥{7çf&}óÚÔ½[»üñëơêf¹”éjÀp¼Y¶8U’øs˜ÔU½w½b|x¬Z­lnU(p̉ïÑâKÔAÍí…ƠjưèÁ=ƒ€]ñăIůPë;ܺ[®Ö}ÏR­ºµYÚf~pÀ»‘ _™:;4ºwîæí³—÷#­‡^!ß\™=»Á‰ƒz.à ~3B'SÚܺ2qubböÄÉÓ—.œ›»:}kị̂fiưñø[¥Z­féü»v³=Œ¥îLXÖè/îß;zûîBĐÂ-ü2 v(×ëA<ÖSïß¿g”4Ăh_‘É„₫¬ W´\«mú¹VÖsKÛ çèx7Kçß|äøÓĂ#“WæüĐ‘ñ=ß~I•«(ܪQø•¬Y~dÛ‡îồµ ³gÏ\:øÄC£N&ä&E­jÄ̓8ø«»¸V®Ơëưyẹ̈ŵ~wjµrá̀ë#{öy™́˯ơơ÷Ÿ:¼/ăäÀ«ÑêîÆÆÖÂÂưé™gÏOONL^ºđÖÜƠɵƠûµjåưàßÏÁï>È ´Ú6hyÚ{/ù&07—jÀÛ ëbû ̃Ü(÷圼“©ÔjN$öøá½c{j5*ÉkE½YÙñål(9 +¥•­ŒUƒJ4}ñ 4ç€ßµcmeéÿû ?¯ƠÉl•·^|áɇÚ‡ƒ±¾^_X¹:wñ̉åk³×¦.>»µYÚµ¡öÀçÖ¿æ†5ĐÜ4‹€¶-®%¢Y˜“Àm'€™ëƯsó¯ỘQ|2<4°¸´ 2z`lhúÆÂV¥öĐ̃‘÷;h[™zØ´I:`z€Û̃]̃,UªĐî̃¼vỵ¼Ûđ»YŒö¼¥…{oüàK‹w¯]>6yîÂøø¨“ͬ­®Ư¹s÷ö͹Û7®Ü˜z'*ºë‘_]2v9‰đæi¼Ôk–£ƠOƠ<‰Ú8¸ÛͺäĂ®üjP 3›Í ܾ»xôÀ­'”ÊƠGíî¯ѬäS¦(K9'°îj¥¾´ṾlëÔë?ØX[í‚À̉ĂÉ.GñÊư…s'^8382–/ôáxo•6ÖVÁŸkµê»ï3~eœ †ÉRºªÆ'K†B7U)Äj;¼²`Ọ˜å ö;‹÷ụ́~îÏ—«-¡úZ²/ P%°ßûëåŒ%¨túÍộÿ³ŒJy ÿƯ_º÷Ÿáa¡äçrÙë61L+N(UeÔ&`G ÙÂ~‹v³à́)Á^n?®I+ÆQÑv;¨Ÿ́¿·pŸ:ºVjơ&œ‹Ÿ$o¿ºÂŵrµ6s/yë₫̉B—è]oôÆn¡sùb˜÷(Y¥§sE/ö?©6{¢pŸ'†+ÿyTk×ơÚdî₫k”(âWLop è J긺îÓÜƯoGººY½»²™ËØƠ͵·^ưmföÜ»Tí÷+¸V½îÅʱQ—6/^̉U»7}ÁknkV@cü:”Q—¥zQ'q~O&JăÄwrùB¾P¨7 ‡ÍS²Í,¨é½å­r̃±nÍ^¹Ù½¢v=÷Æ.ăÀ¹<%đ3›Ơ”VÏ §zÍ./…aÚ Û´4˜®i²a‘À‡‰œ—îd³}żOê —nÖˆ„—±2›•ڭŵàÆƠ+S·ï₫íéÀ½±K9°ßv̀«‡¡”¡ Ú‹7(éÅtX¼–¢v‹Ÿ ºz¡ïGxª²Mº05·ÜlÖ€!ë‹Ègnă¹ƒŒNŒÅƠMüWÈeWnMOœÛ¾÷¨Ç{c—¿\PưKa©̀ˆa¸™—6ËÓ‘ ›4‚̉€aå]6’)Q_ü‰üœZûQŸ¹¬×\²Ëk¢$¾÷h³Z¿y£\¯ơ9ÖÄé7ïܼÖÅåêqà̃ØU,Ø©TëV¦Q̉½%ă·ÍÈ#÷’Ïäk¾¦]«#x̉&ͬX/v@YE¾ ±r¹l.ë”ƯjƶDÇ ~g’±3ËëP€ Ùly}åü©7Ê[Ừ-éqà̃ØUø óp]·)”"² órĂ₫,³yfYƯ J…y¢’Ó²î+ÿd5h„ŸU’uœ\>g±Ù9„.·Ÿ²©×ÜÂjik«2Ï\™<ïÎÍî®X÷Æî3by^6Đ=J¬¸æ¤ ’+½&]•³‘åjø¥o®×‰ûêI1¯̣ sﬓñSÁ™M§đÏf!;ß].aöyǺpúÍ.ge÷8pó.#–_æÂ­SIGÆ–â§rEÁ­ˆ-3¤ÂZÙQ¤5´p«~¸fPØ$äñ̉™l)V°&»XÄ™äb¾ ªU²ư-æÔè])• ù́üí³W&ëƯ3_ơÜ»‘ƒ±:Aû¤"¯IpöT‰ZE,Çl4`_ :úR›óàƠâ*Ÿô —*l‡ơ­F»ôfÑ-œlÆöLĐ"³pµ^«T£ầÄ'=S/3Ù 4¤Í₫'µ^ĂQ¥Ö¸ qa¡æxyy'³´¶uă₫jÆñYïÔëÿ±¾¶̣V¬à̃Ø]F¬L&S¯Ö2A8„…d„ 0‚̀ª¹VµZ­Ơªa6I'ûo-‹ T*¸=햯œ旃¯™‰˜Óܽå•r̃̃Z_™¼pæÈÏ=÷Æ®¾€êøR­Æ[¶È\ˆjÍy[•jµîrK`[vôâZÉR;^“‹/#l§©­c‡Ííß™ÁÏƯ¯Tjsó+ơZu`hàä|ûÁ°ß€{c׉Đ9'—uœ|.ëƠ= …VƠuÈ̀n£ZVx•§4 (ưÅmîʘw}–̃„íÄN¥A¿ÂëAG–|Ι¹}qu3Ÿ±»~æ­Wk„ưöÜ»O„Îf‹Åb  ûN¾œêsc·^÷‚FDơzP“9âÍ] ™=2mÅƠࢣ2ä* ư [³4J“ÍDçÿnĐ̀Û­»öƠ;÷+µÚ₫ÁÂ…¯̃¼>ëíXöBÀ½±{àb±ÏÉd,N¦]¯¹`p€lµN5$=Û’₫ÉhĂˆªÜ¥e‹Û)’°Ê­Ơ„#+î ö!ê®ăd—V7o.®8+g»?|ùÛ;”»ßpó~lùÑËU.ẂLfs«BåæÈ¼lk…cưÖÜâ7l­-Áâ÷Q₫o’µ‹¿ƠPzĂPÎ0 ̉àđ…ùºwơÎâúVe´˜¿5{ûÆ5ư¦;çOê¸7v—8Yë›å|>Wơ+]XIùúi>¡Bvº‚̀©E±ÙHL "S–- ]~¶S©\»·ôçÜÓg̃*Å5.3‰mb»àwĐÉ̃®zùàÁ¥̉ºGÁRÍ ]ỳFj‘æj2ä!ÉzWj\A—ÂZ­z{iuaµ4˜ÏÔÊ¥KçO·»ÎÛäƠ=¿Kđ¹ưŸØ Ç6Ö– …œçzBvơ ɺỉw“VFJJ`Ç~ȯnàn²ưRîF©öI½X«UBM¬j¥¼°²qữj_>ăU6¦.œ«”·́˜.0;ˆä€ÿ³ă¶[¬ [¸œ«µZ¿ŒåÚ‘E9¶Ï˜j³©̃eyˆ†5X·™™Sbi«rsa¹T̃:°§o₫Æ̀Ơ+—ä̉ukỪwëøÛ·Q~ÀH.ûjơ©aÛM:j3~ØgkE-O¸L´ç·₫Œm7ơå̀̃ ï¶G²03yEÖŒØVC!·}[ộ̉ǼƯƠL6S°kçO¾¾rѼMÛYÀ$÷¼¡k¢ưv‡F³è¸}VĐ­á'ú¡A.ƒHf3CµiKiÈâq<Å`„ßñÂ\bO†Ă—°²ºµírµ:{giimct°8ẹ̈åKçƯæÆef–̃Ù2ệyÀ»ºúơ±wè®;@ÓŸ§‡±_R£F-Æb%Öd¥@=é¬ Ï̀Üơ°§2!à?)€Á~¯ƯY®>̉Ÿ;sîd,û•óWV»c¹FÁpÀo3z•+Íÿ́ÊLbYA»ç©[¦}dsyÏơkYƠ½ºÅ$'Oÿ´£~Æx¦ÂÀ[8ꌳA¹€kw–îÜ_ê/n®.]8ëús¶Í ƠJ:@²\ü€ßè€ÚEù9öd˜YAúó´C¬Âs¥R‘QSʃÄwHh¼wYS¥È ŤNÛn”̃I\1¿¥¨“ÙªÔ®ß]ÚªTÆGG§̃üẠ́̉‚™b&YGr»´à̃$¬¶˜SÊØ±ˆM:îṾH®¾ÓnéÈ5‹Ê±¼7öŸf:Ö|¥Ëº±ÇḤ^CVN¡̀cض3¹\.(˜î:Aû½‘Bfh¦̃àÁ³¼•ö¤×Ñeí̉ÖÖå¹Üb¸/sûúơơU@]±¬Ù́+́˜ư| zÓr¤‘Üv³Îü€ G̉ƒ¨‹Û–Ü8ÉÂdsl,qlP±.l+1Iº5+) ¸eô‹èxY'§Ÿ]yÖeu«æŸkS Bóđå!Ù1d́—Ÿºà'HÍܸ7us~d s+ӗΓe›-X~̉ÚZZ…-ˆ#¿¦2bµao¾`÷û“Z¥¡“ô^œ:n[²âôn¤$Ü*µd³Ú¬x§¬.¥Ëq͸àënØlq²nRå:4;œ$[U¦-ÉÛä8™µơÍ‹3·W×JÚ3ë̉íW•­Œ5Ñẹ̈‚Ơ9"±„ˆ̉-QåÀm…馹́íå̀[\:KHhËÈlÀm[¶Œ̃רă›WQ$)ÉV\Ù·®äQU+•J¹\ ôaËRc›c¡« EøcMgåy=ïöÂưÙ;÷‹y§/ă8w¢V©è¼WÑS¬¸¬)¹ªIx5}%™µ«Óđún%Đt äí’üôfƠô’s,6àV~hƳÆgL’™Im‰jưD&åBtÉèà­­,­®®VjµB¡Đ̣NI¡Ëü‰uHĐ9î¡ƠMD™ WâæÖæôơ» +¥ƒ£k‹·î̃¼–ÉØâ‰Ä$ưº"éĐLË3…‹’.Mv,Vª•¥N:½NĐù¶®±v ©u'tƯí·̉sà–́7%OV(B”ç@*S’uèÆF Ɔ̣w6î/̃½yóDÖ=ĂCƠ*7'Œq+F)%€9MU:…{ëàñmÑ5w{ijn÷(œzë U®3h¿±&†l¢ ÖxÙ-ưRIG₫Óx)ƒï­Ô$¤\&ZhûÅ¢ZÆT%q]Ú°ô`î"€%h¥3Ằ““äƠ®đaºỞüí;·n\˜œ=8>ÖẀ•ËU¢ǹC‡ÍEÀ³'[ÙQöRó«´B›«@ÓZomm¾u{iưàH_­tnf’')HÓWXǰ²ÈnÔ™óª«+[́Xí¤Å¤‰ÑM)Z?z‡ØrWx/‘đ$Ü*í@„68‰ưêb^́‰Œ Ă2«éG­Z¹9;}q̣ñ¾¡¡<÷èP1ïw ªYn˜#LîÏRñí†m™ü·P]*RÙ°*[A­ó¢#pSµºfăs1›95{orn!k¹ŸO|ÿ[åÍ đR…Œê.wüÉå•‚½N3Û:+vRÆèvÏo‹Y+e©₫¦—D³Zºv¸2–Ü8 ÀæơLiÖ‘¬H˱HÖÉA¬QzûÔđú̀ć;éäï,¬ùl¶¿èLÍ̃ù3W×J›ÇÇGÖn^»|ÑÿÑ`¤ÑĂ–ëWW†"iŸ×Ù/ßÄIc>5ÛT­÷m±åv#:3Suшe^"ƒH̀(ŨÄ"Ù‹²l¹2±́´åĐ‘K̀çΨ!ÆÖæÆÄÉWÀ>ï/.L_Ư3yy ˜| ….Í:™\Ö®{öP1è*́Û›œ¬å800P̀ÛË«{¾x‘± Nü_¯»\Y†j×Êf3~++̉E-¯ËÖ\÷¨×ꯟ›ư₫É©[‹+‡rF₫ư»Ÿ¯×*r;Z*Û’¯̣·HäÑ5—ØÁ&®Ø]ö'í¾¤ơÛ>’­n×|j‹Áv….t ?·‹[zc¶H·¤M̃+QËÑ’[­K¨w‡‡FF9~èè¹¾!+“óđÿy¯…|L2Ÿw*Ơz¡w}¼9uŸqúÑUÏ!Øi1çlƠÜÍÊ@Ñ)×¼Á₫Ø>Ä´ …¢“±́¬3ĐWô›’ ¬ºÏ¨ÁĐƯªÏ€ï¯—ñ»¿¸¼a¹Ơ½Ă}ö œyí;Sç̃đ+I»n̉©Ûud*ob¯‘w ̣C:ŸÏ€jö…¤”®­(ÔÖ“r̉·̉r´;°aX)‚¢ å<ÉÑ€cÑ›k±ÍÑ×?82º¯X́³7çäó…"æ/ôƠjµbß@½V-öx~²A.ạ́r¸À­ Ơ}ư[å²mƠ3NÁ³ÜŒ“Ïåûp}im-ß×ï÷o©ûˆ…/ä×7+Cư}•ZƯÎ8Ơó=Ø—/­.]<3sé´[«%¹»u‘G¾QÖY.x́{}_bÿ2a$-Ï_@ÛYm§(rû­–̃¶”Vzó*ÅJÅI¸ư¼];VêtĶ…d³&ü`œ…xÍfÛׄ}Ñ p‹×0 =9Î₫T(—K¸,—ËăăB__½Z-•Jă­./9y¨Ö¹Zµ62: ¹¿¯ß –ßÊd l{ wo­¯,Ơ*[ôĐú O"dº⺮ázP ₫„7øǵ¦ÈWåÀf-埬îå£?;V»`Nc¨Oé.2à6 Æ)¥èXˆYÅj‰d] LâóÛ‘e¶cwHvt•D.iÓ‡ ªÉ¹û”„é.î$Å0Öư+03˜;xU˜¹“>¬/=g̃=î:tc1܀͸Ơ1¬À¾%n©Çb•#d<ă–?IiÍjwI;ÍZX±±v~¬âR¸nKW|’½Pâ–9­/¿Go2‘ålùºLÙ ¼qRFt éw€;nTc¥H32œ'…9Ä~Ø’ §×ơ#¥`•ñ¬%[5)Va×X'‘;?ư„w¬́+₫$¡—åd´° H¥5ÿ•ía<̃&̃'ÉÚÙn´Ơ*‹ơí’¢Ó¬Ă†¬ÔY Iz¯ÛXô¦´c™³$¿ơ«O Đ̉ ó¤#ÙÚ¡¥Ó¯jÇ¥ ZÚ’$e‘c×–é—~æ%¼cŸ4Ö%̀®ßFƠue³ú iè–F2Æ­|uR†¤1Øf5‰¶v4=đZ¯ÎDè4®£¶xB+=FV«|`% ˆAËT\đô?¥ÏJoƠßï"ûƠYZÆÉ¥¡›º’âW ŸEeö ó`¡ZFeóMäI ;úDSú6̉HÚiĐÛV¸ez‹qÊ˶Ă7ÚuüÆê·Π°âX5ØJ®}•$?ë•$ö«;-ZbxçlÑI'Ê —:öO±F/)r+aX ­Œ]d& NÉ + ¹£Ïé[ĂAêHroľ1[ª­NWê‡i8°u˜]bIxJá9–!* 9}fă³äXÎ̀ÿ”`6È̉Û7+¤¡›ú́üILج¿đ?È+›ÍC˜#«èM­V«V«årÙƠư••X¼—è5€V>&ĂV%-À) ZƯÅđöµÜô×§nWxn‰^eåc)£nVwb1ëlTDnÔ5`¸+áôƠ#¥4ÖÜ`ĐSä_9?ñ™‰₫ÔßßOÄN†m×€w__¶µµµ¹¹Ik¬’Ù™·ƒù0½aÖGI +1́<iƒ™´]YúÛ®:–ÆSfí·´<Dh?Đ!ăï Çq’Dh bf±ÙŒd]Ö£í F¬àÀ-}uiä­dTÓw³~jèM*₫;[?{``.•J„4'±\)EnyÚŒgC–¦iză´' <Á §´&mXgƠpÚ›»nÄJcMI¤”í âp€Æ3t #ŸÏăÆ`́uL˜ơWs˜®Y~̃ Ø\ 7¥©_Yv WF,+(p›)‹ü'’¢ Ờ±xÀi±ÎT ë†ơÇ+h(Á’mÎRæù3°éC+.Å 6Ù«!Bwđ¤ë[­’àÚḄNÛ¥ZßÇH€µèMJNµ©àá´+‘zi‚~b1lµmXƠÎÊ&‰Đf“¡™'‘l,‘,ơ^)Zc1 ÁŒ±ª2%µ_ϬbàJvđ2ăe¸JÉYAozM_qbg¯“¨406„à§¡»oÀöNˆĐm‰sm!™È?߇’æ˜Hn@Y.́+• ›=S*À †­„n¬ÊÀê½ổKÔ=I´\¯¾úêµk×äQÇî0VYN–¬˜µßXôa¬Đ:h¥đË¢ q-º,m¥H¦é.î€ưÄosaz†Đ.zy $7i€ûûû Ă’7`QpÈÚƒeư—Û†wÀÛ Ă2k.I"ăV¯cccp̉Üồ{²VH-WBWâV²$zͳ Z«₫F>ªN¨ôs™&‚·ƯêYƯ5Mm'}›¸¥P§ëiºóæ¹ç#ô2CÑ<'Od¦M•lÍJ‰äí¤v+”2}öuzÇ{$Å”$ŒÄĂTq©-̉IR´Nî‹´y‰ÍÍ2É£%’Ó°â–¹¬‡gíÀÜVEÎt`se¬ ¦*y,Äă§zÊ ­¼ùæ›J€.妉ÁJÄJJ*́ 'i;Ưđ̉×èíØvHkN.\¦‰$ÎfÍ–M*>±a,E+0Ö%êDXáÀô“üʼnôBuKçp»̃`sƯ¶.Íi.NéÏhKni ”Z.¹÷:ç'«•| âƠIΤ”¥^¬NËël3ú*68É ¶´”¢cŹ́2rƒC2̀¦ ¤¬ÄÙ&8Àf<ëçÖQ«¼W «°åÎ0Ü])ºùyûœ̀Xæ¸Ü”ÆùEiđdÍ–OC,€•G7Q̣b3ŘüÜŒÓx’ÚJ½6»—¶éѤ5×k¾êl4"±ô*å̀ [N)E·¡;«J™Æ.Ơ–ül–ưRÖ 4g†¤I*$o„Ô~±ư¤(7¬̀ 3 x±I ±éJVêL†¶Dèíâ0 bó^[º…c©'{z·3Ø̀Ú¯n¾M2kÀ:›ÍFC°Îu‚x;¡Û­6Ü®¨nlPÆ̀6•ôná$[ÍÙj¡]±ˆz…Ň:‚7:¶?oÓˆe₫S9̀*±²́iÂỬX9œd‹6WüĂQ˜C¤“„jCÈG»Rt·8p[ܸ­Ú”ºøĐYq¦–*±¼8ö0™EèRí„™gJÍá$Đ*mRª¾Û‰¦lWN)ûtÀ;¡uÇÓMƯl|jÉoÖ¡ËXU kVŒcuc…-È7Ö¶S½ âYR¯Ć™.´ ¥4 4I1)yÓØpp% Êœx”&x£eÓ°̣ëâ’”” ¯ÊI æn“S´çôËWJ*”Hié:"rÀo"t,&cYqOæà> ×$•€~ÂÜc¶eøt,°EwÉXäNózÉ¿ ŒAN¡ñ2Q$™ÓZaP¤Î@tÜ+ñ†¼BC´\礖"Êzu`Ă„ơ¦-Ê ÑÓÙØ+}6̉ @’Ï»̣ Õ>€×××·¶¶(‰%U'¡Q ‡ôE¹¨•&H*œøi¹I±O7/—Ët‡¾¾>:L²¼¾áJ¥…ÈÇ̃-öü%‚ééé–. ¬ %ÓHó³Ọ́RĐB̉úH~Û\úE –X:itê”ăÁ`£I²Ö́§Å+smmÍ ’ ñZ,ơÂ]đ7’B>”å"H+ŒÊP$¸Á•²IL˜Y3ÅƠ“côz¨ xøLĐæÑl°ˆ,lđƒ%]ƯÿF± Ê(uRô9đđëx––µtÓQ¦ưĐưNJQ zƯÜÜDñáĐĐP0dƯ–Å`$MCçÀ¬Y%5o9*Á ùàp3Åá)£¥^ĂØV–WÛ*±agÉœ‰Åè%I'D®[¬0¢?|wii oFGGñ¼RËëx 9$.¶¦ṭ+B’¤\[‚[̉2Ÿ+ƠƯH<`$`°–/Uhb†̉]¬p¿z4(¶¥ ü‹ˆ-§{’́k-Ô9*óU?‘¹ä“<|£¼M à‡ÄÚ$ËÅÅ(ƠVN”Y‡r†˜çÈÜQ|‡[đ»xâ¤â+ @¯$ ÿ(3Ôb₫ʳÎa@û1|qllLÖj ñȆÑer¬*eƠỄÙ«««̣|Kz§ï,qL ‹C—áŸ@ Â~xưÙÙ©̀-öøUŒÇÇÇ% í8\L™ƒB¶Œă9Èc h:I†+Ö„u¡cḤ «m8^ ©̉ĂÁå‚H–æ/J.$™Ï›xÅ Ñ3`WÚ={öàŸ|Vè§9óFáiµh$F“¡‹yáxíxôëÄpÉØEbƒ²*¯`Ü ‡‰¦'é…\)Î$‘0~|ÁøàÁƒ8ñ0Ë̉üø$Á˜ª^ÖP<K4ioiT₫Ỉ5=~Ó“¹4úÈ"‰\UÊ¿£ÙzÙÀ#rT”ùàs½{÷âueeEÁm̉ ”æ)´+‹OáêƠ«Xütæ˜ƠÓ?y‰HSăĂ §…¥iđcâ2nx$Ù‰Ô4é²0IIB̉1̀’½ ´vrù)ZJÎr{ˆûÉ¥çáy˜¤.2çç7>.„vÀ %VÖn+œy‡Ó†û€̉KUY¢—Ư¿Ÿrôxn±‹À멈C2_—ŸV€NüƯ»wGFF¤²‡ÛƒAL\̀₫ä’Ư´\´Yi²¦iA¸˜é“@,ˆ)­¤MIµIu¤‘¼…ÄZ¢n|Úps\Lÿ”R?)̃|¾eR$nÅr/₫ èbX̃!„pf¥¬˜¡T7}ñ ?wîÜÁưüq¾̃i$OIáÀ’ ¡sH3áø9R=Ơ—Í â¥HêfôBÀc/­>m¨5®Á+Î~ïƒ'Ø I vxOç˜Ô::$’i¥“€³çèP*˜̀t/7RJwHº.ÆÑ ̉|pJ@é%¦§Æe@/3F¢tyç$×eAWro.jEÇ_§ư£Ç'c̣w™„‘m‰,^\«%ÖSÅyç)ÓBp[ü4;-i‰HFÅMˆ‘rÿ^a’$©dŒ`Ç Ư¤*̉ùåsÉûHơ(Q¼‘™}Œ^ZüB4hñ±kƒñ[ưÑ Æ€»amñf~~i->^iñ!#\¼xñ}ï{_»ó¡OK÷íÛwøđaL ï%QÆđ x½uë~Î̃PÖ gq‹ơĂ“2åëÀ ïƠ-X`đ^‰^‚.¡“>räÈ¡C‡tÄ*N 6í%–xX^^föE@¢u”bÏđđđ>đ¤;ă+àZ¤́aª¸S­«J‹3ŤLOG7ĂÙ¿¿0ˆ¡—ÅôK’½À/;]ô¸?:y,2l¿Îd˜y5x‚ænp#=ưôÓi"“”199yưúu¦æÄô°­`ÅÊaÅV~ö³Ÿ!ÁľúƠ¯̉±!K•×Ă?+=î#ùÈ{ßû̃¤½©©©û·“îe=&8Q=öرcÇÀ< ¼ñJ ½˜˜í¥K—W–›ÈæO Ơ.\h— 3€±z>úè{̃ó¤ù́ ÆĂ?ü /̀ÍÍMLL ̀¨q¸‚ ›ÉQḮ—ß8:ïƠ1Œy°/×Ó}î¹ç?®£ÅüOT±ôX2,%(¢¿™7&â”`@óÇÄ]ˆ$M@ºÄ‡jÁ²€‚̉w!/I‰ùÓ~¢>IÁ^iLLLN†È0=>ÑcCàdJ”¦¹Œœ´Na°Ṃ̉L‚¸îÇâ166z'ëZ`³$?K!™ï#‡—#rÆf̉I|åĂ₫0Đ̉®¸‹Ọ́p0@°€fVµhñI}h÷˜8Ù‹/¾h&%rĐ4đ¤çΓ‡PbXi‚CG7¬ ›É Í$̃°(Ë́â‘Gù”ñ=)¡«|‚ûƒv‚ Í̀̀H¥Å]k &¹”•U>Eê0ü:~‹ưRß Q GgôE‘œ‰y’ iµª«j@2½¡}RøZaÓ2=˽’\G̣à«JhäµÅùÆ~¦̀R*psÖŒè‰đȤª$-$.+y/ÑMpüă’zv0pŒ¹3gÎ\¾|Y<#(x»w{ÿûßÿ̀3Ït0 HL8Àßû̃÷÷/Ål‘#ĂæH¯‹+1Lf™±D\ƯK/½dÅu0d®Äb‰À‘ ¢Â0xH’¤Ê Ê}°…Øå+O›¡G³¥»Rđ£÷îƯK—è•öp̀™I†­µ‡M h‘̉ lRơ¥½Afÿ¦Äm’Àô’.æ&£Ä˜saÅ<¡_dø(„" ä#Eë~衇¤-]Y«W¯²Î"e’x?úÑBFµº1pĂ~đƒ Å€±ltbˆ ²u< 0üO~̣“ßưîwÙvÀˆ¥j*Är \3ÄÑ¥ü,Ùoê“O>ùc?öc̣¼*Ç·%zå?ù»¤¹á=vNnªlĨßÓ}HăË€d/-±tPĂà?VT…íœ`́4Ö%@åŸIúÙ¥{²Ăƒ S·–u?̉À\Ë{ôèÑ$́*\Yúe˯Oå&XL:s̀@Xç<|ø°¤Êj@¤$Â-3Ä?>ñ‰O<ơÔS±áî(ƒXçóçÏ+ }P÷vĐ+1üï|Gf}sŒOIÂØÑS«¤ü¬ÈuT×ëÓŸ₫t́•Ç7%Ö‘ ²RÂwZá±-[ÑË »¤ëÉÿLÖib₫¤ ±7‹N0©Ê­ 6#Yb˜Èæ€_'Û,ëÀV.ÍæqO·G14KJ¿P%”àèlæ\( pWèD²:˜°‚7Ü'V‘¦‚ĐHÑ5ÿå¿ü—'xBé©Û$CÆ$¯\¹B¹Ó)c`º; }@/øæ7¿I‡ô¿x]0ØɉCNlµ:OĐ«¥BèºJ¬ Ù1’_xá…S§N™œÄcÓ€Ù Kƒˆ‚áåâ`¥k¤G̣j6–®¬hÅÀ-~̀cÜKÉè²RÔẩ?Äm¡X~ä#I’±Á<•ïêᜠ_f8$‰@âä’fáÑÈÎû+++·oß–V:œ`¼ v¯m"’ù7ˆt̉°l;kZ̃÷½ï}'Od:ÂaäR‡’‹/1LLFë`w!}Å;~½víäxh³ dľ(Üôx0 ¨@U0€ÛüùÏL˜̀c²–ªœ:í̀øœ<"x´^R}—¦0¤ù'‰$f’§,©Œ“!ă<Ä*̣pÅäù'~â' HÆơ¤¾ —…Ú X‚Ç‚TÅ"œ‚̉Yú•Yô ØJ2c3i$€ÍyyÄ~cy/ÆÅ‹•0Ṛ¾`Ièå×ùùùׂCJ6G}ô¥—^ú́g?k¶cÁÁ?^}ơUvƒm¿êM†Jt„æ@;B[ĂèmX¡•Ä\L\ Â|₫ùç•€~eí₫ú¯ÿG‡d"çüuàsúÚ×¾ºûó?ÿó„ôÓ¿´´ô·û· ùl93pà$d‚œ Æôô4ÔW2tC¢ƒp₫¡}ˆC‚’ ̣Oœ%ËÏ‹cgnZÏ!+3Á9§O9̀áØ±c8I$KùBG2‰?ø&%r,‹kâ௺V,Á€ W“¾¢¤ªß¼yd(É:]£@N{¸W)(n'fiÄBÁ0¯U’LcvvVÉÁW€@̣©$Y­±Ư_üâ¿úƠ¯²nhhˆl¹8{ ÿđÿđ¿₫×ÿú̀g>cV†qxÈñÁµ);@¾ơ­o±}[ÿøăƒˆ0 ăcûØ¿₫ë¿JFB¾tl!ôúç¤e…>VjÈí|óÍ7OŸ>íçC¯Goc]pÿâ/₫bbbâüÿ!íOsssôGDĂØÔÊ42đ… ˆÓüyÿpd!€¸üôOÿ4Å„8óøø8&IV`đ ƠQÉvЧ̀œ8q'€ÎÙ·i`́xÆ×_ưƒü ¨‰n"?! ˆú!‘+……:…±ëÆ|‹r¼XˆAÀăÙgŸM’º1g™G¡è`Ưºǜ3‘Nơ±±±ååe™¬+ Á¡C‡’<Éør¾¬këAû<(Zy|́ï_ưƠ_á•êrK¡ïüÇŒC̣Ë¿üËđ`w^y啨Tû4ÇïÏ₫́ϰÑ47öqܹs‡₫ơ_ÿu³,p(xb$̀x¹Eph™7WèSâ‡qGC(öL&‘(9 ä¡ÀI,óW~åWè2Lôÿđq<Ë4™+oŒ (̣$vÿ¾üå/_¿~ư¿ư·ÿf`æ ALêdØœ„[Öưæ7¿‰ÓOeeH“œĂo¼“M–|]–æ¥ÀQŸA\#Ơr6ké.e0®ç|ĨG ¾…‰-I)̀Î{vc=ÀzṆ̃+₫ F#M¿ÿ(X–̣9®ƠK2}“́öû¿ÿûR(¥Œ#¥ù†Cß¿ÿưï?öØc?ơS?•¨Ù/¿ü²¬ˆ̃zû·́—èŸdûÅú_ºté₫Ïÿù{¿÷{:G”ă‰' wº’ù'ê´D¯äŸ±¼Q̉f̣ø3\9͈“§0{̣ÂăJ°ë/}éKÿư¿ÿw0„?øƒ?Àe‚Ï¡íJ(²9&̣êW¾̣j”äú₫áw!ÉüÈüˆŸƒØc؈X‘”ùà₫ ®Pû“Î ü& íÇ?₫ñ$ŸEϱ3Ü÷L¥g86À‹Bđd‡x $C€:Ë„9kBaxêH~K4Bjvl pàC¼t¸å6&Ùí »abP¤á@ J§8m 8‡, C ‰=É8E€¤îØïŸ₫éŸ̃ºu‹²ÁØï%AÁù3¸̣·~ë· |ø©§Ÿ£ˆtê3LF́~ƒëùJ~&‹Đ-µùưÑ¥47™åÇ0–) Äfaœx́åßÿưßz)´8–́é}¥,Aó!ôÊưSâ~hA±ßøÆ7 &áú$ Sd˜́’ö›$ÆÓO@æI¬ORy†8í S%Ù«‰‘RÛ;Epby$I”¥”đcd9h¡Idü.ewñ¹¡»E-HJL%ÔiNfæi“¾EÅC¤å GÙ€^pKœ%€\R=uœR4¾₫ơ¯sÔ”RKˆñí&¿öÚkW®\¡àE=¹…@Ä@Pë¾öµ¯nÅáüùó€ÓT₫Ö̉ óéeYR‡₫sŸûIJܰ¼ÇL˜Ơ`JJ–¾đ…/Đ£rN‰^ Á BÓ?ÁT±…dAU#æ˜äX6¤éƒ¦GµW¨d „I׃ñBđăäÙZÉ+’®‘“'O=zÔ`¾¦³±…r̀¡†„U÷îƯ3ØÀđDưôÓ†ÀÆà€~'«««ØZäd*&ôLJ¾¡`£–+%«+éH~ë­·ôLú}èC…è"&i†øÊÙ³g?ơ©O0‰ïb₫´ë¨cåg휘˜P’ñ, Ÿ8$#­¬¬€6SÎs~ШJ6ˆD2‘j2„&.L*ë§‹…LD‡z#Ù¢uFº’ _P ôóCj;̉Ä€+*₫‹$¹=ó¤tæ–Ô;R†Ʊ^z'˜3¶5IÆÖt(yÉ @AcD ma)° \EŸŸ:uÊ` JU\YRíu’ôE*£O l|ö³Ÿm7Rœ²e63đTă•‚¸.1d®K ÔM º• û‚Á¬øÛüĐCƯºu‹c$đWo|˜ÑAÅ(hñ&‰WăAXÛác+›a;!,pb Î9ˆơNqÄR,8¥l0eó€Af*sûömĐ$O2ؤ'iÇÚcQ,#E°Ç†X“¨%wGanÊ Û¡̀-aóÚWÈO™ÔüMZ7bråSr`ˆœ aÙ·•v«Ü`ë[V Årq*ö Fu”Øb‹zÚÈ{P?üáo'ÊDâ™`<33C²Yw8±^¶QUDhtÍ–¥º„½#œ| ªkÜæ%–üÁF ~,€P)z†Ï`9 :’Z(i0$¥X+Í•?†PMeJa" äL̉Qxd0?Ë Áñ âÈfmy–°wï̃•¥QtO2_ §ëå\œôY“ Yy|zÅĂP”;-#Q•ơ•áÇœ³ÂŸp³|y‚ đ`ÏĐĐĐ{\%Àô kX–•¡ç²º:d×a:ƒ0'yÈH’×N¬H«ÎÑ ;…F1Ʋă§că"¨Ÿ0‹Øq"7Êчx¥€K|đƒŒÍṔ<É är±₫b¹»f]Q’̃¤,6èë ẹ̈‘î›[ S| oÈ´­$Œà*Óh’LơO¥u„KØq*?&ú«¿ú«”a×Åj÷ÉO~’\;T$IV®µZÚÓ ¬&E›Èh³ØÚ×2‹³ºôẓz ó²÷RĐíùô'™`,KäÅÎDé/Á ÛY.ÉíẠ›´‡“-ƯÅ\ù‚óm)ÀE~O‹OV1P"i­äTˆ¸ü‹Ä~“s`YÑA1‚*CN?Ñÿªÿ3ö½P¯”œ¤Ø.R~–'Vçœ:Đ”º¥†eIL8“¤£Ë2²˜ uăÆ_ú¥_¢ƯÏ>û́G>̣YgP–G7´rU\Ç-Ë‚* e’QđÖfSŒXä„®Øj¾z=#nb ?‚]iv̉g"C£¸v¼r(å?)–H°$?Ó5`± ‚Íæj:Ø€ª\«æP‚4`–ÿ́É\ OmíDĂU¸ˆùÈLÉ– Í ™ÉNKôS@1a΀Ôô¿ÿ÷ÿ₫Ô§>ơ ¿đ è"†;†u|ùå—eÙáXñ_9ïB¯…«J‡™9G‚·ÓÈÉHkÙs8vÿd`†~v½èØ̀; óL¢Ÿ&˜œ=zT&.¦˜~\kÁª&EK0?ơÔS²o› ®¦ÇTäa™ÁWç"2©36è:IV.6×?ĐßS̀B¬}1VU¡_‘á±­Xơs˜†[ íăó7É ¦³NBÚ~À́Ûß₫ö‹/¾ø£?ú£ï{ßûº…äÇ{lrrä\gkzwOLéèÑ£7õdư„"cIă•–¶x:1TµÜ¢̀ô;ÖÍ×8ÇÔl{¦°Kà¹0cØ0а²…ǸaCÁoƯº%™0•¡u&³S„Ñ«{ Ëq^!EwÉ  °!Ó­t,ázÚÄØ¢¤ô üÀ4¤@ÛœúŸ,­K8v+ĂaŒ,Bë!èôƯññq67̉5 Œ:y•4«-œÄ³¤Çf@Â0;ʹj…¿ùæ›Xb¨7€ñóÏ?ÿ /l̀¸Ắ́¬A Tú(^ÁQc}*†hÉhYf~ă7ˆS‘ƒg–‹BËÄÈaö.màcTדKÛêẈÀñº|ù2‘ºŒbô(LBR\*ü¯œ`2A[Éơº”üÛ$lnÎÆ¥¹¥ ƒÑ\]T9p"›ÉSK-Nhå98„b›ô:ĐoeƠK… så@}¯eAuïß¿E¼„¢ú̉X61bÀª&—¿TÚn²1"Ö…}Äăó}ÈÁɸ̀–.̉Ô›BïƠ°̃=)ö Q’9”Uö˜‘ăÔ©Sà̀Ÿÿüçq C̉kMé‚“c9̉¸Ñ±…´Đl´Ä$!rK²‘» 10+Å,ßS|mÆ̀̀ æŸÄñÀÖ8k—e¹+W®¼ÿưï—¤³âÀtv•çf=\.Ö»k₫V€q(±\́®c)ZÉ©¿B{­”̣"e#=X“ÇcUeêY‡­O i&¹@§×øEüÉA¹G…́)[³e;(K´†àØuY”kÖ0S•‘˜I’9LBj^") …×íöíÛ’Há₫fö‹ƒ¤́¾ Ut¬änë²v•É•_Xh”QJ¿¡Tæï~÷»ØÂŸưÙŸư™Ÿù™–0†¶Æ ̀‡̣‰' «8› *$áœqƠl­EÙËVBù.k~u7Ø™(IJϘx¯¿₫úñăÇÉ) ô^ºtIZƯhW~úis­ZöX“‰a>º g ä“Áq'vÇ&4Lơ‘G‰u³ṢÆ@†ÉIè¡(ú] b^G¹±¼”"Ơc½² ¼?0~„_§L²¯ERoqF/yU(ÄxnSÄ]¦e”ôy;vŒ2ØØ %‚hM¹ÜP̣À¼¤æâ¸ ^:û%‡5:Z–MÆ—¹2°,®MơÖÀÿȸ”&²¾1^¿üå/Ÿ9sæ7~ă7 I4KiÁ7ê LSH”huƒ#ç£ư¨"*ÇD‡ßOOO›³)@G1´Œ‡…tzö́Y'ÛMQt ’Đ‹€gá¢-K”HÓ£Ô²đ̉PRfNU)Ñ#ºHxVX"½aùY¹¨‡dIM¡©±¼‹ZÉÆæoQ‘Ü“lÅí´ăw-Ăøt;¢ j ƒôKÛÇ'd«*ÙüƯƠxäÈ<#ßäÆ]`ÂT&Y?‡¤¡P)å$ÍWç¦̉.í$±_₫IR•®"ḥ3ăO²̉ÜUvÄÅĐÔW_}ơÇüÇ ˜¤ øØ†Øú#84Ä'‰«p=7) rK(À¼¥Uçăze?> ĐB́P’Éçà©§œœä1|Œd[.nL?…‚k÷ÅV®&Ê ~",kÅ"E_J8!ơXÍŒø'Rl¶&vJQ)¤,öô33Wâø`@ U¡AqîÇ+_q¥.ơÇçÏ=÷d.Jă¨^\L] ƒp’/ê½ï}ï‰'Ø!,ƯȲ'#«Ö/¾ø¢ë®À˜ûEèq œDÈéđI¢…Wè„øù×^{ gÖBöéTâ ¥ A£eG ́ß'Îü̉K/}ăß¹¡ỈÚq)Y$ ÷„/Cơד'O*ûô½ï}ïñ …́p°å8¾´PD¿éae裲Éđ†J×/^Lz|³L¨c HÆ!p$ƒ ä´e³Ơª̉5e‰Jÿª’T*DºæhjƯ‚Åä”ÄÎJ.Ḱ³¢Å'eX>»Œ]åJ)@/e׋‚K5Ii>²Ư1Wö1$Q[A©MÈÉX[dS΅mB{‡g+ÍrQyFêcÉT–¬r¬¸ÆêÜퟜ[iqtéÉ!ˆBÓ颿ʅ“ö@öw‘ȶ,̀‘FÏ+4 0ƠOúÓ/¿ü2a˜üJ:{L~||Ü«ªÉ¯o¼ñ†TøñzêÔ©ŸÿùŸ'7x’Ư…åE£ƠÍ×Y¡¯<ó̀3I‰P̀âæææHk5G™5gn#,E! N`ÎÀOù‚”±”•®‰ư*~TBöI¼±U¯H“yEo(ó.€L¨—P2 ‘À0µq¢rÊ,î) 9Đ 3$…²̣5ØVˆ¾ÔROúi‰ü™ƒ®I0a(tdagi‚ÁT?ơ©Oq‘ÍØsdé‡_¥~ ¯Îu¥ ¦Øëđ ¢ơ™Ï|†Ă$đáÇ?₫ñK—.AX§cÁ §ô×åjL¸Ûç>÷9së7¬oóáb9F–[)ĐOƒÄb}ỵVB}\,&@Å_™făd|ë[ßú™Ÿù™X£ÿ’¨N¨¯́pĂ “_­e}\‘¤x–Æ€"^s.ÊE¨–ºQP¤¬ÆØ| î“,=s̉¬MÂ…¡ü:ÿ“n%¥Ç¡¡!}2•³ètîÜ9™í”THµçT€¼[€£"-jü†\A!Â4&&&$RüÀö2¼gljjúÔ3'“7Áâ€ó)åVô…¢^gº^)ơSG¢Y¾2€ePáÑ£GA6¨—àÆ<̣N-v´Gÿ<ˆ(ô„–¾/HL™Újo-üØÇ>Ql:1Âf€²¨†Œ”úú׿.7†1üÏÿüÏ VT«-É|M^%à‡:’R8á sƠ7â’÷Á @á¶×Ëfª$đƒÎRĂaÚo6ƒÀd)P§ɑ£wƠ‘L›Kѵ±áÙ́rOê>!¹1Gƒđ.]ưưưÀ8Zઙĩ”/ zR#Í…̀7†Ë2´ âB©dd^́ÅJˆ.$,P|<™å9˜ççÄ¥,¡‚äû·ĂÊ©XVçd®@td~£W–tg® ñ‰O|" ˜Ü{‚A)¾X>r pz/`J'0f¯[ÏÓLæÑ`tđƯï|ç;¼p,u“’º₫—ù—¿ök¿–$XÊăN™’éÛ¬*µé¿ưíoÇ–5å¢̃+†R%åÎ8Lj¬Qßă?nö-³m\±¸°A& â„ ̉² Å6H"5 ̀–Ơ7,>$#°Y W º–H¦o韧,©‰é}å+_¡LIi…N‚½tÇç $•äKăû`ơÀ~•ÂÔ\$Ó-B̀1œŒa `¢:/½ô’½zïvâ(qvA8ÑÜz€ăúơëỵ̈/ÿ"ÉGS·±ÉÉÉ/~ñ‹?÷s?+X&ư±Ú́~₫…/|„ŸÊ»Æ¶GÀ6a‰(ú¢­†2äß’E|JÅpCr ɳ%›0ĐœrIJí REeø©ë2È=U)f ăŸ_ưêWög6¶tL¬@tmÎp C ˆª*+oĐĂ¥ë.MûȤ€mđ `¿.YÉÇ ÓlôT2ª̃,gŒBªüÁ~đÀ dÈkƯ¹±đOÿôOIá—ÈáÆđdĂû̉—¾ôưï_OKÖÛ;&ơmUr•¿~ùË_¦zü2ÇX¡‰”ÇgÎmŒMN´¢Öï’ ³ñ ÈT¾®ßïIè•óáBR ÖG‰a Z h1ÈŒBRư"->ộ̣2X“rˆY°Ô“ “̉ơ¼By @"P,À†<䔹Ê-³A¤._¾̀öj$_·rÛ&'$¡_ €tl`AÿüÏÿË÷¹Ï}nç „ƒû{¿÷{ä‘ggÚCïï₫îï‚oPê /!ªlLL˜VđÏ₫́Ïđ§O}êS†ÎÀV;ưùưßÿưߟ¯½öÚç?ÿy:ÿ²B=~"¦ôB>€uñ†ªøR%7EÂ!Üœ"™º5₫ñÿ‘Ä×b0B¼f0î7ó7qͱcÇ:øéùùy°ư[·nl¸®¯¥ÖDà́ç59}ú4đ cS“Œ¥D2Të?ù“?%¨·๨ ÉH ƒ ́cSL5f0ÀTxYw,cÇq‚Ÿ~úi¶ÓÆN{bb‚ê?ÉWüD‘¤L đ,(ªÓ5zÅÊS}?–¶°ÔXLëKYL@ùGA/ å‚F€cënɘ<˜Ó·¾ơ-2=p{ >„ä?â‰'èçbÇ¿øE°·gyFw˜‘L@nÿ?ÿçÿ¢ÁƠ,ˆz9‚1œ¥ ô fÜăI” RxÅ]pp¿ñoàXsØt¿óïü₫ïÿ>äF.…EÇWvÓ3¼èƠ``ù|̣ɶæó¯ÿú¯@.É÷p8(ư²#Y‚•´*+¥’Q'DƒŒ¤#œÊP€ñ₫Ó?ư­¶<:t Á‘¸¬uà¼+́ëÙ³g}ôQ¨ ÈIƒ-îb¡OŒÎ(N ĐHɷʩࠋ·̃zK)!Dô…r륑Ä‚¼>It ́×È₫#Đ{¹b6¬ EÉ x:Ÿ &`ÅØ&Züv‘L¤‡ĐÅF`&T¤Vâ‡É%æL?‹LĐSĐ,ï¡C‡œ›ÁŒGÀ8qâD12»˜̣œclÀ`2¼|ºË±IV‰D£8/œ<0"́YH´Đd¾ô¥/ưÅ_üÅ+¯¼B¡¼ ¡ôÆĂSƯy¼‚đ›'ƒsƒßăƯ¥ÊOă© ÇÁá”PœºnÂ:ÆTQ¿K~r· †Á|̃xă¿û»¿ƒè.DçFn¥RQ–'!L*'º´&œ-HRT†.iĐsÆq©åTÛT¤h>l©Æ×ùxQ¢/i­ø“‘FÅgŸ}Vº²•Oú-Ó̉ƒd.½!“1ù̉´¶¾¾ă8a渌”»$KÜi˜ e2̉(T>˜óc=&]ƒ 2AđÈ8P¯°¿„3ăÅÀxÁºñÄù%ziD¼t̃LC"“cñIƒ'ó=—Œ`:Máxœ„Ä1ƒ'ÇH OˆWP©«W¯bf¤f³̀ 7•ăü({¿ôK¿”„FÜ „7Ä*pe†}ûöÑdXÔ'† ơéüùóTD_&fȦj`hTùE&3É'7—Y£à̀¢”ï}ï{ñ́8Lô*Eư{Á€JvfPå"~<&îƠʾVê Ê`Ă#Óó̉#CÀÇ?ij³Å£n  »’•l$²ñwîĂâ•Đ"#a©"}N9S:R )ïBÿ)³o#2¿Oô)ªÈËw`₫2©CÆ’Ç˜Ă„¨¢2wœäŒtÜ“V€Ü™’tbz¸ ä„KÁ̃)Ö9•HUxiqđ´8´×²g=1mr:ÈùèH0(Å’ŒØP è2lñ!Ú­L€~K¢Wö ¤7‡Y³9›+/öh‘%Î(¤U# Ags磯ä¦2ïÂ,©o>̉æF-ÉÓ3s°¡›“¹’X‘é _ø‚̀¡_Ç™“;'W¼œ*#¨¸4¶Ÿ{…È0®L‚E˜̉«4É à'ˆ~n™|đ°ßä P̉ëđ'ª‹ÂĐâ @…iP‚yÍÙ ¦aâv•TG†>¡€y¾s'éå°jư¢¤€3ʦh0iô¦ßb:B·"O{Rú Ơ0#A¥n:‡², ~ëîƯ»†ä}Ư‡×Ÿ¤ÍŸ&ƒæÀrqˆñÙy>2Á–ÏDB„’¹Å’ø*½H)5HBWrà†‰–`̀&r‰d^Sb²¤¥)K A{[SÊá̀đ•~BVÔ·+â§\½ ·¢sÀJ¿rt¸%‚̉F˜ƒøđ˜T[Cñ1!Ç1"u”—‚v‚sy­ơôzúÓ<$t)â’ºFÄÖÄĂÓqˆ’BLY=.²ú?/í)ÅÑ̉ÑqṬÀ$µ’â%‰Çä—âpwz2­¼•27Ê.HÓ©̣Ô±Ơª 2÷ăs(ô<6ÀÈ)ÍcÔ˜’̉<©±Ó/€²³2̃“GÜÆ™£/”œ eGd+p\L"•lÍ‹áËæ€4]sñ ¢ÁR¡Œ }èEXbăxÿHø¡V:m¡WÖ ¤C£8ʇ§™À-í‰ÀsMES `F’c’(ѪʷbcI*u £m©¯ œ±m–ôê˜Y!iµ*O¯X.Ơ˜œËZ æG¦CF vƠ¤Yj²ü)ù*ôu"̣`´ÄÜ(₫¯eđ,ÛƠ¨J91:Kk¯cJZ 3—̣WÂÔp8©m=;SE:Q)!Y|8‡œ«YºX4"±º²Ø̃Ë[æ ̉Ư¥ ,`Ê'”º;­ ‰»J+÷Ά̃‘1ö̃6g¨.?[ZXÉe4‹À#́•0f.Ä’écœ%Ó3²‹"×=¥oÉ[¥ùº¬ 6b††~’œq–xôêơq¸Ô–,ÙrdÍ:ƠĐ 7,±…Èp®¤:&[ó™É8‹^BWaă±Ă‰•–c¡+SaØÁM₫Ö+¤ˆ¥·"?÷L‘µû̃107ÖuuÄ*R±cE~Ö9°’~,1¬XÿÙVlXwr )ƠXNB¬Y%NêÙ¹Aº‹¨N.Û¡“́ -yïÙ®:˜vgÅĐVrnplwu’oô@©0™ú“ê¿H«r̉eº®›TeFǰ^H€n@2),=pà@l„=v[\\ä1̣…˜kàÀ®’Ä~ gtçØoz̉.n»"B·…Ïévåó5;'B[Z‹Ï$):ÉIµ2ÂXh6Ų~+ªç̀obu] Ô48 Ă²Ô5EÉĂW¯^¥ØniÛà₫T”ƒ.y²ÏØ1Nb¿¸Ú̃ö­Y;ÁSâ³cóƠvfW,Ïqà”Rt’x«ëvX₫™ MøÊÿd_¼ôË7„®$ô*,©'©Á̉M‚4§zXA˜ UERZûpL¼ÔŸeư>…Î¥A¯® ›9pËÈÇ·‹w ]oó¼î4ûí¨i–¥+~`³-: ½Iâ´`Ḯפ@×=,å¯2 uwŒ^ĂTY7ña=.O¯{H́—+§¶%H¬Đ±¼÷íbÂÛçÀƯpW8pM Û´6·Ḱ̉´IÆ-W7•ÔÑCö›cók%½Á̉jí'‘À”k- Wm)ÀÛäĂ)ÈÿÏ̃-·ÂPOưÿßÜ鸳!+¸»lrΓí¤MC}}%!goy²63üïs׋͇×ƠçQ´(J׬{~ÿO'̀Ơ›O=<ơ'×d|Ÿ1–ôê!ͲHœ}”Å.âR—ù\³™4üS&O#Mî¯N%z—%°8_Soú~0¸Kɧ×ßGälïå°Ă#s Ñ~^×¶|X}1ơÍøXœÁsq5k[|›l#Ư•ư.íp₫Í̃™rtqW̉6̃[¼ªr¾!t<È/ˆ±…«ÓĐª“t…!ç'̣ ưø‰ùîràZ íÑ­̃NÛtb]–×ÍGÔóº InY–ÚN 7¶¦̣åÀGùh„ø˜¡ƠRnŒ¹Oéa¹µb[s¶å+{ñß•=Ñ€%àMÔ{YƠêä6üLÈü¨ü@>\Ôp1­ûªBŸ4y4T2¶ƒƠ‹¶|q\´bq”¿7öè›e{‡j%à¨âÖ•‰nøơ&×k¸yÙPÍ ü¶ß§ÉVÆy´l‡‘_Oß/<üÙo¿ö°XMWÚ„=as­|µIå½êí2Û%̣_©³a`̉¥aQÖê+ư>Z°2ÎMø¤.[p*̣éCÁ¯µ_›ư6»E¯©păf ’d“ú㤻"Vl®Æ• u—tù°îçé;×­–q₫m)Û"®ÅÏEçÑu±ø,¦QêÚ~†u•æ›uµÄ&Đ7Â7.îÄ̃mºX´W.Kíă¾h5+Oß§÷eMÆEiƠ 9Ky°b£å Ụ̂U­—­yxº¶Íëp’ X±WÛMî'_¶u4¦̀UẸ̀Æeñ|ô7e,ê^ÿBè¼măd¹éûd#¿![OƯ¬] ö¼L¥ö Ư°¡G«Ü†¿cN₫©ù"Öüʬ¨Ïk¿‰qó•¯Ú*3W]®ä.CÎ}¸I23Ê p3 öØÙù¼ak₫-¸ô<đ Ïß~+–%đ”¥'¿đ(¹Y‹y}ÆóÔ‚U=f¾&ăI‹¿J¬¯ø=ku©Ú^y-ÍH¾è».¦¼L·±ơªÀOÀ\7đ?K¿7t.¦u[ŒßÎÿ•1C¶¢=MÍÑNơæ¸â2y’a½]$"ç̃øy©Kû¶ƯN¬¤›WvƠ†Èlµ¢²•d³½ửë¸}ª¸RVEVZuuÑáư ÔµŸ6é½[½9.8ÆÊî¹,3V<\e6¿úßG'¬ư:´¶í“JÖ•g‘uơ©å†, ÷©sßÈû{n‰kie+Jç×$·—EÔùÚë4ÓMüÎ]JögOü¬3Z-ʹÙû8û}¢€Y™®ĐZ|ç«9„B(Y„ÖÅZWÓŸkêơß_1¦áf­o‡ ¤mM&jMV«̃aỶĐMÚÎØËYIñơ™ĐÚ£̃®VJg,*WØ7«]ë₫,­\ñ³¡?߸IX«ëº»ó50­cFÉZØZº"„8{™dOy±x° c̣læk  ĐT²¿j]“z’ Xb!ô•¼¢R¥wÛ—̣­đ™u¿ơ&£̉Ó‚^áï÷ï«ß$FÂ5B„¶SÏ¥ ¢­㙤+¾^Ă›d³»^Ă«Ó q¡u³pƠ5`ªi¤]–>– 8d˜ÿÀÓJ !5yÄϵØ)æÔÚCG·°§]‡íƒṛµmÔ:ëuN=7 c»ÅƠÁWæ:e\Slïp3MuöÎX.̣†Cè+Ùc¿.9Dºè*à@ë̀9$ñô”"]øuNư·6%¢á¦gj˨~€Óèq¿P; æÛ!Q/ü4§¹ë &çPơJn¦ơ†ü û$X<n¸Û~₫ ̉…Ÿ́À!:H/ª51Ϧ}ß7ÍâÄèˆỲ!„\Ç6 Ë.á,›N!Ôn¾uă§>ûÀĐxrh4É *Çñc¿]€‰’,†k₫·ŸÅä §yóđ…~|è¹.P½öâh¼qH>a¹¡̃t&=*ô$(ŸÑĂáÄøØÛ˜ï{‰‰ ËvEÖĂÑ₫¾³¯{™̉ïù“û?ö‘aƒ¢M•4å—\îà©ưĂăsjâ_ü›oüä»ßééj“fg˜çÍ_x½#ÆJ¶æKç»;_{MĂu‹ÿîëߺïWD Mè¦È"E4E…¯öôŒèrÓ KWƯº¾T*öuŸ^`„© yÑ4² ˆXT7\‘s‰¯ îY‹–;»Bëû¹/́|₫™+wÅb>{®ëD¢¯ÍyYù wbi’O±Â,ñMÉGTơKW¬~÷ûæ4.`Y6›NÚ–UæÙMkXÅà9.7̉b¼ó®{¾ơÍ]{Ë»đUÇñ|Ï÷¾ b•8vסÖgw.ÍHHĂª"Ÿ97˜7K·¾kQuܪxTË>µ+™?sªå­Æ²M÷©̀…3KUœ(MÇA.à•åBZ„Æù Öo|ïªuwø…L•NŒÏn¼.V;«ÑøµknûÊCUÆ#0q–NxĐƒåØ?ưƠ+{·áÎËú+ˆ|X×{ú‡&’™›¯ŸßPWkF“ßøî/OtăíäÙöÓC÷#Îá¨8¶wéÊ Ë×̉z°K@ј&‹†F8mvÍ̉Ë›††G·½ô¢G1ÇŒU¼xDbL©¦åöô§÷;`ÖñI@Ö»ëÄ¡7ªh̃j‚N%ÆÚ<×ơªïØ•UƠ*àAÀ‹f ǘ‚`³ ㆋ„Ry¤kè*÷ÂØÄÓ¿>̉38o‰ù E’x8¬ªÊ‹ëMÛ=Öz¯ͪ²ˆK k”&íǾ‘€œIu¾§ Ƕ_<±ü¦ƠwüÑgÎvµ"̉̃½aªM\×s¼ÿA'ÆĂj¡ävơôok>ÎpB,j ̀H0`c, ÖŒ ÷?«*‘ÊÂc%p£’+‡3àÍ^%­ˆÄ°`éÊ“Ç>ºí/|hƯ,’Y”3ª̀Ÿ\*—û÷ŸlOç¬úêÁ‘±|.ÖC¬È,FẠ̊3·:v¼£÷±çö}̣®÷À ̣%z‡f(r;…e*ß{æƯvûÄÈÜó‡ßô‘Ï̀äiHỲñD_!-TS8Ư7R*¢×/h<a$Í•l„$Q„µ‰„Ô_í?±ơåVäLÇ÷P¡R¦E—ñà¬I¡œÊq`5³æ®ºó£Í[ŸZrĂÊeÙI`0¼êB,§ë¡¬™éI‚Tf×Vñ&̉¸Ü‚†ú±8ÅD˜éºé aÿÜ®#‡[{5Y²'-VD#ăÉ, SFE†(«¼ ̀,0çï₫ä—:N¶ˆ\ÀÆÜT–¤o[r]ưÍMMơ†"'̉…‘d[÷ù”Yô&¤ë²]G‚Eêḳ3›/"_'­=G;Á(  ÀṂE+¤©¤µJŒ„M C¨åfXỌ́•¦'œk{yĂƯŸèêOÀ\º¡„ !cåtv^H'o¸®qÁœÊP,ª¶uơŸí1y7R5UA¦º0’¨ªˆTČ֮̃}ǺJ¥ê#¦ă×!e;y»Ú÷ă©2áb5%IA`ó.Y¹ñ}‰DrƠ†M½Ă™Xèơ+æÔqŸ+‡ÆƯç¶:,–̀™;·:>~ ˆ§ÚºG ¹x,¦j ¢0›Ë§sù¡‰\" ]¢øÖ4ÓvTØ_ h́’pD½ùĐ.‚h‹3Uh̃ú÷ßr×§{¤…)FÆä‡>Ï̉¦…Q xÍIÅ"[4ư9³ôL!×Ñ7By/rX́ñÑÄÀĐ 0ÖOtöëđ|ªP(@:fdS#¬K¬¶·¥%*`ÊƯH‚z´yëÏá¢Ól1ä»?ö™xÓªÎ̃ ÈEá‹ió ÷o ±¾Á ËvLÛ.X%²›DçÖÂƠÙ5\[w_ëé …e/¨©­Î ư%³8‘Î#5$2H å6…´†œxêtoM….a×Ă2>ô\(3¬ˆäa[Óê¢$üϾ̀T-<ÛŸBÂ…† )̣ÚæÔç,Ë-N¾`J&xËƠaQ\¹₫F¥¾btÏÑ̃t:çxn(1G†`%ßs¢áèĐxđAF¢k’ÖƯRih°$°È° ÂGÅη,½^i{åÀŒHü¾/üeQ­ËTD4Ȩ®^?¿v~C•0o˜PY³Đª!UQÙwMϱ´ I8V4›µv¤»rYD *Åø¬ÊHïx–A­xådêc€)Îl™Iˆ"¡ˆL‹Çc¯lÙóâÓ—è4^6°Y³ç}îÁ‡‡mil$íTa]YvƯ¬ˆ&ăé>R )±x̉Êæ‰¦…ơpHç8Gä̉"#€'²VQc†<–H›¦Í ²YH†£±b)k1₫T¢¢¨I]¹DDL4ËÅbú¡—¾́àK÷O/XÓ̉›üÛ¯¿̉=Éfâ($b§i^m̀Pˆ̃cđP:“.YD=O*6â$î̉÷¥] +IB*‘ÇüdÀΤV ·Ü1"×QÄ% ̀²ơ ¥™X$¼ơGßè;Ó1}ÅƠ·Ư~ÿ—₫zoÛ ÁJ‚JDhÍ­‹WEB /œ£́u]K•èª%•Á̀‹!g†WÊ¡‰7Ù(Qw®›Ë•´pÚ˜qÛ³I[§̀“²¾5ö><i¢b|%/}₫—ÏüW>›™¶m¤H¬̣®{ï×WŒLdP̃ËSâ{\eT‹:¤ÍDP<¨(®´ơY^Jút.—Éå³ù<‚æÂXnŸyvvu¬¾2\‹û¾],"‡“0G M̉º°Yº¬Ër* 9A(víß̣X¡¿lưp‰¿ƠÖÍmX´lÔt `P³ĂïB «8ác‰$f ñ[ È)‹ªêŸë ˆ×¨GR9̉FɤgÇøỏÜ™®àʃ̣̃‹t”GÙ^„Ûñ¼üÀñƒ/ưÔ²¬+H¶—̉¤‰mD.&ÂB•‘´¢:jrÓ€t a’1c02 Ïă91¦)céóy3Ÿ)P‰Té yV#Q EJƠ¼ÿ`É¥̉)³:®ƒÄ!, É&SD£ÑDçƒ[ŸrçÊ´Ñ¥€!₫“£ïø@,b”!)À¦©" ~”†&Ă- ‹́zùeTÚ+̣bcM]_ÿĐđxç̉5Y‡ð‚⡃ͩ„%°̉ÂÙƠ jÜ€µl(–…©e»x\ßÁ§7oƒ"¼b)û{Ô}!— Gâ·®[£É‚ª ÀDU1ÈËi•]+Ë|¿¼ ¨Ùœùè÷Ü»½¹aö»"«ˆ.ÍM3“Ë_èí,®6¯Œh†®B©¸>m9^Év,×Ó$®{ß“í-üËÜM¿÷ó§¾úƠ‡ U$Û₫"Á¬&HLÄñ™|áø¡S?üáûvm»đâ`÷öçfÏ›ỵ̈î­‰ñQI‘Û1b•È»¡PX ¡äG­pr q;U‘Æ.ÿ'W®<öï|¡ăẴtû*<î< ‰ \842ñëÍÿà‡'[^.¾v?.đ7m¸ñÎ5×§3Ù\®Î¤ ¦u®¯'—Ë^è(p§e«o§h͆Z)áû3ÓlbtđÑG₫ăƯkn¨Œê–‡E·¡ø#£‰Í›ù³'̉{¶³T|ưTF̀­{Ư?Y®?046‘Êtôï?y„´fù,-ÈØ₫œç:WÆ‘;wî;üÑ̃A~ Á2=?x́G{wïéî<é_̉yêgÏư LSƒ"ÇÔUG‘U4Ym,ŸW½rqă’ysÜw¤yçUVÈg₫ùÿ!¬Kù|öÇ?ẓà₫Ư©Äè›ù"Âæ·v²éÉúøb¡…²º¶:̃̃7‚DKÓlBÓ/)ÊUrÅÉÑzüÀ½üÛ‚º ) —;d$LJöIHxĐd#“¢E®+Îj ¸3S°Ï´ŸºªÀÈÖQ.}¹ Ë]è€*2ƒ‹èHöóáä‡1ov¥À†eXáù矸ÚÀ®`Ä+*ˆÅÈ.3uq7¼¥\’ÿÎa7̉î HÑG &r»·nñ}ï,B~lC•n̉ddبO¨lÊ€T\¤˜ôü åø±3mǯƯ¿•Q.‡©© Ub1’‰V¹ØÏè²2Tºà?·ùñi1×ƠF‘&ñ=½x¶]FUn°M¬E¬Çp¯´´œ~ơèt=vfảiˆ$›ôªèÉ*̉§§pÓÄz邽kÛóV©øÎÆr\$K¬|Áœd|º́ôÔ¶ädg°ÛÎ?´ç¥i|ồƒ÷Ù® qè:̃Ô¯t'·Wƒ©³:f"k½đ́æb>û†É# P‚§¬ơÇåÿo=Ư{x߯¦÷Á3 LÓt†em²9LA .6BË q”<é¼µ{ç®ÔøÈ; ',ùA#Ù÷™Ât±{Mj¤%>Ó?úüæïMÿ£gÏ£¼’Èv±G4@ ™’ŒøÜt‚;v¤'†ßaÀr™Ô¡#-F4BÚrd—‚¥ Zl‘ KöXçÀ¶gŸô§©j₫­àéüUÎ3߈DE a1^àEIŒÆâªf́̃¹mÇ–'ß§₫O ¦®kăÚx‡ÿ`¹̣@ e€íIEND®B`‚spotweb-20130826+dfsg2/images/touch-icon-iphone.png000077500000000000000000000071001226620506000217500ustar00rootroot00000000000000‰PNG  IHDR99z̉tEXtSoftwareAdobe ImageReadyqÉe< âIDATxÚ́Zipg™îûî™S#ÉÙ–dI–ß!ÇÆHáTØJU*›,¡vSÅđ‹#ûƒe«¶BÁfwk)ø±Ä !›Ă‡œĂe;'¶EdˇNë]#4£¹gúî̃·Çf8@¬8)̣UY5ƠÑ<ư~Ïû¼Ïóµ1ä/gacưë_VâF|Ạ¢È°ER,Ïs¼à“ư², ùᾩøØG†ĂqfQÔ…H1 EÑ‚$E¢u₫@@E9đHR8„‚ùBáøk¯|îWÅ|î#ÀZ߸̣Á¿ÿZSs3E⿟ă8–"¼IÇp £I…… 8†ªº±năV9ưÙÿU©Tn(Öh}Ăÿ₫_k×Z– ~†^1́¹±„ªVLĂTMP’Íe››WÍ¥2Ñå­pt:>zC±nưÔ®wF ]oÿr²ÿRÊEC×-Ó,• €p†\±,³¦¾áë>^ĐĐ¹ùËr7a¿øÚ™ Uè~µÓ4Œwư6üíĂ´´®"0ŒçyDZ¢ËêŸ>Ú“Z̀î¸û>U)ÿÙ&Ă¯#V@#F[p‚´̣3ùlæ÷µ~ëm=ño÷̃ó¥¶ÖöÖ–Ö–•V·y%éđɾ¹TvÛæÛẃÈ.¦SKÁăx0Rç‘¢äơxe0 Gå@~ ¢än¨®¿[0lYûÓÁI55;¿|‘aØ=÷=øøhkYIEàĐ^"G*JÿøÜd239›l‰Ơt¬jÚyç熉§¯(†·tljÜxFP˜m ƒb„À Î1ỚÜÄ¥ =ƒ}g“‰©ÿÿH&5/–Đ̃`ä,ÄV>ôƠG¾̣Đ¢À"¶í †± 5>“z½wÄ0€WúÚE–ú̃£îÚ±ưŸ¾û푾k¨+ôq*9“GpÊ |EƯÑLÛv0₫á´'mY³©cư–ØË4 ¹ |¥®kk6l¥Å nVF.ölÚö©Çøă»wï"¡ŸÔ˜$ ¨¯÷ ́?Ö­êVXöAMúF'Ú–×v¬\æÙ€WK'gFûÎ^_a£ó™ù™á^=3% œè“i/# Đ{ĂPÁëk^ƠvÇ®»Önتf>—ñ‡"rm“ÄS[6¬ûö·¾ƠÔñB>A3̀'Ît¼)¥i’çØ‹CñúˆÿÓ›Ûx†Ú{èíÿ>đ†ULN _\€¾Ä/]œé_̃²º}ÓË;¶à$TÊv"<<ë“ø¦Ûïܹ½¯¯obfN§…Uơ [ÚY†vC1"x–Ÿyé­ó©\9(‚8v±X„Á1´ UÑŸ>wüXw¿À±˜₫̃†^S§“$ƠÔ¶nƯ'w5ulDAY¯ÀẪI<ă8Ÿ‡‡÷äKåJE¯(*”ß˳"Ïâ“ç/xgĐ4¿Đq’Èá(¢ë*Ø‚W̃è±Lú÷́ĐTÈ'2ifF÷ÿüɪY.‰ç£ưgf'.Q%¶‘¹é¸•²I÷à†ưÍUEU9ṛâ‰!#`h„÷ÓE’¸_–cµc3É̃₫ÑTN‘=n ®ơŸ9éÀ«> ”Jy ÷ôà¹î£ơ±{úf*9ÛÑÖ²}ûíĐæ¥ê (pF“Od/M$OíJ†‚~(0‚E‘€̃ F!â÷L&̉ X¸C‘w¯Ă>£âè{mø̉ư+ÜwcsG"1·03æơyTEß”/–Ê¥R©RæY:±°xđx·b ±V©¨ giÇ1 ÀĐÿ{øÔOë‚e(‚"`oª”ÆÀíbèơœ± +Zn¹mú̉¹úƠ·¾rzäà[ “4I²%y%°©–e8v%́÷IÓ™\¹¬ø}‰gUMÛßơ›̃áÉX4‚¦̀vlÔq[P̉,OÄƠSz‰XÁ•~̣Î/ÏÅư5ơ3‹đT>°¾5¶¹½ÉïsåsC³Ùéó U(—=<ß«+”* Á‰̣ñß $̣ÀO(!† @kʵ‹¸;„pljëV×5·YTÄ©^ µb+j=^®Œj¦ăíDC}4H'ûƦMơy=0 € u¡ÁÑ©ĂoŸwPÚø' \M(8Â1ª^B,#I(0IA)èr©øA±‚Q̃tÛÆ ;›£b]CxÏîÛEI¬˜z2;saôੳu²ñĂ~©É™Îåê¢đÁ“½Ă Ù’ªé’Ä`(J@‚ iĂ4A­«³Ír(› q¨}¥\ú w¼û̃Âk?“®`FƠ…ÿø•/’œÎ–sE¼ªWẴpGS´bG'SR857›,”̣EÅè'³ű Â&4¾iÙeUJeU±`ß¡Ï\¾âhÏ›¯\­Y×€•aù=<Â4¬Ï—t˜µ!éó;7D‘øtªPP²™HÁ²°¿¾&‹†W¯ŒP:2™.–'̣™LYUIËW4H ÅhXJX¶•Ï êJb Væ“åÑ̃ăñ¡‹Kç«ï¹ÿ o¬TÖB²X̣­iª]V,+Zu7 ˜7<Ëúx/Cé,• iSsƯâbùøé!(8N2,‰hª–›» Hîøp…>‚9 —0ŒôË̃W÷ö¼ƠuuQß/ÖØ̣æ¿yø)[Đ*:¤5+ë<Ur0Ơ1”9¯H‰¼ˆ¡%WA'9‹Â<`đTZElŒ3dC—c8‚¹Æ½¢§€4â/ˆÙ±g~4Úßû@ßÖ5ë6ßûwßÏ[–nÔÈ¢WâÚWDữM¤å}°U$Fáx•{ºƒ’a9ˆ Ü+đŒ^ÇR4eÍĐ’DL(- Vơsˆ,…ÙûØôøđ̉óÖ¦mŸ̃}ÿׯR G"A/Ç̉QDöÀ ¬+á8n04²_T”ùÅ,Mm Ë8œ†ô¥ øCpWƒñ¤n…¸ă— û2H­NRœbH»|ä©¥æf–˜ !ĂܾóóÛvß?‘*{yÊ)° íZđB<Å̉8ÏÀl¤Jf^±I q¦PœKå&fçÆfî¸e•,††ÀäñúDÛ6À¦CÀPhx×ÿºxQ’á%Óơü¤çg—˜c9^¸mÇ×́Ø“*ªŸ ,$$0a¿̣± „Ă瀪¶3™É•…ùÅâ|&—LNéIt4ÖEd©&®¸±̀†(2ES¶eă®,GQÎ̀N¿yà'ï ’×†5¶¢uë®=éYă¯æh e$ÀK(Áç_À)Tz*—Ôt+_¬@uY¨hF2“‡™´P¨L%æE EÀ²¸©ˆ ml hVY:ưâSWϧkĂ:?73u©¯iưV&="ºgIYâÀ@Yvđ• °dN^]ë(•ñ8R^BÑx¯,gRô¹áÁñÉ$8׈_âh̉°lĐT ÅyA,MŸí>̣+MUß¿ÀăÄ¡–Ê…ügïúBMÈë—XPpŸ¢ÀÈ¢‹Lt±áÆB`B ´8ŸJ$hÆbY”åÜÆ^HÏ ÷ ³8ß´,« ©è« ZK‘Ôâà‰w½ _•Ú—x–QÈ-Fk—m»u³ÀQY…ñö’a[jÓ$¥hÆ›'{¿÷ưüç“OÊB¤µi5¼ n%ŸÎäç ²à ɪË&u)*é ©Á×Ïœ8hæu;…¼ÖợÁ=÷́©_QGàồD˜4ĐÑĐ$N¤2¹£Ǵ}êúÎYXHB¥ß8~heë¡̃r©`Í à8NàÁëñP¤Ç5¸ ¹8æ\ç³âñ‘¾ûö=öưïĐ0«1Är,ˆĐưCăû¼¼ÿùg‡û/ÆïöÑ2í·¶Ưư™ ét¦X,+•ÙDb1›™ŸŸ*¤°Hó&Í´}´ĂqÜ̉ŒèŸÂ ߽?xÿ-í+,ÄR5ăôé̃C‡¿Ôr\Éüƒ’Ñ̃²~"-H'E›˜œ}ù×ư$Vǿ'ÚưÈç†Îuë\÷uÏ}_M,¤ŸÙßy×Ư_®oXîJăYk×îyÏ•eÿÊüËÏ^üçŸv Ç_ïî«©}(Ï ^Ü÷‹_¿ÙU.å₫́I9Dzn´CP@y%‡^z0½uê£ư3#7ˆºg3°¨¯nÚ€ơA…Hí&_xö—Å|æ£ÇZuḮ9T†-E«×@LÁaCv˜YȾväĐMñ,ăDh*0.®[¶ƒ]FZ5ưê~¨svqá¦ÀJ³l^5Keú Pºç®ƠGY`rÀûÇ ¯|Ö±­›«CL3̀ßÎÏjQÁܸgS&‚uvvÎÏÄo–ç±HmEQÁ|9W²Ôe»=ü¥ÏÙ–yS`…X6¥ú´À^NSöe颿Ơă]c½7ËsnH«¹|AÑ ÇFÜÄúb‹Á Ẩymß3¿wqÓ`úçŸ₫ùđà€ˆ¢äơÊ Ë°<_‰v¿ÓÓ{êØuĐÄëovÜfªYTM0¼t.Û‚¿ªơñÿwùpÖÿ 03냲$ß^IEND®B`‚spotweb-20130826+dfsg2/images/touch-icon-iphone4.png000077500000000000000000000253751226620506000220520ustar00rootroot00000000000000‰PNG  IHDRrr¿*tEXtSoftwareAdobe ImageReadyqÉe<*ŸIDATxÚ́}€]e™öéưö¹wúLf&=! „PH *R~Et׺Ö_,¨‹‹₫¬ «»¢ü.Rv© ªH‡$Bé…I¦fúÜ™Ûï=ưœÿ}¿3¢¿º2à|Ü\n=÷œç¼ßó>oùÎPÔô˜ÓczLé1=¦Çô˜ÓczLé1=₫ưN;ö}°,뺮¢j¢$[–YßÜÊqÏqÉÚz8fN^Y÷|lthàïÖƒxñ‚`[€Äôr)U×ÀĐ´ièó/UƠPª&ƠØ2Ë(å“UUÍÍíÏhn6m;RD^®&­&C3¹b©·`å£OÜ}Ë#}ÁÆÿ^`4—.?ë”3ß#𬬨4å)’8cælß6LËReIÓT¦’‰(€åØNH“ Óyeh×óÀH)ß‡í° CQ>CÑ ËÀ+ºiçËF&_Z»aÓ ×ÿpï­/°̣¼pÁeŸú́¾P[P4U±m›cYĂ Î² K38ß< °Y¡É+4Ë̉äE ơ|_€ï°Œăx<ÇÂ'=ÏÍ—̀\IÏÊù’^¬»÷îú₫?}Âó¼#µçÜ”ÅĐû́×®ºâ ŸEÁ÷|€Éql ó\Oä¹À(`^[¶Ë± @WÖ­°Ê¦[([ËUL‚É_2˶=ÉơXH„ ̣~¹¢g •BÙ(Vt5œH¤ªÓĂCï|XÏ|Ï…_ü̉ç92u‹†M,ΕLÏumׯT,Id ˵mX·PvLÓv<›S Àê¯J$úz»ÀOÁûº»K…qAæ,X̉ĐÜV[]gê¥|¹\*¹²nZfăŒ¶w>¬’¬|ü3Ÿë.îØ?ËƠÆ¥±ô¸^Φjj;Û÷ÚfÙĐ+ă£Ă`ȶ픋9Ë4ôr™xUj¨¿WQC`Úz¥̀ ¢m™‡z<3ç-üñ¯nEe<$P)WŒRŨ©«?‚û?Ea%’.#ỵ̈î'öơôϨ‰nèY·é¥Ơ€@2 ûk_¬”Kp_,ä‚§®ăLálÁùèÙß₫âóO~à’ËÀZ(ê†m•J¥w>¬²¬¦óæpzü₫HV?gÙikŸ{"xëo`z訪®}ï…—F¢Q9.fÇ[\ÏF"¡xr ·3–ª•Ea$“LK:ˆgééçæ2ă;6¯'Ă ææṾ4ºuD’–¨{]_?ưÜ÷÷»WÏlidHÙq=EÀ\iÏç̃q—¦ÆÍbÉÈJ@­¦e7¸́KWưë#÷̃öô#÷;¶ư&÷Ÿ°VÊÅ%'Ÿạ́¡L¾ÈñlXû^Ư¢WJ‡Ă—ù[ß¿ê;µ5Uà«@eûbÈˆäˆ ŸP öö÷ ŒÂP ­ Ơ¡ºèø“âÉ$hØ7‰́…Ƭù‹ØPr0ơªÊ¼Léº÷ÿí¯̀Y¸ä×₫́.½\Dï‚LÀĐ€I €àÀ‚A½ĐåºÇ÷vö‚ æ9&R«<ÏÏ·`Åû.́8µa¥ßHĐ¡jáæ9KFÆ 0me‰OiÜÎ-‹øV\đ¡«¯¹öäVÅH£UI|S0[ñX0¼"lËEƯnïîCkuÜd,ÜÚ‚O‚"NÄbgóÛ÷;^ƯsĐé½Ü .5UÓX.¢±́́º ©™ô`}ă ǧ"¡G±ù́hmm}±TÑ4%“Éô÷t 8üŸØ¿gụ̂ ?-ˆœ$G+‘x ø‹¾́S_üÚW¿ªyOpdPđ‚¨r=¿ú™O~̣̣…sZÀÑ#đIß#¹‚;•&; ÀËaK'„ˆ)Ă;@D›‡A Ào¹.̀9´p°_Åwq{ 3«©₫7¿₫Ơ=+Ϲöª+Q|Ià@wûP7XÊŒù'ó©™«« J́fAhăM"¤&Tt"q¢mKN›{üÉù̀Øî­~ô>è ơÿ́' Cêëmh[6–-@øi¸àåS4½7ö‰TÍg¿üí¸ôâd úđIÇ…pÁŒ,ËÁiÍ2†Æîù㋦í%‰ •Ap¹Ri®¯Ưµ¯ >®Ê‚ă8̀2B"H²'Àg+¦Ơ5æUU×èê8ê.ËóǛØh×̃-Ti´©¶—Ă6…ŒÆ¢¥â=Kî´ #ĂëåypP'ZfÏ?cÅmsº¡çŸù‡ºÆ-ó–æ‹eIàaCaÁƯµu#@v©gưàGÿö¡ ß+<¯¶å˜–ÅsËu/ çE+ÏI’¸n[û¬†÷a ÀnË’ gÚ§ÜTUD]ưƒp2tÓúÀY'ÂWÀeÁfaªÁ½" O¯ßuơ/WJ;̉½#“=ºÖzèèxuÜæ.\:{ñr¹q¾KĂœ?êpĂ ©º .ÇÁ á¡99¶ă-KÊ’e§-=yùĐĐèú5O>ưđoMR 3ŒöI,GÈa.i›{¸Æ\ú‰ÏösMMuº¡ă)ÂÄ ÚŸ‡‰Dpƒ×82W€y@YƯúÀ³[ww+„‹e]ÛÉç²ÑhXUUØB$¤Áæ…áô@T ,T„™Åq2Ïß|ÿóX³N*'p#ƒG] üÿăƠ]¯À­©eö¢Sßl[B0 üRÏm ¼`â>hZ–ù¨ªJèlØúêäü9mçœñú—^غîÙ¾î}ûöîàyZS$t\ÀsœxÍơ¿zÿùçʲHùàÊ`†̣°Y"<‰¦Â® hĐÉ×Üô„çû‘HØqíà¤Â‡àœ‹À’~Q‘[ë€aa;@_c¹R<(Ă Èoydăî®à'`×#ÑX!—=6Áëî}ư½ơÍm'ŸưXĂlÓ¼l€/†=Än1-- Àd`h y*đL4k¨I,9nöø¥Zọ́æ—ŸyÜ ̀X×÷Áfk«ŸÓÖ(°œçzúäà³›ơ€ÉôđWmÚưØ ;C`~Àóˆ5Ø£ ÜĂÛ†[¥¢çsù¥‹› ÓÛ,”*đUà}˜†mÿâ'·́íǺ7zÆwèP4z,s@^`h}Ưÿ̃2k₫iï¾$1cĂđT0ù©\Œ|À!ÄÜ@=`Œéû,CƠÆĂÉèñó[/½àÜ}̉̉ŰÂ_pÊĐP¹úÆ•eĂ"”EÏK¹Á₫®)¼‚ơíß¹97Ü[S× i‘6đ"Ñ.p¤*đf ăy¤G$J|F”Lơ°*5VÇO]ÔqÑ®®¡¡±|*i Ø+‚Êbxögyκ­û^µƠu|(S$ZRŒ£“ÀË:(J,!¬;³e¬á± <ÍäK<·…ø[d 8O¨@YÁƒ̉ni¨³}ÏÊ ˜ @û{¶­_•O¸¢©ª‚vJ‚"L€Ù‚³GPYÀ‘#¡'KÔ8 `0§{2ßZW›Œö enûĂËƠ±xH!’ƒr|÷±U¯¼´­k«ÄĐP̀s0÷aøY™hâ9â¦F¡D´ăÀĐĐÈ|+_6ˆY£‹†¯ĐÄ2à )?>°¯{ÿ«S.ƒÔ5Ô×½aÍ“C:Êx" ©đó(}h&’Aæk¢ Q!EmReP¸p `Ú×ơ Öl®Mœwê‚&?²f{]2<’É̃ùÈÚ®1ɬ±$¬Â‘È‹…HŸÀ…âƒÇWág±æØZ[%ˆ¢e{¶ï̃§6h-›cƒ&†¬í›7LÑ46Ä6»·®ß³mLÄ…'œªå’¼¢/]Ơؘå+fM<ÜŸÎ'¢j2¢’QœOs]t%¸'0¢Ñl©©&¦¶&‰+Nœ³µ½ó·½¤( b ø¬„zƒr½O1HÓ‡n ¬Í™eZêRáâø~ª* ¢ÿ0‹ĐckCB7´XܦíÓÇR &çzyóKÏ}ûG7lÙ7<²çÅmëŸGăß»úG§^Đ5Uµ@±Ú01…PbüÜM†”ÁI¶ˆµ]ïĐªøT„bơïüËơëw PÙ=™ôđç]ôàs›Ñ#ù>À`c^œ 0®gmÇ›r}|7h{x ßÚT—w} ¼TßP:œsểƯû»FÆI°â»n8¬xƒ‰̀‘ U‹îï¼ă‘ak¨àH̉k_Oÿ¬–Æ₫Aø9ßshÇ´"Î{ 6à5¾/)Úá·¿1ÇÖ÷\ø‘Œ§Ø…́c¿¿ùÊ«²~G—@|5`ư?$ï ̃\ây"<™ÆÚdu* i(o‰˜­XNM*™Œ†È̀å %}ư½-ÍơsÛ]ǃï{KÓ¶Hºí.R_í́»åƠ®OO$*(J7¬rŨMUÙ‰€]—¸(3ß>¦{€€0rs½êÚ×ÑŸq `9oñ…—}zóæư›ºí’\>XpK• ªÉÀyc›Ÿ_*1Y[:§eÅq ¯¸h…›q.>yÑÜä’™u©¸êåQtÅtI©®̉¤xöµu×~UçŸyBH•`K“‹ 3\EŸ]·íî?¾L40=I ¨‘!¦’ ĐtJ·ëjCH€$¸–ºÜú¥+đâÖ:·Û4Œw½÷â§Öí$î"). ÿSÏœßZÜœ&8樢3œÎ’Î̃QPÿííéB¶V9…Ï,@ TjmMr,“Ă$º" ¥Ç-ÇY¶h̃«½ºå°$¯c˜æïßÚÑŸ â1j"Ÿ†N^‘¤®₫áăZk`® UêE›b!º{£‰€éPƒ‹€µŒ‰|îT‚æ¢|f¸Â”Fyô_Ưöû'Öïæó)˜¶p3mç®?¼XƒÙ͸§,uâ¼¶FP³a™-Ô:aĂÆÍƯƒ¾àq Xè¶[_“4 ½¢›`wå¾½½{~[C±bŒe Årù™µÛsxK™HN’Œ©Í`h»p挖úĐqS}2«x¾å;đ1đEËơ]†bRµơ‡ß<đ–ö @ÔĐ<«â†;6=RßÔ¢ÖÏ/”àđåJ±Tn›QṣIm 6œºlf¢^̉ÂbÅÓ×mëx~Ăg7îlª©E´bY1TSM¥¢…¬9–ăHPjÙ.0hÓ¶ƒ¬ÍÈx¾&wû·x¡¨›€ ‡1$Ṇ̃HTP¬3›TM̃º}‡éùJHfvŸ[ R È/ ²«lyyơa"ûÖYk]Sëe—.ªé´æqÉÅ+Yµ™Å̉“ư‰KÏ<{ù q¤_6L®ÜBScÙ|:Ÿnǹƒă.ưÇ}Ïm¬?넹4Í0ù=oá Íb»°gï~Z¢ă‰Äư¦KEĂªçxÀUQí‰6sÊ’H426Ă)íù,zDtó>íK¼è#ªoܽ¿­áMS+Qe8[ —i—åÀ «Ă¨ \/ʦnL-n=á”3?ùơ¯¯Ú2°asº®*¬TÍØÓ9˜‚“¸ñÚχB påc™¢ ª ”å–MÛgX‘‰î́Ñc!{n[ô¸9Ơ]ùÿ~bí©óÚꪢ†éXe§ª:<Ëniß×u ÔŲ|SSˆdÓvåS/÷—¢ÑD©bPÁ’O²QA¥†Bû£@çÛª€Fí­¯«.JÀ¢ ©Öº–Ë+ÅbP´g^›B$pÁ¥Ÿúđ¾pÏc»Aúh2ΧPHJă)ơª¯ü¯X89^(Cpå8åb°í9à‘AÛÉ‚··+këaENZ”¥µnWWB[I0-̀–hM ç³ ¦Êù|‘ciYQ··÷́ëK×$£¦Ce³9 –HôÊEZR&ÊÉåE Îe[Cª¿o ›É‚zØẻ™‚†ÅÈ''µ5UçóI5Éh¦ÈÛ ₫Ç «áRH Ơ›¯è– ¸:ÈÇĂUJyL¯B<ÚƯ6L‹ÇØƠ%MÖ!Ăf$eIå—àÔH„­¿ú±HXö3Wéc¯k=Ü‘·ÖùK–ßz×=í£•ö®a$¸hJ ¬$H‚°l~K"¬qØØ®‰HC¬‘đ<€¨²Ö¤XXL%"ÈÇ"j*ª¨ˆœÀ +ó4+0\CMo}4jÑÀ(P,ĐˆEÓQ-V,–‚€b ƒiÂ>H]Ó DKđC$]M½f¿èÄYØ¥@À{˜êT¬<ºû†}ë­èüăô^{Ưµ÷¯Ú5˜Îcƒæ)`?1ÏiPIE”¼Î:wó092gaî{yÎZUfd9|±<‹YúÀÑÂD¶̃we>¬)¥¨˜ª̉¨aƒØñà`cjäFÁI¬;€«¹\‡8(ÚŸtF¾OMÆÊtàÊHf+ăđûä4Ó`₫ơµ‰W¹wơ“¾‘Ừơ]øáÏƯxĂußø÷ûÇB́&ë€åÜ5!8P̉Á‹AµḲ$ ¶8̀&NUQ%L&#Đ.!Ï̉,Åø”ÇP¬å{@ÄÇ’ù̉/å#›.¬0 ®JÂt‘Ç,”?oUL, 3‡̃ơ2E~Áü?ƒLˆm®‹8¨¦†Ô}¿ú₫áW° ¬ú§¯ÿ“Ÿ₫Ø—ú;˜=ØP×Ôë«cöp¤Á‘'}Å:.R@:àỦjˆMp2H"´dÛxÀ"p´Hs6)`ÀLH F•¥Ævô%áEV/BtDé®SÂ_¦P„=~`IË M :q?±(,—à‹₫ky ́ô¡›ô†1=2°FăÉï^}Ưéçœư­_< ËA_  Đa›)&×%£8÷IËvX½vlƯ)đ³`Ư,)èä`G-P"!Lg1[*“Ô>èLâ›ê[×m[k”¨đ^̃wÑ´][ĂẰ€—çH?‹Y!'-ÈLcΟ¸̉hCªVH±ÁâY{ëSÚo®¹¢XÈ¿L̃¬HÖ4üü7Å›fƯüĐđ1²*‡ƒ¹âlÛlx¶­1¥`?΅ºÀ ̉~ [äẻÁ’~ϲƯ´*†17¦,0 ‹e;}$†v "€‹NQ Â¦Ïḍ#z3‚Æ̣–ù”Î'Â*i‹ä‚.F4.âưƯªăb›(pµ¦³,¦zå‚í)*dBêx†eA«›f±¢²ÙBåñ—Jóóç-[Ä̉ ñT;lY~Å4in¬…óQ)4‹> ‚^ °ĹFA÷†Ơ>d!´É¹l0dƒ́f¦²[ăÎ^wơ›_èö¦HàƯï¿́—7̃ø›G_6L[î©/â2˜ơÎ}N¡JØ ¶ a•Љ1’à‹¼Oºw“r,̀ÿ1}Hàª`ú— ĂrÜn–ô X ²Ạ̊†ƯƒÏm~µ))ÄTÉÇ [,X=9ƒ*CŸ-»÷^’…ñl €¯¯NåJk!>ú$Êsl̉ÄLZÈ[AÎÅM+Vÿí7\ûזѼEÖú¾K>ñ‰+¾ø‹ûÖà”'Mñ₫kv ¦^*F™%2ˆ&Oăj3èp ª(8íCÜa»̃D@‚ă@cṂĐÖ'¼ûÈbúº­UƠ"§Ÿuî‹;:“qMBĂDt$[ô1ç̉² ~‰Ñ́³Œ†Dƒ3ظÊbƒ%&₫„E5/̀©¿wpßp¦3i(ëz:W0MÀl@E²ăˆ8 "N¤JlöMÛ-2^f_—®Û&í̃3 Ÿ ÉR¦PfI81vaËßÄ…Z0Tc¸€qC*ß³á¡Í/¿pd/~óF¬5UÓ$’8”&Äû‚* Ao- , BHâaèTS„°*‘8•,A Z-‰âø ßấÅÅE|́¢Æù*[êØ’Ñ̀K lÛ0-°M†T¹é lÈçy`›œó̉Æ0i E+pî ±ÈaF5(óÁ €ÉAbª€KQWÅ´Îu÷oziµä®Ị̈Æa>°{ûÖª¨¹(‘ƒ)km0‡Â@¤Q hf3²܈nh è †#é@\dFŒf¡wʬăkBtçàKc·Ơ'+*Xt"…0ô$ÉĐ@¾kxt¹Ø³}ÛÀŒy5}9x¶l –‹‹]h:ˆ¯ĐAùëCîî́¦äª»~¼eưÚ£—k~}JÀ2|.w̉igĂ´—‰R…XHĐTÊdơ †X¸Z=ˆ¸Ç’~`²<)¦Ư½!b³F«^sª!¢(ƒ;û°Ü/̉¨~˜Ú<®5À^x ·ÅÓ’ê JH̉ïøï‡ÂÑ„ Ă#ù"ÍQṣ‚Öñ‚éz¶Ỷ-xlŸt2¶ă-_Øđ»¾?<8@ÍñºVzd`Á¢“ZÚfÂ‚× k˜ú/„ÿ"<Q  ±Ö ¼L]àʉ1ó#²NB?Èoø¾ă¹1-’P¶µï–…¦g1\\’ ̉ÛdUåƠ#‡@jÈ\æ̃ûd}EPä¡ÜüÖºÙÍ5‰ˆ|aºh’¸¨ø×²A,ƒÚ‡“· A¹ùº+s™ñ£]jz#º5;6~î{ߪ.ŸÆƠv`JÀJÁS~âqđOWpd™´çRˆ-ÉvzÄLú |E7ƯÖmw ÙÑ£ «ËÜMơqƯTĂÓøÎjé—?¼̉=̉BêH††^~汕§¿ë¬Ö–:²ú ưxäDL€î̃ ̣í(=:®çăG>½£gøÅu;~wÇ­{wl ®²êɇN;÷Ïå”etT©ª™Ơ`)ºçøă¿¬vI’%(¡03ƺ¤Á‡è$ÀÜZé7ÿçÇGCHáœ@OÇî—Ö®mmù¨‚"düˆ—í͕ʓ«ª¹ÀÀH]²÷ +'¹WqÓÖ½ÿuÛ=xè̃‘Á¾?á™ñôúƠOŸá‡+ă£ÊƠÂÑrQ‡£³g·:®›Ë岹뼡‹XƒTËó?pâ©ËWœr.jÇ&t70X¬\âw©Iwäè’>S ¿Ñ±Ü+Û:n¾éæm›^ưË×J[ơ䃧}^f<½iíª­ëŸ¯mlÍẻUƠuƒºN\~¶¡›[çö÷¾ëÜ †‡û[Úæz®©(!T¦)̣L¶hM¬¶ç֥⠔óJOÇV0ØƠÏ<³x~kkm‚Æ 1 ©b™„‡óÿ ªE3*ëHßuÏÊ{ï¼½sß®¿½}YQëSá‹̃ưệË@!¹=×û{Y{ùÅU ­ó¾÷¶D²₫¡ß̃‰%ï½å?Úæ Æ“Ơ—]ñM“m§Df•äáÑœ(‰Néí+œü~pùé§Ï¾ølpMÁ:¦@$Á<Å á> ‡¢¡oÛÑñû₫ø̀èƯïØÿs®¨uæ¼½÷]C ’#F/óá₫ƒçŸǵẩB¹R(U*e³¨WrE£«cŸĂ ®a…×1ó}¯Î>í"<Ço €=tïƯËO\°d^36ƠÆ)8ü‡‹Kûáç_Ørç¿}æñ•…Ü댸^ăZÆ?(¾H¢$ˆ–à„)¸•RåpuLÍJú-±UK^=ééei¦È̉ù­§Î?m8o%ëúºÚß2¯ơ¦`…½Üø̉Ó«×}xáœfŒÓ¼°'¶ARØ’ͮ۸kå}l]¿ ‚ˆ ÿđDzåç0ôdë)á1Asv3¢1ĂÏÆcQTûúFAk0€_–ßI3Ç Kâw®¹₫‡ß₫ÊèPßÛVÅ|æáûï{ß»—·ÖW9$À…56¿ûî½ûÎ=Û7¾ñl…ïüI‘ôà=ÜM¬éóI¹ßEöë¨₫₫\¤¨›Ë4‘µøºÚº¹‹—¾m`…±åå§úó__÷£o³aÓλî¼÷Ù'íwߌ¦ÁE’‡N‹?¹DÙ¡Oƒÿsäy2)äKr₫ƒÙ±¨Å´œà3ÍfÇF̃ÜŒR!ûàƯ7­}îà³z:÷Ε‡_ZÛæ„̣ µ̣zöƒÖ 0áêdl,ẀẀ“æ6zd­*¶²LW_áơ¬®<ö°RxE†Q¸ÁƯ,†züCڤȲ“?7[̣œ¤y±mZ’ÄXH]ÜZsÊüF× ₫P¶±Xoç¾·¬G|áh'/EM.́xx>rúODÄ>©J“—ñÈyËf‘„ÂÍRL÷pîæŸ|÷Pcÿ;… ̉4™À€ØĐ!ñ_ƒ4xÅq×0&"W’ÓvHïÆxeĂÊ+{w¾mtëQL¬1l2Yă“²Ö¥ƒơ§“đëÑIH⑌5ElƠ'׿CJÁ²±_£™íƯ£}ØuiX±‡æ̣„"²°>=‰¨˜b0G-–퀓Âus,ÙÎX&ûøÊ;̃âưŸªÖÊr v¹|2’đY:(ØX;é½üƒ—j'Wă ûÇ {_YcÛö4¬dvÛ¦ DÁ ‰ă¡‘W¾ăbi<¨ ü‰†bŸvl‡ç9Ó´áyÇ`æÙGï{ë÷Ê’G£9ºơf¢³‚đÊrpÑu0Ü@9•\Îæc:‚jïO÷wä2cÓ°N’^m‚\ù¤÷§Àpɪ̀@É"vAï_p1ÂAP€—nØ×7ú»ÿ¼₫­, LuXñÏ®ˆ¹̣2)Ïx”‰‹.܃ùt¬e“Á̉e—çc×Đh®â˜åñôÈ1Ùÿ) k(’à8p,ƒóƒ*WQ Ö°ùy.®„lÈÙỖÿđ¿<&¦:uaÅ.x^ïâ…g^ËW‘”6áPß›@1°V\¶\[ÜÔÍáL);:ؾó•cµÿS6ÊbI'Qà°hDR«¥&m0ˆè %;鯀,¶îÜǿƒçMĂú§Ë2%S9ú5ø^sM%@°V…₫Ó?¦60’ÑMsûÆá₫OU—År*[6–¤& `R"SÉưAÄ{ dÏ3Û÷÷¯ú~Ë2§aưó‰ÅóÅ’ÀsÔÁ RTQ₫k÷¯a\»Ưó¬Ó=”}ééGí₫OÙ?́¤Ñä"kh¸HÎÁT+)gMpmĐñJ9}vư^=Ưc¹Uï(X9\ØÅ;x)âƯư KƯ D"|¨;¢'ÂW×r:Çn¿á×[ü{U„B¡,IÂk¬êăŸg I–ÉbÁd&€&í±,Cwơ§Û·®}kzß9–~²H5qÁăêûÔ¡Ä0¸±g7µïÛ´jJ¸Ü© kzd¨opTÆø• €)² €$¶'†KFđ̀wÛ̃^§Rêhß=%rSÖb>Ó;0’³Ă²‡ÇóélăxĂ0đZ9øGDh™çˆƒœÇöưbIø…íƯö¯Ç$_ơf5…G,‘̉+¥†æ™`¤J(êØfˬ¥r9 Ă4«ol©˜öÜÙṣ¥i9;Ö=¹úɇ¨éñF->ä!Y¯N.̉< ̀ô˜ÓczLé1=¦Ç;yü?Bä¥ÊØ[’IEND®B`‚spotweb-20130826+dfsg2/index.php000077500000000000000000000364151226620506000163000ustar00rootroot00000000000000connect(); /* * Create the setting object as soon as possible because * we need it for a lot of stuff */ $settings = SpotSettings::singleton($db, $settings); /* * Disable the timing part as soon as possible because it * gobbles memory */ if (!$settings->get('enable_timing')) { SpotTiming::disable(); } # if /* * The basics has been setup, lets check if the schema needs * updating */ if (!$settings->schemaValid()) { throw new SchemaNotUpgradedException(); } # if /* * Does our global setting table need updating? */ if (!$settings->settingsValid()) { throw new SettingsNotUpgradedException(); } # if /* * Because users are asked to modify ownsettings.php themselves, it is * possible they create a mistake and accidentally create output from it. * * This output breaks a lot of stuff like download integration, image generation * and more. * * We try to check if any output has been submitted, and if so, we refuse * to continue to prevent all sorts of confusing bug reports */ if ((headers_sent()) || ((int) ob_get_length() > 0)) { throw new OwnsettingsCreatedOutputException(); } # if # helper functions for passed variables $req = new SpotReq(); $req->initialize($settings); $page = $req->getDef('page', 'index'); # Retrieve the users object of the user which is logged on SpotTiming::start('auth'); $spotUserSystem = new SpotUserSystem($db, $settings); if ($req->doesExist('apikey')) { $currentSession = $spotUserSystem->verifyApi($req->getDef('apikey', '')); } else { $currentSession = $spotUserSystem->useOrStartSession(false); } # if /* * If three is no user object, we don't have a security system * either. Without a security system we cannot boot, so fatal */ if ($currentSession === false) { if ($req->doesExist('apikey')) { $currentSession = $spotUserSystem->useOrStartSession(true); throw new PermissionDeniedException(SpotSecurity::spotsec_consume_api, 'invalid API key'); } else { throw new SqlErrorException("Unable to create session"); } # else } # if SpotTiming::stop('auth'); /* * And check if the security groups need updating */ if (!$currentSession['security']->securityValid()) { throw new SecurityNotUpgradedException(); } # if # User session has been loaded, let's translate the categories if ($currentSession['user']['prefs']['user_language'] != 'en_US') { SpotTranslation::initialize($currentSession['user']['prefs']['user_language']); } # if SpotCategories::startTranslation(); /* * Let the form handler know what userid we are using so * we can make the CSRF cookie be user-bounded */ $req->setUserId($currentSession['user']['userid']); /* * Only now it is safe to check wether the user is actually alowed * to authenticate with an API key */ if ($req->doesExist('apikey')) { /* * To use the Spotweb API we need the actual permission */ $currentSession['security']->fatalPermCheck(SpotSecurity::spotsec_consume_api, ''); /* * but we also need a specific permission, because else things could * be automated which we simply do not want to be automated */ $currentSession['security']->fatalPermCheck(SpotSecurity::spotsec_consume_api, $page); } # if SpotTiming::start('renderpage'); switch($page) { case 'render' : { $page = new SpotPage_render($db, $settings, $currentSession, $req->getDef('tplname', ''), Array('search' => $req->getDef('search', $spotUserSystem->getIndexFilter($currentSession['user']['userid'])), 'data' => $req->getDef('data', array()), 'messageid' => $req->getDef('messageid', ''), 'pagenr' => $req->getDef('pagenr', 0), 'perpage' => $req->getDef('perpage', 10), 'sortby' => $req->getDef('sortby', ''), 'sortdir' => $req->getDef('sortdir', ''))); $page->render(); break; } # render case 'getspot' : { if (strpos($_SERVER['HTTP_USER_AGENT'], "SABnzbd+") === 0) { $page = new SpotPage_getnzb($db, $settings, $currentSession, Array('messageid' => $req->getDef('messageid', ''), 'action' => $req->getDef('action', 'display'), 'username' => $req->getDef('username', ''), 'apikey' => $req->getDef('apikey', ''))); } else { $page = new SpotPage_getspot($db, $settings, $currentSession, $req->getDef('messageid', '')); } # else $page->render(); break; } # getspot case 'getnzb' : { $page = new SpotPage_getnzb($db, $settings, $currentSession, Array('messageid' => $req->getDef('messageid', ''), 'action' => $req->getDef('action', 'display'), 'username' => $req->getDef('username', ''), 'apikey' => $req->getDef('apikey', ''))); $page->render(); break; } case 'getnzbmobile' : { $page = new SpotPage_getnzbmobile($db, $settings, $currentSession, Array('messageid' => $req->getDef('messageid', ''), 'action' => $req->getDef('action', 'display'))); $page->render(); break; } # getnzbmobile case 'erasedls' : { $page = new SpotPage_erasedls($db, $settings, $currentSession); $page->render(); break; } # erasedls case 'catsjson' : { $page = new SpotPage_catsjson( $db, $settings, $currentSession, Array('search' => $req->getDef('search', $spotUserSystem->getIndexFilter($currentSession['user']['userid'])), 'subcatz' => $req->getDef('subcatz', '*'), 'category' => $req->getDef('category', '*'), 'rendertype' => $req->getDef('rendertype', 'tree'), 'disallowstrongnot' => $req->getDef('disallowstrongnot', ''))); $page->render(); break; } # getspot case 'markallasread' : { $page = new SpotPage_markallasread($db, $settings, $currentSession); $page->render(); break; } # markallasread case 'getimage' : { $page = new SpotPage_getimage($db, $settings, $currentSession, Array('messageid' => $req->getDef('messageid', ''), 'image' => $req->getDef('image', Array()))); $page->render(); break; } case 'newznabapi' : { $page = new SpotPage_newznabapi($db, $settings, $currentSession, Array('t' => $req->getDef('t', ''), 'messageid' => $req->getDef('id', ''), 'apikey' => $req->getDef('apikey', ''), 'q' => $req->getDef('q', ''), 'limit' => $req->getDef('limit', ''), 'cat' => $req->getDef('cat', ''), 'imdbid' => $req->getDef('imdbid', ''), 'artist' => $req->getDef('artist', ''), 'rid' => $req->getDef('rid', ''), 'season' => $req->getDef('season', ''), 'ep' => $req->getDef('ep', ''), 'o' => $req->getDef('o', ''), 'extended' => $req->getDef('extended', ''), 'maxage' => $req->getDef('maxage', ''), 'offset' => $req->getDef('offset', ''), 'del' => $req->getDef('del', '') ) ); $page->render(); break; } # api case 'rss' : { $page = new SpotPage_rss($db, $settings, $currentSession, Array('search' => $req->getDef('search', $spotUserSystem->getIndexFilter($currentSession['user']['userid'])), 'page' => $req->getDef('page', 0), 'sortby' => $req->getDef('sortby', ''), 'sortdir' => $req->getDef('sortdir', ''), 'username' => $req->getDef('username', ''), 'apikey' => $req->getDef('apikey', '')) ); $page->render(); break; } # rss case 'statics' : { $page = new SpotPage_statics($db, $settings, $currentSession, Array('type' => $req->getDef('type', ''))); $page->render(); break; } # statics case 'createuser' : { $page = new SpotPage_createuser($db, $settings, $currentSession, Array('createuserform' => $req->getForm('createuserform'))); $page->render(); break; } # createuser case 'editsettings' : { $page = new SpotPage_editsettings($db, $settings, $currentSession, Array('editsettingsform' => $req->getForm('editsettingsform'))); $page->render(); break; } # editsettings case 'edituserprefs' : { $page = new SpotPage_edituserprefs($db, $settings, $currentSession, Array('edituserprefsform' => $req->getForm('edituserprefsform'), 'userid' => $req->getDef('userid', ''), 'data' => $req->getDef('data', array()), 'dialogembedded' => $req->getDef('dialogembedded', 0))); $page->render(); break; } # edituserprefs case 'editsecgroup' : { $page = new SpotPage_editsecgroup($db, $settings, $currentSession, Array('editsecgroupform' => $req->getForm('editsecgroupform'), 'groupid' => $req->getDef('groupid', 0))); $page->render(); break; } # editsecgroup case 'editfilter' : { $page = new SpotPage_editfilter($db, $settings, $currentSession, Array('editfilterform' => $req->getForm('editfilterform'), 'orderfilterslist' => $req->getDef('orderfilterslist', array()), 'search' => $req->getDef('search', array()), 'sorton' => $req->getDef('sortby', ''), 'sortorder' => $req->getDef('sortdir', ''), 'filterid' => $req->getDef('filterid', 0), 'data' => $req->getDef('data', array()))); $page->render(); break; } # editfilter case 'edituser' : { $page = new SpotPage_edituser($db, $settings, $currentSession, Array('edituserform' => $req->getForm('edituserform'), 'userid' => $req->getDef('userid', ''))); $page->render(); break; } # edituser case 'login' : { $page = new SpotPage_login($db, $settings, $currentSession, Array('loginform' => $req->getForm('loginform'), 'data' => $req->getDef('data', array()))); $page->render(); break; } # login case 'postcomment' : { $page = new SpotPage_postcomment($db, $settings, $currentSession, Array('commentform' => $req->getForm('postcommentform'), 'inreplyto' => $req->getDef('inreplyto', ''))); $page->render(); break; } # postcomment case 'postspot' : { $page = new SpotPage_postspot($db, $settings, $currentSession, Array('spotform' => $req->getForm('newspotform'))); $page->render(); break; } # postspot case 'reportpost' : { $page = new SpotPage_reportpost($db, $settings, $currentSession, Array ('reportform' => $req->getForm('postreportform'), 'inreplyto' => $req->getDef('inreplyto', ''))); $page->render(); break; } # reportpost case 'versioncheck' : { $page = new SpotPage_versioncheck($db, $settings, $currentSession); $page->render(); break; } # versioncheck case 'blacklistspotter' : { $page = new SpotPage_blacklistspotter($db, $settings, $currentSession, Array ('blform' => $req->getForm('blacklistspotterform'))); $page->render(); break; } # blacklistspotter case 'logout' : { $page = new SpotPage_logout($db, $settings, $currentSession); $page->render(); break; } # logout case 'sabapi' : { $page = new SpotPage_sabapi($db, $settings, $currentSession); $page->render(); break; } # sabapi case 'nzbhandlerapi' : { $page = new SpotPage_nzbhandlerapi($db, $settings, $currentSession); $page->render(); break; } # nzbhandlerapi case 'twitteroauth' : { $page = new SpotPage_twitteroauth($db, $settings, $currentSession, Array('action' => $req->getDef('action', ''), 'pin' => $req->getDef('pin', ''))); $page->render(); break; } # twitteroauth case 'statistics' : { $page = new SpotPage_statistics($db, $settings, $currentSession, Array('limit' => $req->getDef('limit', ''))); $page->render(); break; } # statistics default : { SpotTiming::start('renderpage->case-default'); if (@$_SERVER['HTTP_X_PURPOSE'] == 'preview') { $page = new SpotPage_getimage($db, $settings, $currentSession, Array('messageid' => $req->getDef('messageid', ''), 'image' => array('type' => 'speeddial'))); } else { $page = new SpotPage_index($db, $settings, $currentSession, Array('search' => $req->getDef('search', $spotUserSystem->getIndexFilter($currentSession['user']['userid'])), 'pagenr' => $req->getDef('pagenr', 0), 'sortby' => $req->getDef('sortby', ''), 'sortdir' => $req->getDef('sortdir', ''), 'messageid' => $req->getDef('messageid', ''), 'action' => $req->getDef('action', ''), 'data' => $req->getDef('data', array())) ); } # if SpotTiming::stop('renderpage->case-default'); $page->render(); break; } # default } # switch SpotTiming::stop('renderpage'); # timing SpotTiming::stop('total'); # enable of disable de timer if (($settings->get('enable_timing')) && (!in_array($req->getDef('page', ''), array('catsjson', 'statics', 'getnzb', 'getnzbmobile', 'markallasread', 'rss', 'newznabapi')))) { SpotTiming::display(); } # if } catch(PermissionDeniedException $x) { /* * We try to render a permission denied error using the already created * renderer first. We do this, so pages which are supposed to output * XML, can also output their errors using XML. * * If no page is initiated just yet, we create an basic renderer object * to render an error page */ if (! ($page instanceof SpotPage_Abs)) { $page = new SpotPage_render($db, $settings, $currentSession, '', array()); } # if $page->permissionDenied($x, $page, $req->getHttpReferer()); } # PermissionDeniedException catch(InvalidOwnSettingsSettingException $x) { echo "There is an error in your ownsettings.php

" . PHP_EOL; echo nl2br($x->getMessage()); } # InvalidOwnSettingsSettingException catch(OwnsettingsCreatedOutputException $x) { echo "ownsettings.php or dbsettings.inc.php created output. Please make sure theese files do not contain a PHP closing tag ( ?> ) and no information before the PHP opening tag (
" . PHP_EOL; echo nl2br($x->getMessage()); } # OwnsettingsCreatedOutputException catch(SchemaNotUpgradedException $x) { echo "Database schema has been changed. Please run 'upgrade-db.php' from an console window"; } # SchemaNotUpgradedException catch(SecurityNotUpgradedException $x) { echo "Spotweb contains updated security settings. Please run 'upgrade-db.php' from a console window"; } # SecurityNotUpgradedException catch(SettingsNotUpgradedException $x) { echo "Spotweb contains updated global settings settings. Please run 'upgrade-db.php' from a console window"; } # SecurityNotUpgradedException catch(DatabaseConnectionException $x) { echo "Unable to connect to database:
"; echo nl2br($x->getMessage()) . PHP_EOL . '
'; echo "

Please make sure your database server is up and running and your connection parameters are set
" . PHP_EOL; } # DatabaseConnectionException catch(Exception $x) { echo 'SpotWeb v' . SPOTWEB_VERSION . ' on PHP v' . PHP_VERSION . ' crashed' . PHP_EOL; if ((isset($settings) && is_object($settings) && $settings->get('enable_stacktrace')) || (!isset($settings))) { var_dump($x); } # if echo $x->getMessage(); error_log('SpotWeb Exception occured: ' . $x->getMessage()); } # catch spotweb-20130826+dfsg2/install.php000077500000000000000000000700611226620506000166320ustar00rootroot00000000000000 Test your Installation
PHP settings Value Result
PHP version = 0), true, "", "PHP 5.3 or later is recommended"); ?>
timezone settings
Open base dir might be a problem"); ?>
Allow furl open
PHP safe mode
Memory limit = (128*1024*1024), true, "", "memory_limit below 128M"); ?>

createPrivateKey($settings['openssl_cnf_path']); /* We need either one of those 3 extensions, so set the error flag manually */ if ( (!extension_loaded('openssl')) && (!extension_loaded('gmp')) && (!extension_loaded('bcmath'))) { $_testInstall_Ok = false; } # if ?>
PHP extension Result
ctype
curl
DOM
gettext
mbstring
json
xml
zip
zlib
Database support
DB::mysql
DB::pdo_mysql
DB::pgsql
GD
FreeType Support
GIF Read Support
GIF Create Support
JPEG Support
PNG Support
OpenSSL
At least 1 of these must be OK
these modules are sorted from fastest to slowest
openssl
gmp
bcmath
Can create private key?

Include files Result
Settings file
Own settings file

Please continue to setup Spotweb Next

Please fix above errors before you can continue to install Spotweb

'MySQL', 'host' => 'localhost', 'dbname' => 'spotweb', 'user' => 'spotweb', 'pass' => 'spotweb', 'submit' => ''); } else { $form = $settings['mydb']; unset($settings['mydb']); } # else if (isset($_POST['dbform'])) { $form = array_merge($form, $_POST['dbform']); } # if /* * Dit the user press submit? If so, try to * connect to the database */ $databaseCreated = false; if ($form['submit'] === 'Verify database') { try { $db = new SpotDb($form); $db->connect(); $databaseCreated = true; /* * Store the given database settings in the * SESSION object, we need it later to generate * a 'ownsettings.php' file */ $_SESSION['spotsettings']['db'] = $form; /* * and call the next stage in the setup */ Header("Location: " . $_SERVER['SCRIPT_NAME'] . '?page=2'); } catch(Exception $x) { ?>
getMessage(); ?>

Please correct the errors in below form and try again
Database settings
Spotweb needs an available MySQL or PostgreSQL database. The database needs to be created and you need to have an user account and password for this database.
type
server '>
database ' >
username '>
password '>

'custom', 'host' => '', 'user' => '', 'pass' => '', 'port' => 119, 'enc' => false, 'submit' => ''); } else { $form = $settings['mynntp']; unset($settings['mynntp']); } # else if (isset($_POST['nntpform'])) { $form = array_merge($form, $_POST['nntpform']); } # if /* * Dit the user press submit? If so, try to * connect to the database */ $nntpVerified = false; if ($form['submit'] === 'Verify usenet server') { try { /* * Convert the selected NNTP name to an actual * server record. */ if ($form['name'] == 'custom') { $form['buggy'] = false; $form['hdr'] = $form; $form['nzb'] = $form; $form['post'] = $form; } else { foreach($serverList->usenetservers->server as $provider) { if (extension_loaded('openssl') && isset($provider->ssl)) { $server = $provider->ssl; } else { $server = $provider->plain; } # if if ( (string) $provider['name'] == $form['name'] ) { # Header usenet server $form['hdr']['host'] = (string) $server->header; $form['hdr']['user'] = $form['user']; $form['hdr']['pass'] = $form['pass']; if ( (string) $server->header['ssl'] == 'yes') { $form['hdr']['enc'] = 'ssl'; } else { $form['hdr']['enc'] = false; } # else $form['hdr']['port'] = (int) $server->header['port']; $form['hdr']['buggy'] = (boolean) $server['buggy']; # NZB usenet server $form['nzb']['host'] = (string) $server->nzb; $form['nzb']['user'] = $form['user']; $form['nzb']['pass'] = $form['pass']; if ( (string) $server->nzb['ssl'] == 'yes') { $form['nzb']['enc'] = 'ssl'; } else { $form['nzb']['enc'] = false; } # else $form['nzb']['port'] = (int) $server->nzb['port']; $form['nzb']['buggy'] = (boolean) $server['buggy']; # Posting usenet server $form['post']['host'] = (string) $server->post; $form['post']['user'] = $form['user']; $form['post']['pass'] = $form['pass']; if ( (string) $server->post['ssl'] == 'yes') { $form['post']['enc'] = 'ssl'; } else { $form['post']['enc'] = false; } # else $form['post']['port'] = (int) $server->post['port']; $form['post']['buggy'] = (boolean) $server['buggy']; } # if } # foreach } # else /* and try to connect to the usenet server */ $nntp = new SpotNntp($form['hdr']); $nntp->validateServer(); $nntpVerified = true; /* * Store the given NNTP settings in the * SESSION object, we need it later to update * the settings in the database */ $_SESSION['spotsettings']['nntp'] = $form; /* * and call the next stage in the setup */ Header("Location: " . $_SERVER['SCRIPT_NAME'] . '?page=3'); } catch(Exception $x) { ?>
getMessage(); ?>

Please correct the errors in below form and try again
Usenet server settings
Spotweb needs an usenet server. We have several usenet server profiles defined from which you can choose. If your server is not listed, please choose 'custom', more advanced options can be set from within Spotweb itself.
Usenet server
username '>
password '>

'public', 'username' => '', 'newpassword1' => '', 'newpassword2' => '', 'firstname' => '', 'lastname' => '', 'mail' => '', 'userid' => -1); } else { $form = $settings['myadminuser']; unset($settings['myadminuser']); } if (isset($_POST['settingsform'])) { $form = array_merge($form, $_POST['settingsform']); } # if /* * Dit the user press submit? If so, try to * connect to the database */ $userVerified = false; if ((isset($form['submit'])) && ($form['submit'] === 'Create system')) { try { /* * Store the given user settings in the * SESSION object, we need it later to update * the settings in the database */ $_SESSION['spotsettings']['adminuser'] = $form; /* * Very ugly hack. We create an empty SpotSettings class * so this will satisfy the constructor in the system. * It's ugly, i know. */ class SpotSettings { } ; /* * Override the SpotDb class so we can override userEmailExists() * to not require database access. */ class DbLessSpotDb extends SpotDb { function userEmailExists($s) { return (($s == 'john@example.com') || ($s == 'spotwebadmin@example.com')); } # userEmailExists } # class DbLessSpotDb /* * Create an DbLessSpotDb object to satisfy the user subsystem */ $db = new DbLessSpotDb($_SESSION['spotsettings']['db']); $db->connect(); /* * And initiate the user system, this allows us to use * validateUserRecord() */ $spotUserSystem = new SpotUserSystem($db, new SpotSettings(array())); $errorList = $spotUserSystem->validateUserRecord($form, false); if (!empty($errorList)) { throw new Exception($errorList[0]); } # if /* * and call the next stage in the setup */ Header("Location: " . $_SERVER['SCRIPT_NAME'] . '?page=99'); } catch(Exception $x) { ?>
getMessage(); ?>

Please correct the errors in below form and try again
Spotweb type
Spotweb has several usages - it can be either run as a personal system, a shared system among friends or a completely public system.

Please select the most appropriate usage below.
Single user Single user systems are one-user systems, not shared with friends or family members. Spotweb wil always be logged on using the below defined user and Spotweb will never ask for authentication.
Shared Shared systems are Spotweb installations shared among friends or family members. You do have to logon using an useraccount, but the users who do log on are trusted to have no malicious intentions.
Public Public systems are Spotweb installations fully open to the public. Because the installation is fully open, regular users do not have all the features available in Spotweb to help defend against certain malicious users.
Administrative user
Spotweb will use below user information to create a user for use by Spotweb. The defined password will also be set as the password for the built-in 'admin' account. Please make sure to remember this password.
Username '>
Password '>
Password (confirm) '>
First name '>
Last name '>
Email address '>

database(); /* * and create all the different settings (only the default) ones */ $spotUpgrader->settings(); /* * Create the users */ $spotUpgrader->users(); /* * print all the output as HTML comment for debugging */ $dbCreateOutput = ob_get_contents(); ob_end_clean(); /* * Now it is time to do something with * the information the user has given to us */ $db = new SpotDb($_SESSION['spotsettings']['db']); $db->connect(); /* * add the database settings to the main settings array for now */ $settings['db'] = $_SESSION['spotsettings']['db'];; /* and create the database settings */ $spotSettings = SpotSettings::singleton($db, $settings); /* * Update the NNTP settings in the databas */ $spotSettings->set('nntp_nzb', $_SESSION['spotsettings']['nntp']['nzb']); $spotSettings->set('nntp_hdr', $_SESSION['spotsettings']['nntp']['hdr']); $spotSettings->set('nntp_post', $_SESSION['spotsettings']['nntp']['post']); /* * Create the given user */ $spotUserSystem = new SpotUserSystem($db, $spotSettings); $spotUser = $_SESSION['spotsettings']['adminuser']; /* * Create a private/public key pair for this user */ $spotSigning = Services_Signing_Base::newServiceSigning(); $userKey = $spotSigning->createPrivateKey($spotSettings->get('openssl_cnf_path')); $spotUser['publickey'] = $userKey['public']; $spotUser['privatekey'] = $userKey['private']; /* * and actually add the user */ $userId = $spotUserSystem->addUser($spotUser); # Change the administrators' account password to that of this created user $adminUser = $spotUserSystem->getUser(SPOTWEB_ADMIN_USERID); $adminUser['newpassword1'] = $spotUser['newpassword1']; $spotUserSystem->setUserPassword($adminUser); # update the settings with our system type and our admin id $spotSettings->set('custom_admin_userid', $userId); $spotSettings->set('systemtype', $spotUser['systemtype']); # Set the system type $spotUpgrader->resetSystemType($spotUser['systemtype']); /* * Create the necessary database connection information */ $dbConnectionString = ''; switch ($_SESSION['spotsettings']['db']['engine']) { case 'mysql' : { $dbConnectionString .= "\$dbsettings['engine'] = 'mysql';" . PHP_EOL; $dbConnectionString .= "\$dbsettings['host'] = '" . $_SESSION['spotsettings']['db']['host'] . "';" . PHP_EOL; $dbConnectionString .= "\$dbsettings['dbname'] = '" . $_SESSION['spotsettings']['db']['dbname'] . "';" . PHP_EOL; $dbConnectionString .= "\$dbsettings['user'] = '" . $_SESSION['spotsettings']['db']['user'] . "';" . PHP_EOL; $dbConnectionString .= "\$dbsettings['pass'] = '" . $_SESSION['spotsettings']['db']['pass'] . "';" . PHP_EOL; break; } # mysql case 'pdo_pgsql' : { $dbConnectionString .= "\$dbsettings['engine'] = 'pdo_pgsql';" . PHP_EOL; $dbConnectionString .= "\$dbsettings['host'] = '" . $_SESSION['spotsettings']['db']['host'] . "';" . PHP_EOL; $dbConnectionString .= "\$dbsettings['dbname'] = '" . $_SESSION['spotsettings']['db']['dbname'] . "';" . PHP_EOL; $dbConnectionString .= "\$dbsettings['user'] = '" . $_SESSION['spotsettings']['db']['user'] . "';" . PHP_EOL; $dbConnectionString .= "\$dbsettings['pass'] = '" . $_SESSION['spotsettings']['db']['pass'] . "';" . PHP_EOL; break; } # pdo_pgsql } # switch # Try to create the dbsettings.inc.php file for the user @file_put_contents("dbsettings.inc.php", "
Installation succesful
Spotweb has been installed succesfuly!
 
You need to create a textfile with the database settings in it. Please copy & paste the below exactly in a file called dbsettings.inc.php.

							
Spotweb retrieves its information from the newsservers, this is called "retrieving" or retrieval of Spots. You need to schedule a retrieval job to run retrieve.php on a regular basis. The first time retrieval is run this can take up to several hours before completion.
'; ?>
getMessage(); ?> getTraceAsString(); ?>

D…„@sœ€æUq’ÿHL•I{’UzVz­ÿQTùD„””úÿYW¥T…¯_„¤z{µLŒ–~œÿy……ÿb`ƒ…‚&­#hŒ­lŒ§kŒ´O™‹¥ưÿjhO”ÖV™–‹k”®o“´u”£v–²Œ”›’”‘nœ¯ÿy{U«q­-‰œE½Eq¦«:Ă0›™ÿ‚†y¢ÖXµƒp­¥¢Ÿ£_¶‹aµ˜y­¦~¹7¥¥œÇ¥>Æ¥Ek½ei½k¤¦£…­»ÿr½m{µ¦ˆ®ÉBÎax½tÄ­Bt¼™È¬Jª­_½Ư Îö‰µ¼yµí«­ªÅ­_µ¶v¾§ÂB¬­·pÇgÏ­T‘µ½rÆs•µÄL×SLÖhÿœ™¥µ»ï®0¥µÈͶKĐ´Y†»î~Æ¢_Æÿϵ_Ơ¶F–ÉI´¶³´µ¾Ç†ŒÇ‹µ´Øÿ¤¤¢¾ƠœÀƠ­½Ä˜Å³Ơ½RÔ½YϽl®½Ñ»½º“ÂÿƯ¾MƠ½tµ¼ß“Γ¼½Ç›Î”™ÎzÎư\×ÿ¾Á½×ÅXñÅàÆL߯S¶Æ̀̃ÆZ×Åz–ËÿƯÆaÜÆh¶ÆÙ¡ËóáÆpÍûÅÇÄÅÆĐ¨Ö¢ÿÿÿ¼ºṽưßÎg½ÎÔ”ÖÿæÎaÁÍÛÛÏ{ÍËϨ̉ûæÏiéÍwåÏpƒßÿÍÏ˫ߣ’ç¦çÖn´Øü·ƯËéÖƒưÊÈí×wđƠ„ÔÖÓ̉×à·Üÿ±ßÿÙÖèî̃|¿ßư£èỵ̈Ư‹îß„¬çÿµçÿƯßÜáƯïä̃Ưµï¿²đÆßàêưÚÚ»đǯîÿÄèÿîçöç‹ùæ™̉êưççƯæèåÍïÿâëóà́ûùï¦÷ï¬äđƯÏ÷×ïïåÔøàîđíîïùßöḉñôùö«̃÷üèöêøöÅÿ÷´ư÷ºđ÷́÷öíñ÷úööÿöøôư÷öèÿđđ₫ñîÿùÿÿö₫ÿüÿÿÿ!₫Created with GIMP!ù ÿ,`È₫ÿưÓD° A\˜PàB† Œ(‘`C…/jÊ×ÏŸGS=Èñ#H"IvürdÂ+=¶TiræË’,QºD¨ Ωđíè3¦Ç C{₫<*ôeQ“(›̣|j©Ó¥Q‡>ÂGƠă£@vníêïkX„c—ËU-X¶d×¢mkT®À±dÁMƒ›wï\º&ợ]*øoßÁF ßå Ød Ădư=^̀ëäx#_Îlrg7öx9´è¥¥E“M}Ú(ëÊ®†íX¶j®1_‹Îmû6oĐ·ñư₫7{÷GƯŒ‡ßƯỵæ½}C¼ßtâÁ…__₫\2B4Ùµ₫£ù̃úxà³›'¯¾ßùé«»g/ÿ}üàù́‡÷©?|~úøơ—ƯèíG |ûá#`v ×àmª¡hï%‘`Y¸†i‡ÿx˜ˆ"Gâ…‘ )®Øâ~, ¤"Œ/†ă?3Úˆ °c?îç£@< dxC₫S$’±àä“P>Ùd”T²0e•P^‰¥“ZnÙ%– qĂM3ÎI 1Ăs‘˜d‰¦ ±Y¦3g¦¹æ˜sÖ g˜xºigœ}̉ùfœîôÓ3´̀£è<̣́ù7…袆)¢‹2ê(¤†bJ馗Nªh¥q*i¦¤ Ä<̣xôJ(₫åŒK˜¬º «¬´¶êÏ«±2:k©µîz«¯¹ÚÚ«<¿ª,¯¸[ë(’#O9å¼’k«ĐJK­µÎbí´Ơ^ëO¶àr«́³ßn+.¹êvëÏ&’àR9Ư".¼̣̉k¯»øÎ[ï½ñú»ï¹­ö«/Àù₫ël¡Œ4’K7Û43đ£¬2́0ÄçjñĂO¼ª<ćqÅư4̀qÆ —|qÇ 9r9ư,â)Í4CŒ¹ÿ¸́̀2Ól3Î:óụ̈£Ÿư¢÷?ư ° ÿƇ?îï|·h)À@…?̀ ÿ&XÁ .đ¤-ø@„„p„„ )HB ‚p…,¡@^±ÁQ°đ‚‘8Bh(Bư₫9Üa o8¿ Îpˆ?4â?xH ¶P‰Lt"uˆM0âù»"#¨XE-fñ\ˆ±?-†ñcdÄ·Ø4®ñŒn,#/̣Pä! t¼ˆñ˜Ç„́±~¼# ̣ÇAÖQ†L¤"ÉÈF6²Œ¤$#‰IZ’•¼ä$3©IJ ¤“’ä$(+ùR~à@‡:ÔQ|4 ’wˆ¥,gy‡W~̉”§Lå*[iË4€–À́ep‰JU²̉•°æ,…iJT‚c—\æ8AÍjV³–¤,¥3¡‰̀ONÓÖÄæ-/AˆA✄ Ä*ºéËo‚“âô¥6Q¹KD–œ₫Ø&+ưÁ‰x3—Ïdå îéÍ|̉S ưd&!®p…-8ô q ;É †:t M()ơYàẲ4h=ùéO€ị̂)>Z”jô–ƒ°‚L¯0ÓA¨´ 2µMuúR_¢̉#ưHHºOô´¨<ÁIQê‘*U .ơ'8bz…/Äá ½ÄMÛÉ Z«[8j*=̉Q¨ Ơe5ªTÑ̉–¢ô£[¥h[Q:P±Æt WĂÜ@‰¸NÓ xµê^ªJ¨˜ä¬P!¬:èúV¡â“±)%́ W½ÆA«!¥l,{Ô ŸiưHgWIW¸6Ÿ‹m,I…©BèÔ²Uí₫kH_ Ѫv¶•¦=,>¹’X'0lH¹\Ñúv[é°ềâ3¹€eîQq›[Çôđ&uíùÙëbןơXÅ (A^JŒw~Ånv+ÉĂ֛ʔ¥0Ûë^iÆ7–óåm}“y_a‚“Ÿü¯ÿ+ÊNX“¾¤#̀à;øÁ°„'Lá '̉)h@ 1H g`ĂÎ0ˆ‰a s˜Ä">q=r›cÙÏ; YÍ[Æ/V±g^ ỲÙ²’Ílç47¤]₫²1?ÑKd Çà´síæb.ºÑ¾Tr¤}h;ô™Ï|ætB2 ép~b̉Áp4¼¬KVªC*Æđ7Ñ¡JxÎ Ö)8å7xa„K ƒø€uªSđM^_;Àơ§—-lȼˆ6²Uœ;hÓ˜êà Ríỉz•êèg)RÀíJóbHˆÁ%¸ r $ÈÓẸ̀ Xà£> ½–°ƒÛĂ"øjÈ‹‹oôÙ'ÿ7.>îuOÇ·8,{ơS₫bwÿúÛÿ°ö-L₫̣›ÿüèO¿ú%<†E¶ưÆüç_₫÷'̉₫ô_°üóÏÿăÿ×´X€Ô~ø ø ¨€€H€8÷G&˜È`ØÈ ØH8‚(‚&8€)¸‚,Ø‚.ø‚0ƒ†´ ‹ä HƒdƒX‚tTeĐH ” ™0HXÀƒáƒ Heđ ?¨HH̀À ¬`„L˜HO…Fèàp#}Tá…‰4…P…ƒt…º…€„`(†yD†fø…`h%Ná ^˜Gh˜†kÈ ºĐ†vx8†₫zȇ_††D‡}HGˆ}” ‚8ˆnØGpȈƒäˆ†„[؈8H:@…T(„}” Xˆ…Eø†Ÿ¸‰¡h„HØJ(€G¨H³8ƒ5xƒ¹(ƒ¼Ø‹¾ø‹ÀŒÂ8Œ2ˆƒ‰¤ƒhŒ†„Œ‹ q‹Rh†D„°h‹ˆ‰­è„ux†Th…X¨…M8†Ûø†q؈ex’Hlx‰y”‰rØƒçØ‰aˆ›˜ˆè˜¨†}Ć„Hwx{˜æ8éH ÉtD‰ƒø˜X÷ˆtä‰á8‡¯ØG£H̉HG¨˜«ˆÙƒ‰‰ÎˆĐ˜µÈ…ÙÊ8H̀È₫/ H1IŒ6é‹­ / Âpîơ“₫0‚ €Ô  C™ `=‰@é^ ˜”DIG7€”`/`PNù”P•II¡ àBp ‘"à đM –aÙRI– q Zđùđ " OY\!–Ci—a đjé}y–­Đ  ×đ@ÉT&˜  ˜¡‚¹–~é­à†€™a˜t5—X— ñ đ9¥éB ÁT­é¯Ù™ù ‰‘I&‘—©i•#HĂùÂp–" ™&¡ „₫ÉœiXB9•a\·é× à•¼¹@É™t$ n)åiđ•réœÿPyù—€ÙÙ ø™Ÿß y$ G™” ĐM¹ù”ÏÉŸwiu`Z ry“ ¡úÉ¡ ‚À aë€t´đ û@a(ª¢ä* * ¡Ñ¢+ÚHÉ` ½p):a> ¤úĐH₫ HJ£1¤AÊH…:Ê£ Á^@Ô7 aTj¥XÊHG¤ ±¥W¥€d“0p̉0¥^€ \J¦tT]PÁÿ@¥n:¦ƒ”[°§A§vú¦ƒ´0¨₫„:¨ °¦‘^Ơ@ç°üH÷°P©–j©K`¢Ê¨ ©’º ª¢*ª™ú›Ú¨©}4Đª®êª8°A¥éذ¨ªG₫p©¼Z©AI«¶«eʪ¯úªđ«‹¬é«ttđ¬Đú¬0Å0«‹ê¦© HøpĐ­̃ê­gÀ£´­ÚGÛú­èzàP§×Ú©̀JG& #0%0Ñ€§ÚjZm •  ‚  ª` ́z§] H%ú°°a ªP°€ªHÈĐ-`ÔđP¥ú a±äó:Jú»±‰ä {±û£.*₫aCÚ²‹äÛ#û²pjHëp₫p¯ ±>{³ö³@;Hë€ -€ RZ£?¢a ë†Ë´R;µT[µÿP¢'¢CKŒ9º£=ú£M¢O¥aª±k“f¦jʦ{£ é‹‚Z¨„z¨qªîúƯŒÄZ¬­«ÖZ«·º¬xK„[¸†{¸‡‹·û¶æ¬Ñ ­ÓZ­́j«w›·À¯óZ¯< ±úʸÀ8±)+¹Kj¶[Œ(k±¢»¤,[ºÁ˜³;{Bkµ²;»´;‚C05»+@€‡P·›»5°»½û»₫p½>ĐĐ+½Ôk½ØÛCMAĐf`pj ¾ă[¾ç›¾ë{Fa<±ö«€!₫+{À_¹¿ưû¿ܾ4@]àaa€ƒCÀ ÜÀ ́‘aSüD°¿lÀ̉» &l{pÀ ,Â$́&¼ (¬Âÿ0Á<Àr »P Pq4lĂ8¬Ă&qiQoñnq+̀R %| Ç`PlÂJ̀Ä.́ÄPlR,CPĂAÁ;á<́ÅpđI ÆAÆ”q†A~¡V́Ëp ¿pÇZ¼s|Åwü ỳÅ₫<_üđÚ ̃đ₫°],Èg\ȇœÈ‹ÜÆ>a P±§aɵñˆ°½.\Ç}l ÜÉÑûÉv|Ç¢¼Å3GpgœÆÏĐ“¼Ê­üÊS˳\˳a ø` ư É̃A¿üËÁ|Ñ&áÄ¡,ỀË|Ê¿` ÎŒLĐÊG „üá á µ|Í­¬Í…ÜÍß̀Ë¢a ê¬é¼ÎÈü]`&,ÍÔLÍâđ̀đ,Ï ŒÊơ|ÏÖ|MQ€ÆjL₫À!×ĐÆc̀!¦¡ÎíάÑ=>Đó̀ÏÔŒ âÀqÑ=ÍờÑ-L Đ\@₫…́LàpĐ&̉*ư,í̉ÂóQ 6­Î8}Í̀"½Ñ$ưÑíÔơl ¨0Ô&\ĐÔ$ÀĐkŒĐLíÔPmĐ¾œƠm! ZíËüAÔô¼Ñ¢  ÖÍŒÔc]Ö&ƯÔ\°1=Ó1ÂlíÖ+íL₫#÷Q̀ zÍ>m§<̉¨0ÖíP̉>ØÔ„]̉ÿ ×míÖU­ w½ÖưÔ-Ù1R"·q""` öĐÿ;ÚíP àÙ -Ú£í¿¥}Ú&½°Í$ ©n«ä¯Û³]Û¶Û8â"2Ü>ÀÄm ÀÊͰÅĂ]ÜÇÜËbƯÜÖüÁ+à.P?đIà©`̉Ö Ø­ƯÜíƯàM$@¢̃F’~À Q°†ỗñ H[’%qßRR»üƯß₫ưßà>à^à~àà ¾à ̃à₫àá ;spotweb-20130826+dfsg2/js/dynatree/skin-vista/loading.gif000066400000000000000000000060471226620506000230760ustar00rootroot00000000000000GIF89a÷÷áœïĂ:ơÚ„v\ ₫üôÿ₫üÜ«₫úïÏ¡₫ưø÷â¡óÓođÇFô×|ó̉köÜÿ₫úöÜ‹øä¥̣Î_ùèµ·ûïÈùê»ư÷äưøç̣Ïbư÷æôƠuơÚ‡í»¡}…g üóƠä±øåªơÙ‚̣ÍYùé¹î¾)₫üöûïÊüỡö̃’ñÊRúë½₫ûñú́Áâ°óÑfüôÜ붪„üó×ưùëøæ®öƯđÈLîÀ0ñËSùè´ïÄ?ûđϘv ₫úíïĂ8í»!øå©p đÇHûñÑîÀ2ú́Â÷à˜ö̃”úíÄî¿.üóÙïÂ6öß–øă£×§ñËU¿”øæ¬ûđÎóÓqùé·ñÊPúíÆ÷âŸüơàûñÓôÖzùè²₫ûóùç°í¼#éµôÖxñÉѹôÖẉÎ]ơÙ€Æz óÑhđÆC‹l Èœ̣ÏdïÄ=đÆEđÅÁ¸—£°‰ưöâó̉j̣Í[ÍŸí¼%ïÂ4ÿÿ₫ÿÿÿÿÿÿ!ÿ NETSCAPE2.0!ù,®ÿ˜&¼àăÂ…Z(h"€,$\P²ÀB* ”¬àÑÉ $Ô @…Ñ °ƒ†&&₫Ù!'À Op<Đ)đ  TvL@ôƒX °¢é NZLàP•(‹%(XaÆ«9₫t!¢„Nh „Á €„=¦0¨#በ< !¤Â‡:R&ø ƒÆiÚô%Úàj$ !ù,«ÿø§  L"! >d(ü¥„JVüyaâBB(8hH‚¤E ^đ GĂ yŒA 9$LCƒÀ.¬LØàÁaœÔ'™" 8ú' N`™:Ô4z̀Ñ3´Ë 7₫œùP¡ÇÄ0"D ¬ DÇ‚`8˜Q‚`™j`<ᦂ› £´)ó‡H”(¨ ”«G€!ù,­ÿøÇ„ # đDCŒ#(ü @ 4$Q²BB¤0C… %.¤ h € /¼0aA "L!ÁË X0˜(pÄ‹ZÜÀ˜@ô ₫Đ 1”¨CW`è8ÓT‰'_‚D©@ôIK‚P£c"9q̉0p‚A4GĐ!ApFsÜ0đ "̀ …₫™Băĉ(1.˜!¦‡–„!ù ,­ÿˆÂ &Œ¦H‘O (Ødø4hPbÂG˜À²"‚’(Høƒ. %Hè°̣›v&Lü£d€?z²S ,2’Đ@À¢è &,4øAD‡S7,€APFS|ØøƒÀ) düñú£¨ƒcÖ‰¢Ă@By¬ù9° ;'xpP$Ή £|`0c䄜vp Æ …!ù,°ÿˆŒ$&̀Á†(Øà { L˜À'Âe Øñà F„"p̀tHØ <(ÁA`DXLü3&††?*‚³S`(HpĐH#¥è<øA$ˆS%+F I#fÑ ^COÑ,7–`øsæ‡ܸ0°Â NRpÁKˆ„=¢Ạ̀¦ˆ€5 ”ø˜¸G„ƒ)9háT Z( !ù,©ÿ¸áO’*́QÆœÑF‚NN £pÁ :Dİ0Áƒ,V‚Hs"‡Âh¨C ‰ÈˆóG†8.è@áO‚₫!á AX(]p¦ÁNĐ(€€G8âD¢DI•?ˆàtE„PNHXåF:ÇLƒ#ܸBâ9$ÖÄÀk¢pP/$"đØ¢0 !ù ,©ÿˆA öBă‡6  \đ„  A0b N°pcÇC„ÿ°Hx„E&ƒ| á@âŸ0Düi‚Á›  y0cO ̃äÀCB‚.HåđÑpƒÍ„HI,x¤Ë2@½,h°äO„#p"Ø$qfÇ@2fD˜EÉI’ĐÀ̀Fđ"q̀ 7n,¡°‚̉,ø‘0 !ù,°ÿ(CK’+&d¤Î=(¸à‡@̀ 3 B |Â@GD`Iˆ€  …Q#BàVLü£‡Æ‡?wº¼Á²S '†‘¢ èŸ3H€sä‰S,YÓ@‚Ó¡V\àh°¦è 2Zür&•;øØa )px"E@Â7$Pà¡D˜k L\b"…‚”ÀáT#( !ù,§ÿ¨â–`1åƒ F0€€…*ü™’À›#°8` E`”2™Lp!â ’€ĂdHÄ?@´ùƒá37ẬÇDŒT‚₫™3åD‹g’µóCŒ (uâ!G‚å°ç„Í^$d¹y‚–\è(¥‹;ÀÁáA‘#9VDT @‡$ÖÈ!¡Ô„8L$ !ù ,©ÿxGÁ0&$ÁÁƒ' ”Àç‡0ÀAG!•˜XAĂ¡‹bf$,ÁA€…<$±`‡‰Aü9…Gœ ¨Ä`bD  Բń‚,H? 0€aÉ HOˆø‡ 9DṆ̃'Ë&pêùđc`I"$́²§Ä) qÄ(AO+ÀX ÑÁE˜à €ÀR* ̣¸¡0 !ù,®ÿ˜¡Å &Ḷ€L€ VĐ(˜eA‰;˜8p‚`†B"”   Iȃ côøC ªLüåĂ?R¤¸°Sàœ2 BHà£èjÊd‰ ‰Ó Q¢ÀjQ”=è0¦h i´ü²£”€8̉Œ†„, 0¨“#a9L̃°™ÁÀ͇ &î`¥D¤8UÀ€I‰' !ù,§ÿxÀH #&ô‘¥ƒ† ((ĂÄ v˜À¤ˆBK^àA ”"GđLH¸â¢…h&ˆ`"p„€/'@€àO $Lè¤Ç Æ´*ĐĂ!Tv́đÂôÏ"0–pè@•é l\<Đƒi?tpüÁÁäH„¡SÆQé$a:AÔ(”‰ ÀŒ):h ¨34Lß«b̉€`Sµ ’( ;spotweb-20130826+dfsg2/js/dynatree/skin-vista/ui.dynatree.css000066400000000000000000000240631226620506000237310ustar00rootroot00000000000000/******************************************************************************* * Tree container */ ul.dynatree-container { font-family: tahoma, arial, helvetica; font-size: 10pt; /* font size should not be too big */ white-space: nowrap; padding: 3px; margin: 0; /* issue 201 */ background-color: white; border: 1px dotted gray; overflow: auto; height: 100%; /* issue 263 */ } ul.dynatree-container ul { padding: 0 0 0 16px; margin: 0; } ul.dynatree-container li { list-style-image: none; list-style-position: outside; list-style-type: none; -moz-background-clip:border; -moz-background-inline-policy: continuous; -moz-background-origin: padding; background-attachment: scroll; background-color: transparent; background-position: 0 0; background-repeat: repeat-y; background-image: none; /* no v-lines */ margin:0; padding:1px 0 0 0; } /* Suppress lines for last child node */ ul.dynatree-container li.dynatree-lastsib { background-image: none; } /* Suppress lines if level is fixed expanded (option minExpandLevel) */ ul.dynatree-no-connector > li { background-image: none; } /* Style, when control is disabled */ .ui-dynatree-disabled ul.dynatree-container { opacity: 0.5; /* filter: alpha(opacity=50); /* Yields a css warning */ background-color: silver; } /******************************************************************************* * Common icon definitions */ span.dynatree-empty, span.dynatree-vline, span.dynatree-connector, span.dynatree-expander, span.dynatree-icon, span.dynatree-checkbox, span.dynatree-radio, span.dynatree-drag-helper-img, #dynatree-drop-marker { width: 16px; height: 16px; /* display: -moz-inline-box; /* @ FF 1+2 removed for issue 221*/ /* -moz-box-align: start; /* issue 221 */ display: inline-block; /* Required to make a span sizeable */ vertical-align: top; background-repeat: no-repeat; background-position: left; background-image: url("icons.gif"); background-position: 0 0; } /** Used by 'icon' node option: */ ul.dynatree-container img { width: 16px; height: 16px; margin-left: 3px; vertical-align: top; border-style: none; } /******************************************************************************* * Lines and connectors */ /* span.dynatree-empty { } span.dynatree-vline { } */ span.dynatree-connector { background-image: none; } /* .dynatree-lastsib span.dynatree-connector { } */ /******************************************************************************* * Expander icon * Note: IE6 doesn't correctly evaluate multiples class names, * so we create combined class names that can be used in the CSS. * * Prefix: dynatree-exp- * 1st character: 'e': expanded, 'c': collapsed * 2nd character (optional): 'd': lazy (Delayed) * 3rd character (optional): 'l': Last sibling */ span.dynatree-expander { background-position: 0px -80px; cursor: pointer; } span.dynatree-expander:hover { background-position: -16px -80px; } .dynatree-exp-cl span.dynatree-expander /* Collapsed, not delayed, last sibling */ { } .dynatree-exp-cd span.dynatree-expander /* Collapsed, delayed, not last sibling */ { } .dynatree-exp-cdl span.dynatree-expander /* Collapsed, delayed, last sibling */ { } .dynatree-exp-e span.dynatree-expander, /* Expanded, not delayed, not last sibling */ .dynatree-exp-ed span.dynatree-expander, /* Expanded, delayed, not last sibling */ .dynatree-exp-el span.dynatree-expander, /* Expanded, not delayed, last sibling */ .dynatree-exp-edl span.dynatree-expander /* Expanded, delayed, last sibling */ { background-position: -32px -80px; } .dynatree-exp-e span.dynatree-expander:hover, /* Expanded, not delayed, not last sibling */ .dynatree-exp-ed span.dynatree-expander:hover, /* Expanded, delayed, not last sibling */ .dynatree-exp-el span.dynatree-expander:hover, /* Expanded, not delayed, last sibling */ .dynatree-exp-edl span.dynatree-expander:hover /* Expanded, delayed, last sibling */ { background-position: -48px -80px; } .dynatree-loading span.dynatree-expander /* 'Loading' status overrides all others */ { background-position: 0 0; background-image: url("loading.gif"); } /******************************************************************************* * Checkbox icon */ span.dynatree-checkbox { margin-left: 3px; background-position: 0px -32px; } span.dynatree-checkbox:hover { background-position: -16px -32px; } .dynatree-partsel span.dynatree-checkbox { background-position: -64px -32px; } .dynatree-partsel span.dynatree-checkbox:hover { background-position: -80px -32px; } .dynatree-selected span.dynatree-checkbox { background-position: -32px -32px; } .dynatree-selected span.dynatree-checkbox:hover { background-position: -48px -32px; } /******************************************************************************* * Radiobutton icon * This is a customization, that may be activated by overriding the 'checkbox' * class name as 'dynatree-radio' in the tree options. */ span.dynatree-radio { margin-left: 3px; background-position: 0px -48px; } span.dynatree-radio:hover { background-position: -16px -48px; } .dynatree-partsel span.dynatree-radio { background-position: -64px -48px; } .dynatree-partsel span.dynatree-radio:hover { background-position: -80px -48px; } .dynatree-selected span.dynatree-radio { background-position: -32px -48px; } .dynatree-selected span.dynatree-radio:hover { background-position: -48px -48px; } /******************************************************************************* * Node type icon * Note: IE6 doesn't correctly evaluate multiples class names, * so we create combined class names that can be used in the CSS. * * Prefix: dynatree-ico- * 1st character: 'e': expanded, 'c': collapsed * 2nd character (optional): 'f': folder */ span.dynatree-icon /* Default icon */ { margin-left: 3px; background-position: 0px 0px; } .dynatree-has-children span.dynatree-icon /* Default icon */ { /* background-position: 0px -16px; */ } .dynatree-ico-cf span.dynatree-icon /* Collapsed Folder */ { background-position: 0px -16px; } .dynatree-ico-ef span.dynatree-icon /* Expanded Folder */ { background-position: -64px -16px; } /* Status node icons */ .dynatree-statusnode-wait span.dynatree-icon { background-image: url("loading.gif"); } .dynatree-statusnode-error span.dynatree-icon { background-position: 0px -112px; /* background-image: url("ltError.gif");*/ } /******************************************************************************* * Node titles */ /* @Chrome: otherwise hit area of node titles is broken (issue 133) Removed again for issue 165; (133 couldn't be reproduced) */ span.dynatree-node { /* display: -moz-inline-box; /* issue 133, 165, 172, 192. removed for issue 221 */ /* -moz-box-align: start; /* issue 221 */ /* display: inline-block; /* Required to make a span sizeable */ } /* Remove blue color and underline from title links */ ul.dynatree-container a /*, ul.dynatree-container a:visited*/ { color: black; /* inherit doesn't work on IE */ text-decoration: none; vertical-align: top; margin: 0px; margin-left: 3px; /* outline: 0; /* @ Firefox, prevent dotted border after click */ /* Set transparent border to prevent jumping when active node gets a border (we can do this, because this theme doesn't use vertical lines) */ border: 1px solid white; /* Note: 'transparent' would not work in IE6 */ } ul.dynatree-container a:hover { /* text-decoration: underline; */ background: #F2F7FD; /* light blue */ border-color: #B8D6FB; /* darker light blue */ } span.dynatree-node a { display: inline-block; /* Better alignment, when title contains
*/ /* vertical-align: top;*/ padding-left: 3px; padding-right: 3px; /* Otherwise italic font will be outside bounds */ /* line-height: 16px; /* should be the same as img height, in case 16 px */ } span.dynatree-folder a { /* font-weight: bold; */ /* custom */ } ul.dynatree-container a:focus, span.dynatree-focused a:link /* @IE */ { background-color: #EFEBDE; /* gray */ } span.dynatree-has-children a { /* font-style: oblique; /* custom: */ } span.dynatree-expanded a { } span.dynatree-selected a { /* color: green; */ font-style: italic; } span.dynatree-active a { border: 1px solid #99DEFD; background-color: #D8F0FA; } /******************************************************************************* * Drag'n'drop support */ /*** Helper object ************************************************************/ div.dynatree-drag-helper { } div.dynatree-drag-helper a { border: 1px solid gray; background-color: white; padding-left: 5px; padding-right: 5px; opacity: 0.8; } span.dynatree-drag-helper-img { /* position: relative; left: -16px; */ } div.dynatree-drag-helper /*.dynatree-drop-accept*/ { /* border-color: green; background-color: red;*/ } div.dynatree-drop-accept span.dynatree-drag-helper-img { background-position: -32px -112px; } div.dynatree-drag-helper.dynatree-drop-reject { border-color: red; } div.dynatree-drop-reject span.dynatree-drag-helper-img { background-position: -16px -112px; } /*** Drop marker icon *********************************************************/ #dynatree-drop-marker { width: 24px; position: absolute; background-position: 0 -128px; margin: 0; } #dynatree-drop-marker.dynatree-drop-after, #dynatree-drop-marker.dynatree-drop-before { width:64px; background-position: 0 -144px; } #dynatree-drop-marker.dynatree-drop-copy { background-position: -64px -128px; } #dynatree-drop-marker.dynatree-drop-move { background-position: -64px -128px; } /*** Source node while dragging ***********************************************/ span.dynatree-drag-source { /* border: 1px dotted gray; */ background-color: #e0e0e0; } span.dynatree-drag-source a { color: gray; } /*** Target node while dragging cursor is over it *****************************/ span.dynatree-drop-target { /*border: 1px solid gray;*/ } span.dynatree-drop-target a { } span.dynatree-drop-target.dynatree-drop-accept a { /*border: 1px solid green;*/ background-color: #3169C6 !important; color: white !important; /* @ IE6 */ text-decoration: none; } span.dynatree-drop-target.dynatree-drop-reject { /*border: 1px solid red;*/ } span.dynatree-drop-target.dynatree-drop-after a { } spotweb-20130826+dfsg2/js/fancybox/000077500000000000000000000000001226620506000166715ustar00rootroot00000000000000spotweb-20130826+dfsg2/js/fancybox/blank.gif000077500000000000000000000000531226620506000204500ustar00rootroot00000000000000GIF89a€ÿÿÿ!ù,D;spotweb-20130826+dfsg2/js/fancybox/fancy_close.png000077500000000000000000000027551226620506000217000ustar00rootroot00000000000000‰PNG  IHDR;0®¢´IDATHÇWkL“W†–RËÅr[ÑB±\œ ă2&!$&‚%ŒÁBˆLÄgd&K„%&Lpå¢3û· ‚Ûè#™„ Èbæ%Q(-½è·y¿æëG+â—>o|!//Ï/##C±wï^½^¯lkk ́îî¢wÍ‘Œ Ϻ[~HI(€mIIIÁ§N̉\»v-®¥¥E_WW·ûêƠ«÷ơơíË̀̀Œ©®®¹páB4~?ÀD:¬+ßÊHV®$#‡̉\¿~Ưp÷î]ăÓ§O¯X­Ö‰7’Çf³ƯñâÅ;wî•––ÆFGG‡ñ”lkSr ªâââBÊÊÊvƯ¼yóÀÊÊÊÏR²'O8̉ñ—/_₫é̉̉̉´¡¡¡j²Å6e›í4€V|ôèQưÈÈȧ‡c‘ b§¯áZ+<°™1ànSGG‡Ơl6¿fÙØưÄ}—Z­%›̃v.ª¶oß–ŸŸ¯,u2tûöm{lĺª”PäädÓôô´]Ø=ô¾ÀX“«<‘Ë9ê””]kkkƯn_"å₫₫~«\._ÙŒTÉ^ºti] ïíí-Ñjµ1d›9\ çË¡=}úô$ʯÂN·B*FOO•l ?₫Äû‡Àâ`.™PÛÈŹ¹¹{ªIÁd29k7÷¦§§›²³³7ÄX£Ñ¬ÖÔÔX\c₫₫₫+ËËË6²5::ú-l%`<ŒKM.BI‹,>°°°đ# wuuYÅÆ ƒIp_SSÓº0o3©(ùÄ:µµµö́ÙoxOṿ®ư„ø"₫êx£ÑX°¶¶ö€„³²²ÜvFÉ…¹7ḅ„„)=èfëbđđđUäs.$$$c: đ÷aöđÈÈHCqqq ½zơÊá)n………kbrȹH‡††ḷááÇÎDkhh¨ NÆX»ÛG¤A¿ÍNWƒv÷ JK É·*&%÷¹Åǜ™3i3Aïv–Ó—àØ@¼ƒ™ˆóñùùù1<{ö¬›ÊrO1'Ú¬M¬C}”¿ñ~ȺZâÔÄÄÄrœ³ß³°MÜ„º¤]I‰ rµÔKcccÎÚÿ̃K·är–°G©T¡\Ú¼ï©.·‚ªª*3·̀QÏ + q9ɹëüüürÂÂÂjPV}‚[ÉÀVI©­ârààlÆX5#m 2ö9µ³T¸±Íä4y×áßØØøÎ;¯¬¬4£Î¤ăăă÷0V“miË”ñÖ©ë\Çíá;ôë|vvÖR^^n–Æ]œH®é_¿#›lÛíp‹|t€|×¢„.ă’7̣øñă9Á í†Ú ®DÂÔÔ”E(îËííít(\jÉÛÜp,º]:´Ó#‘c‡´ê:;;ÿxôèÑ́/Ï̉̉̉<. ÷Pư¼S"5²-·«@×”]“|vU=ºN;-^:xđàïçÏŸÿ‡€m<**j„æ€vé1ÖMe[^¯>n—=ŒaQ6~œ¾‘ư-@₫·Ñ™LÖÈs'X6‡ucØVÀf×\™hçjËn^9; |T•Œ ;̀2©¬³ƒmlz½•~E(¹̀BÙH,È;Iå“&ÿx.–eCYWù>_¾"(؈Ư(AÏ)YÖOôưô^ßP³̃éù´*fq-miIEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancy_loading.png000077500000000000000000000237231226620506000222060ustar00rootroot00000000000000‰PNG  IHDR(à×2/'IDATxÚíƯteeƠ7đ±÷̃{Ç̃{ïvEÅ^TDQl€Á®YV@_E¬K&¹If’i™’LÉôÆ0ƒˆ/|k}ûwÖóä;s sO’sïä[Yë¬$gnröÙÏ̃Oùÿw™7oïÄuT\¿ˆëü¸ÎëÑu~zæQI†)ÿ½"®‹â‹kQ\Ă=¾¥g_”dÙëß!qMĵ$®V\ûéj%Ẹ̀Æ,܃Ko°?…+ I–…q=ˆ€GǵjW’L#àÙq̀!ạ́E¦_ÍK^4\Ắ«¯fÿ:/¹øllƯínw~ô£½äZ׺V]'Ùf¤ÁVÉf}íÿîw¿»y||ụ̈G>̣‘‹k²çá$Û´lƯđ†7:öØc×Ç5q½ë]¯ÚƯèFCgŸ}öö 6\ñ¢½hyđæ7¿ùĐ=îqá›Üä&C½°ÿw¼ăB´Z­KŸÿüçf₫MozÓ¡ưèG[FFF.{îsŸ;ês×¹Îuïu¯{ ?èAZt›ÛÜfA·,iß[̣̃–±óÎ;ï’ï}ï{›C{ƒ×¿₫ơ 8<<¼' x»ÛƯnÁđ€E÷¼ç=‡ưWŒa¼Ơ­n5”¼´C·àä“Õ|₫ùçïzƯë^g¾êûƠ¯~U ñ¸<¥ußû̃wä₫÷¿ÿ¢[Üâ“Ú‹ûƒaƒµ ø|`M´‘}¥̀ÚÓ¶́‚ .ØuÖYgm!úèG?:Aà̉ÅlÏĐ̃ùÎwü»́=pÀ‹h½N[GqÄ3Ï›û₫÷¿¿™VK‚Mù{·¾ơ­ĐG!léïƠ&`+käÚ×¾öäÏw½ë]‡=¼ÓChÑp–½ØKU\m: Ø2ç½ăï?́°ĂV¿ímoë[ß:v衇®~æ3Ÿ¹̀ÿóÖNºå-o¹à>÷¹ÏHØdqñnRań(`¿ý«_ưêÆ¸6|₫óŸ_ÿ¹Ï}nư7¾ñüà×p*Ău—»Üea,K±?́a+.k6{œơ›Rüà/~üă¿$₫èâG=êQKâçEa‹ «N¸₫†•&æĂ!̃Î4\¬v'q™ăơ¬g>üá_ÜÉ–Æ‹oûÛ/˜ÊA:ü₫ô–:“ëđ„¥l2†{"–»UmKàƠL$&ê…ÏxÆ3–=ùÉO^Ê›ÙcƯ^\\V…7½éM«bµXó¡}hÍË^ö²ξ~»¶ gLÚÅœÇÑÂ4?éIOẒ¸Ç=n‰ ¼ârWM@Ó‹ÍÁqÇ7AHFnÚ±BÄœ¸̉=ë­aô"¦vú̉—¾t¹éˆÀ¦‚0–È¥̀¤‚&« ÈN,mÖ̃Û̃ö¶Ù9úc¸—¼ûƯï·Âê‰O|â’×¼æ5+ă3 h-¶b£¡µ¥iƯm™ă%ÚyWpiip°ím[w¸Ă¾á oXyÈ!‡¬2̀î±³—¼ä%Ë GĂJHó̃T/Ư­ 뀷§5ÎB«„c4¬!p1¬–ŧ?ưéK9 ­ölËoMÂÊ7¾ñ«̉rW :è I³sÅ₫pÔZÜ+‹áñÀ̉JPZúêW¿zEy^ûÙÏ®í[ÀŸ¹ø}ï{ßꉉ‰Ç‹lgŸ]Ơ !LxJ>£ÂLߨ¯¾“N:i£!†Ë&3‚’½<ư>à'³¨WÀ7¿ùÍcÇs̀:ö•ø¹ù@MÆpoḄ¼ç=ï?ưôÓ·‚>â³W^yåU_ÿú×7&˜¸àóà2×Í“~ó›ßÜôå/yJN₫;ꨣւÛhfC Ăû׿₫ơHáâ~Sƒ”ñ%ÏÎƠ„0₫ nÖ̉ơâ¿x9¦™ÑJŸ‹`FÁnÀK/h*}¾v'é÷P6s̃Ä¿Ỏö±KP_IÀ⳦&­ÈÍƠ'àT÷¬±ÂOæ*O²G̉đ$ Ỏđ$ Ỏđ$ Ỏđ$ Ỏđ$ƯàIZ3À¡{Ç“8T‡Ư´Ÿ{Ê“8ÓFX̃˜Đ¼̀“8sÀ¥ö³Ÿm…]g?)Ưë>OâI¨~;aĐ}ç ºSO=u³Ó{b X“=0Æn ¸Oâô§–%áœL“YÀ”24_øZâ”SNÙ”ÎÊÓu¤ê&Œo’'q6*lµ đ@$¸´dI %Ø`ÀĂ?ÿùÏ·BúŸứgæ!‡é$ø¤5¯NèCÔ/jÁÙ7Ù]PS„ºá«†¿øÅ/n€ËĐ́²eË₫ơñ|]f>Í₫đ‡?Ü™<™ṕ¯MƒĐ­O|âë #AœA‚jArĐ*P› \÷9P¤m…r9¼ôâ‹/̃½~ưúË{JfPŸ€¸pˆ¥Â•%¹y³sM<‰{ñ"…ƒ»tăÆW,Z´hæ FØ-¤Å~ XÀt¨‡ơ½öµ¯]µzơêËQ²06Ø 'iµç“°³ä4ûD8-³ D(Ö–OBcJ.óöÀI)ipA`eǺV†âDC¹2W’đêÙ –„—± ¤­cæ¶w½ë]cáƠË3rÚIMbL?ˆDœ]Á• kÉ'Á³y¬¥àíS®\¥•Áß@‡ñt¿—¯®ñ$fív²¥ —̉ƒZÓÈm›Rl§Ø¢¡~Îs3¸ºk̀ #{ECÄHŒ¤|ºúyñ‹©¥ 0Mî‚ÚO‘‡7iơRá C̀¸É!³Ăªç“ÄzºLî!Ù!LÚC$¸g(Ù{eśÔôÂAO2ˆÂE(J¾ª531Á»#ˆÄGÜÏq́j$b6Ó>cZ±œ¹—X¥ÇvßÎ&Mص̣$W›¡÷9C¨Êoø¬Åå,÷ä=±ÁrJ$/ö³I9­åû'1™'g˜Ü̉]¤-—¤v¤áI¤áI¤áI¤áIdîó$vØ0Í%d¯œ‘¨¦2XwÙ¯ù$Îè¸B°cB{@ơ¯}ík4×Jµ–JJp²ëOR”ɘơÚ8v̉VŸĂ˜N„ºĂ“{"•€ùƯï~·]Ùƒ̣$âáÔâ©ñ$ÎÅY@çc¨>fà¿øÅV,@)¬¹«‰J*©¾¦\ xɬNuĐ¹³o`Ø«>ö±­uËĂ-†P}.ç•ñ$u˜ùư^?£¬ÁÊ(‡¿:Eû  ²tt~Ée¡»-àä°AàÔà´Tͧ0² V;ÀPnÄîEœJÅÚ§3äƠ$D©64ƒÀL€zª Ở̀"†xˆË@µp¹î„NX¯i@̣ÜĐ¢Vy%€xdø2OâˆI@é†Ôëgçbé÷nVX; Çđ(rPRyVmÄ~=Xôe†ĐÔ~WM@v(Xl5âG ,hms ¨Ûµ‰iESeÍ £=„!]€"÷§âIÜÏåïåụ̈—¿Ü&‹= s®R̀iF< \¡Ă₫”kéP [ÚÚ²ÿøÇ[Pfsóưºy’V‰')pe^iX÷µjø?Å̃ä•”x’ÁÚxg²…fù¿Wbh^µº[-öû¥/}iî.¼zƒï£ ƯæÔ.iv<‰8Èœfåà œ‚WçóNF₫ÉøE]„«Û™¯₫₫₫Kv5 'Ú¡ÇÀ™ư܉+9F!µnXÊ»ñ^¸\ö¥Î•¤(oívع´Lâh±Ñ“lîânñ$Eˆ<„ŸêR^Ó5]óc½^}ƠUW]¹nƯºGÛ®-Z€t…íd‹´‘{Œ˜±́pè©êåÖ]~™­üiđuWè%†£K±ươLÔ¦œ‡ !ÙNªe9`"vϰ³K+ŒûVv—Öï~ {ôœX²dÉe;wîüO¼ä̉ÚwvB(ô~Ï û²{†Ix>œ’³ ’7Œ'ưùOvÖg™ Œ­Iyơ5PiÀ[´•ÛåTŒ”=VP’û°™4ẈÖîm·Ú·^´ÆY59~Ÿ€âr ‡—°)`¯=åIlp¼8ïiŒ°¶û¥₫t!Zé)Ob¸íùØYÇrûÁ”÷´ ¼ ª˜äפ¼›¡%v7O2Ă£h­<É`Ă“4`5ÚJÑÁưâ 1Ow'‘<0T®œ€æ¨đ•.2øï|gaƒ¤Úó´6%ÀḶ$ÓÀ« èrˆá›äI1C‹+ñ'đjèÊ7mID#Ç$ gèăÆ£ÄƠÚ6ÂqöØ t+†pBܪ3°a…Ü‹ơgo¹Ó3ÜÚ=M´<*›­“¥£÷q²Ưúà7Ñơ@; \ê>ÁJ¥öâI„*(¦ï¶,„ §<É@®£¸’́Zí0)Ư¤§,œ̀Ê×Ë“äË<ä́̀°vªJÁ™àˆ¹”ßåơ¯T§!h Æçí¡T.ß{h¼ø ‰èÂß©.eè̀®0XNtMóTüV±nQKy5¥₫°Ÿø:_#áe›´£:x’\xIe<áÉ~FåøÈÀûÙ¤ôÂzÁÏŒ'aWV wâIxº̉~6é÷»Ê“ $Ä´¨m”‚'®Ñƒ~¬×+V¬ø×\°ëøă_ŸêcÖîÅ¢ªdTpnwbèđ$eD5kN…F}L„Xm¢ôä¶¾¾¾K#u‡̉€µ¶I7½ƒ°%À’“Đ¢µÖ°M÷[VŒÿÿZVí·D€DVâÎÁÁÁƯ¹Vmr äL¹Ç—áFÖär“¦LơóPÖ₫ö·¿]â÷Đb^(–Ëå₫¯bêŒóIZ9¡ọ̈îDÓït;9í´Ó¶lÚ´é?±åZ×fwƯåI`gbÂÎMæ y.˜8‘ùÇ… ^µ//KMöú{²å· ȉ,yÈѦCœ,̣‰mps̉÷L@öÆsË́Ù¢!/yu? ;«”*Ùî•©´™Îî¥ëưIç5ưI¤áI¤áI¤áI¤áI₫ky’\[¡Û­Yó$6¨‚…ßµ ¹xĂwÎ'qO,?ŒºÔÀ±%~PQœ …GêăIœ‰)ÑéP^µ‚E§úÓEÆDnz!Ö°§<‰œX5¶)G©ªŸj¤÷ƒˆ7Ư+W¸èZ>I9ªÍÉ VCÈÜÙTŒ+̃DĐ-P):o¬¦iU铨´™¶XúpH@â72¢ï¬+J]·¼aô3maD³Ë,œ328NªQáX€Ê©‰Ë­ăÜÏmÙ­j2¯Âar±laöÁ<­FÉ{ÊImè.„Cđ^Ú1¥ˆ¸t¿Ä“LÚ)“xBh »¤ë {„u«Iá™@¢pÅ´Z¦&¦BYi÷È#\ch47G©.`{T%;Sä¦Jx½àoSSY»µñ$Œ:]2µ˜xa€Sµ[¸&­³SL"1ùqS¹1eè̀'D¦D—%Vª“H¸*O‚ü á _˜¤Ç5!˲8kÄ$ w†K›ßRöJĂ[ {z¹Å₫ö²/µ̣$…'¸OÂ,"bq“~~ÙIjÏ'É•ŸPaÂå;¼̀ÅxàèŸÿüçh(?®¯+<‰aå,"Íٸפ̀›K}2XÙï%Ä4Xm°LÊû©‡)UỪR¹Êz&jÂÑ!ËUÁ¾©9OA= 4±FƯºU«V]®Â£a5wƺ+ …¬Æ\Yª[ù$}ŒöFFFöQHKư„ÁËÎđËŸ“kđªyÓk̃3» kL;Q6r›Œd á¬'xâœ»ä ±f/‰‚tré¶äR¨½Ø° /‡{‚ÿØ“¼²Ï‰°øĂvSÉĂÏ>û́mHíí¨M̃ÁÅ–Ê盈(¹)2¿v% ÷ÙŸ­VÊaê) Ñ߯V¶D™N¦¨ĐÓ®“•›ª4CcÙ1R€xmÓ̀d&©‡l±;m©«̣$4m˜9‡\_Í̀eÖ< ÊGºRhrËo¬X¿­… UöW—/yN–ÅÚxp M.:¬R?¦àIÂY“·, _+4è,`;ô 954Q[pƒdñû̉@‹cH§äơó¦hàS'ỎZ<ôĐCWÿăÿØ=G®Ÿ´8ÿxĂ Ù×eưkfÖíÅ-FPîv¸ôèèè¿ ©xc—8…v°’c‚!«6‘t5†Ÿ“ΣK)GơLỐPA¯Ư»wÿï¯ưëí&]ÙV³Î:k;àܤ͑ ¬6Øu SÊüêˉ/̉)Ñ<»Ö¥Nơ±Hà[›¦†bX¥˜¾;zàlÀ“qÄkt´̣¤ªR%>­@gÑù÷V,Ô9ưNWéê³.ˬ9çœsv$¢°ÅΔî3́ÖeS‹ô4N̉Γ˜ø»¶a·Tpá…îÊE¿¬½0 ë3äÁÍyt¥.€ƯçIŇÙÁ.ÓN¹ÏƒY"`)¹¥Ÿ½r¨RoọIl¥́”Ë<‰²‘¨¯RJd±g {\R¼®†¸Z/µ„¥Đ¨9Ç“ v!§¤áI¤áI¤áI¤áI¤áIºÂ[+O2K>ω|’©2µá-¶÷S){Γ\¹ë½Ă= [U•RÂK+wLà̀«€àJ  Ä]†Dn‰vF¦œjơîLÊ[ ,Ï] 1Át¸ èw‰C~ơP?ObXSCåÉŸ D‹ĐV÷Ä¢!rœµ<¦©Ly‘©ºRÖBCBôAĂwÖ% *¹4pÀsDNÂrÏkª"¿WR{­NááØ¥\ÊÅ}¶¥©m¢#&yÂfmf›)ÇDakE·p´G3pL­€3O20Obxip.j“Gs¢ºy’½ĐØ2Lê߉'¡I‚™~RÎ`ƯNR€@†)W#+׬ƒ7È«sÇ̣ivFí(`?#W¦%€Éín¬…Ç–ÀwD¬êº2û¹/íC_ sîªáă_eí(à|83\zíÚµÿ îËôÀVå·¿ưí䉨ˆ–yP’ _ç̣sj>;"̃,´=j ®<è ƒVhwîçôö•xSgQÙÑ àw}­°±˜¶“< ó°Ă[ù{Úç›Ä±¥ÔÉ₫}f̀' cŒ6FcQÛhỤ̂åË/c%Á§z©>d·zƒ"̉…$Ƴ~ÄTñï|g3\úOúÓ%Ÿù̀g&Û.×Ú§#!ó[m@Árëô ³üIF¨m¢6œzê©[8H¹Ië-À“œt̉I›h̉PªÍee·Øơ(F·>Uí3ÉóâÈJ ¶j<¥øÖ·’(úe˜RAÎbøh#êm3åàI°˜‘u³Ñg¬6Ñáj-­¥h¤₫¼%Ă¡äbNµ Ø6„ưŒ₫ä“Õ$#w°Rc0QÖæĂJxûÁv‡ëj>‰¢`J§é½DCyUñ½ú‚‰Ù́³n£¾0PRzµa•†»€ö8MîxEc2_Ù])¹¥%]7ÜÉ̉y½äIrEÇ, ÆÜ¸ơejÉ÷­6å65û'ñ½¨ü¥UCLaíu·êÎ-©'ébÂKĂ“4 cW¢/O5ûz(Î($âg ‚¨•'1¹j–¬¶Qd@́ˆ<‘‰}dæ@»á °}¥|:#‘Øùú³ÂLÁ¬W ¹xøá‡¯àJœÛ^^Oö|qæë,‰ÈÊù$ƒ‘"´>Äíqù)qđ˜cY87”†‘}¢&k5 çf@¸>¹&µVpd'è|ÍÉJmú‹AälŒ[ăæ9]ƒdƯØ+"u€ê¥ lº’ûlWl43‚F¬­Ç{́„|%A₫#Jk©Eׄw2Eëîöq7„¬à\LØ+s¶ mE£Ơ9kÇóvW/{Źö;´G, ƒa–’Ưeêµ¥ö›6H½êø7É“ˆ:*eÙàIPµ«”µ*¥D¶²—*Ùî7dÀz‹äN11uÔ^èNƯ­†'ix’†'ix’†'ix’†'ix’†'ùïäIlûsă€¹À“´ghçPyÛûÁyû‘'):¹·9®M!(Ñ#ex×öß™d†Íf$`Q; cï̃ºuëQ™Â±s~N‚ÅdÂAJ:‡ ´”÷̃¤@ôĂ—G)ƒ©ûd‘?âD—NpJ’ñ«ê£Oƒz˜ü'Ls_.O 8 !€HkŒä çc\IÊĐÙ«Fí„lEáåĂW&m\,®5E¨ï…x ö&77¸(# 4›«NµU2›½€Đ­(½̣߉'áņ³4¶¦:Mk©ë·KÁ4)´¤2¾́ûÀÿZ™ëƒ́£¾xs[Œu}ó ?ëïêèǾ1HÅơ‘ù0fíuµqn­̀0aßy°Ä@‰Vú•` P׿êu·hK.‰<Œ<5PÚJ2m•œ%öéáØLàyNïHEîFĐgQIoyEMVçIP ÅGܽċèd…'A6ªPæ3¶^˜% S̃ƯäPëuņfÓÎ'Ù«ĂFho\:Fœa–Ñáh×ÔBÈ””0Dvfµé!%³¬•>”´3H[²rR:áĂQs™è̃lùEIÍBqu®j)Ä,•tÙ$„ ¬Hik½AùÙ’ʸÉBRL&, È₫ÔpuÚ«X’²ku·Itÿ~¯¦´ă+W®¨?²Z­ ¤'ƯiͰ€2º½€¹ơíííf£Ñ¸Ă²OqúKđ{”\.$ÎN.Ê=”­îïïÏ…-R444d‰̃´'´G\\œ₫ñăÇáôX÷)Æb˜\æˆ\̀₫ÇÇÇ«ZZZ.X,–EZÜÛÛk‹Å:W¤H¶©©iK ¿wï^®R©Œ$Ừ±p~!!!Ês”Ÿ…“º"…ZâîƯ»f̉øøưwcÄÁ\"! ‰ÓÓÓOöơơÓ½^o…¯7]‘NMMY·́ç¼½½uËËËÛ¤kttô+èzăAœjbØ×ÇÇG‰(>7??ÿ wuu™#MJJ̉/..Ú‚‰~É”••™h~uuơôă0>µ—à_ø_₫¶V«½`0’pjjªá0R¤Í§ÏơÉo"Vl¾Hǘ ¼=˜=844T“““s™„666¬î’™ùXÀ³gÏlV[[[éï6·‡ÄÏÏOz›RZZú9 Í̀̀X₫Rƒ¶8ºoúúú¾‡±PN- ü¦ÑhΠÖÖĐóçÏ >¥–‘‘ap'½lĸP:ĐO”S̃J…Bq&--­’„ÖÖÖ,ÿÅ·{199i$ùêêêF™LöÆÂ÷K$’Ó*•ªåît–JB ¹CN52¶”Baú ˆĂ0˜?_›››#Áªª*“«üuENu/”?Ñ¿$Û›Zâ„ØØØ߲ܳđ6|¯s‡ÜYéi₫'4ôó€}ÁeK'à¤T*ƠÂÄ5¨8Oh^[îT®’’’Ö)**2rÉüù\‹± ı7Ä\ÀU^^^iAAA%H«n!zI»„€³gÏđ8°r4`¬H³/ "¶9•³D.É—(̣»—}}ư–»¤………F“Éd#ˆ± ‡tÛ—L ¸Hù5˜ñkÔëA|zzÚTPP`tæw ¤‰‰ ƒ ̉?0̃\%¬{ß%±{-̣Ơ¥²A^†ú}¼Á¥¥¥A!†Ê D&£GLBÊp Xnkk£KáPFºXçkqßC K;Đ9NH»¾ßÑÑñÛ́́́ô+' ‘=‡GĂCdG/Ÿ”Hµ¬ËáC`ßÓ gJû$›MUƒªÓF€~̀̀̀üµ®®î/n´ñđđđAÚØ§WymërúôÙ÷ØcÁH6EăÇÀuà  Ñß ´â+ư‰DơO„Xé ¸Ö ˜`³¾p·±¥¥Åj6›_°í¬₫,ö=J¡P(‰ÓƯÊQÙT999º₫₫₫ÓàØ$¢»wïÚ¢££7œo|ôè‘MX=Æ}¾—¹ó~(µ¹6›m÷ööZÅbñº'Qd{íÚµMA¼»»û´F£‰$nÖØ¸}!!!̣̣̣c”_…•ºÅ̃mö@WW—•8¢ư>p4XK$Ô~rqVVÖá¾¾¾`4íØk—äơơơ›ö½ÄưüüÖ·ˆë̃½{߀ë=ô«8ƠÄ‚°Üßß_ƒ(>677÷wttXƯ‘"rAäI¼´´ÔBvÏ=û íD ŒWí+́/ö_ñ®Á`È5™LOÈ8==Ưä0%%Å(ˆÓ/µ]Ùo V{”…>-øù°zphh¨>//¯ŒÖÖÖ́‚È[ñññqG ƠÖÖVÆ£/„Ưí# P£̃¦]¾|ùK2¶yÁZ­ÖHî̃KüÎ;›Ư7ärùè åỘ‘`ĂôzưQÔÚ2œœ´y›>'Nœ0 ©³°°đÂùưÀÀ€CJ;Ú)€†bʇĂ[£V«fffVÑÊÊWÂ;ƯM+'8ÛÜ¿ßLï«««ëe2ÙGè ß%,‘H`à%”»ÿÈĐ]*¹uƯT`ăH)¦/ ñp:Ó°ÏçgggGȰ²²̣̉6¢ªë| üöY ƠÙƠj'ÅÆÆàœ½ÅÆ[Øû·Êă‘‘#Ùư‚í|`Wp9̉ 8,•J pq *Îc€[Ʀ+ªª* ¸¶ö½pá‚™Kæ¿ÈçZôå’ÆÎts×úúúfªTªKH«!R‰ÀÛ‘‘aÂåÀÎÑ<€¾ Ó¹€ˆØçTÎ’§QL¾F‘ß>üëêê6½-..6[,‡èèèèôƠyÄí\2E¼t*à: âçáÆoQ¯ñ©©)KAAÙƯ¾S mç4DÿB=p8™{×!±},̣Ñ¥r ^ú}—¼Á§OŸN „´*ƒ¸Y>´)Ă5`±¹¹™…ë@)q1ç+Ç⮋@‡v2` q¬fư}{{û333S/Ư<¨Z³¸4<@vộJIÔÀ\./»®>]S¢xOrØU5¨:Í4xáç“'O₫~åÊ•8ÑFĂĂĂéĐ̀{zÇ&1—Û«Ï®ËF²‹(?._uˆ₫  ÿ›è¿H$ªăwÙ6“ÇF2—¿§k®hÇʼ/‡xæDv ø (…Üwm’x̀Aæđx½u₫r)™$ˆå•$ñI“Âÿơü.m•#Üa·MºI¡À~¹ûÛDú×E²i6,oïëvTéÀO¡IEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancy_shadow_s.png000077500000000000000000000001571226620506000223740ustar00rootroot00000000000000‰PNG  IHDRLW¡6IDAT×EÊÁ €0ÄÀa©!¢úo rü.?Û²kŒ;¨à fÓÖ7xº­n[gpKUùv¼dêău‡IEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancy_shadow_se.png000077500000000000000000000005401226620506000225350ustar00rootroot00000000000000‰PNG  IHDR‰ 'IDAT8ËTQnC13¼^¡Ú9zÿ M½ÁÚöç̣¤F¢$رž®×€]ó üÔ~Ớûđ¬5«;|ßïđ"yÖ¡ Àñ7¼¦Ñp‚EûbĐ£zŸ}®„»7©[DÆä:²¶²$0“'YRY£ ¡rƒÍM™ÄçpQơ:Pm.Q׫‘ƒáƒÀ <í@-§&̣BqR¹ °̃™‚/OƠSÙœ/z³U‡ØÑÿň„3%$µCƠ©Ÿß€Ø‡mX¢æÚ¤Î; ²,´¹ơ¸k£Øǿá½₫tˆ¶WüFá_@Ff̣Ÿ¿O#́|[Đ•?IEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancy_shadow_w.png000077500000000000000000000001471226620506000223770ustar00rootroot00000000000000‰PNG  IHDR̃’%.IDAT×cüÿÿ?Hˆ‰1)f ÑL Àe3C1;”‰s@å@˜ª |yc:IEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancy_title_left.png000077500000000000000000000007671226620506000227270ustar00rootroot00000000000000‰PNG  IHDR g%ê"¾IDAT(Ï“M(ĂqÇ¿öfLfS¼Få­¼dN^Ü(²œÄi5RJqÁÍq'å$J¡\vĐâh9ŒX+VÄ´©ÉKÏßÿïeûÿW~¿Ûÿó{ÿó|ŸïÈO_ÔĐ@+G*₫¬ƒä"/©eøl¹cÛÏd¨EÇXï7H:É0æư₫¸Ÿèöœ‘Öđ_h€Åïb._:Â~Ư¯#Âü#—×£†s ÅX ÿÓ<×̣#¿ûAV!FßîíÄ“`PŒ5Àêv½~Ø.åXDZ¶£%¢­ÔØ ZØĂ‡DΈ«9uêâ×Dµ!9Ö°N¥h~M™.”p*Đ–kaB%:#ÊÉ%|æW.MJ¾éUnL*­wR¥ú*Mc89VU’]í3 ®~öNQT4ahÁ+aå!ó_è"úmEÁß9ü Œ[́Ä Æ1,<`¯¢˜‹lä20ŒQùae휥íJûÅK„|V̉Æ£úÿ *,đ'Záȃ¿­¹IEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancy_title_main.png000077500000000000000000000001401226620506000227020ustar00rootroot00000000000000‰PNG  IHDR ýÚ‘'IDAT×c``g`eøÿ„n’ &Le`Èb`pg`ĐËÀW–VYṢIEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancy_title_over.png000077500000000000000000000001061226620506000227330ustar00rootroot00000000000000‰PNG  IHDRĉ IDAT×c```X ¨¤Å¡˜ IEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancy_title_right.png000077500000000000000000000007721226620506000231060ustar00rootroot00000000000000‰PNG  IHDR g%ê"ÁIDAT(Ï}SK(„Q=fÆcŒ¼‡Æc$Ê«<2V v +±RH)Å;ËY)+Q e3 M,Ébˆi)̣Ȩ‘G®sÍ?úg₫ÜoyÎ÷Ư{Î=Œ0 ¥s̉‘ ’@ACy;{ÙöN/—! ɤ£(B9Èá3/S|ÿ̃ë ÷~29#‚à‘Ơê»z—3Üdñ%*‚'T–‹ơ'I8C¶BPĂ²æï…ø|™käfꈋ‚áÙ q·|êH ơGÀ¶«o!¦íTa ơ{"k‹ưGK°±?Avø…đ¢ V:iĐÀU^:pƒjäq¼Qg\ ñD é¡)ÜŒ~–Iwø³­(EÍÑ{Ú¹;&,…m:c ¯¸–¶tÇx4ơ佺Âfù%Á`ËÚ5¶$^¬<ÊP,8Ñú(SĂqp`v”#Wù’&ß°7 ûNoÇœE'jPđ÷¡á(œa†`7êP̀@…ăpùạ̈®º*×0‰At –z­ê0-²k#èCåLùÍ»Å! P§CË"™S´Đ¡jê,d€̉4k@ëmt([Y"Íư¿‚ÿ/đkDÈỀƠIEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancybox-x.png000077500000000000000000000003131226620506000214550ustar00rootroot00000000000000‰PNG  IHDRH7BŸ-tEXtSoftwareAdobe ImageReadyqÉe<mIDATxÚ´1€0 Ư RÅʧyOQB!Q@†“í&¶RB Ä@¨ûLU6›{x³OŒDµïU=¦Ü̃ÄeÙk™Û`ͤĐZM´ ­.̉:íĐo;RĂN¬ÄL€¨Ÿó#tu+GIEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancybox-y.png000077500000000000000000000002601226620506000214570ustar00rootroot00000000000000‰PNG  IHDR(¬]́“tEXtSoftwareAdobe ImageReadyqÉe<RIDATxÚLŒ]€ ƒ‡€zÂưOG8 ºÙÆ>ØäK÷Ó-E„Q½µË€¾Ù§¢:‹CÎù©©ºÛ̃ÀÁX?˜¹”qơ®;Ö1ædo¯1Hÿ@59™IEND®B`‚spotweb-20130826+dfsg2/js/fancybox/fancybox.png000077500000000000000000000356671226620506000212340ustar00rootroot00000000000000‰PNG  IHDRFàĂ;~IDATxÚí x\eơÿ§IÚ¦M÷̉B¶@ÙAYdQ¡+»ˆÊVd³.€ "XvdS@A@”]”]AQ%™ỉ&é=MÓ%]è¾°ÔßùÜÿyçÿæöÎ̀½“™æÎôÎó¼O’›™IîwÎ{̃å|Îyc±îƯ¥M‘ö”´·¤½¹…Ú[ú7§èÿà÷ÑGZ íˆ#(ûÔ§>ƠwŸ}öé·ë®»öÿƠ¯~Uqï½÷âg¿ă9æùúZ_oH{WZ³´ziµ[¸Ơëß~Wÿ—L‚”Jë+­|=ö|î¹ç¾ă;vºùæ›w½đ 'üú׿>è₫ûï?ôàƒ{Î9猽îºëv”¯£ä1ˆ×èkK3 t†´i3¥%¤Mí¥–ĐÿÿåÛiDá“ïÏM~ơ«_}×]wíûÆo³dÉ’[?øàƒ÷₫çz|øá‡Ó–/_₫À¿₫ơ¯ă¿ñoŒßqÇG¨@ươ½<ÅÙÇúÄzS[₫—é̉övư¯%z#vÚi§a't̉¸?üᇯ^½ú9·‹-ú¸­­íc÷ơ•+W₫Y,lç8`ûáÇå½ô=KÜÂ\!­)$¢Øâđ?]îa)ùÄ¿ưíoïúâ‹/~íă?nă†ÅR6I×ù@,h÷¹½yä‘s¸¡µk×~,¾¦[÷9đÀ×vØa›ù˜Ñ£G¯™ä³²Ö™ÂM̀œ9ó£tsñ›lan¸á†©ÿ /8ÂÈưƯ)?(m{|a_|q›°äñÇ_|Í5×t|⟨gX¾ổKÛn½ơÖN±¦i8`n\>™©øqzµrC5eeeỞ ¦‰ơÔÉÍƠïµ×^ơ>qR₫YY>;qâÄ ¹‰eË–}”JY $E1₫ĂííVUUµßÿô§?½Qîá¹¶ƒ_aø´«:ê¨9¿øÅ/æ‹8]O>ùä’I“&5ÑŸy»$t’7UĘ@XÎî»ïî"ÿt̀u¦óü ] aÄRg>Y¦ó]܈{¨–.»Æ…îsüñÇwó9\pÁ÷dOÖNÎ-ÇóäoÆ8^Ç¡âS~ÿûß/Â,A<_‡å`!8`D²̃/¨0cäŸ>XǜYÍÍÍoq#]tQ·›d”̣̣)¶C–ećökXWé‚“Eëỉ>å·+%l 0?˧Uëgæ5t{TBLŸ³c[˜Ñ"̀₫b}§È>Ëïơf>´'lf^‚U¸-‹Hº’ÛÊÄ':sŸ¿ÊC÷€|9ßs Z~øĂ¶~ç;ßiç×,ṢÖ/|á ³ù=£O¦”ùÁ´ &Ô‰Ïq£؇°Ư†ki{I×=FnnŒ~Ó¼æ%AL9Öë’` —ɵ£ø~†ë8óù„ÈÎX§,¼æßtÓMóeSh£ÎÖO·Øa‡¦Ë2a¦8́̉Æ d‚ÇäK,w¢:Y>¬ûM·áƒÂ²A6¯>ÖÑè¹v´‰¾'x Í̉¯gzè¡3åffÈZd&T|Ít¿5̃ƒ™±8ÇF/,…†ă²$Đéú₫̉MN”QîrY&7§®½öZß–sÆg¬—y#Ê;ï¼×}æxï K‚„5âÄq¢_üâḉ·ß~32ù aT’¡v—ăÍđún‹H]àí*ís"ÎY"̣M²^zш3gΜ §œrÊz·ß±í{ï½—tĐ" £´3yO}ïÀ‹È“2ñü³đ9̉­:Ä„›\K…ͺ¢Lđ¦ËÎǘĂ?|£₫&‹Q)¹í [ûJ;RÄù¾Xá-² ₫âüùó̀ c LóeËsMÖt̀¬s ÎÛn»Eă-̉¾Ï{é{ßv`{æ™g6]~ùåm?ùÉOÚ¾₫ơ¯7pÓøªÛºè62Ùsæ,8pºág>󙙇rÈL&~>—F˜nỦØT:@Ú1ˆ#ƒOư¡;ï¼óí¦¦¦9ÿKñhooo–M­¸üí‡ƠRå}/Ϫ´Â0ä²h”á®qp ß̀heNÓÈ5ÖCtdhÆ}ík_›Ë°P Ù‚0²”˜¥sDa’[›̉؆§>áHí SÄ¢oC ù_ÿ̉—¾ôß«®ºjMVäïÈø"¿“v›ú”3ơµûë{ßÚİ`m$;hÆéÆ¥[ÍüÁ~ĐÂŒ1°ˆ“O>¹Q3 +‘-‰9Ÿứggéº(À"̃tvú|8^·0Ư6ĂơFÆj`4ùº´ïHû‰´kåC»YÚ¯äû_ñ½l\«¿û>w¢¾v¬¾—çfxZaØWq}º ¦Ÿ~úéâá›èN\Ă`%ˆ‚tÄãâ%vÂt Ÿ¨éă&è'ÏÍ-í›̉&i¬́ ư₫›ú»‰úÜ úÚ´á“@[›|ÚX N+2Ö`„¡œîẶáóŸÿü,œ/VÔƒư˜TQÈ₫:Œ×›¯áƯ}ơæÔ¶¿^Û]Ÿ³¾¦ÂíSz" {15²€l”¸N“Î^“ÂÈFRRă´efk¥ cÄécYP_½ÉÚ-*\m ₫®¿>·̀_§ Ѳº7jÍ\aÄ2fÉlƒ½##F5]˧O "L:±25ßF ±đ%Lơl+äB˜¼̉=¸±e‰Ơ§£ØR¦®”wÚ!·|4pë5Úá?!†a₫̃¤^(€ ~¯ĐW…¹¢7i‡}ôÓ 8T«ÿ[¯Ñ<Î’6/d¨Ù–µdM;ˆY“-íà†¤Ơô‚(5ú·Ưp¢oÚÁK‰§|ă7n¶Ăç‡v°ÄT.‘Æ®ù´-(Ê4ư›—èÿà‰2̉î"{0›t/f“×s2Ñ^¼¸…­¦Fÿ¦—0¾h·(2,ỏáy?{=/íö®ä›vp‹B7JåcüĐaç|}ÓAEÉD;„óơM;ŸÂC"ëü ßéh‡°s¾¾i¿¾Å/ívÎ×íà¢ưˆÓSÚ¡·9__´C6âd¢rÂù²SG|:œ¯oÚ!•8©æ1Ù̉8_₫ÿ₫÷¿Wëvư.‘¥ÿê1í`ÄñÍ%íó­ ‘]²6‚nˆÂ5îJ; qÂK;xùB!2_“§7\EP ïå—_^&#Ç,àE™IVó³|"Ê'Öb0´lè0̉›uÙl|â‰'Ëâl~yy¹ƒzaüËs̃Ăª:::Ö?û́³Kñ?=°˜đ̉t7ÇMl d^ Å.Eä«°"ºqkñu ­̣Ï®ÓßÇM˜E»_qĐguV³1ÿ¡ù•ÀDsÏ=÷,>ï¼óZ{́±.¬ăg?ûY‡ôá„@X 8“o@ÜZ°³Ú€œo8i#̀o~ó›…¢t']ˆaYœ`ó”)SÚÁ>°*bÚÁs^ươ÷!#Ît ̃×ǵ)Ü´ƒ‰(âTxnGÚqÇ71° kMèók'sđ !İ_Ø´ƒ=WáfñUœ8߸ŒL5X Ä8~)àä/ô´CÂÍùBSÑ}2ƯÖ‹ó-tÚ!ÁœE¶!§dˆnøæ7¿ÙpÚi§5AFéMf‚ÉT‘à¸< @-Ö#‹Á:åñ ’vˆă0eg«]–äí?úÑÚhW\qÅ<đ2CJe‡ B—â+₫†5•Îm “v.àP Œ.Üs~6\ŒŸ.A7’8g„•ÀëñƠGrWèi{!èp¾̀nỊ̉ÑœQÉ"ª²á|{vđÍù’!û­o}«AºT« ­™8_p3ü¯£[ú¤5ư8ß-B;d´œ%:™́5A†C`̉YƯŒ‡¬bĂs膈#]²œçÛ+´CFœơÄOlÙl đ!5Ăùʬr.‚!~«Àwđ•åa™đ!ˆ`öơPWVîRV¼-E;d ‘$aº ¹0ẁˆ±~–jÏ! îwÿư÷Ÿ¡ü]¤2ù̀ªơ\„¦¶ƒḈÖ™ß0fY   DÀJđ+ˆÀ° ÉéElf±$èÚ!ĐÖ&C87ŒÆHB‚>Ťưáxe>«‡ éi¶43Ûr]ۼǷàoX a ÁÅ)'ư ÏgÎCƒÎGmÓ 2E"s]ÛÁéÛm·]­5suü‡8¸™ ̣*Œó\†x,¨‡œo`ÚÁo˜6—µ<ư×X13ÎçÛk´C.8ßnŒo9ß@´CPq̉Ñaç|Ơv°›LL×fH¦£ÂÎùªíànPÖ¾ï¦ ´CØ9_ß´C&^ B;„ó D;ˆ2Ñaç|Ó~ɪL´CØ9ßÀ´ƒßyL&Ú¡ àÄ ´Ă%—\²AîơĂt¢ø¡ÂÎùöívη×h‡‚@æ{ƒv;çÛk´C!ÔóíÚ¡êùö íPơ|CK;øư”ă±Üs¾½F;ä„óeSÜE[ ½8tµR†p)¸CeE­₫‘H•Ơ_¬µÄ„d’ÔL‰›ó…»ûÓŸ₫Ô›g8_"–đ¿Öµ¢­íàPUˆ¥yĐAÁØU! ¨Èƒ>¸ˆh×dt¨¦Â¢,äVĂØäYÛ‚J-+2ÖQêÇB² êÛœ/Ñ8<êágÂrŒ0Z»’2*à­2u_¨±¦ :R¦ë›rí:CtÍ3L¿¯Đßơsu£ £ŒK’ó%¶$¨E+Å%úHaăU[Á[ñ1„W₫üç?wAnÊœbéZļ5̀›È1ÖÑO}ÈP)£»Ç+.߸qă_d‘XOă{®ñ;…êkJ3 ”1DK3UbGêWª€‰¨¨H·"H‚&¡ÓNâÖX̉́Ù³×^yå•óT„J,If]Ü2‰ñXöH‰v“j£%¬̣Çÿexđ«¯`Mÿ³• d9n/ź@Cäƒâ^\Ç1Kİ ê Én•¬iÖSW\»[6ÂØ¢đɽcÅ*&fÓ¦Mÿ“eÁê§zjD#Ûi|Ï5~ǃç̣]0L'NFa`sÅÑ΢́Åzn#Nóå9T>“]²• ,ØP__¿RF¦œ¯Ÿ1R̃÷»Æ̃ÿưRo¸]®Ïơjüç˜çóZƯ«H%oç‹€hR„ầpƒU² Đ$!Ơu¤æ@Fàczà|mQ¶‘ï™›”ôr)-×JÓxÏ5¯ă=tǮ«tA`Î?¢Î8mt'ƠHœ{qÜYXŒ½ˆ!”Ă¡ ­äæ₫ùÏveÄƯx ¯å=x/íV¾ùÇBdƒg6Ÿ6P¥ơáb€„b₫ª9' Bµ3¨Ăúú ªlaJ¬m‡…tø;76wîÜUAE1×*5ñw̃ÓÚv(É( •Ëp®’ˆÅL·™¹‰Í2JÍ5¤T¦OˆÄ Cfñ¨ˆÄ‹|L™ûèW_}ơư´7Iñåæl…áµ¼ïÅ{êhUa[MÚz¾|ºÜóĐT~Ö³|Ídy°y,„×™€óí£ó>Ññ!¸…›‘é@ÖÖbïÁ{ñºÀªËQƠóå&™Ă€ẹJ´ˆªD̀ípw†Û(i{È6åëÜ ĂpO…á=4àÏöÆú7ʃUN’(Û øº₫Fs ̉V™Ç³7®NÏ#Êù–ª‰!ÜOæ!ó5ÖÜÚSaxÛ̀×`›‰Bú"ª8Næ-2D;ø*d¸)qí•€UˆÉ)tC "| Ï÷™₫gó1Ct ̣ñ ÎN¿”ªĺ©0¼‡ú+ ¤Côo ñET1LĂÖ‘‚8ø†\n"¤\£Ëà7đ?Æ/1Lăx•ó­&•‡D ,dQ¦‹Á]¤–GaÓ¿1̀—0Z[ÓùÄ­¥8™U6ÖÉà«<KbÚÏ5¥À“œ/+mè9—`¸nGN”đÈ‚\w%̃S·='èßêë—óƯl~iJ̉RRÀWIEÖÍÍØEI³ä|» # á{¹v¾¼g`a¼†_ø^&~X‘™Í" ;u&e‡Ô=‡ ̃O6œß®4cÆŒ‡s=\ó»’GJ0µ˜l,„C_,a’]«±Êïg+L̉ùJ6ïyf‚'篴d+ ¯5<̃3°óơrƬ•́ªÎ\£®8>ƦÀ•ø™Éœ®µ²ÅY“õ´ăde\•«%ïÅ{f3\ûâ|̉™çd ;ûàIû‚Tù‰́έSl>đ"’×hÓ:̃‹÷̀v‚—Ñ,Î7×Ât[H;XÚ‰’Vó°Ùœ’½åeâË2n;đk6­x̃Kßs³%AØ9_{ ¤̀¢ïŒyóæÅ³Ư¨âµ©Óf8ÏQ|w²¾ö }¯‘^U…PÏ×½µ9JçŸRœÈHFà‹ị̈¦t“Öåúà{®ñ;£Ï=R_»‹¾—çÖf!Ôóµƒùư”|â†v̉aöów^¤öϵ]¥×ÎÑç|^_³“¾Ç +δY¤ ̀œo,…8ÚvTçy:Ræ$'YÈIzí}Îú!è—)ÿ:¬pb¦€ÛPƯ–§s‘ưt{¸¶CôÚúœÑÓ×o¸6Œœ¯Ÿ˜ơ@½Ùmtö:^„ôûíơwvˆÖw ;¬œo¯ơ ­+m1 $́œo·‡LG̣̉¼¡ç|·5*›ÖÇúJ+áç „ó ‚ưs‰%JR¿¢çëS”뫹Vª-)’_Q ‚óM!†»«ôQlqJ´Jư’SΗ=ÉY¬ÍçëĂbJ\ÍŸûJëÇ×|Q››ùl·ÉÙçå¶o*K±[©‡å1Êô{çç| ăp¾Rđ¢¢Qt®+Âä)"ât+"–+%RĐœ5…¥ØƯ%fYK_¦Ÿ~_n}˜7a…P}èꫯnȰÎp¾à"TTdSœkT2ă(hÉM\Êñ‰yÆ´2×Üϲ̉úë× Äñë_²â|‰ÀáQΗ¸’†ø”&¤§´º :­̣pYq¾N¶ÄåCŒƒ-S!L7 –2H…́wD ÂùPȉ-A²›´Ư¥ídă*eWbÊ8Œ.`©Ưǘ³V¦ÓÈ]¢nÂR‚Ăø^kă%c¯‰Œå °F¡!*Êhơ-;ªµLPaö¡åD¯m†_üBez A !‹"ïÖüp¾.abÖhdæ.U”*̀¶Ú…Æ«({JÛ[…9 ×Â$@̀ØVÀÏ0—ỀàgΗ9 >‰̉ûZ#/çk SâácÊƠjëH4ÂƠ&˜.¤Â|2§ÂÀ́2ỏÄ¿P~Æ’’¬nÆùê¹ΤOXç°À"r|̉U¶0%®å@_Ë¿ThW¦âŒ²º₫eWËjr' æ(â'æđ•.d†o E,‡a¿ĂŒTUüÇt&w¦̀-] q Âùª0ö¯̀úZnÍ_[ƯiŒv§±*±½r* <Ơ»$pÈt+nÔt3@D-^c ¯›d „¤?>GÏOɦ+ÙK3±3 Æ ơ5Ă­¯=‡ÉƯ¨”*‚$çÚ.~Œp,˜û ‚©½‰¨=á|=F%{“»ŸKœ!–¯íơîŒ@ù•’N˜¤ ©đ<‹®an?׫1pÔyJÎyA†wSêË”ë×A–8ĂÔ׌r- vÊ—0N)Z̉ŒY3i×r8_s~}B$'Û=)t́²˜WW*síÁ˜ºaj5£¬yÍ?‹È¬…Á:äF§[ơĂÿÁ₫ >ƾΨ„P|Í–óu9ߘ+̉×åˆû[₫f¨56Ûc̣*Œ×5fÄ́̃åóu- JR¬›́MªöV¦e=8äy&Ưêlæ7ÂxE ʬmM÷øk¹€@Ă‚jÎ×CwLÚ:1₫ǼèUØƯ+ˆ0¡ç|=¨…k}¬­ˆRkv\nOƒl;„óMA1¤Û”ZÚº9â&ôœ¯Gˆ¶Ä#4sÅ›́m2dk3ôœ¯Oô£Äe9nßăŒ`AɪPs¾0·Ï±»“}Í“ñx -œ€¢êcù/'Ư'¨(¡æ|³àîÜĂzrb˜(¡å|³„=ç?A)hÎ7èjÁs¾[̣jÎ×µpLç|3¶ Ps¾+ëWđ-o„óơ˜È•zåË‚>BÍùº̉4b”äÚbrÂù‚6É5çk-K\ E¯nI.…ÉI=_N6–²#ḿózp¾YoTYP}­]»¾®Ùm‰Ë¢úxqÁù†(Sh‡‚:¦6±#`ÅË/¿¼¨€éVÔ₫·ưàlqV‹ég­˜K]·̉ë¦>[Êb‹Ô*ÂäIL×ÅFGl”⣭R©":IUh9ís•‰z L…µŸ̉ß ôµVÍ|ƒ¼ “́DàđÀ:ÉÂù"ŒíÓJà a(î%µ5;Á\M¬)`×2˜đk…nU°„²Å)I±™•¿®ÄÍ[;΀ˆ‰%qm̉¤It¥6* ^`h̃-·Ü2_º“™MÇ5L[P˜áº™=ÈjF¤rk#ªÔÚw'^ä^F÷ơé&†ó%T‚0”±¥Û€”ñ3q%ÊÜ V¶HÄ2%±ăt;8`Iû°#̀6§;DăEƒ,hh€Ơ½¼q₫| t7ˆ7Lµ!ƒrŸ7›ºxƒŸ¡²µñ¦¥¼m;ôÖ…c–ª> €Ÿ¥|¶W%útÂl«Íd[¡¿í-̀2—(I«É¹0Ü4Ö84ø\÷â|¹N#¨O _9ix …Ơñ7”‹Ó‚~»̉bƯV£‰£Tœaê{YƯª¿Ơ­JÜ{3ùp¾ÎMõ ₫…c›íC3½8_†ơG}t1h½è;5(ç«ƯX¶WFZ]k°e5}­¯eyơ1&hoæ,ˆÀ(C÷I7Ëåw8lü u}-η:ç«øÆxg¬cH†!VÅ+PbÍ–“£S®„qæ,L̉ øj¾ç(y½ùŒơ|ñOrÖZ'¹2Jụư=÷ܳˆáܵ©ÀÏ®j9ă•u£Ưj¸¶ +$ë–äº+9yÜ™.gË(e*"fFêÿ¶¼ûî»ä,7-¯”̣Ú­>…ÙSÅ™ ÍXÏhuÈĂÔjºr•ÜùL¹ëJp¾”€„¸„f€£ăçL¸¼ @cu¤ó@”3Z8"´}üsaöUârOf'ËߌvùAỌ̈Á 4æuæK—ĂÛeXI'˜üIéfÈêS̃ ÊùÊ í¯Ậ́®>gœZ툇º&}îf~„¡ë@lâgèRVƯđT­RÖS­rô‡Riư<°˜‘,‹Qé0Tg7ơ7c]3Ô׸G¥̉¼Mđđ5|ú܈sºœFÆÜ†ư^G—¤æ¬|‚ rèÜjr´ö¦ß ±ăkvÖ®4F}̀HíJC,áùLi^&x Ó0»¬ßÀ5ÖOLà¸F÷Âï0#æ:3^ü®¯âÀŒRz­Cc^#ơ´6¸³ ×{jÚ]±Ôq:é³»Ñ Ë¿ô·fÀy®“óÄOƠùˆă?Ø­c•͈nFék„"7 ΗlZHNơ#Úă0c–Ùo›Öéôk1¦û˜iG R‹±×Nư=VÜ}̣¶ˆt… ¬ƒ0ÖbJ̉j5z]e‚́,Å}²Ưv°ç0;XÖ2B‡ê!1Ơß•ËT×µ’{ +Á #†ç”Ă&ßÑ”²E<‹Æơ`kÓ Ï;ª(£´ ÓVá²›æÜ"Ăủ±Âî2*™=,aØÖÔ3 ’‰`dó÷„óµmù•¡V²'ve®¨ÂÛÚœªIåN扙‡ s­+>Í^•û<œ!0†Ñi9ÛÁÖ^̀@kTºE÷cRq¾öê«À¯xq¾Y†TŒ0¦ë W+âÚ¨*w…Xú¤Ú̃Üâ7,&_œ¯åK̀\e kÿ·̀µṕ“*ê•€[̃8_+q¢Â¸K Ø¾Å«àNV])Ôœ¯kó»Ÿ5$—YƯ§¯Gt²¤§>&Ôœ¯k³Û½êëÊH‰¹Â(=&Ôœ¯ExÛ̃^‹Ä’t1¥l„ 5çëÑUúxDJ=|K… 5çë1—yˆá…ô¸+…NL‘`á•SP’kp(Ôœ¯Q•ªfÎQ³Ps¾®®Ô#æ·¨ºRo?"ηĐ8ß̃&ôơ|{ëúz¾½ơÈ%ç›È±0¯÷¦09á|‰1±ñz¾…f1¶u$ö,jT óWơ,›£ăĂ) Q)°3‹";6ç{üñÇ7P¡bÊpw„SÀ̀I³0PUƠT)&¯QĂ'çKÍ^©¨Ø¤à¡SäëœsÎi¾₫úëçÁÔ³0ÉîA”D”̀œ̃uhµ³8ơe ŹfbMÙÜB- œŒ́₫'Ë0 h…ME*qH8>†Đó[„o×ÂÇIÎ7[~a®®R(Ưp¾„JÄjááñè.B‡;%l)PJ5hjüQèbßû̃÷Z®¼̣ÊvW"Fa Ăđ í ]e68+ô¥©ÛË÷ÔâÄŸØÇạ̀¸†#†¾̉âës¯¹æyT…F0ơM…- psr3Óác°1F®#ˆb.ΗØơUW]5ï®»îBùøD Âù„ó¥ËàS¨Öe˜̀9Z@Ñè«\LQcs¾N×ÂĐ}2"“†£1GÆóZF1‹$/Ha qáÓ†Z ñ=7Ë :ïă&¹‚F~dÁµƒ›Y¡ O¨Sàö‘‡ÑS,2 sÊ)§4IrEÙ(äđU /¡¼v¡ ă˜=#œ‹àaÓÉCâg­²êk¦̀H¥¥àfâs¡9º˜f¾ÎäÙ-Beâ|¹d̃2¦¾>0çza€ ±|ƯJ“BSHlj³jhhXûöÛo¯Óƒç3Ó¨äT Ï$²Z¦‹°cTÆRÄIÏ8묳Hdvüä“O.©ªªZ)Ä,“‚6kíTØgŸ}v IùË_–jdas¾¦\$ƯÈÍùbASàøÁW7°́Ú¹T–üñÇ»˜Ç ]‘¼J¶"‚T€µÅ¸9_r¯™Û`-²rṼ=öØâY³f­a•]^^ ³­²²r%¥±Ư³Ưb[$…Âǰ$0{/óđĂ/1cÆ=ˆ¡’½¿ưíoË8‡ Ø̉“{1ÆZL=_¾>̣È#űoœ0gº‘; {3E/Œ5 'kÖ»cå&9…Éæ×áÅ»îFU­ï2 ·È¹& ¨è8_ü ´)hŸ,êơ|†ơÉ“'7Áɘ}cÅÄùÚ…L¢„'Ơ·Öâ©çkHp¨ƒ~ĐÈ6±œpF+ƒÂÂá’[ÀđÍW™Û4á›b…Êùâd–å&f€‡ác¸!œ1Î×0̀c®¸â '—À4r ”£)\ÎäCqv $zPœn¦̀\`ÑT“æ«5çëc%í¬•X@“뵪X±q¾t@DºŸº₫×›ơ‘²’³„´Z$È|''éè©x8_|Ö̉¬§K0?ÑɃ”\“`n8ÁP.dƠlf¸ø˜;ï¼³óÆóôÀF;¥ —æXxF'ƯoqRÿ‰Ä*€DJÖ2+æt42L^ươ刂E‘ÑFm_jõwß} ÅÚê‹B/BXN·#;/^¼á‰'X‚ơÈM;ø*•A¸_AÏ:•¿«b†̀B“S0¢´G‰È*œ)ÖRWW·Z(°8"7€(Åù”Ù—5RS¬ûB‰bä|™ÛL}ôÑG—PáÈQ˜á̃zë­0½zC¥¬©f>đÀœC°XKaơFiµR}uMMÍjeªØG¤W_}u鯯ăk₫ù%$sŶÎW¶,É·69ƠÎậ{îY(‚­°îHà_ØrĐá[ÎuÏI¥Ï°́qê_¶ñ¦â¨çËÎq¾±ˆó8߈óEœoÄùFœ¯ơˆàÄ4ˆóÍ LÄùF])ư#â|S ×çëñˆ8߈óÍ×¶C,â|Ór¾5ö)]±­‘óơ:\ ?¨™‡8‰ØÖÀù²çK­‡kä¨EeƠqpj;pƯ §Ka/¾2·ñ‘Ă^a@Wah”x£Á3!ƯÏ0d§H¡ăfr L£8ˇX¡s¾ f|µ1#úâ|)+‰Ơ1é#{…¯>œáƘI«¤ ÀÛIVI“—îOàp¬ùLÙiÉ‚•ªÄjªÏ?ÿüÖÿüç?+>’å"Ơj*ŚÍT̉ 5/»́²v0VÍ@)Î7³dl)ÜƯœ9sÖBO‘·D#̉5 C„ׂœAR±ØÄÇ?@Y[r´´vá'rươ¯]¶jƠª^xá…¥LÖ¨¾Êl÷¹ç[ ÈD UÅ‚‘l6ˆpMư«29ö V-§đ—2•o”̉Öị́^I ưx<¾ê¶Ûnë_½øâ‹Û~úé%<ú®»îZÀ‘ÊßÅ™ ák¬Ós ̃ÇØ,]7H%ç—_~y™&P$đ#‚®.¢{±n¢ûPfçëz}ÂgJOamT ñèZ’;àœCÀ"V́œ¯̀IjÅ/ĂïèÎ\sHp„±ÇñG8jë8¡ẫóeK¹˜Åù^{íµ ̣ÖÑÎø›™>’¶gƯ¬8£S}-aq¾*LuC%ç‹8߈ó8ßXÄùFœ¯yDœoG'¦yDœoa"Î7êJéç›b¸8_GÄù¦xDœo¾¶bù9J¨(8_!c÷«®çëu2ñh¶1=B#[çKèƒH#ÅtlfFS­BÇNm*dYü¸đNư!¶D•³˜̉˜Ú( Á504bL”{Ù*ö| ¹RÑPRt%„‰)0tØa‡ÍD@ÂZ<œ/Ư °FnºkX 8«©“Gà 2ÜFè‹’óåÆ-ẩ9=a ¬´ Øç{ Dhu;Ï—.ùà”Ô.³hq¶Ü44¸9̉™ëøqăÆƠ)Öä|ÉXñIâG¤X1Đ0»X –@ă:ÍmΗn„å$R¥ˆ ç\,œo·h"́1k(ÎLœ/–ƒ ăZơ¹ºXœ¯œ§;`à&—€Ÿ3ƯVĂ(¥Û)óæqLtÁ Çyr\³AKåtó.J· ³LjQͳ³Q̉Y´Ư §K¢œ>¨ªĐ S Gw×̃̃¾^®©­­]Í Å/½ổ2Y2!­ F.™ÆÏL₫ U˜<% O>ùäFrä¦øÙ¢/}q¾8aA[ ̉¼–¯>œă|Η®qÁ´Arfà|§2ùƒê´đøx,MÂi!. ªÄ‰VŸ~úéÍ=öØ’¹sç®ÁßX‚y‰YE’—”Ân¥‚"i€R<œ/Cîï~÷»Epw¯½öÚû7ÜpCI]4ÉAåÖ±**±2"ác@Î8›@N·hb™åYđ<†å|p1WÄY(™js¸18ß»ï¾{!–C—‘µS-T~‰l¶›o¾y>‹J,ǤưÉ)ÍB—·Xy’…=ó•™ë\º‰¦›đé ½„¡¡È*‘*Ï x³ă«¯¾º+Ñd¸Ù€&o²(„qug~sï½÷.¤,­&P$„ëmQt•µÓTº¢±ăväEYÏWƠS¦L™'»°3 æ{f¾ Uź Dbœ’ÚžQÅq@Ó°œ1k!Ư­›ÊI8ø«¨q‚cƒÈG<+¶5p¾, m°r @ä¢ÍufÇlWø̀(>Ηïu¨îÊ©îIM™Âç|cù©í[øœo Gœo,â|#Î7â|cçq¾œèzDœoa"Î7êJéç›b¸8_GÄù¦xDœïØvˆ8ߘç P´Us¾û1Î)Çà²ÜÆ,ÎÄŒp«±®éá»I‘Ú1àiÖµâæ|ÍIĆóE,†@›¹Fä€@¢©àZŒÂt#LYI¢†í@S1@Z1ÂZXÂd#S²t QL)[®a1Ûz‹"k#°ˆè§e¡“ ¸&g@®gBBobJ};œ¯©rù@0뢖±'J×ú,Ó~‹!¢È‘Ír¤ệ–––u0yzí0yœ¯Să—¬,AÄ‚3SLœ¯s:±jjQ +³̉ÁÆTc)ˆMN3̃gŸ}ê¬üEĂù:Å•ëuDbnâ₫á5&é"öÿàç©V©·‚ơ1qFk¦2Ù-·Ü̉)4C'ûÓN;­I-%ă§Sf.C—"¿€¯ülU„.8aªp”o¿ưö ₫E .—Ñiåư÷ß¿ÈR™„aÔ2É8m@"4­W¸ )íSÇÍÁøâH‰b₫8_g̃Bbœ£]Æp_ Î7YÏ'*a“²ÓƯÏÅê˜6ÇAW=_&eÇ|ƒ”“äˆøeR§·#–º´0̉blä<,O³á§ÊñÄ῭̣^ 04°¢XI£n\9 HÄc©  ‹ gÅXûˆµtPœdQ~G† V† MˆMØ_«Zkñ¥ۮ ßqÇt‹˜VwÆ:¤Jt«©u0zѶ†„ô₫k¹₫úë;t&¿W¿bRp 9gÓƠ4§ ø9_²ô­ªÎp¾Ơä"ßnå&%̀¨Dô ¶•r¾SYÿÜ¥9Ơ¹8;²(êùFœo,â|#Î7â|S<"Î7Å#â|Ó<"Î7Í#‚Ó<"Î7ƒ0çu¥ôˆóM1\Gœ¯Ç#â|S<"Î7_Û±ˆóM&6a×­óuŸÈeJJ²YÛ 9ßQAAI[h"ÎÚíđ]¶9}È[đÂT ©¬¬\ƠƠƠµóeåZ¥)~̀F¸ÁYÙ §¬-Å1ô\·¢æ|(¤„IÚä±ND\N°€‹A$­@iJ®.ÂZX!Xeèœc™9´q88S-‰đk©ÈJ| ÖW+B'C/v]à‚·HêQyÔOÿ=êViEÅƠ„lB½*02ºÄ’°(¬̀µ(„vyW¾ùæ›ïSÉŒRn Ë0y=ôĐb*Îr ̃ăk±â ¤héÅ›F9ü}hŹçÛjr”Ü¡-|\mêà$ÂÑàopÎ>+´ çÇ2è¿̣Ê+UóM@ª×‘g€…`=vY₫X‘p¾Æ’;PSD=–!ÎM· ±kùf4üÔ&N<ƒÀøù'çËhFwb„bÔ‚çgüP¡ SÅẸ̀ä“OvI["OătF)Y2 c4²QhPœü¬GB.çKÖÜÔ%ŸơÓöå+̃q¸Xøœé¼ÏGrWÁÔóu-¸ÁN8a.$g&Î׌JÖ|&óÄ’ Ϊ2\‹wNBŸÓKÍ¿8B̉ 5AäM¶[¬˜úè¹>-'üœ/H*‰VRœl¸^áq¤$aÈ䯙ç° nVÛ&%ơK‡‚·g%-Ö̉BYZ“*"̀ÆJkbHF-V UX Ö¡EŒÛ)“mvđ°ª@›ƒ¶Ûn»Úă;n‰½÷Ö&™øøI´h5¾‚%$¸- Å#¨½uœPqs¾Ü(Xt2Kđ1¶0øÎf"ziÎ+FΗ59̉ú<6¾·jη:q¾[¬Eœo,â|#Î7â|cçq¾ÍÖ'¶%[½₫íPr¾»K›¢Nï¿:Øí¿ú7§èÿĐëÿTû[çưæ’ùIEND®B`‚spotweb-20130826+dfsg2/js/fancybox/jquery.fancybox-1.3.4.css000077500000000000000000000212241226620506000231770ustar00rootroot00000000000000/* * FancyBox - jQuery Plugin * Simple and fancy lightbox alternative * * Examples and documentation at: http://fancybox.net * * Copyright (c) 2008 - 2010 Janis Skarnelis * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated. * * Version: 1.3.4 (11/11/2010) * Requires: jQuery v1.3+ * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html */ #fancybox-loading { position: fixed; top: 50%; left: 50%; width: 40px; height: 40px; margin-top: -20px; margin-left: -20px; cursor: pointer; overflow: hidden; z-index: 1104; display: none; } #fancybox-loading div { position: absolute; top: 0; left: 0; width: 40px; height: 480px; background-image: url('fancybox.png'); } #fancybox-overlay { position: absolute; top: 0; left: 0; width: 100%; z-index: 1100; display: none; } #fancybox-tmp { padding: 0; margin: 0; border: 0; overflow: auto; display: none; } #fancybox-wrap { position: absolute; top: 0; left: 0; padding: 20px; z-index: 1101; outline: none; display: none; } #fancybox-outer { position: relative; width: 100%; height: 100%; background: #fff; } #fancybox-content { width: 0; height: 0; padding: 0; outline: none; position: relative; overflow: hidden; z-index: 1102; border: 0px solid #fff; } #fancybox-hide-sel-frame { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; z-index: 1101; } #fancybox-close { position: absolute; top: -15px; right: -15px; width: 30px; height: 30px; background: transparent url('fancybox.png') -40px 0px; cursor: pointer; z-index: 1103; display: none; } #fancybox-error { color: #444; font: normal 12px/20px Arial; padding: 14px; margin: 0; } #fancybox-img { width: 100%; height: 100%; padding: 0; margin: 0; border: none; outline: none; line-height: 0; vertical-align: top; } #fancybox-frame { width: 100%; height: 100%; border: none; display: block; } #fancybox-left, #fancybox-right { position: absolute; bottom: 0px; height: 100%; width: 35%; cursor: pointer; outline: none; background: transparent url('blank.gif'); z-index: 1102; display: none; } #fancybox-left { left: 0px; } #fancybox-right { right: 0px; } #fancybox-left-ico, #fancybox-right-ico { position: absolute; top: 50%; left: -9999px; width: 30px; height: 30px; margin-top: -15px; cursor: pointer; z-index: 1102; display: block; } #fancybox-left-ico { background-image: url('fancybox.png'); background-position: -40px -30px; } #fancybox-right-ico { background-image: url('fancybox.png'); background-position: -40px -60px; } #fancybox-left:hover, #fancybox-right:hover { visibility: visible; /* IE6 */ } #fancybox-left:hover span { left: 20px; } #fancybox-right:hover span { left: auto; right: 20px; } .fancybox-bg { position: absolute; padding: 0; margin: 0; border: 0; width: 20px; height: 20px; z-index: 1001; } #fancybox-bg-n { top: -20px; left: 0; width: 100%; background-image: url('fancybox-x.png'); } #fancybox-bg-ne { top: -20px; right: -20px; background-image: url('fancybox.png'); background-position: -40px -162px; } #fancybox-bg-e { top: 0; right: -20px; height: 100%; background-image: url('fancybox-y.png'); background-position: -20px 0px; } #fancybox-bg-se { bottom: -20px; right: -20px; background-image: url('fancybox.png'); background-position: -40px -182px; } #fancybox-bg-s { bottom: -20px; left: 0; width: 100%; background-image: url('fancybox-x.png'); background-position: 0px -20px; } #fancybox-bg-sw { bottom: -20px; left: -20px; background-image: url('fancybox.png'); background-position: -40px -142px; } #fancybox-bg-w { top: 0; left: -20px; height: 100%; background-image: url('fancybox-y.png'); } #fancybox-bg-nw { top: -20px; left: -20px; background-image: url('fancybox.png'); background-position: -40px -122px; } #fancybox-title { font-family: Helvetica; font-size: 12px; z-index: 1102; } .fancybox-title-inside { padding-bottom: 10px; text-align: center; color: #333; background: #fff; position: relative; } .fancybox-title-outside { padding-top: 10px; color: #fff; } .fancybox-title-over { position: absolute; bottom: 0; left: 0; color: #FFF; text-align: left; } #fancybox-title-over { padding: 10px; background-image: url('fancy_title_over.png'); display: block; } .fancybox-title-float { position: absolute; left: 0; bottom: -20px; height: 32px; } #fancybox-title-float-wrap { border: none; border-collapse: collapse; width: auto; } #fancybox-title-float-wrap td { border: none; white-space: nowrap; } #fancybox-title-float-left { padding: 0 0 0 15px; background: url('fancybox.png') -40px -90px no-repeat; } #fancybox-title-float-main { color: #FFF; line-height: 29px; font-weight: bold; padding: 0 0 3px 0; background: url('fancybox-x.png') 0px -40px; } #fancybox-title-float-right { padding: 0 0 0 15px; background: url('fancybox.png') -55px -90px no-repeat; } /* IE6 */ .fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_close.png', sizingMethod='scale'); } .fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_left.png', sizingMethod='scale'); } .fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_right.png', sizingMethod='scale'); } .fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; } .fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_left.png', sizingMethod='scale'); } .fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_main.png', sizingMethod='scale'); } .fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_right.png', sizingMethod='scale'); } .fancybox-ie6 #fancybox-bg-w, .fancybox-ie6 #fancybox-bg-e, .fancybox-ie6 #fancybox-left, .fancybox-ie6 #fancybox-right, #fancybox-hide-sel-frame { height: expression(this.parentNode.clientHeight + "px"); } #fancybox-loading.fancybox-ie6 { position: absolute; margin-top: 0; top: expression( (-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'); } #fancybox-loading.fancybox-ie6 div { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_loading.png', sizingMethod='scale'); } /* IE6, IE7, IE8 */ .fancybox-ie .fancybox-bg { background: transparent !important; } .fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_n.png', sizingMethod='scale'); } .fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_ne.png', sizingMethod='scale'); } .fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_e.png', sizingMethod='scale'); } .fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_se.png', sizingMethod='scale'); } .fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_s.png', sizingMethod='scale'); } .fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_sw.png', sizingMethod='scale'); } .fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_w.png', sizingMethod='scale'); } .fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); }spotweb-20130826+dfsg2/js/jquery-json/000077500000000000000000000000001226620506000173465ustar00rootroot00000000000000spotweb-20130826+dfsg2/js/jquery-json/jquery.json-2.3.js000077500000000000000000000111501226620506000224740ustar00rootroot00000000000000/** * jQuery JSON Plugin * version: 2.3 (2011-09-17) * * This document is licensed as free software under the terms of the * MIT License: http://www.opensource.org/licenses/mit-license.php * * Brantley Harris wrote this plugin. It is based somewhat on the JSON.org * website's http://www.json.org/json2.js, which proclaims: * "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that * I uphold. * * It is also influenced heavily by MochiKit's serializeJSON, which is * copyrighted 2005 by Bob Ippolito. */ (function( $ ) { var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g, meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' }; /** * jQuery.toJSON * Converts the given argument into a JSON respresentation. * * @param o {Mixed} The json-serializble *thing* to be converted * * If an object has a toJSON prototype, that will be used to get the representation. * Non-integer/string keys are skipped in the object, as are keys that point to a * function. * */ $.toJSON = typeof JSON === 'object' && JSON.stringify ? JSON.stringify : function( o ) { if ( o === null ) { return 'null'; } var type = typeof o; if ( type === 'undefined' ) { return undefined; } if ( type === 'number' || type === 'boolean' ) { return '' + o; } if ( type === 'string') { return $.quoteString( o ); } if ( type === 'object' ) { if ( typeof o.toJSON === 'function' ) { return $.toJSON( o.toJSON() ); } if ( o.constructor === Date ) { var month = o.getUTCMonth() + 1, day = o.getUTCDate(), year = o.getUTCFullYear(), hours = o.getUTCHours(), minutes = o.getUTCMinutes(), seconds = o.getUTCSeconds(), milli = o.getUTCMilliseconds(); if ( month < 10 ) { month = '0' + month; } if ( day < 10 ) { day = '0' + day; } if ( hours < 10 ) { hours = '0' + hours; } if ( minutes < 10 ) { minutes = '0' + minutes; } if ( seconds < 10 ) { seconds = '0' + seconds; } if ( milli < 100 ) { milli = '0' + milli; } if ( milli < 10 ) { milli = '0' + milli; } return '"' + year + '-' + month + '-' + day + 'T' + hours + ':' + minutes + ':' + seconds + '.' + milli + 'Z"'; } if ( o.constructor === Array ) { var ret = []; for ( var i = 0; i < o.length; i++ ) { ret.push( $.toJSON( o[i] ) || 'null' ); } return '[' + ret.join(',') + ']'; } var name, val, pairs = []; for ( var k in o ) { type = typeof k; if ( type === 'number' ) { name = '"' + k + '"'; } else if (type === 'string') { name = $.quoteString(k); } else { // Keys must be numerical or string. Skip others continue; } type = typeof o[k]; if ( type === 'function' || type === 'undefined' ) { // Invalid values like these return undefined // from toJSON, however those object members // shouldn't be included in the JSON string at all. continue; } val = $.toJSON( o[k] ); pairs.push( name + ':' + val ); } return '{' + pairs.join( ',' ) + '}'; } }; /** * jQuery.evalJSON * Evaluates a given piece of json source. * * @param src {String} */ $.evalJSON = typeof JSON === 'object' && JSON.parse ? JSON.parse : function( src ) { return eval('(' + src + ')'); }; /** * jQuery.secureEvalJSON * Evals JSON in a way that is *more* secure. * * @param src {String} */ $.secureEvalJSON = typeof JSON === 'object' && JSON.parse ? JSON.parse : function( src ) { var filtered = src .replace( /\\["\\\/bfnrtu]/g, '@' ) .replace( /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') .replace( /(?:^|:|,)(?:\s*\[)+/g, ''); if ( /^[\],:{}\s]*$/.test( filtered ) ) { return eval( '(' + src + ')' ); } else { throw new SyntaxError( 'Error parsing JSON, source is not valid.' ); } }; /** * jQuery.quoteString * Returns a string-repr of a string, escaping quotes intelligently. * Mostly a support function for toJSON. * Examples: * >>> jQuery.quoteString('apple') * "apple" * * >>> jQuery.quoteString('"Where are we going?", she asked.') * "\"Where are we going?\", she asked." */ $.quoteString = function( string ) { if ( string.match( escapeable ) ) { return '"' + string.replace( escapeable, function( a ) { var c = meta[a]; if ( typeof c === 'string' ) { return c; } c = a.charCodeAt(); return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); }) + '"'; } return '"' + string + '"'; }; })( jQuery ); spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/000077500000000000000000000000001226620506000203655ustar00rootroot00000000000000spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/images/000077500000000000000000000000001226620506000216325ustar00rootroot00000000000000spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/images/ajax-loader.png000077500000000000000000000007671226620506000245440ustar00rootroot00000000000000‰PNG  IHDR##́÷®jsBITÛáOà0PLTEÿÿÿñññññññññññññññññññññññññññññññññññññññññññññï¼HbtRNS"3DUfwˆ™ª»̀Ưîÿv• pHYs ë ë‚‹ ZtEXtSoftwareAdobe Fireworks CS5qµă6IDAT(‘c` 0¥¥* ˆˆ̀̃sæ̀™&$–Ơ»BwïNBèêÚ º’Xµz÷n°ĐS¸¢U«w820Wß½÷ªŒ}Ơª`Ûjï½{²œ¹*̀`¾÷î D_ç̀iP#lß½+ËÍœYs̀»wÀFÍœ w÷ºw`;%:`ú́₫ÿQÍp!̃ÿ¿A”GG#\ˆóÿˆP\ˆS ÜË Đ…̀ˋЅÄËKĐ…ØÊÓàlF¨/̉̉ `B‚‚`™´´@˜"AAĂ--U¦*$S•c 5‰()„TCC\Œ”„”€B0{˜€B.ÆÆJJJ0EÀÈvqq )"9W,„,ÂÀ dll„*BĐSX§œđ èIEND®B`‚spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/images/form-check-off.png000077500000000000000000000005541226620506000251350ustar00rootroot00000000000000‰PNG  IHDRºWí?sBITÛáOàBPLTEÿÿÿ­­­§§§™™™†††|||qqpfffZZZOOONONONONNODDD:::333'''/wtRNS"""""""""""""""""""""¡^ñÄ pHYs  ̉Ư~ütEXtSoftwareAdobe Fireworks CS5qµă6tEXtCreation Time8/20/10I[ VIDAT•uÑG€0 Ñ-ôrÿ«2VvùäY²¥Ù:„oÁÛ#ˆ· ^‚x â!ˆ» ¦lñµ2i#΂8 â(ˆƒ ö‚hf1úÊÄN[Q‹¡)T~ñA% ,<y'IEND®B`‚spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/images/form-check-on.png000077500000000000000000000007141226620506000247750ustar00rootroot00000000000000‰PNG  IHDRºWí?sBITÛáOà`PLTEÿÿÿÿÿÿ§§§'('!!!­­­™™™ŒŒŒ:::ABAƒƒƒ|||ttt333..-ffftttZZZOOǸ̀̀NOO|||tttkkkfffZZZ333ĂÄÄ­­­½ƠÉ tRNSÿ3333333333333333̀33w™3DDDDUfw™ó0oË pHYs  ̉Ư~ütEXtSoftwareAdobe Fireworks CS5qµă6tEXtCreation Time8/20/10I[ IDAT•uÑÙ …a°®E%µ;yÿ·́!]œ)ö¿`’or‡Rÿ»íJvɳ€EĐZKdĨ¨¹ –¿¢Ö©­dú3`¡®4›P‰}Çè½O+ÇÅ‚:çäf½søF¼Y øB=¯–6à3Ơ±X' đ!µ kçxŸk†¡YFà)ëƠu×Á_L & ^ă|OIEND®B`‚spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/images/form-radio-off.png000077500000000000000000000007051226620506000251540ustar00rootroot00000000000000‰PNG  IHDRºWí?sBITÛáOà`PLTEÿÿÿÖÖÖÆÆÆ¶¶¶¬¬¬©¨¨¦¦¦„„„tttcccSSSKKK™™™„„„yyylmlcccSSSKKK:::---.---..--..-.!"!Œ …é §QIDATxÚ”ÔÏ+DQÆñcæ ‹ñ+’¤,•,îÊBDJl°´$k†…¢0C”ØX KÅK¥øDĂ¡Ø(̣=ờ41Ó¼ơéms{fî{¯‡*½F;Êp‹ćâʤ©€z;8D?ªD#¦pÉÿ °†¼`ơ¨DöQ‚ˆN÷' [_Ü£ó¸Á;.0„­_D…0¦¾Œs“¾p†j ¸­øÂÉ\1ơ7 ¤€§,êÅn@ùhÈФwN4ă6—ë.Íů;$oZ0­ûŸZ5‘:\ë‚É ú¾ÿ@E|t¡µÄ:Ú´̃ÎĂ3.z˜C§¤–ăfa%eO2ÀÖô<Øg¡wúÍv”G±ªÉ$B<çJöxÛâÖ–₫Ÿ¨>ÛÁû ˜Üjv£N²ä™Ükß°ïØ ËB{âư]IEND®B`‚spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/images/icons-18-black.png000077500000000000000000000016471226620506000247660ustar00rootroot00000000000000‰PNG  IHDRv$€¯sBITÛáOàPLTEÿÿÿ\bA½tRNSÿ"ˆîƯw'<‰x pHYs œ œổßtEXtCreation Time2/3/11ç?®atEXtSoftwareAdobe Fireworks CS5qµă6ÊIDATX…íWÁnÚ@]vWö5Ó`çê*‘Ï&Èäj·.\ëF!WL¹â’Âïw)¥í¼±dơ©¼›G³3³oß́¬•ºà‚ ₫è¨é$”%hÛ¯-|ûÿ$÷ßBïÏY/û˜z娧}¡â\ü!.2!đ›g=RYaÙE`03áó ­N«LØ™ÓÏ”…£OC̀ª«—άm¸ûÊ>"‚LQfëµâüzT™₫fï£\´® ° Å`̣˜è”¼w£¡Ê¯1"ª,F)(SAñÆƠuÁ¿qÊ-ư.í]ƯÀ¢€r¢aÄ,ƒ+\A*Á”]¡Äm%%P}₫¼;QÖƒ;KaZ‘²‹qËÍRù˜Í<1‚MM÷ùœ%³áÊÛœo:Æ@ŒÍ Ë-;nyÑi6Å¢ñlMIIJkJty”É´¦zͼư½#÷.&-Ø·G²!Vă»átúoaC5â¡G Ùíµ~Âûn¿ƒÈسN›đey–ckà}—îèOđíWD¾Ÿ³àÑéN—aH6qô‰«Ă”k6op©ƒt×lô®ïsËœµüV‘=+oC³ 6&$0u«X=Nwª::ƯĂ1¯̀<€Ôœ bz¸µsđÁ.v÷nÆ-r‡M¦ O︓îdÏdÂOΣ7&¸3®³œ.Ûóî»–É€ÓĂÄ3̀`] ÆÅœ}¿T§Ü ü@ÊÔ2gw¼è†² L-Üͪ³¸ó>mă¼9›ÉĐfR|‹WK q•}Ä÷bơ¦ü(2Ư•œ©–9[…\wº¤uÙumJrî¢w«ü§Z5ôg Z̃wF¼ưÛLƯĐâ—A₫W4ø₫P1ºÔè™·ố*™0‹ÖÜI¼ït́D¾Œoz/* §Û¨3óèܲÆ!Ô×^^\pÁÂw̉rªZ¤EƯIEND®B`‚spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/images/icons-18-white.png000077500000000000000000000016541226620506000250300ustar00rootroot00000000000000‰PNG  IHDRv$€¯sBITÛáOàPLTEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ)+ÀÈtRNSÿ"ˆîƯw'<‰x pHYs œ œổßtEXtCreation Time2/3/11ç?®atEXtSoftwareAdobe Fireworks CS5qµă6ÏIDATX…íWÁnÚ@]vWö5Ó€suä³ 5¹z[ ®u+ÈW,Røư.M¬h̃X2E=D*ïæÑ́›Ù·3;k¥®¸âÿ:>Çt RÊS´í„×¾Ăûo¡—¬JVç˜.€}¦â'ØÂ>z™ôuù9ÜÂrˆ‘x&|Å¢u³ÊD1Ă\Y8úÉ£êê¹3j€y2'‚ŒLQæë¥âúT€˜áîb¹ÖXĐºbOƒÅ`đ„¨ ~†v£¾r·ÀXa•%X ̃’7>¯$¯9óĐkÇAWDw|Í/¢38¢~̀,½êƯ@(¡”]c‰ÛA –Œ êƯÓ¡‘́ í,„a³ˆ1²́Ür½R!F3%ØLçnÁ‚Ùh\̣ƒ2ƒ½ă›NcÆæ…å–Çơ÷<é,Ÿb̉x¶¦$bÑ5¥º|-“é†6[æ=8Cí='-Ùw@²!ÖÄ Ïë]s9Ă]ÀÅ4›… ơhi!º½Ơs¼ïvÉ'`ÆơµI¾̀å[ï»̀¯berªµ·U'F¾Ÿ·'èPú“æi’M;ÎlÊ-ªy-ëë.…º«wú+¯†à{ËœµœHö¬¥÷‹ªÉyVÁÆD Lư*–¯;U½:Ư£1Ï̀œ@Öœ ØÄ§µĐ¡v±¿wsfĐ_N÷cªsexx¯h'{öT&üäpcB;ăµ[rí¤¹l/»ï’…˜ p)©0Ï0ƒ4ºBÅåœư¼R—Ü üAÆ+¨eÎzíx̉5å˜Z´›UKfñçƯlă²9;“Aẻ$ ^- đª¡xß…foÊo‚yÈgNÛœ­"^wº¤mÙumJwчµ{«V ưÙ‚–÷oÿ6S74¾Á´ü¯¨ñư¡&bt©ÑÿnéÙu:a=Ưxp'ñ¾Ó›ô ~kB1?*ôQd:N÷q'÷èܲÆ!Ô—³¼®¸â„ß ªs·i‡ÜIEND®B`‚spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/images/icons-36-black.png000077500000000000000000000024631226620506000247630ustar00rootroot00000000000000‰PNG  IHDŔ$GßMÜsBITÛáOà PLTEÿÿÿøŒMtRNSÿ™×Z‡ pHYs Ă Ă4)$«tEXtCreation Time2/3/11ç?®atEXtSoftwareAdobe Fireworks CS5qµă6fIDAThíY±Gz´Á DˆÔÉ ‚‹Ú¤#ù. n/X¼#ˆXZ!YºŒÿ0"!@Đ“úæ':s°ŸàÄB˜¥ƯrWï•4}ÀÙƯÔUUw¿®®ªîͲ3f̀˜1ăÿ–$?Â÷ßbÿE¸ ‰^ÁwƠ~“™\wH’b…·A×$x¾E’’¼wóàư×íF%ämh\/ơd2•å̉k+i|ß#I׃ ?"‡đíÂ×Ái n›Ưlµ¨lHË¥<ùùTîS1½}Œ y“0”oQ”Â:=ªÈÉùŸ ÜÇYƒx\Ÿ)JAu¢?Ẉ́ưm‘C-ÉEi+‘­VYʬ8Êœ`&eîrÔ‰císHwƠQÖ1c;PVJ‚×fw$¢U¢™¦/¨̣‹V±¸ 5rÁưfîJôÜ-Ă²î¼¼ &a²́'ø¾m̃£́´è¹(ê_XÜQö́/pjơè9œ{IJÜɯ¸A9%ç’’Rô ™o8c–Ùö©ŒîäyĐ~ª¨£ưÜeUưçL{´¦ö(8U*¼FGBÅѦpRm²¸³h2 ƠẬ̉ßàn óªÇ¹Ÿ©½ñèMpˆ Îjpo¼XÅ’¢$ÜüĂA₫å3KÜu±V€Èஇw‡̣bw§̃ÉzP¢N¸Œ³À+Ï]t]Qø̉¬X¶³₫–æèàIÄÎw=Q#npµØÙº‰olE7hÄo9gŒ@¥+^}[Ü­ơ³êÊđ‰&»́àĂ~ơß 8å¢qĐsºñ()¾3¸ƒeXÜơïj5öDî.N;Åÿ¬·OǹÎaà×zû¬đ(^qÉ<ZXe7%8ÛElơđÔṔÚ³-ˆè~5ällˆ&Àxsw°¾ˆ?Éî uư:á×÷iÔÍ|!º.àßz®îï ̀˜1cÆŒ3fØø ̃÷¶£fIEND®B`‚spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/images/icons-36-white.png000077500000000000000000000024631226620506000250270ustar00rootroot00000000000000‰PNG  IHDŔ$GßMÜsBITÛáOà PLTEÿÿÿÿÿÿÿÿÿÿÿÿơ¥stRNSÿ™×Z‡ pHYs Ă Ă4)$«tEXtCreation Time2/3/11ç?®atEXtSoftwareAdobe Fireworks CS5qµă6fIDAThíY±Gz´Á DˆÔÉ ‚‹Ú¤#ù. n/X¼#ˆXZ!YºŒÿ0"!@Đ“úæ':s°ŸàÄB˜¥ƯrWï•4}ÀÙƯÔUUw¿®®ªîͲ3f̀˜1ăÿ–$?Â÷ßbÿE¸ ‰^ÁwƠ~“™\wH’b…·A×$x¾E’’¼wóàư×íF%ämh\/ơd2•å̉k+i|ß#I׃ ?"‡đíÂ×Ái n›Ưlµ¨lHË¥<ùùTîS1½}Œ y“0”oQ”Â:=ªÈÉùŸ ÜÇYƒx\Ÿ)JAu¢?Ẉ́ưm‘C-ÉEi+‘­VYʬ8Êœ`&eîrÔ‰císHwƠQÖ1c;PVJ‚×fw$¢U¢™¦/¨̣‹V±¸ 5rÁưfîJôÜ-Ă²î¼¼ &a²́'ø¾m̃£́´è¹(ê_XÜQö́/pjơè9œ{IJÜɯ¸A9%ç’’Rô ™o8c–Ùö©ŒîäyĐ~ª¨£ưÜeUưçL{´¦ö(8U*¼FGBÅѦpRm²¸³h2 ƠẬ̉ßàn óªÇ¹Ÿ©½ñèMpˆ Îjpo¼XÅ’¢$ÜüĂA₫å3KÜu±V€Èஇw‡̣bw§̃ÉzP¢N¸Œ³À+Ï]t]Qø̉¬X¶³₫–æèàIÄÎw=Q#npµØÙº‰olE7hÄo9gŒ@¥+^}[Ü­ơ³êÊđ‰&»́àĂ~ơß 8å¢qĐsºñ()¾3¸ƒeXÜơïj5öDî.N;Åÿ¬·OǹÎaà×zû¬đ(^qÉ<ZXe7%8ÛElơđÔṔÚ³-ˆè~5ällˆ&Àxsw°¾ˆ?Éî uư:á×÷iÔÍ|!º.àßz®îï ̀˜1cÆŒ3fØø ̃÷¶£fIEND®B`‚spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/jquery.mobile-1.0a3.css000077500000000000000000001530431226620506000244150ustar00rootroot00000000000000/*! * jQuery Mobile v1.0a3 * http://jquerymobile.com/ * * Copyright 2010, jQuery Project * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license */ /* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. * Note: Code is in draft form and is subject to change */ /* A -----------------------------------------------------------------------------------------------------------*/ .ui-bar-a { border: 1px solid #2A2A2A; background: #111111; color: #ffffff; font-weight: bold; text-shadow: 0 -1px 1px #000000; background-image: -moz-linear-gradient(top, #3c3c3c, #111111); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #3c3c3c), color-stop(1, #111111)); -msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#3c3c3c', EndColorStr='#111111')"; } .ui-bar-a, .ui-bar-a input, .ui-bar-a select, .ui-bar-a textarea, .ui-bar-a button { font-family: Helvetica, Arial, sans-serif; } .ui-bar-a .ui-link-inherit { color: #fff; } .ui-bar-a .ui-link { color: #7cc4e7; font-weight: bold; } .ui-body-a { border: 1px solid #2A2A2A; background: #222222; color: #fff; text-shadow: 0 1px 0 #000; font-weight: normal; background-image: -moz-linear-gradient(top, #666666, #222222); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #666666), color-stop(1, #222222)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#666666', EndColorStr='#222222)')"; } .ui-body-a, .ui-body-a input, .ui-body-a select, .ui-body-a textarea, .ui-body-a button { font-family: Helvetica, Arial, sans-serif; } .ui-body-a .ui-link-inherit { color: #fff; } .ui-body-a .ui-link { color: #2489CE; font-weight: bold; } .ui-br { border-bottom: 1px solid rgba(130,130,130,.3); } .ui-btn-up-a { border: 1px solid #222; background: #333333; font-weight: bold; color: #fff; cursor: pointer; text-shadow: 0 -1px 1px #000; text-decoration: none; background-image: -moz-linear-gradient(top, #555555, #333333); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #555555), color-stop(1, #333333)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#555555', EndColorStr='#333333')"; } .ui-btn-up-a a.ui-link-inherit { color: #fff; } .ui-btn-hover-a { border: 1px solid #000; background: #444444; font-weight: bold; color: #fff; text-shadow: 0 -1px 1px #000; text-decoration: none; background-image: -moz-linear-gradient(top, #666666, #444444); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #666666), color-stop(1, #444444)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#666666', EndColorStr='#444444')"; } .ui-btn-hover-a a.ui-link-inherit { color: #fff; } .ui-btn-down-a { border: 1px solid #000; background: #3d3d3d; font-weight: bold; color: #fff; text-shadow: 0 -1px 1px #000; background-image: -moz-linear-gradient(top, #333333, #5a5a5a); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #333333), color-stop(1, #5a5a5a)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#333333', EndColorStr='#5a5a5a')"; } .ui-btn-down-a a.ui-link-inherit { color: #fff; } .ui-btn-up-a, .ui-btn-hover-a, .ui-btn-down-a { font-family: Helvetica, Arial, sans-serif; } /* B -----------------------------------------------------------------------------------------------------------*/ .ui-bar-b { border: 1px solid #456f9a; background: #5e87b0; color: #fff; font-weight: bold; text-shadow: 0 -1px 1px #254f7a; background-image: -moz-linear-gradient(top, #81a8ce, #5e87b0); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #81a8ce), color-stop(1, #5e87b0)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#81a8ce', EndColorStr='#5e87b0')"; } .ui-bar-b, .ui-bar-b input, .ui-bar-b select, .ui-bar-b textarea, .ui-bar-b button { font-family: Helvetica, Arial, sans-serif; } .ui-bar-b .ui-link-inherit { color: #fff; } .ui-bar-b .ui-link { color: #7cc4e7; font-weight: bold; } .ui-body-b { border: 1px solid #C6C6C6; background: #cccccc; color: #333333; text-shadow: 0 1px 0 #fff; font-weight: normal; background-image: -moz-linear-gradient(top, #e6e6e6, #cccccc); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #e6e6e6), color-stop(1, #cccccc)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#e6e6e6', EndColorStr='#cccccc')"; } .ui-body-b, .ui-body-b input, .ui-body-b select, .ui-body-b textarea, .ui-body-b button { font-family: Helvetica, Arial, sans-serif; } .ui-body-b .ui-link-inherit { color: #333333; } .ui-body-b .ui-link { color: #2489CE; font-weight: bold; } .ui-btn-up-b { border: 1px solid #145072; background: #2567ab; font-weight: bold; color: #fff; cursor: pointer; text-shadow: 0 -1px 1px #145072; text-decoration: none; background-image: -moz-linear-gradient(top, #4e89c5, #2567ab); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #5f9cc5), color-stop(1, #396b9e)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#4e89c5', EndColorStr='#2567ab')"; } .ui-btn-up-b a.ui-link-inherit { color: #fff; } .ui-btn-hover-b { border: 1px solid #00516e; background: #4b88b6; font-weight: bold; color: #fff; text-shadow: 0 -1px 1px #014D68; background-image: -moz-linear-gradient(top, #72b0d4, #4b88b6); text-decoration: none; background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #72b0d4), color-stop(1, #4b88b6)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#72b0d4', EndColorStr='#4b88b6')"; } .ui-btn-hover-b a.ui-link-inherit { color: #fff; } .ui-btn-down-b { border: 1px solid #225377; background: #4e89c5; font-weight: bold; color: #fff; text-shadow: 0 -1px 1px #225377; background-image: -moz-linear-gradient(top, #396b9e, #4e89c5); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #396b9e), color-stop(1, #4e89c5)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#396b9e', EndColorStr='#4e89c5')"; } .ui-btn-down-b a.ui-link-inherit { color: #fff; } .ui-btn-up-b, .ui-btn-hover-b, .ui-btn-down-b { font-family: Helvetica, Arial, sans-serif; } /* C -----------------------------------------------------------------------------------------------------------*/ .ui-bar-c { border: 1px solid #B3B3B3; background: #e9eaeb; color: #3E3E3E; font-weight: bold; text-shadow: 0 1px 1px #fff; background-image: -moz-linear-gradient(top, #f0f0f0, #e9eaeb); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #f0f0f0), color-stop(1, #e9eaeb)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#f0f0f0', EndColorStr='#e9eaeb')"; } .ui-bar-c, .ui-bar-c input, .ui-bar-c select, .ui-bar-c textarea, .ui-bar-c button { font-family: Helvetica, Arial, sans-serif; } .ui-body-c { border: 1px solid #B3B3B3; color: #333333; text-shadow: 0 1px 0 #fff; background: #f0f0f0; background-image: -moz-linear-gradient(top, #eeeeee, #dddddd); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #eeeeee), color-stop(1, #dddddd)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#dddddd')"; } .ui-body-c, .ui-body-c input, .ui-body-c select, .ui-body-c textarea, .ui-body-c button { font-family: Helvetica, Arial, sans-serif; } .ui-body-c .ui-link-inherit { color: #333333; } .ui-body-c .ui-link { color: #2489CE; font-weight: bold; } .ui-btn-up-c { border: 1px solid #ccc; background: #eee; font-weight: bold; color: #444; cursor: pointer; text-shadow: 0 1px 1px #f6f6f6; text-decoration: none; background-image: -moz-linear-gradient(top, #fefefe, #eeeeee); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #fdfdfd), color-stop(1, #eeeeee)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fdfdfd', EndColorStr='#eeeeee')"; } .ui-btn-up-c a.ui-link-inherit { color: #2F3E46; } .ui-btn-hover-c { border: 1px solid #bbb; background: #dadada; font-weight: bold; color: #101010; text-decoration: none; text-shadow: 0 1px 1px #fff; background-image: -moz-linear-gradient(top, #ededed, #dadada); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #ededed), color-stop(1, #dadada)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ededed', EndColorStr='#dadada')"; } .ui-btn-hover-c a.ui-link-inherit { color: #2F3E46; } .ui-btn-down-c { border: 1px solid #808080; background: #fdfdfd; font-weight: bold; color: #111111; text-shadow: 0 1px 1px #ffffff; background-image: -moz-linear-gradient(top, #eeeeee, #fdfdfd); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #eeeeee), color-stop(1, #fdfdfd)); -msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#fdfdfd')"; } .ui-btn-down-c a.ui-link-inherit { color: #2F3E46; } .ui-btn-up-c, .ui-btn-hover-c, .ui-btn-down-c { font-family: Helvetica, Arial, sans-serif; } /* D -----------------------------------------------------------------------------------------------------------*/ .ui-bar-d { border: 1px solid #ccc; background: #bbb; color: #333; text-shadow: 0 1px 0 #eee; background-image: -moz-linear-gradient(top, #ddd, #bbb); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #ddd), color-stop(1, #bbb)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#dddddd', EndColorStr='#bbbbbb')"; } .ui-bar-d, .ui-bar-d input, .ui-bar-d select, .ui-bar-d textarea, .ui-bar-d button { font-family: Helvetica, Arial, sans-serif; } .ui-bar-d .ui-link-inherit { color: #333; } .ui-bar-d .ui-link { color: #2489CE; font-weight: bold; } .ui-body-d { border: 1px solid #ccc; color: #333333; text-shadow: 0 1px 0 #fff; background: #ffffff; } .ui-body-d, .ui-body-d input, .ui-body-d select, .ui-body-d textarea, .ui-body-d button { font-family: Helvetica, Arial, sans-serif; } .ui-body-d .ui-link-inherit { color: #333333; } .ui-body-d .ui-link { color: #2489CE; font-weight: bold; } .ui-btn-up-d { border: 1px solid #ccc; background: #fff; font-weight: bold; color: #444; text-decoration: none; text-shadow: 0 1px 1px #fff; } .ui-btn-up-d a.ui-link-inherit { color: #333; } .ui-btn-hover-d { border: 1px solid #aaa; background: #eeeeee; font-weight: bold; color: #222; cursor: pointer; text-shadow: 0 1px 1px #fff; text-decoration: none; background-image: -moz-linear-gradient(top, #fdfdfd, #eeeeee); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #fdfdfd), color-stop(1, #eeeeee)); -msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fdfdfd', EndColorStr='#eeeeee')"; } .ui-btn-hover-d a.ui-link-inherit { color: #222; } .ui-btn-down-d { border: 1px solid #aaaaaa; background: #ffffff; font-weight: bold; color: #111; text-shadow: 0 1px 1px #ffffff; background-image: -moz-linear-gradient(top, #eeeeee, #ffffff); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #eeeeee), color-stop(1, #ffffff)); -msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#ffffff')"; } .ui-btn-down-d a.ui-link-inherit { border: 1px solid #808080; background: #ced0d2; font-weight: bold; color: #111; text-shadow: none; background-image: -moz-linear-gradient(top, #cccccc, #eeeeee); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #cccccc), color-stop(1, #eeeeee)); -msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#cccccc', EndColorStr='#eeeeee')"; } .ui-btn-up-d, .ui-btn-hover-d, .ui-btn-down-d { font-family: Helvetica, Arial, sans-serif; } /* E -----------------------------------------------------------------------------------------------------------*/ .ui-bar-e { border: 1px solid #F7C942; background: #fadb4e; color: #333; text-shadow: 0 1px 0 #fff; background-image: -moz-linear-gradient(top, #fceda7, #fadb4e); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #fceda7), color-stop(1, #fadb4e)); -msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fceda7', EndColorStr='#fadb4e')"; } .ui-bar-e, .ui-bar-e input, .ui-bar-e select, .ui-bar-e textarea, .ui-bar-d button { font-family: Helvetica, Arial, sans-serif; } .ui-bar-e .ui-link-inherit { color: #333; } .ui-bar-e .ui-link { color: #2489CE; font-weight: bold; } .ui-body-e { border: 1px solid #F7C942; color: #333333; text-shadow: 0 1px 0 #fff; background: #faeb9e; background-image: -moz-linear-gradient(top, #fff, #faeb9e); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #fff), color-stop(1, #faeb9e)); -msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#faeb9e')"; } .ui-body-e, .ui-body-e input, .ui-body-e select, .ui-body-e textarea, .ui-body-e button { font-family: Helvetica, Arial, sans-serif; } .ui-body-e .ui-link-inherit { color: #333333; } .ui-body-e .ui-link { color: #2489CE; font-weight: bold; } .ui-btn-up-e { border: 1px solid #F7C942; background: #fadb4e; font-weight: bold; color: #333; cursor: pointer; text-shadow: 0 1px 1px #fe3; text-decoration: none; text-shadow: 0 1px 0 #fff; background-image: -moz-linear-gradient(top, #fceda7, #fadb4e); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #fceda7), color-stop(1, #fadb4e)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fceda7', EndColorStr='#fadb4e')"; } .ui-btn-up-e a.ui-link-inherit { color: #333; } .ui-btn-hover-e { border: 1px solid #e79952; background: #fbe26f; font-weight: bold; color: #111; text-decoration: none; text-shadow: 0 1px 1px #fff; background-image: -moz-linear-gradient(top, #fcf0b5, #fbe26f); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #fcf0b5), color-stop(1, #fbe26f)); -msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fcf0b5', EndColorStr='#fbe26f')"; } .ui-btn-hover-e a.ui-link-inherit { color: #333; } .ui-btn-down-e { border: 1px solid #F7C942; background: #fceda7; font-weight: bold; color: #111; text-shadow: 0 1px 1px #ffffff; background-image: -moz-linear-gradient(top, #fadb4e, #fceda7); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #fadb4e), color-stop(1, #fceda7)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fadb4e', EndColorStr='#fceda7')"; } .ui-btn-down-e a.ui-link-inherit { color: #333; } .ui-btn-up-e, .ui-btn-hover-e, .ui-btn-down-e { font-family: Helvetica, Arial, sans-serif; } /* links within "buttons" -----------------------------------------------------------------------------------------------------------*/ a.ui-link-inherit { text-decoration: none !important; } /* Active class used as the "on" state across all themes -----------------------------------------------------------------------------------------------------------*/ .ui-btn-active { border: 1px solid #155678; background: #4596ce; font-weight: bold; color: #fff; cursor: pointer; text-shadow: 0 -1px 1px #145072; text-decoration: none; background-image: -moz-linear-gradient(top, #85bae4, #5393c5); background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #85bae4), color-stop(1, #5393c5)); -msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#85bae4', EndColorStr='#5393c5')"; outline: none; } .ui-btn-active a.ui-link-inherit { color: #fff; } /* button inner top highlight -----------------------------------------------------------------------------------------------------------*/ .ui-btn-inner { border-top: 1px solid #fff; border-color: rgba(255,255,255,.3); } /* corner rounding classes -----------------------------------------------------------------------------------------------------------*/ .ui-corner-tl { -moz-border-radius-topleft: .6em; -webkit-border-top-left-radius: .6em; border-top-left-radius: .6em; } .ui-corner-tr { -moz-border-radius-topright: .6em; -webkit-border-top-right-radius: .6em; border-top-right-radius: .6em; } .ui-corner-bl { -moz-border-radius-bottomleft: .6em; -webkit-border-bottom-left-radius: .6em; border-bottom-left-radius: .6em; } .ui-corner-br { -moz-border-radius-bottomright: .6em; -webkit-border-bottom-right-radius: .6em; border-bottom-right-radius: .6em; } .ui-corner-top { -moz-border-radius-topleft: .6em; -webkit-border-top-left-radius: .6em; border-top-left-radius: .6em; -moz-border-radius-topright: .6em; -webkit-border-top-right-radius: .6em; border-top-right-radius: .6em; } .ui-corner-bottom { -moz-border-radius-bottomleft: .6em; -webkit-border-bottom-left-radius: .6em; border-bottom-left-radius: .6em; -moz-border-radius-bottomright: .6em; -webkit-border-bottom-right-radius: .6em; border-bottom-right-radius: .6em; } .ui-corner-right { -moz-border-radius-topright: .6em; -webkit-border-top-right-radius: .6em; border-top-right-radius: .6em; -moz-border-radius-bottomright: .6em; -webkit-border-bottom-right-radius: .6em; border-bottom-right-radius: .6em; } .ui-corner-left { -moz-border-radius-topleft: .6em; -webkit-border-top-left-radius: .6em; border-top-left-radius: .6em; -moz-border-radius-bottomleft: .6em; -webkit-border-bottom-left-radius: .6em; border-bottom-left-radius: .6em; } .ui-corner-all { -moz-border-radius: .6em; -webkit-border-radius: .6em; border-radius: .6em; } /* Interaction cues -----------------------------------------------------------------------------------------------------------*/ .ui-disabled { opacity: .3; } .ui-disabled, .ui-disabled a { cursor: default !important; } /* Icons -----------------------------------------------------------------------------------------------------------*/ .ui-icon { background-image: url(images/icons-18-white.png); background-repeat: no-repeat; background-color: #666; background-color: rgba(0,0,0,.4); -moz-border-radius: 9px; -webkit-border-radius: 9px; border-radius: 9px; } .ui-icon-disc { background-color: #666; background-color: rgba(0,0,0,.3); -moz-border-radius: 9px; -webkit-border-radius: 9px; border-radius: 9px; } /* Alt icon color -----------------------------------------------------------------------------------------------------------*/ .ui-icon-black { background-image: url(images/icons-18-black.png); } .ui-icon-black-disc { background-color: #fff; background-color: rgba(255,255,255,.3); -moz-border-radius: 9px; -webkit-border-radius: 9px; border-radius: 9px; } /* HD/"retina" sprite -----------------------------------------------------------------------------------------------------------*/ @media screen and (-webkit-min-device-pixel-ratio: 2), screen and (max--moz-device-pixel-ratio: 2) { .ui-icon { background-image: url(images/icons-36-white.png); background-size: 630px 18px; } .ui-icon-black { background-image: url(images/icons-36-black.png); } } /* plus minus */ .ui-icon-plus { background-position: -0 0; } .ui-icon-minus { background-position: -36px 0; } /* delete/close */ .ui-icon-delete { background-position: -72px 0; } /* arrows */ .ui-icon-arrow-r { background-position: -108px 0; } .ui-icon-arrow-l { background-position: -144px 0; } .ui-icon-arrow-u { background-position: -180px 0; } .ui-icon-arrow-d { background-position: -216px 0; } /* misc */ .ui-icon-check { background-position: -252px 0; } .ui-icon-gear { background-position: -288px 0; } .ui-icon-refresh { background-position: -324px 0; } .ui-icon-forward { background-position: -360px 0; } .ui-icon-back { background-position: -396px 0; } .ui-icon-grid { background-position: -432px 0; } .ui-icon-star { background-position: -468px 0; } .ui-icon-alert { background-position: -504px 0; } .ui-icon-info { background-position: -540px 0; } .ui-icon-home { background-position: -576px 0; } .ui-icon-search { background-position: -612px 0; } /* checks,radios */ .ui-icon-checkbox-off, .ui-icon-checkbox-on, .ui-icon-radio-off, .ui-icon-radio-on { background-color: transparent; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; background-size: 20px 20px; } .ui-icon-checkbox-off { background-image: url(images/form-check-off.png); } .ui-icon-checkbox-on { background-image: url(images/form-check-on.png); } .ui-icon-radio-off { background-image: url(images/form-radio-off.png);} .ui-icon-radio-on { background-image: url(images/form-radio-on.png); } .ui-icon-searchfield { background-image: url(images/icon-search-black.png); background-size: 16px 16px; } /* loading icon */ .ui-icon-loading { background-image: url(images/ajax-loader.png); width: 40px; height: 40px; -moz-border-radius: 20px; -webkit-border-radius: 20px; border-radius: 20px; background-size: 35px 35px; } /* Button corner classes -----------------------------------------------------------------------------------------------------------*/ .ui-btn-corner-tl { -moz-border-radius-topleft: 1em; -webkit-border-top-left-radius: 1em; border-top-left-radius: 1em; } .ui-btn-corner-tr { -moz-border-radius-topright: 1em; -webkit-border-top-right-radius: 1em; border-top-right-radius: 1em; } .ui-btn-corner-bl { -moz-border-radius-bottomleft: 1em; -webkit-border-bottom-left-radius: 1em; border-bottom-left-radius: 1em; } .ui-btn-corner-br { -moz-border-radius-bottomright: 1em; -webkit-border-bottom-right-radius: 1em; border-bottom-right-radius: 1em; } .ui-btn-corner-top { -moz-border-radius-topleft: 1em; -webkit-border-top-left-radius: 1em; border-top-left-radius: 1em; -moz-border-radius-topright: 1em; -webkit-border-top-right-radius: 1em; border-top-right-radius: 1em; } .ui-btn-corner-bottom { -moz-border-radius-bottomleft: 1em; -webkit-border-bottom-left-radius: 1em; border-bottom-left-radius: 1em; -moz-border-radius-bottomright: 1em; -webkit-border-bottom-right-radius: 1em; border-bottom-right-radius: 1em; } .ui-btn-corner-right { -moz-border-radius-topright: 1em; -webkit-border-top-right-radius: 1em; border-top-right-radius: 1em; -moz-border-radius-bottomright: 1em; -webkit-border-bottom-right-radius: 1em; border-bottom-right-radius: 1em; } .ui-btn-corner-left { -moz-border-radius-topleft: 1em; -webkit-border-top-left-radius: 1em; border-top-left-radius: 1em; -moz-border-radius-bottomleft: 1em; -webkit-border-bottom-left-radius: 1em; border-bottom-left-radius: 1em; } .ui-btn-corner-all { -moz-border-radius: 1em; -webkit-border-radius: 1em; border-radius: 1em; } /* radius clip workaround for cleaning up corner trapping */ .ui-corner-tl, .ui-corner-tr, .ui-corner-bl, .ui-corner-br, .ui-corner-top, .ui-corner-bottom, .ui-corner-right, .ui-corner-left, .ui-corner-all, .ui-btn-corner-tl, .ui-btn-corner-tr, .ui-btn-corner-bl, .ui-btn-corner-br, .ui-btn-corner-top, .ui-btn-corner-bottom, .ui-btn-corner-right, .ui-btn-corner-left, .ui-btn-corner-all { -webkit-background-clip: padding-box; -moz-background-clip: padding-box; background-clip: padding-box; } /* Overlay / modal -----------------------------------------------------------------------------------------------------------*/ .ui-overlay { background: #666; opacity: .5; filter: Alpha(Opacity=50); position: absolute; width: 100%; height: 100%; } .ui-overlay-shadow { -moz-box-shadow: 0px 0px 12px rgba(0,0,0,.6); -webkit-box-shadow: 0px 0px 12px rgba(0,0,0,.6); box-shadow: 0px 0px 12px rgba(0,0,0,.6); } .ui-shadow { -moz-box-shadow: 0px 1px 4px rgba(0,0,0,.3); -webkit-box-shadow: 0px 1px 4px rgba(0,0,0,.3); box-shadow: 0px 1px 4px rgba(0,0,0,.3); } .ui-bar-a .ui-shadow, .ui-bar-b .ui-shadow , .ui-bar-c .ui-shadow { -moz-box-shadow: 0px 1px 0 rgba(255,255,255,.3); -webkit-box-shadow: 0px 1px 0 rgba(255,255,255,.3); box-shadow: 0px 1px 0 rgba(255,255,255,.3); } .ui-shadow-inset { -moz-box-shadow: inset 0px 1px 4px rgba(0,0,0,.2); -webkit-box-shadow: inset 0px 1px 4px rgba(0,0,0,.2); box-shadow: inset 0px 1px 4px rgba(0,0,0,.2); } .ui-icon-shadow { -moz-box-shadow: 0px 1px 0 rgba(255,255,255,.4); -webkit-box-shadow: 0px 1px 0 rgba(255,255,255,.4); box-shadow: 0px 1px 0 rgba(255,255,255,.4); } /* Focus state - set here for specificity -----------------------------------------------------------------------------------------------------------*/ .ui-focus { -moz-box-shadow: 0px 0px 12px #387bbe; -webkit-box-shadow: 0px 0px 12px #387bbe; box-shadow: 0px 0px 12px #387bbe; } /* unset box shadow in browsers that don't do it right -----------------------------------------------------------------------------------------------------------*/ .ui-mobile-nosupport-boxshadow * { -moz-box-shadow: none !important; -webkit-box-shadow: none !important; box-shadow: none !important; } /* ...and bring back focus */ .ui-mobile-nosupport-boxshadow .ui-focus { outline-width: 2px; }/* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. * Note: Code is in draft form and is subject to change */ /* some unsets - more probably needed */ .ui-mobile fieldset, .ui-page { padding: 0; margin: 0; } .ui-mobile a img, .ui-mobile fieldset { border: 0; } /* responsive page widths */ .ui-mobile-viewport { margin: 0; overflow-x: hidden; -webkit-text-size-adjust: none; -ms-text-size-adjust:none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } /* "page" containers - full-screen views, one should always be in view post-pageload */ .ui-mobile [data-role=page], .ui-mobile [data-role=dialog], .ui-page { top: 0; left: 0; width: 100%; min-height: 100%; position: absolute; display: none; border: 0; } .ui-mobile .ui-page-active { display: block; overflow: visible; } /*orientations from js are available */ .portrait, .portrait .ui-page { min-height: 480px; } .landscape, .landscape .ui-page { min-height: 320px; } /* loading screen */ .ui-loading .ui-mobile-viewport { overflow: hidden !important; } .ui-loading .ui-loader { display: block; } .ui-loading .ui-page { overflow: hidden; } .ui-loader { display: none; position: absolute; opacity: .85; z-index: 10; left: 50%; width: 200px; margin-left: -130px; margin-top: -35px; padding: 10px 30px; } .ui-loader h1 { font-size: 15px; text-align: center; } .ui-loader .ui-icon { position: static; display: block; opacity: .9; margin: 0 auto; width: 35px; height: 35px; background-color: transparent; } /*fouc*/ .ui-mobile-rendering > * { visibility: hidden; } /*headers, content panels*/ .ui-bar, .ui-body { position: relative; padding: .4em 15px; overflow: hidden; display: block; clear:both; } .ui-bar { font-size: 16px; margin: 0; } .ui-bar h1, .ui-bar h2, .ui-bar h3, .ui-bar h4, .ui-bar h5, .ui-bar h6 { margin: 0; padding: 0; font-size: 16px; display: inline-block; } .ui-header, .ui-footer { display: block; } .ui-page .ui-header, .ui-page .ui-footer { position: relative; } .ui-header .ui-btn-left { position: absolute; left: 10px; top: .4em; } .ui-header .ui-title, .ui-footer .ui-title { text-align: center; font-size: 16px; display: block; margin: .6em 90px .8em; padding: 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; outline: 0 !important; } .ui-header .ui-btn-right { position: absolute; right: 10px; top: .4em; } /*content area*/ .ui-content { border-width: 0; overflow: visible; overflow-x: hidden; padding: 15px; } .ui-page-fullscreen .ui-content { padding:0; } /* icons sizing */ .ui-icon { width: 18px; height: 18px; } /* fullscreen class on ui-content div */ .ui-fullscreen { } .ui-fullscreen img { max-width: 100%; } /* non-js content hiding */ .ui-nojs { position: absolute; left: -9999px; } /* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ .spin { -webkit-transform: rotate(360deg); -webkit-animation-name: spin; -webkit-animation-duration: 1s; -webkit-animation-iteration-count: infinite; } @-webkit-keyframes spin { from {-webkit-transform: rotate(0deg);} to {-webkit-transform: rotate(360deg);} } /* Transitions from jQtouch (with small modifications): http://www.jqtouch.com/ Built by David Kaneda and maintained by Jonathan Stark. */ .in, .out { -webkit-animation-timing-function: ease-in-out; -webkit-animation-duration: 350ms; } .slide.in { -webkit-transform: translateX(0); -webkit-animation-name: slideinfromright; } .slide.out { -webkit-transform: translateX(-100%); -webkit-animation-name: slideouttoleft; } .slide.in.reverse { -webkit-transform: translateX(0); -webkit-animation-name: slideinfromleft; } .slide.out.reverse { -webkit-transform: translateX(100%); -webkit-animation-name: slideouttoright; } .slideup.in { -webkit-transform: translateY(0); -webkit-animation-name: slideinfrombottom; z-index: 10; } .slideup.out { -webkit-animation-name: dontmove; z-index: 0; } .slideup.out.reverse { -webkit-transform: translateY(100%); z-index: 10; -webkit-animation-name: slideouttobottom; } .slideup.in.reverse { z-index: 0; -webkit-animation-name: dontmove; } .slidedown.in { -webkit-transform: translateY(0); -webkit-animation-name: slideinfromtop; z-index: 10; } .slidedown.out { -webkit-animation-name: dontmove; z-index: 0; } .slidedown.out.reverse { -webkit-transform: translateY(-100%); z-index: 10; -webkit-animation-name: slideouttotop; } .slidedown.in.reverse { z-index: 0; -webkit-animation-name: dontmove; } @-webkit-keyframes slideinfromright { from { -webkit-transform: translateX(100%); } to { -webkit-transform: translateX(0); } } @-webkit-keyframes slideinfromleft { from { -webkit-transform: translateX(-100%); } to { -webkit-transform: translateX(0); } } @-webkit-keyframes slideouttoleft { from { -webkit-transform: translateX(0); } to { -webkit-transform: translateX(-100%); } } @-webkit-keyframes slideouttoright { from { -webkit-transform: translateX(0); } to { -webkit-transform: translateX(100%); } } @-webkit-keyframes slideinfromtop { from { -webkit-transform: translateY(-100%); } to { -webkit-transform: translateY(0); } } @-webkit-keyframes slideinfrombottom { from { -webkit-transform: translateY(100%); } to { -webkit-transform: translateY(0); } } @-webkit-keyframes slideouttobottom { from { -webkit-transform: translateY(0); } to { -webkit-transform: translateY(100%); } } @-webkit-keyframes slideouttotop { from { -webkit-transform: translateY(0); } to { -webkit-transform: translateY(-100%); } } @-webkit-keyframes fadein { from { opacity: 0; } to { opacity: 1; } } @-webkit-keyframes fadeout { from { opacity: 1; } to { opacity: 0; } } .fade.in { opacity: 1; z-index: 10; -webkit-animation-name: fadein; } .fade.out { z-index: 0; -webkit-animation-name: fadeout; } /* The properties in this body rule are only necessary for the 'flip' transition. * We need specify the perspective to create a projection matrix. This will add * some depth as the element flips. The depth number represents the distance of * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate * value. */ .ui-mobile-viewport-perspective { -webkit-perspective: 1000; position: absolute; } .ui-mobile-viewport-transitioning, .ui-mobile-viewport-transitioning .ui-page { width: 100%; height: 100%; overflow: hidden; } .flip { -webkit-animation-duration: .65s; -webkit-backface-visibility:hidden; -webkit-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */ } .flip.in { -webkit-transform: rotateY(0) scale(1); -webkit-animation-name: flipinfromleft; } .flip.out { -webkit-transform: rotateY(-180deg) scale(.8); -webkit-animation-name: flipouttoleft; } /* Shake it all about */ .flip.in.reverse { -webkit-transform: rotateY(0) scale(1); -webkit-animation-name: flipinfromright; } .flip.out.reverse { -webkit-transform: rotateY(180deg) scale(.8); -webkit-animation-name: flipouttoright; } @-webkit-keyframes flipinfromright { from { -webkit-transform: rotateY(-180deg) scale(.8); } to { -webkit-transform: rotateY(0) scale(1); } } @-webkit-keyframes flipinfromleft { from { -webkit-transform: rotateY(180deg) scale(.8); } to { -webkit-transform: rotateY(0) scale(1); } } @-webkit-keyframes flipouttoleft { from { -webkit-transform: rotateY(0) scale(1); } to { -webkit-transform: rotateY(-180deg) scale(.8); } } @-webkit-keyframes flipouttoright { from { -webkit-transform: rotateY(0) scale(1); } to { -webkit-transform: rotateY(180deg) scale(.8); } } /* Hackish, but reliable. */ @-webkit-keyframes dontmove { from { opacity: 1; } to { opacity: 1; } } .pop { -webkit-transform-origin: 50% 50%; } .pop.in { -webkit-transform: scale(1); opacity: 1; -webkit-animation-name: popin; z-index: 10; } .pop.out.reverse { -webkit-transform: scale(.2); opacity: 0; -webkit-animation-name: popout; z-index: 10; } .pop.in.reverse { z-index: 0; -webkit-animation-name: dontmove; } @-webkit-keyframes popin { from { -webkit-transform: scale(.2); opacity: 0; } to { -webkit-transform: scale(1); opacity: 1; } } @-webkit-keyframes popout { from { -webkit-transform: scale(1); opacity: 1; } to { -webkit-transform: scale(.2); opacity: 0; } }/* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ /* content configurations. */ .ui-grid-a, .ui-grid-b, .ui-grid-c, .ui-grid-d { overflow: hidden; } .ui-block-a, .ui-block-b, .ui-block-c, .ui-block-d, .ui-block-e { margin: 0; padding: 0; border: 0; float: left; } /* grid a: 50/50 */ .ui-grid-a .ui-block-a, .ui-grid-a .ui-block-b { width: 50%; } .ui-grid-a .ui-block-a { clear: left; } /* grid b: 33/33/33 */ .ui-grid-b .ui-block-a, .ui-grid-b .ui-block-b, .ui-grid-b .ui-block-c { width: 33.333%; } .ui-grid-b .ui-block-a { clear: left; } /* grid c: 25/25/25/25 */ .ui-grid-c .ui-block-a, .ui-grid-c .ui-block-b, .ui-grid-c .ui-block-c, .ui-grid-c .ui-block-d { width: 25%; } .ui-grid-c .ui-block-a { clear: left; } /* grid d: 20/20/20/20/20 */ .ui-grid-d .ui-block-a, .ui-grid-d .ui-block-b, .ui-grid-d .ui-block-c, .ui-grid-d .ui-block-d, .ui-grid-d .ui-block-e { width: 20%; } .ui-grid-d .ui-block-a { clear: left; }/* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ /* fixed page header & footer configuration */ .ui-header, .ui-footer, .ui-page-fullscreen .ui-header, .ui-page-fullscreen .ui-footer { position: absolute; overflow: hidden; width: 100%; border-left-width: 0; border-right-width: 0; } .ui-header-fixed, .ui-footer-fixed { z-index: 1000; -webkit-transform: translateZ(0); /* Force header/footer rendering to go through the same rendering pipeline as native page scrolling. */ } .ui-footer-duplicate, .ui-page-fullscreen .ui-fixed-inline { display: none; } .ui-page-fullscreen .ui-header, .ui-page-fullscreen .ui-footer { opacity: .9; } /* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ .ui-navbar { overflow: hidden; } .ui-navbar ul, .ui-navbar-expanded ul { list-style:none; padding: 0; margin: 0; position: relative; display: block; border: 0;} .ui-navbar-collapsed ul { float: left; width: 75%; margin-right: -2px; } .ui-navbar-collapsed .ui-navbar-toggle { float: left; width: 25%; } .ui-navbar li.ui-navbar-truncate { position: absolute; left: -9999px; top: -9999px; } .ui-navbar li .ui-btn, .ui-navbar .ui-navbar-toggle .ui-btn { display: block; font-size: 12px; text-align: center; margin: 0; border-right-width: 0; } .ui-navbar li .ui-btn { margin-right: -1px; } .ui-navbar li .ui-btn:last-child { margin-right: 0; } .ui-header .ui-navbar li .ui-btn, .ui-header .ui-navbar .ui-navbar-toggle .ui-btn, .ui-footer .ui-navbar li .ui-btn, .ui-footer .ui-navbar .ui-navbar-toggle .ui-btn { border-top-width: 0; border-bottom-width: 0; } .ui-navbar .ui-btn-inner { padding-left: 2px; padding-right: 2px; } .ui-navbar-noicons li .ui-btn .ui-btn-inner, .ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner { padding-top: .8em; padding-bottom: .9em; } /*expanded page styles*/ .ui-navbar-expanded .ui-btn { margin: 0; font-size: 14px; } .ui-navbar-expanded .ui-btn-inner { padding-left: 5px; padding-right: 5px; } .ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner { padding: 45px 5px 15px; text-align: center; } .ui-navbar-expanded .ui-btn-icon-top .ui-icon { top: 15px; } .ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner { padding: 15px 5px 45px; text-align: center; } .ui-navbar-expanded .ui-btn-icon-bottom .ui-icon { bottom: 15px; } .ui-navbar-expanded li .ui-btn .ui-btn-inner { min-height: 2.5em; } .ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner { padding-top: 1.8em; padding-bottom: 1.9em; } /* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ .ui-btn { display: block; text-align: center; cursor:pointer; position: relative; margin: .5em 5px; padding: 0; } .ui-btn:focus, .ui-btn:active { outline: none; } .ui-header .ui-btn, .ui-footer .ui-btn, .ui-bar .ui-btn { display: inline-block; font-size: 13px; margin: 0; } .ui-btn-inline { display: inline-block; } .ui-btn-inner { padding: .6em 25px; display: block; height: 100%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; position: relative; } .ui-header .ui-btn-inner, .ui-footer .ui-btn-inner, .ui-bar .ui-btn-inner { padding: .4em 8px .5em; } .ui-btn-icon-notext { display: inline-block; width: 20px; height: 20px; padding: 2px 1px 2px 3px; text-indent: -9999px; } .ui-btn-icon-notext .ui-btn-inner { padding: 0; } .ui-btn-icon-notext .ui-btn-text { position: absolute; left: -999px; } .ui-btn-icon-left .ui-btn-inner { padding-left: 33px; } .ui-header .ui-btn-icon-left .ui-btn-inner, .ui-footer .ui-btn-icon-left .ui-btn-inner, .ui-bar .ui-btn-icon-left .ui-btn-inner { padding-left: 27px; } .ui-btn-icon-right .ui-btn-inner { padding-right: 33px; } .ui-header .ui-btn-icon-right .ui-btn-inner, .ui-footer .ui-btn-icon-right .ui-btn-inner, .ui-bar .ui-btn-icon-right .ui-btn-inner { padding-right: 27px; } .ui-btn-icon-top .ui-btn-inner { padding-top: 33px; } .ui-header .ui-btn-icon-top .ui-btn-inner, .ui-footer .ui-btn-icon-top .ui-btn-inner, .ui-bar .ui-btn-icon-top .ui-btn-inner { padding-top: 27px; } .ui-btn-icon-bottom .ui-btn-inner { padding-bottom: 33px; } .ui-header .ui-btn-icon-bottom .ui-btn-inner, .ui-footer .ui-btn-icon-bottom .ui-btn-inner, .ui-bar .ui-btn-icon-bottom .ui-btn-inner { padding-bottom: 27px; } /*btn icon positioning*/ .ui-btn-icon-notext .ui-icon { display: block; } .ui-btn-icon-left .ui-icon, .ui-btn-icon-right .ui-icon { position: absolute; top: 50%; margin-top: -9px; } .ui-btn-icon-top .ui-icon, .ui-btn-icon-bottom .ui-icon { position: absolute; left: 50%; margin-left: -9px; } .ui-btn-icon-left .ui-icon { left: 10px; } .ui-btn-icon-right .ui-icon {right: 10px; } .ui-header .ui-btn-icon-left .ui-icon, .ui-footer .ui-btn-icon-left .ui-icon, .ui-bar .ui-btn-icon-left .ui-icon { left: 4px; } .ui-header .ui-btn-icon-right .ui-icon, .ui-footer .ui-btn-icon-right .ui-icon, .ui-bar .ui-btn-icon-right .ui-icon { right: 4px; } .ui-header .ui-btn-icon-top .ui-icon, .ui-footer .ui-btn-icon-top .ui-icon, .ui-bar .ui-btn-icon-top .ui-icon { top: 4px; } .ui-header .ui-btn-icon-bottom .ui-icon, .ui-footer .ui-btn-icon-bottom .ui-icon, .ui-bar .ui-btn-icon-bottom .ui-icon { bottom: 4px; } .ui-btn-icon-top .ui-icon { top: 5px; } .ui-btn-icon-bottom .ui-icon { bottom: 5px; } /*hiding native button,inputs */ .ui-btn-hidden { position: absolute; top: 0; left: 0; width: 100%; height: 100%; -webkit-appearance: button; opacity: 0; cursor: pointer; } /* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ .ui-collapsible-contain { margin: .5em 0; } .ui-collapsible-heading { font-size: 16px; display: block; margin: 0 -8px; padding: 0; border-width: 0 0 1px 0; position: relative; } .ui-collapsible-heading a { text-align: left; margin: 0; } .ui-collapsible-heading a .ui-btn-inner { padding-left: 40px; } .ui-collapsible-heading a span.ui-btn { position: absolute; left: 6px; top: 50%; margin: -12px 0 0 0; width: 20px; height: 20px; padding: 1px 0px 1px 2px; text-indent: -9999px; } .ui-collapsible-heading a span.ui-btn .ui-btn-inner { padding: 0; } .ui-collapsible-heading a span.ui-btn .ui-icon { left: 0; margin-top: -10px; } .ui-collapsible-heading-status { position:absolute; left:-9999px; } .ui-collapsible-content { display: block; padding: 10px 0 10px 8px; } .ui-collapsible-content-collapsed { display: none; } .ui-collapsible-set { margin: .5em 0; } .ui-collapsible-set .ui-collapsible-contain { margin: -1px 0 0; } /* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ .ui-controlgroup, fieldset.ui-controlgroup { padding: 0; margin: .5em 0 1em; } .ui-bar .ui-controlgroup { margin: 0 .3em; } .ui-controlgroup-label { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .3em; } .ui-controlgroup-controls { display: block; width: 95%;} .ui-controlgroup li { list-style: none; } .ui-controlgroup-vertical .ui-btn, .ui-controlgroup-vertical .ui-checkbox, .ui-controlgroup-vertical .ui-radio { margin: 0; border-bottom-width: 0; } .ui-controlgroup-vertical .ui-controlgroup-last { border-bottom-width: 1px; } .ui-controlgroup-horizontal { padding: 0; } .ui-controlgroup-horizontal .ui-btn, .ui-controlgroup-horizontal .ui-checkbox, .ui-controlgroup-horizontal .ui-radio { margin: 0 -5px 0 0; display: inline-block; } .ui-controlgroup-horizontal .ui-checkbox .ui-btn, .ui-controlgroup-horizontal .ui-radio .ui-btn, .ui-controlgroup-horizontal .ui-checkbox:last-child, .ui-controlgroup-horizontal .ui-radio:last-child { margin-right: 0; } .ui-controlgroup-horizontal .ui-controlgroup-last { margin-right: 0; } .ui-controlgroup .ui-checkbox label, .ui-controlgroup .ui-radio label { font-size: 16px; } /* conflicts with listview.. .ui-controlgroup .ui-btn-icon-notext { width: 30px; height: 30px; text-indent: -9999px; } .ui-controlgroup .ui-btn-icon-notext .ui-btn-inner { padding: 5px 6px 5px 5px; } */ .min-width-480px .ui-controlgroup-label { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0; } .min-width-480px .ui-controlgroup-controls { width: 60%; display: inline-block; } /* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ .ui-dialog { min-height: 480px; } .ui-dialog .ui-header, .ui-dialog .ui-content, .ui-dialog .ui-footer { margin: 15px; position: relative; } .ui-dialog .ui-header, .ui-dialog .ui-footer { z-index: 10; width: auto; } .ui-dialog .ui-content, .ui-dialog .ui-footer { margin-top: -15px; }/* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ .ui-checkbox, .ui-radio { position:relative; margin: .2em 0 .5em; z-index: 1; } .ui-checkbox .ui-btn, .ui-radio .ui-btn { margin: 0; text-align: left; z-index: 2; } .ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner { padding-left: 45px; } .ui-checkbox .ui-btn-icon-right .ui-btn-inner, .ui-radio .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; } .ui-checkbox .ui-btn-icon-left .ui-icon, .ui-radio .ui-btn-icon-left .ui-icon {left: 15px; } .ui-checkbox .ui-btn-icon-right .ui-icon, .ui-radio .ui-btn-icon-right .ui-icon {right: 15px; } /* input, label positioning */ .ui-checkbox input,.ui-radio input { position:absolute; left:20px; top:50%; width: 10px; height: 10px; margin:-5px 0 0 0; outline: 0 !important; z-index: 1; }/* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ .ui-field-contain { background: none; padding: 1.5em 0; margin: 0; border-bottom-width: 1px; overflow: visible; } .ui-field-contain:first-child { border-top-width: 0; } .min-width-480px .ui-field-contain { border-width: 0; padding: 0; margin: 1em 0; }/* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ .ui-select { display: block; position: relative; } .ui-select select { position: absolute; left: -9999px; top: -9999px; } .ui-select .ui-btn select { cursor: pointer; -webkit-appearance: button; left: 0; top:0; width: 100%; height: 100%; opacity: 0.001; } .ui-select .ui-btn select.ui-select-nativeonly { opacity: 1; } .ui-select .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; } .ui-select .ui-btn-icon-right .ui-icon { right: 15px; } /* labels */ label.ui-select { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .3em; display: block; } /*listbox*/ .ui-select .ui-btn-text, .ui-selectmenu .ui-btn-text { display: inline-block; min-height: 1em; } .ui-select .ui-btn-text { text-overflow: ellipsis; overflow: hidden; width: 85% } .ui-selectmenu { position: absolute; padding: 0; z-index: 100 !important; width: 80%; max-width: 350px; padding: 6px; } .ui-selectmenu .ui-listview { margin: 0; } .ui-selectmenu .ui-btn.ui-li-divider { cursor: default; } .ui-selectmenu-hidden { top: -9999px; left: -9999px; } .ui-selectmenu-screen { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 99; } .ui-screen-hidden, .ui-selectmenu-list .ui-li .ui-icon { display: none; } .ui-selectmenu-list .ui-li .ui-icon { display: block; } .ui-li.ui-selectmenu-placeholder { display: none; } .min-width-480px label.ui-select { display: inline-block; width: 20%; margin: 0 2% 0 0; } .min-width-480px .ui-select { width: 60%; display: inline-block; } /* when no placeholder is defined in a multiple select, the header height doesn't even extend past the close button. this shim's content in there */ .ui-selectmenu .ui-header h1:after { content: '.'; visibility: hidden; } /* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ label.ui-input-text { font-size: 16px; line-height: 1.4; display: block; font-weight: normal; margin: 0 0 .3em; } input.ui-input-text, textarea.ui-input-text { background-image: none; padding: .4em; line-height: 1.4; font-size: 16px; display: block; width: 95%; } input.ui-input-text { -webkit-appearance: none; } textarea.ui-input-text { height: 50px; -webkit-transition: height 200ms linear; -moz-transition: height 200ms linear; -o-transition: height 200ms linear; transition: height 200ms linear; } .ui-input-search { padding: 0 30px; width: 77%; background-position: 8px 50%; background-repeat: no-repeat; position: relative; } .ui-input-search input.ui-input-text { border: none; width: 98%; padding: .4em 0; margin: 0; display: block; background: transparent none; outline: 0 !important; } .ui-input-search .ui-input-clear { position: absolute; right: 0; top: 50%; margin-top: -14px; } .ui-input-search .ui-input-clear-hidden { display: none; } /* orientation adjustments - incomplete!*/ .min-width-480px label.ui-input-text { vertical-align: top; } .min-width-480px label.ui-input-text { display: inline-block; width: 20%; margin: 0 2% 0 0; } .min-width-480px input.ui-input-text, .min-width-480px textarea.ui-input-text, .min-width-480px .ui-input-search { width: 60%; display: inline-block; } .min-width-480px .ui-input-search { width: 50%; }/* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ .ui-listview { margin: 0; counter-reset: listnumbering; } .ui-content .ui-listview { margin: -15px; } .ui-content .ui-listview-inset { margin: 1em 0; } .ui-listview, .ui-li { list-style:none; padding:0; zoom: 1; } .ui-li { display: block; margin:0; position: relative; overflow: hidden; text-align: left; border-width: 0; border-top-width: 1px; } .ui-li .ui-btn-text { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } .ui-li-divider, .ui-li-static { padding: .5em 15px; font-size: 14px; font-weight: bold; counter-reset: listnumbering; } ol.ui-listview .ui-link-inherit:before, .ui-li-dec { font-size: .8em; display: inline-block; padding-right: .3em; font-weight: normal;counter-increment: listnumbering; content: counter(listnumbering) ". "; } ol.ui-listview .ui-li-jsnumbering:before { content: "" !important; } /* to avoid chance of duplication */ .ui-listview-inset .ui-li { border-right-width: 1px; border-left-width: 1px; } .ui-li:last-child { border-bottom-width: 1px; } .ui-li .ui-btn-inner { display: block; position: relative; padding: .7em 75px .7em 15px; } .ui-li-has-thumb .ui-btn-inner { min-height: 60px; padding-left: 100px; } .ui-li-has-icon .ui-btn-inner { min-height: 20px; padding-left: 40px; } .ui-li-heading { font-size: 16px; font-weight: bold; display: block; margin: .6em 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } .ui-li-desc { font-size: 12px; font-weight: normal; display: block; margin: -.5em 0 .6em; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } .ui-li-thumb, .ui-li-icon { position: absolute; left: 1px; top: 0; max-height: 80px; max-width: 80px; } .ui-li-icon { max-height: 40px; max-width: 40px; left: 10px; top: .9em; } .ui-li-thumb, .ui-li-icon, .ui-li-content { float: left; margin-right: 10px; } .ui-li-aside { float: right; width: 50%; text-align: right; margin: .3em 0; } .min-width-480px .ui-li-aside { width: 45%; } .ui-li-has-alt .ui-btn-inner { padding-right: 95px; } .ui-li-count { position: absolute; font-size: 11px; font-weight: bold; padding: .2em .5em; top: 50%; margin-top: -.9em; right: 38px; } .ui-li-divider .ui-li-count { right: 10px; } .ui-li-has-alt .ui-li-count { right: 55px; } .ui-li-link-alt { position: absolute; width: 40px; height: 100%; border-width: 0; border-left-width: 1px; top: 0; right: 0; margin: 0; padding: 0; } .ui-li-link-alt .ui-btn { overflow: hidden; position: absolute; right: 8px; top: 50%; margin: -11px 0 0 0; border-bottom-width: 1px; } .ui-li-link-alt .ui-btn-inner { padding: 0; position: static; } .ui-li-link-alt .ui-btn .ui-icon { right: 50%; margin-right: -9px; } .ui-listview-filter { border-width: 0; overflow: hidden; margin: -15px -15px 15px -15px } .ui-listview-filter .ui-input-search { margin: 5px; width: auto; display: block; } /* Odd iPad positioning issue. */ @media only screen and (min-device-width: 768px) and (max-device-width: 1024px) { .ui-li .ui-btn-text { overflow: visible; } }/* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ label.ui-slider { display: block; } input.ui-slider-input, .min-width-480px input.ui-slider-input { display: inline-block; width: 50px; } select.ui-slider-switch { display: none; } div.ui-slider { position: relative; display: inline-block; overflow: visible; height: 15px; padding: 0; margin: 0 2% 0 20px; top: 4px; width: 66%; } a.ui-slider-handle { position: absolute; z-index: 10; top: 50%; width: 28px; height: 28px; margin-top: -15px; margin-left: -15px; } a.ui-slider-handle .ui-btn-inner { padding-left: 0; padding-right: 0; } .min-width-480px label.ui-slider { display: inline-block; width: 20%; margin: 0 2% 0 0; } .min-width-480px div.ui-slider { width: 45%; } div.ui-slider-switch { height: 32px; overflow: hidden; margin-left: 0; } div.ui-slider-inneroffset { margin-left: 50%; position: absolute; top: 1px; height: 100%; width: 50%; } div.ui-slider-handle-snapping { -webkit-transition: left 100ms linear; } div.ui-slider-labelbg { position: absolute; top:0; margin: 0; border-width: 0; } div.ui-slider-switch div.ui-slider-labelbg-a { width: 60%; height: 100%; left: 0; } div.ui-slider-switch div.ui-slider-labelbg-b { width: 60%; height: 100%; right: 0; } .ui-slider-switch-a div.ui-slider-labelbg-a, .ui-slider-switch-b div.ui-slider-labelbg-b { z-index: 1; } .ui-slider-switch-a div.ui-slider-labelbg-b, .ui-slider-switch-b div.ui-slider-labelbg-a { z-index: 10; } div.ui-slider-switch a.ui-slider-handle { z-index: 20; width: 101%; height: 32px; margin-top: -18px; margin-left: -101%; } span.ui-slider-label { width: 100%; position: absolute;height: 32px; font-size: 16px; text-align: center; line-height: 2; background: none; border-color: transparent; } span.ui-slider-label-a { left: -100%; margin-right: -1px } span.ui-slider-label-b { right: -100%; margin-left: -1px } spotweb-20130826+dfsg2/js/jquery.mobile-1.0a3/jquery.mobile-1.0a3.js000077500000000000000000004033051226620506000242400ustar00rootroot00000000000000/*! * jQuery Mobile v1.0a3 * http://jquerymobile.com/ * * Copyright 2010, jQuery Project * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license */ /*! * jQuery UI Widget @VERSION * * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://docs.jquery.com/UI/Widget */ (function( $, undefined ) { // jQuery 1.4+ if ( $.cleanData ) { var _cleanData = $.cleanData; $.cleanData = function( elems ) { for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { $( elem ).triggerHandler( "remove" ); } _cleanData( elems ); }; } else { var _remove = $.fn.remove; $.fn.remove = function( selector, keepData ) { return this.each(function() { if ( !keepData ) { if ( !selector || $.filter( selector, [ this ] ).length ) { $( "*", this ).add( [ this ] ).each(function() { $( this ).triggerHandler( "remove" ); }); } } return _remove.call( $(this), selector, keepData ); }); }; } $.widget = function( name, base, prototype ) { var namespace = name.split( "." )[ 0 ], fullName; name = name.split( "." )[ 1 ]; fullName = namespace + "-" + name; if ( !prototype ) { prototype = base; base = $.Widget; } // create selector for plugin $.expr[ ":" ][ fullName ] = function( elem ) { return !!$.data( elem, name ); }; $[ namespace ] = $[ namespace ] || {}; $[ namespace ][ name ] = function( options, element ) { // allow instantiation without initializing for simple inheritance if ( arguments.length ) { this._createWidget( options, element ); } }; var basePrototype = new base(); // we need to make the options hash a property directly on the new instance // otherwise we'll modify the options hash on the prototype that we're // inheriting from // $.each( basePrototype, function( key, val ) { // if ( $.isPlainObject(val) ) { // basePrototype[ key ] = $.extend( {}, val ); // } // }); basePrototype.options = $.extend( true, {}, basePrototype.options ); $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { namespace: namespace, widgetName: name, widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, widgetBaseClass: fullName }, prototype ); $.widget.bridge( name, $[ namespace ][ name ] ); }; $.widget.bridge = function( name, object ) { $.fn[ name ] = function( options ) { var isMethodCall = typeof options === "string", args = Array.prototype.slice.call( arguments, 1 ), returnValue = this; // allow multiple hashes to be passed on init options = !isMethodCall && args.length ? $.extend.apply( null, [ true, options ].concat(args) ) : options; // prevent calls to internal methods if ( isMethodCall && options.charAt( 0 ) === "_" ) { return returnValue; } if ( isMethodCall ) { this.each(function() { var instance = $.data( this, name ); if ( !instance ) { throw "cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'"; } if ( !$.isFunction( instance[options] ) ) { throw "no such method '" + options + "' for " + name + " widget instance"; } var methodValue = instance[ options ].apply( instance, args ); if ( methodValue !== instance && methodValue !== undefined ) { returnValue = methodValue; return false; } }); } else { this.each(function() { var instance = $.data( this, name ); if ( instance ) { instance.option( options || {} )._init(); } else { $.data( this, name, new object( options, this ) ); } }); } return returnValue; }; }; $.Widget = function( options, element ) { // allow instantiation without initializing for simple inheritance if ( arguments.length ) { this._createWidget( options, element ); } }; $.Widget.prototype = { widgetName: "widget", widgetEventPrefix: "", options: { disabled: false }, _createWidget: function( options, element ) { // $.widget.bridge stores the plugin instance, but we do it anyway // so that it's stored even before the _create function runs $.data( element, this.widgetName, this ); this.element = $( element ); this.options = $.extend( true, {}, this.options, this._getCreateOptions(), options ); var self = this; this.element.bind( "remove." + this.widgetName, function() { self.destroy(); }); this._create(); this._trigger( "create" ); this._init(); }, _getCreateOptions: function() { var options = {}; if ( $.metadata ) { options = $.metadata.get( element )[ this.widgetName ]; } return options; }, _create: function() {}, _init: function() {}, destroy: function() { this.element .unbind( "." + this.widgetName ) .removeData( this.widgetName ); this.widget() .unbind( "." + this.widgetName ) .removeAttr( "aria-disabled" ) .removeClass( this.widgetBaseClass + "-disabled " + "ui-state-disabled" ); }, widget: function() { return this.element; }, option: function( key, value ) { var options = key; if ( arguments.length === 0 ) { // don't return a reference to the internal hash return $.extend( {}, this.options ); } if (typeof key === "string" ) { if ( value === undefined ) { return this.options[ key ]; } options = {}; options[ key ] = value; } this._setOptions( options ); return this; }, _setOptions: function( options ) { var self = this; $.each( options, function( key, value ) { self._setOption( key, value ); }); return this; }, _setOption: function( key, value ) { this.options[ key ] = value; if ( key === "disabled" ) { this.widget() [ value ? "addClass" : "removeClass"]( this.widgetBaseClass + "-disabled" + " " + "ui-state-disabled" ) .attr( "aria-disabled", value ); } return this; }, enable: function() { return this._setOption( "disabled", false ); }, disable: function() { return this._setOption( "disabled", true ); }, _trigger: function( type, event, data ) { var callback = this.options[ type ]; event = $.Event( event ); event.type = ( type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type ).toLowerCase(); data = data || {}; // copy original event properties over to the new event // this would happen if we could call $.event.fix instead of $.Event // but we don't have a way to force an event to be fixed multiple times if ( event.originalEvent ) { for ( var i = $.event.props.length, prop; i; ) { prop = $.event.props[ --i ]; event[ prop ] = event.originalEvent[ prop ]; } } this.element.trigger( event, data ); return !( $.isFunction(callback) && callback.call( this.element[0], event, data ) === false || event.isDefaultPrevented() ); } }; })( jQuery ); /* * jQuery Mobile Framework : widget factory extentions for mobile * Copyright (c) jQuery Project * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license */ (function($, undefined ) { $.widget( "mobile.widget", { _getCreateOptions: function() { var elem = this.element, options = {}; $.each( this.options, function( option ) { var value = elem.data( option.replace( /[A-Z]/g, function( c ) { return "-" + c.toLowerCase(); } ) ); if ( value !== undefined ) { options[ option ] = value; } }); return options; } }); })( jQuery ); /* * jQuery Mobile Framework : resolution and CSS media query related helpers and behavior * Copyright (c) jQuery Project * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license */ (function($, undefined ) { var $window = $(window), $html = $( "html" ), //media-query-like width breakpoints, which are translated to classes on the html element resolutionBreakpoints = [320,480,768,1024]; /* $.mobile.media method: pass a CSS media type or query and get a bool return note: this feature relies on actual media query support for media queries, though types will work most anywhere examples: $.mobile.media('screen') //>> tests for screen media type $.mobile.media('screen and (min-width: 480px)') //>> tests for screen media type with window width > 480px $.mobile.media('@media screen and (-webkit-min-device-pixel-ratio: 2)') //>> tests for webkit 2x pixel ratio (iPhone 4) */ $.mobile.media = (function() { // TODO: use window.matchMedia once at least one UA implements it var cache = {}, testDiv = $( "
" ), fakeBody = $( "" ).append( testDiv ); return function( query ) { if ( !( query in cache ) ) { var styleBlock = document.createElement('style'), cssrule = "@media " + query + " { #jquery-mediatest { position:absolute; } }"; //must set type for IE! styleBlock.type = "text/css"; if (styleBlock.styleSheet){ styleBlock.styleSheet.cssText = cssrule; } else { styleBlock.appendChild(document.createTextNode(cssrule)); } $html.prepend( fakeBody ).prepend( styleBlock ); cache[ query ] = testDiv.css( "position" ) === "absolute"; fakeBody.add( styleBlock ).remove(); } return cache[ query ]; }; })(); /* private function for adding/removing breakpoint classes to HTML element for faux media-query support It does not require media query support, instead using JS to detect screen width > cross-browser support This function is called on orientationchange, resize, and mobileinit, and is bound via the 'htmlclass' event namespace */ function detectResolutionBreakpoints(){ var currWidth = $window.width(), minPrefix = "min-width-", maxPrefix = "max-width-", minBreakpoints = [], maxBreakpoints = [], unit = "px", breakpointClasses; $html.removeClass( minPrefix + resolutionBreakpoints.join(unit + " " + minPrefix) + unit + " " + maxPrefix + resolutionBreakpoints.join( unit + " " + maxPrefix) + unit ); $.each(resolutionBreakpoints,function( i, breakPoint ){ if( currWidth >= breakPoint ){ minBreakpoints.push( minPrefix + breakPoint + unit ); } if( currWidth <= breakPoint ){ maxBreakpoints.push( maxPrefix + breakPoint + unit ); } }); if( minBreakpoints.length ){ breakpointClasses = minBreakpoints.join(" "); } if( maxBreakpoints.length ){ breakpointClasses += " " + maxBreakpoints.join(" "); } $html.addClass( breakpointClasses ); }; /* $.mobile.addResolutionBreakpoints method: pass either a number or an array of numbers and they'll be added to the min/max breakpoint classes Examples: $.mobile.addResolutionBreakpoints( 500 ); $.mobile.addResolutionBreakpoints( [500, 1200] ); */ $.mobile.addResolutionBreakpoints = function( newbps ){ if( $.type( newbps ) === "array" ){ resolutionBreakpoints = resolutionBreakpoints.concat( newbps ); } else { resolutionBreakpoints.push( newbps ); } resolutionBreakpoints.sort(function(a,b){ return a-b; }); detectResolutionBreakpoints(); }; /* on mobileinit, add classes to HTML element and set handlers to update those on orientationchange and resize*/ $(document).bind("mobileinit.htmlclass", function(){ /* bind to orientationchange and resize to add classes to HTML element for min/max breakpoints and orientation */ $window.bind("orientationchange.htmlclass resize.htmlclass", function(event){ //add orientation class to HTML element on flip/resize. if(event.orientation){ $html.removeClass( "portrait landscape" ).addClass( event.orientation ); } //add classes to HTML element for min/max breakpoints detectResolutionBreakpoints(); }); }); /* Manually trigger an orientationchange event when the dom ready event fires. This will ensure that any viewport meta tag that may have been injected has taken effect already, allowing us to properly calculate the width of the document. */ $(function(){ //trigger event manually $window.trigger( "orientationchange.htmlclass" ); }); })(jQuery);/* * jQuery Mobile Framework : support tests * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. * Note: Code is in draft form and is subject to change */ (function($, undefined ) { var fakeBody = $( "" ).prependTo( "html" ), fbCSS = fakeBody[0].style, vendors = ['webkit','moz','o'], webos = window.palmGetResource || window.PalmServiceBridge, //only used to rule out scrollTop bb = window.blackberry; //only used to rule out box shadow, as it's filled opaque on BB //thx Modernizr function propExists( prop ){ var uc_prop = prop.charAt(0).toUpperCase() + prop.substr(1), props = (prop + ' ' + vendors.join(uc_prop + ' ') + uc_prop).split(' '); for(var v in props){ if( fbCSS[ v ] !== undefined ){ return true; } } }; //test for dynamic-updating base tag support (allows us to avoid href,src attr rewriting) function baseTagTest(){ var fauxBase = location.protocol + '//' + location.host + location.pathname + "ui-dir/", base = $("head base"), fauxEle = null, href = ''; if (!base.length) { base = fauxEle = $("", {"href": fauxBase}).appendTo("head"); } else { href = base.attr("href"); } var link = $( "" ).prependTo( fakeBody ), rebase = link[0].href; base[0].href = href ? href : location.pathname; if (fauxEle) { fauxEle.remove(); } return rebase.indexOf(fauxBase) === 0; }; $.extend( $.support, { orientation: "orientation" in window, touch: "ontouchend" in document, cssTransitions: "WebKitTransitionEvent" in window, pushState: !!history.pushState, mediaquery: $.mobile.media('only all'), cssPseudoElement: !!propExists('content'), boxShadow: !!propExists('boxShadow') && !bb, scrollTop: ("pageXOffset" in window || "scrollTop" in document.documentElement || "scrollTop" in fakeBody[0]) && !webos, dynamicBaseTag: baseTagTest() }); fakeBody.remove(); //for ruling out shadows via css if( !$.support.boxShadow ){ $('html').addClass('ui-mobile-nosupport-boxshadow'); } })( jQuery );/* * jQuery Mobile Framework : events * Copyright (c) jQuery Project * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license */ (function($, undefined ) { // add new event shortcuts $.each( "touchstart touchmove touchend orientationchange tap taphold swipe swipeleft swiperight scrollstart scrollstop".split( " " ), function( i, name ) { $.fn[ name ] = function( fn ) { return fn ? this.bind( name, fn ) : this.trigger( name ); }; $.attrFn[ name ] = true; }); var supportTouch = $.support.touch, scrollEvent = "touchmove scroll", touchStartEvent = supportTouch ? "touchstart" : "mousedown", touchStopEvent = supportTouch ? "touchend" : "mouseup", touchMoveEvent = supportTouch ? "touchmove" : "mousemove"; // also handles scrollstop $.event.special.scrollstart = { enabled: true, setup: function() { var thisObject = this, $this = $( thisObject ), scrolling, timer; function trigger( event, state ) { scrolling = state; var originalType = event.type; event.type = scrolling ? "scrollstart" : "scrollstop"; $.event.handle.call( thisObject, event ); event.type = originalType; } // iPhone triggers scroll after a small delay; use touchmove instead $this.bind( scrollEvent, function( event ) { if ( !$.event.special.scrollstart.enabled ) { return; } if ( !scrolling ) { trigger( event, true ); } clearTimeout( timer ); timer = setTimeout(function() { trigger( event, false ); }, 50 ); }); } }; // also handles taphold $.event.special.tap = { setup: function() { var thisObject = this, $this = $( thisObject ); $this .bind( "mousedown touchstart", function( event ) { if ( event.which && event.which !== 1 || //check if event fired once already by a device that fires both mousedown and touchstart (while supporting both events) $this.data( "prevEvent") && $this.data( "prevEvent") !== event.type ) { return false; } //save event type so only this type is let through for a temp duration, //allowing quick repetitive taps but not duplicative events $this.data( "prevEvent", event.type ); setTimeout(function(){ $this.removeData( "prevEvent" ); }, 800); var moved = false, touching = true, origTarget = event.target, origEvent = event.originalEvent, origPos = event.type == "touchstart" ? [origEvent.touches[0].pageX, origEvent.touches[0].pageY] : [ event.pageX, event.pageY ], originalType, timer; function moveHandler( event ) { if( event.type == "scroll" ){ moved = true; return; } var newPageXY = event.type == "touchmove" ? event.originalEvent.touches[0] : event; if ((Math.abs(origPos[0] - newPageXY.pageX) > 10) || (Math.abs(origPos[1] - newPageXY.pageY) > 10)) { moved = true; } } timer = setTimeout(function() { if ( touching && !moved ) { originalType = event.type; event.type = "taphold"; $.event.handle.call( thisObject, event ); event.type = originalType; } }, 750 ); //scroll now cancels tap $(window).one("scroll", moveHandler); $this .bind( "mousemove touchmove", moveHandler ) .one( "mouseup touchend", function( event ) { $this.unbind( "mousemove touchmove", moveHandler ); $(window).unbind("scroll", moveHandler); clearTimeout( timer ); touching = false; /* ONLY trigger a 'tap' event if the start target is * the same as the stop target. */ if ( !moved && ( origTarget == event.target ) ) { originalType = event.type; event.type = "tap"; $.event.handle.call( thisObject, event ); event.type = originalType; } }); }); } }; // also handles swipeleft, swiperight $.event.special.swipe = { setup: function() { var thisObject = this, $this = $( thisObject ); $this .bind( touchStartEvent, function( event ) { var data = event.originalEvent.touches ? event.originalEvent.touches[ 0 ] : event, start = { time: (new Date).getTime(), coords: [ data.pageX, data.pageY ], origin: $( event.target ) }, stop; function moveHandler( event ) { if ( !start ) { return; } var data = event.originalEvent.touches ? event.originalEvent.touches[ 0 ] : event; stop = { time: (new Date).getTime(), coords: [ data.pageX, data.pageY ] }; // prevent scrolling if ( Math.abs( start.coords[0] - stop.coords[0] ) > 10 ) { event.preventDefault(); } } $this .bind( touchMoveEvent, moveHandler ) .one( touchStopEvent, function( event ) { $this.unbind( touchMoveEvent, moveHandler ); if ( start && stop ) { if ( stop.time - start.time < 1000 && Math.abs( start.coords[0] - stop.coords[0]) > 30 && Math.abs( start.coords[1] - stop.coords[1]) < 75 ) { start.origin .trigger( "swipe" ) .trigger( start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight" ); } } start = stop = undefined; }); }); } }; (function($){ // "Cowboy" Ben Alman var win = $(window), special_event, get_orientation, last_orientation; $.event.special.orientationchange = special_event = { setup: function(){ // If the event is supported natively, return false so that jQuery // will bind to the event using DOM methods. if ( $.support.orientation ) { return false; } // Get the current orientation to avoid initial double-triggering. last_orientation = get_orientation(); // Because the orientationchange event doesn't exist, simulate the // event by testing window dimensions on resize. win.bind( "resize", handler ); }, teardown: function(){ // If the event is not supported natively, return false so that // jQuery will unbind the event using DOM methods. if ( $.support.orientation ) { return false; } // Because the orientationchange event doesn't exist, unbind the // resize event handler. win.unbind( "resize", handler ); }, add: function( handleObj ) { // Save a reference to the bound event handler. var old_handler = handleObj.handler; handleObj.handler = function( event ) { // Modify event object, adding the .orientation property. event.orientation = get_orientation(); // Call the originally-bound event handler and return its result. return old_handler.apply( this, arguments ); }; } }; // If the event is not supported natively, this handler will be bound to // the window resize event to simulate the orientationchange event. function handler() { // Get the current orientation. var orientation = get_orientation(); if ( orientation !== last_orientation ) { // The orientation has changed, so trigger the orientationchange event. last_orientation = orientation; win.trigger( "orientationchange" ); } }; // Get the current page orientation. This method is exposed publicly, should it // be needed, as jQuery.event.special.orientationchange.orientation() special_event.orientation = get_orientation = function() { var elem = document.documentElement; return elem && elem.clientWidth / elem.clientHeight < 1.1 ? "portrait" : "landscape"; }; })(jQuery); $.each({ scrollstop: "scrollstart", taphold: "tap", swipeleft: "swipe", swiperight: "swipe" }, function( event, sourceEvent ) { $.event.special[ event ] = { setup: function() { $( this ).bind( sourceEvent, $.noop ); } }; }); })( jQuery ); /*! * jQuery hashchange event - v1.3 - 7/21/2010 * http://benalman.com/projects/jquery-hashchange-plugin/ * * Copyright (c) 2010 "Cowboy" Ben Alman * Dual licensed under the MIT and GPL licenses. * http://benalman.com/about/license/ */ // Script: jQuery hashchange event // // *Version: 1.3, Last updated: 7/21/2010* // // Project Home - http://benalman.com/projects/jquery-hashchange-plugin/ // GitHub - http://github.com/cowboy/jquery-hashchange/ // Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js // (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped) // // About: License // // Copyright (c) 2010 "Cowboy" Ben Alman, // Dual licensed under the MIT and GPL licenses. // http://benalman.com/about/license/ // // About: Examples // // These working examples, complete with fully commented code, illustrate a few // ways in which this plugin can be used. // // hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ // document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/ // // About: Support and Testing // // Information about what version or versions of jQuery this plugin has been // tested with, what browsers it has been tested in, and where the unit tests // reside (so you can test it yourself). // // jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2 // Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5, // Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5. // Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/ // // About: Known issues // // While this jQuery hashchange event implementation is quite stable and // robust, there are a few unfortunate browser bugs surrounding expected // hashchange event-based behaviors, independent of any JavaScript // window.onhashchange abstraction. See the following examples for more // information: // // Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/ // Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/ // WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/ // Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/ // // Also note that should a browser natively support the window.onhashchange // event, but not report that it does, the fallback polling loop will be used. // // About: Release History // // 1.3 - (7/21/2010) Reorganized IE6/7 Iframe code to make it more // "removable" for mobile-only development. Added IE6/7 document.title // support. Attempted to make Iframe as hidden as possible by using // techniques from http://www.paciellogroup.com/blog/?p=604. Added // support for the "shortcut" format $(window).hashchange( fn ) and // $(window).hashchange() like jQuery provides for built-in events. // Renamed jQuery.hashchangeDelay to and // lowered its default value to 50. Added // and properties plus document-domain.html // file to address access denied issues when setting document.domain in // IE6/7. // 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin // from a page on another domain would cause an error in Safari 4. Also, // IE6/7 Iframe is now inserted after the body (this actually works), // which prevents the page from scrolling when the event is first bound. // Event can also now be bound before DOM ready, but it won't be usable // before then in IE6/7. // 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug // where browser version is incorrectly reported as 8.0, despite // inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag. // 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special // window.onhashchange functionality into a separate plugin for users // who want just the basic event & back button support, without all the // extra awesomeness that BBQ provides. This plugin will be included as // part of jQuery BBQ, but also be available separately. (function($,window,undefined){ '$:nomunge'; // Used by YUI compressor. // Reused string. var str_hashchange = 'hashchange', // Method / object references. doc = document, fake_onhashchange, special = $.event.special, // Does the browser support window.onhashchange? Note that IE8 running in // IE7 compatibility mode reports true for 'onhashchange' in window, even // though the event isn't supported, so also test document.documentMode. doc_mode = doc.documentMode, supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 ); // Get location.hash (or what you'd expect location.hash to be) sans any // leading #. Thanks for making this necessary, Firefox! function get_fragment( url ) { url = url || location.href; return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' ); }; // Method: jQuery.fn.hashchange // // Bind a handler to the window.onhashchange event or trigger all bound // window.onhashchange event handlers. This behavior is consistent with // jQuery's built-in event handlers. // // Usage: // // > jQuery(window).hashchange( [ handler ] ); // // Arguments: // // handler - (Function) Optional handler to be bound to the hashchange // event. This is a "shortcut" for the more verbose form: // jQuery(window).bind( 'hashchange', handler ). If handler is omitted, // all bound window.onhashchange event handlers will be triggered. This // is a shortcut for the more verbose // jQuery(window).trigger( 'hashchange' ). These forms are described in // the section. // // Returns: // // (jQuery) The initial jQuery collection of elements. // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and // $(elem).hashchange() for triggering, like jQuery does for built-in events. $.fn[ str_hashchange ] = function( fn ) { return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange ); }; // Property: jQuery.fn.hashchange.delay // // The numeric interval (in milliseconds) at which the // polling loop executes. Defaults to 50. // Property: jQuery.fn.hashchange.domain // // If you're setting document.domain in your JavaScript, and you want hash // history to work in IE6/7, not only must this property be set, but you must // also set document.domain BEFORE jQuery is loaded into the page. This // property is only applicable if you are supporting IE6/7 (or IE8 operating // in "IE7 compatibility" mode). // // In addition, the property must be set to the // path of the included "document-domain.html" file, which can be renamed or // modified if necessary (note that the document.domain specified must be the // same in both your main JavaScript as well as in this file). // // Usage: // // jQuery.fn.hashchange.domain = document.domain; // Property: jQuery.fn.hashchange.src // // If, for some reason, you need to specify an Iframe src file (for example, // when setting document.domain as in ), you can // do so using this property. Note that when using this property, history // won't be recorded in IE6/7 until the Iframe src file loads. This property // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7 // compatibility" mode). // // Usage: // // jQuery.fn.hashchange.src = 'path/to/file.html'; $.fn[ str_hashchange ].delay = 50; /* $.fn[ str_hashchange ].domain = null; $.fn[ str_hashchange ].src = null; */ // Event: hashchange event // // Fired when location.hash changes. In browsers that support it, the native // HTML5 window.onhashchange event is used, otherwise a polling loop is // initialized, running every milliseconds to // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7 // compatibility" mode), a hidden Iframe is created to allow the back button // and hash-based history to work. // // Usage as described in : // // > // Bind an event handler. // > jQuery(window).hashchange( function(e) { // > var hash = location.hash; // > ... // > }); // > // > // Manually trigger the event handler. // > jQuery(window).hashchange(); // // A more verbose usage that allows for event namespacing: // // > // Bind an event handler. // > jQuery(window).bind( 'hashchange', function(e) { // > var hash = location.hash; // > ... // > }); // > // > // Manually trigger the event handler. // > jQuery(window).trigger( 'hashchange' ); // // Additional Notes: // // * The polling loop and Iframe are not created until at least one handler // is actually bound to the 'hashchange' event. // * If you need the bound handler(s) to execute immediately, in cases where // a location.hash exists on page load, via bookmark or page refresh for // example, use jQuery(window).hashchange() or the more verbose // jQuery(window).trigger( 'hashchange' ). // * The event can be bound before DOM ready, but since it won't be usable // before then in IE6/7 (due to the necessary Iframe), recommended usage is // to bind it inside a DOM ready handler. // Override existing $.event.special.hashchange methods (allowing this plugin // to be defined after jQuery BBQ in BBQ's source code). special[ str_hashchange ] = $.extend( special[ str_hashchange ], { // Called only when the first 'hashchange' event is bound to window. setup: function() { // If window.onhashchange is supported natively, there's nothing to do.. if ( supports_onhashchange ) { return false; } // Otherwise, we need to create our own. And we don't want to call this // until the user binds to the event, just in case they never do, since it // will create a polling loop and possibly even a hidden Iframe. $( fake_onhashchange.start ); }, // Called only when the last 'hashchange' event is unbound from window. teardown: function() { // If window.onhashchange is supported natively, there's nothing to do.. if ( supports_onhashchange ) { return false; } // Otherwise, we need to stop ours (if possible). $( fake_onhashchange.stop ); } }); // fake_onhashchange does all the work of triggering the window.onhashchange // event for browsers that don't natively support it, including creating a // polling loop to watch for hash changes and in IE 6/7 creating a hidden // Iframe to enable back and forward. fake_onhashchange = (function(){ var self = {}, timeout_id, // Remember the initial hash so it doesn't get triggered immediately. last_hash = get_fragment(), fn_retval = function(val){ return val; }, history_set = fn_retval, history_get = fn_retval; // Start the polling loop. self.start = function() { timeout_id || poll(); }; // Stop the polling loop. self.stop = function() { timeout_id && clearTimeout( timeout_id ); timeout_id = undefined; }; // This polling loop checks every $.fn.hashchange.delay milliseconds to see // if location.hash has changed, and triggers the 'hashchange' event on // window when necessary. function poll() { var hash = get_fragment(), history_hash = history_get( last_hash ); if ( hash !== last_hash ) { history_set( last_hash = hash, history_hash ); $(window).trigger( str_hashchange ); } else if ( history_hash !== last_hash ) { location.href = location.href.replace( /#.*/, '' ) + history_hash; } timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay ); }; // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv $.browser.msie && !supports_onhashchange && (function(){ // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8 // when running in "IE7 compatibility" mode. var iframe, iframe_src; // When the event is bound and polling starts in IE 6/7, create a hidden // Iframe for history handling. self.start = function(){ if ( !iframe ) { iframe_src = $.fn[ str_hashchange ].src; iframe_src = iframe_src && iframe_src + get_fragment(); // Create hidden Iframe. Attempt to make Iframe as hidden as possible // by using techniques from http://www.paciellogroup.com/blog/?p=604. iframe = $('