├── .gitignore ├── AADecoder.php ├── AAEncoder.php ├── LICENSE ├── README.md └── composer.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | tests -------------------------------------------------------------------------------- /AADecoder.php: -------------------------------------------------------------------------------- 1 | 5 | * @link https://github.com/mervick/php-aaencoder 6 | * @license MIT 7 | */ 8 | 9 | /** 10 | * Class AADecoder 11 | */ 12 | class AADecoder 13 | { 14 | const BEGIN_CODE = "゚ω゚ノ=/`m´)ノ~┻━┻/['_'];o=(゚ー゚)=_=3;c=(゚Θ゚)=(゚ー゚)-(゚ー゚);(゚Д゚)=(゚Θ゚)=(o^_^o)/(o^_^o);(゚Д゚)={゚Θ゚:'_',゚ω゚ノ:((゚ω゚ノ==3)+'_')[゚Θ゚],゚ー゚ノ:(゚ω゚ノ+'_')[o^_^o-(゚Θ゚)],゚Д゚ノ:((゚ー゚==3)+'_')[゚ー゚]};(゚Д゚)[゚Θ゚]=((゚ω゚ノ==3)+'_')[c^_^o];(゚Д゚)['c']=((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)-(゚Θ゚)];(゚Д゚)['o']=((゚Д゚)+'_')[゚Θ゚];(゚o゚)=(゚Д゚)['c']+(゚Д゚)['o']+(゚ω゚ノ+'_')[゚Θ゚]+((゚ω゚ノ==3)+'_')[゚ー゚]+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+((゚ー゚==3)+'_')[゚Θ゚]+((゚ー゚==3)+'_')[(゚ー゚)-(゚Θ゚)]+(゚Д゚)['c']+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+(゚Д゚)['o']+((゚ー゚==3)+'_')[゚Θ゚];(゚Д゚)['_']=(o^_^o)[゚o゚][゚o゚];(゚ε゚)=((゚ー゚==3)+'_')[゚Θ゚]+(゚Д゚).゚Д゚ノ+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+((゚ー゚==3)+'_')[o^_^o-゚Θ゚]+((゚ー゚==3)+'_')[゚Θ゚]+(゚ω゚ノ+'_')[゚Θ゚];(゚ー゚)+=(゚Θ゚);(゚Д゚)[゚ε゚]='\\\\';(゚Д゚).゚Θ゚ノ=(゚Д゚+゚ー゚)[o^_^o-(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ+'_')[c^_^o];(゚Д゚)[゚o゚]='\\\"';(゚Д゚)['_']((゚Д゚)['_'](゚ε゚+(゚Д゚)[゚o゚]+"; 15 | 16 | const END_CODE = "(゚Д゚)[゚o゚])(゚Θ゚))('_');"; 17 | 18 | 19 | /** 20 | * Decode encoded-as-aaencode JavaScript code. 21 | * @param string $js 22 | * @return string 23 | */ 24 | public static function decode($js) 25 | { 26 | if (self::hasAAEncoded($js, $start, $next, $encoded)) { 27 | $decoded = self::deobfuscate($encoded); 28 | if (substr(rtrim($decoded), -1) !== ';') { 29 | $decoded .= ';'; 30 | } 31 | return mb_substr($js, 0, $start, 'UTF-8') . $decoded . self::decode(mb_substr($js, $next, null, 'UTF-8')); 32 | } 33 | return $js; 34 | } 35 | 36 | /** 37 | * @param string $js 38 | * @return string 39 | */ 40 | protected static function deobfuscate($js) 41 | { 42 | $bytes = array( 43 | 9 => '((゚ー゚)+(゚ー゚)+(゚Θ゚))', 44 | 6 => '((o^_^o)+(o^_^o))', 45 | 2 => '((o^_^o)-(゚Θ゚))', 46 | 7 => '((゚ー゚)+(o^_^o))', 47 | 5 => '((゚ー゚)+(゚Θ゚))', 48 | 8 => '((゚ー゚)+(゚ー゚))', 49 | 10 => '(゚Д゚).゚ω゚ノ', 50 | 11 => '(゚Д゚).゚Θ゚ノ', 51 | 12 => '(゚Д゚)[\'c\']', 52 | 13 => '(゚Д゚).゚ー゚ノ', 53 | 14 => '(゚Д゚).゚Д゚ノ', 54 | 15 => '(゚Д゚)[゚Θ゚]', 55 | 3 => '(o^_^o)', 56 | 0 => '(c^_^o)', 57 | 4 => '(゚ー゚)', 58 | 1 => '(゚Θ゚)', 59 | ); 60 | $native = array( 61 | '-~' => '1+', 62 | '!' => '1', 63 | '[]' => '0', 64 | ); 65 | $native = array( 66 | array_keys($native), 67 | array_values($native), 68 | ); 69 | $chars = array(); 70 | $hex = '(o゚ー゚o)+'; 71 | $hexLen = mb_strlen($hex, 'UTF-8'); 72 | $calc = function($expr) { 73 | return eval("return $expr;"); 74 | }; 75 | $convert = function ($block, $func) use ($bytes, $calc) { 76 | while (preg_match('/\([0-9\-\+\*\/]+\)/', $block)) { 77 | $block = preg_replace_callback('/\([0-9\-\+\*\/]+\)/', function($matches) use ($calc) { 78 | return $calc($matches[0]); 79 | }, $block); 80 | } 81 | $split = array(); 82 | foreach (explode('+', trim($block, '+')) as $num) { 83 | if ($num === '') continue; 84 | $split[] = $func(intval(trim($num))); 85 | } 86 | return implode('', $split); 87 | }; 88 | foreach ($bytes as $byte => $search) { 89 | $js = implode($byte, mb_split(preg_quote($search), $js)); 90 | } 91 | foreach (mb_split(preg_quote('(゚Д゚)[゚ε゚]+'), $js) as $block) { 92 | $block = trim(trim(str_replace($native[0], $native[1], $block), '+')); 93 | if ($block === '') continue; 94 | if (mb_substr($block, 0, $hexLen, 'UTF-8') === $hex) { 95 | $code = hexdec($convert(mb_substr($block, $hexLen, null, 'UTF-8'), 'dechex')); 96 | } 97 | else { 98 | $code = octdec($convert($block, 'decoct')); 99 | } 100 | $chars[] = mb_convert_encoding('&#' . intval($code) . ';', 'UTF-8', 'HTML-ENTITIES'); 101 | } 102 | return implode('', $chars); 103 | } 104 | 105 | /** 106 | * Detect aaencoded JavaScript code. 107 | * @param string $js 108 | * @param null|int $start 109 | * @param null|int $next 110 | * @param null|string $encoded 111 | * @return bool 112 | */ 113 | public static function hasAAEncoded($js, &$start=null, &$next=null, &$encoded=null) 114 | { 115 | $find = function($haystack, $needle, $offset=0) { 116 | $matches = array(); 117 | for ($i = 0; $i < 6 && $offset !== false; $i ++) { 118 | if (($offset = mb_strpos($haystack, $needle, $offset, 'UTF-8')) !== false) { 119 | $matches[$i] = $offset; 120 | $offset ++; 121 | } 122 | } 123 | return count($matches) >= 6 ? array($matches[4], $matches[5]) : false; 124 | }; 125 | $start = -1; 126 | while (($start = mb_strpos($js, '゚ω゚ノ', $start + 1, 'UTF-8')) !== false) { 127 | $clear = preg_replace('/\/\*.+?\*\//', '', preg_replace('/[\x03-\x20]/', '', $code = mb_substr($js, $start, null, 'UTF-8'))); 128 | $len = mb_strlen(self::BEGIN_CODE, 'UTF-8'); 129 | if (mb_substr($clear, 0, $len, 'UTF-8') === self::BEGIN_CODE && 130 | mb_strpos($clear, self::END_CODE, $len, 'UTF-8') && 131 | ($matches = $find($js, '゚o゚', $start)) 132 | ) { 133 | list($beginAt, $endAt) = $matches; 134 | $beginAt = mb_strpos($js, '+', $beginAt, 'UTF-8'); 135 | $endAt = mb_strrpos($js, '(', - mb_strlen($js, 'UTF-8') + $endAt, 'UTF-8'); 136 | $next = mb_strpos($js, ';', $endAt + 1, 'UTF-8') + 1; 137 | $encoded = preg_replace('/[\x03-\x20]/', '', mb_substr($js, $beginAt, $endAt - $beginAt, 'UTF-8')); 138 | return true; 139 | } 140 | } 141 | return false; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /AAEncoder.php: -------------------------------------------------------------------------------- 1 | 5 | * @link https://github.com/mervick/php-aaencoder 6 | * @license MIT 7 | */ 8 | 9 | /** 10 | * Class AAEncoder 11 | */ 12 | class AAEncoder 13 | { 14 | /** 15 | * Encode any JavaScript program to Japanese style emoticons (^_^) 16 | * @param string $js 17 | * @param int $level [optional] 18 | * @return string 19 | */ 20 | public static function encode($js, $level=0) 21 | { 22 | $result = "゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); " . 23 | "(゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);" . 24 | "(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] " . 25 | ",゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] " . 26 | ",゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];" . 27 | "(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];" . 28 | "(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];" . 29 | "(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + " . 30 | "((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+" . 31 | "((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+" . 32 | "((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+" . 33 | "((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];" . 34 | "(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+" . 35 | "((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+" . 36 | "((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; " . 37 | "(゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\\\'; " . 38 | "(゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];" . 39 | "(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];" . 40 | "(゚Д゚) [゚o゚]='\\\"';" . 41 | "(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+" . 42 | "/*´∇`*/(゚Д゚)[゚o゚]+ "; 43 | 44 | for ($i = 0, $len = mb_strlen($js); $i < $len; $i++) { 45 | $code = unpack('N', mb_convert_encoding(mb_substr($js, $i, 1, 'UTF-8'), 'UCS-4BE', 'UTF-8'))[1]; 46 | $text = '(゚Д゚)[゚ε゚]+'; 47 | if ($code <= 127) { 48 | $text .= preg_replace_callback('/([0-7])/', function($match) use ($level) { 49 | $byte = intval($match[1]); 50 | return ($level ? self::randomize($byte, $level) : self::$bytes[$byte]) . '+'; 51 | }, decoct($code)); 52 | } 53 | else { 54 | $hex = str_split(substr('000' . dechex($code), -4)); 55 | $text .= "(o゚ー゚o)+ "; 56 | for ($i = 0, $len = count($hex); $i < $len; $i++) { 57 | $text .= self::$bytes[hexdec($hex[$i])] . '+ '; 58 | } 59 | } 60 | $result .= $text; 61 | 62 | } 63 | $result .= "(゚Д゚)[゚o゚]) (゚Θ゚)) ('_');"; 64 | return $result; 65 | } 66 | 67 | /** 68 | * @var array 69 | */ 70 | protected static $bytes = [ 71 | "(c^_^o)", 72 | "(゚Θ゚)", 73 | "((o^_^o) - (゚Θ゚))", 74 | "(o^_^o)", 75 | "(゚ー゚)", 76 | "((゚ー゚) + (゚Θ゚))", 77 | "((o^_^o) +(o^_^o))", 78 | "((゚ー゚) + (o^_^o))", 79 | "((゚ー゚) + (゚ー゚))", 80 | "((゚ー゚) + (゚ー゚) + (゚Θ゚))", 81 | "(゚Д゚) .゚ω゚ノ", 82 | "(゚Д゚) .゚Θ゚ノ", 83 | "(゚Д゚) ['c']", 84 | "(゚Д゚) .゚ー゚ノ", 85 | "(゚Д゚) .゚Д゚ノ", 86 | "(゚Д゚) [゚Θ゚]", 87 | ]; 88 | 89 | /** 90 | * @param int $byte 91 | * @param int $level 92 | * @return string 93 | */ 94 | protected static function randomize($byte, $level) 95 | { 96 | $random = [ 97 | 0 => [['+0', '-0'], ['+1', '-1'], ['+3', '-3'], ['+4', '-4']], 98 | 1 => [['+1', '-0'], ['+3', '-1', '-1'], ['+4', '-3']], 99 | 2 => [['+3', '-1'], ['+4', '-3', '+1'], ['+3', '+3', '-4']], 100 | 3 => [['+3', '-0'], ['+4', '-3', '+1', '+1']], 101 | 4 => [['+4', '+0'], ['+1', '+3'], ['+4', '-0']], 102 | 5 => [['+3', '+1', '+1'], ['+4', '+1'], ['+3', '+3', '-1']], 103 | 6 => [['+3', '+3'], ['+4', '+1', '+1'], ['+4', '+3', '-1']], 104 | 7 => [['+3', '+4'], ['+3', '+3', '+1'], ['+4', '+4', '-1']], 105 | ]; 106 | while ($level--) { 107 | $byte = preg_replace_callback('/[0-7]/', function($match) use ($random) { 108 | $numbers = $random[$match[0]][mt_rand(0, count($random[$match[0]]) - 1)]; 109 | shuffle($numbers); 110 | $byte = ltrim(implode('', $numbers), '+'); 111 | return "($byte)"; 112 | }, $byte); 113 | } 114 | $byte = str_replace('+-', '-', $byte); 115 | return str_replace(array_keys(self::$bytes), self::$bytes, $byte); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Andrey Izman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://stand-with-ukraine.pp.ua/) 2 | 3 | # PHP AAEncoder and AADecoder 4 | 5 | `AAEncoder` - Encode any JavaScript program to [Japanese style emoticons](http://utf-8.jp/public/aaencode.html) (^\_^). 6 | `AADecoder` - Decode encoded as aaencode JavaScript program. (゚Д゚) ['\_'] 7 | 8 | ## Installation via Composer 9 | ```sh 10 | composer require "mervick/aaencoder" 11 | ``` 12 | 13 | ## Usage 14 | ```php 15 | // aaencode: 16 | echo AAEncoder::encode(file_get_contents('/path/to/file.js')); 17 | // Also, you can customize encoding level, may be >= 0, default 0. 18 | // Be careful, the greater the level of encryption the larger output file. 19 | // It is not recommended to use more than 3 20 | echo AAEncoder::encode(file_get_contents('/path/to/file.js'), 2); 21 | 22 | // aadecode: 23 | echo AADecoder::decode(file_get_contents('/path/to/encoded.js')); 24 | ``` 25 | 26 | ## Requirements 27 | PHP >= 5.4 28 | 29 | ## License 30 | MIT 31 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mervick/aaencoder", 3 | "description": "Encode/decode any JavaScript program to/from Japanese style emoticons", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Andrey Izman", 8 | "email": "izmanw@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "php": ">=5.4.0" 13 | }, 14 | "keywords": [ 15 | "aaencode", 16 | "aadecode", 17 | "aaencoder", 18 | "aadecoder", 19 | "javascript" 20 | ], 21 | "autoload": { 22 | "psr-0": { 23 | "AADecoder": "", 24 | "AAEncoder": "" 25 | } 26 | } 27 | } --------------------------------------------------------------------------------