PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/resources/compiler/cJSCompiler.php

https://github.com/mibamur/amplesdk
PHP | 324 lines | 213 code | 61 blank | 50 comment | 32 complexity | 8d649717610a23201c857bb071c2158e MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. class cJSCompiler
  3. {
  4. var $output = "";
  5. var $aStrings = array();
  6. var $keyword = "munged";
  7. var $debug = false;
  8. function cJSCompiler() {
  9. }
  10. function readFromString($sString) {
  11. $this->output = $sString;
  12. }
  13. function readFromFile($sFileName) {
  14. $this->output = $this->output . join("", file($sFileName));
  15. }
  16. function getOutput() {
  17. return $this->output;
  18. }
  19. function addOmmitArray($aOmmit) {
  20. for ($nIndex = 0; $nIndex < count($aOmmit); $nIndex++)
  21. $this->addOmmitString($aOmmit[$nIndex]);
  22. }
  23. function addOmmitString($sString) {
  24. if (!in_array($sString, $this->aStrings))
  25. array_push($this->aStrings, $sString);
  26. }
  27. function stripComments() {
  28. $sData = $this->output;
  29. // Strip '//' comments
  30. $sData = str_replace('://', '?????', $sData);
  31. $sData = preg_replace('/\/\/.*(\r?\n)/', "", $sData);
  32. $sData = str_replace('?????', '://', $sData);
  33. // Strip '/* comment */' comments
  34. $sData = preg_replace('/\/\*.+\*\//Us', "", $sData);
  35. $this->output = $sData;
  36. }
  37. function stripSpaces() {
  38. $sData = $this->output;
  39. // replace tabs with spaces
  40. $sData = str_replace(" ", " ", $sData);
  41. // Strip ' : ' spaces around
  42. $sData = preg_replace('/\s*([=\+\-\*\/\?\:\|\&\^\!<>\{\},%;\(\)])\s*/', '\\1', $sData);
  43. //
  44. $sData = preg_replace('/\s*(if|for|with|do|while|try|catch)\s+/', '\\1', $sData);
  45. // strip carriage returns
  46. $sData = preg_replace("/\r\n|\r|\n/", "", $sData);
  47. // strip all more than one spaces
  48. $sData = preg_replace("/\s\s+/", "", $sData);
  49. // correct the bug produced above
  50. $sData = str_replace("else", "else ", $sData);
  51. $sData = str_replace("else {", "else{", $sData);
  52. $sData = str_replace(";}", "}", $sData);
  53. $this->output = $sData;
  54. }
  55. /*
  56. * Obfuscates variables (starting with any known variable prefix)
  57. *
  58. */
  59. function obfuscateVariables() {
  60. $sData = $this->output;
  61. preg_match_all('/[^a-zA-Z]([a-z][A-Z][a-zA-Z0-9_]+)/', $sData, $aTemp);
  62. $aValues = array_unique($aTemp[1]);
  63. sort($aValues);
  64. reset($aValues);
  65. // $aValues = $this->_normalizeArray($aTemp[1]);
  66. // Debug
  67. if ($this->debug)
  68. echo "Processing local variables:\n";
  69. for ($nIndex = count($aValues)-1; $nIndex >= 0; $nIndex--) {
  70. $sReplace = /*$nIndex < 26 ? chr(97 + $nIndex) :*/ $this->createToken($nIndex);
  71. $sData = str_replace($aValues[$nIndex], $sReplace, $sData);
  72. // $sData = preg_replace('/(\W)' . $aValues[$nIndex] . '(\W)/', '$1' . $sReplace . '$2', $sData);
  73. // Debug
  74. if ($this->debug)
  75. echo $aValues[$nIndex] . " [" . count(array_intersect($aTemp[1], array($aValues[$nIndex]))). "] -> " . $sReplace . "\n";
  76. }
  77. // Debug
  78. if ($this->debug)
  79. echo "\n";
  80. $this->output = $sData;
  81. }
  82. /*
  83. * Obfuscates private properties (starting with "_" prefix)
  84. *
  85. */
  86. function obfuscatePrivates() {
  87. $sData = $this->output;
  88. preg_match_all('/(\._[a-z_]+)/i', $sData, $aTemp);
  89. $aValues = array_unique($aTemp[1]);
  90. sort($aValues);
  91. reset($aValues);
  92. // Debug
  93. if ($this->debug)
  94. echo "Processing private members:\n";
  95. for ($nIndex = count($aValues)-1; $nIndex >= 0; $nIndex--) {
  96. $sReplace = "." . $this->createToken($nIndex);
  97. $sData = str_replace($aValues[$nIndex], $sReplace, $sData);
  98. // Debug
  99. if ($this->debug)
  100. echo $aValues[$nIndex] . " [" . count(array_intersect($aTemp[1], array($aValues[$nIndex]))). "] -> " . $sReplace . "\n";
  101. }
  102. // Debug
  103. if ($this->debug)
  104. echo "\n";
  105. $this->output = $sData;
  106. }
  107. function obfuscateStrings() {
  108. $sData = $this->output;
  109. $sDataTemp = $sData;
  110. if (count($this->aStrings))
  111. $sDataTemp = str_replace($this->aStrings, array_fill(0, count($this->aStrings), ""), $sDataTemp);
  112. // find "values"
  113. preg_match_all('/\"([a-z0-9_\-+\#\:\;\/\.]{2,})\"/i', $sDataTemp, $aTempValues);
  114. // find .properties
  115. preg_match_all('/\.(\$?[a-z][a-z0-9_]{2,})/i', $sDataTemp, $aTempProperties);
  116. /*
  117. $this->aStrings = array_unique(array_merge($this->aStrings, $aTempValues[1], $aTempProperties[1]));
  118. sort($this->aStrings);
  119. reset($this->aStrings);
  120. */
  121. $this->aStrings = $this->_normalizeArray(array_merge($this->aStrings, $aTempValues[1], $aTempProperties[1]));
  122. // Debug
  123. if ($this->debug)
  124. echo "Processing public properties and string values:\n";
  125. // manually replace most used property "prototype"
  126. $sData = str_replace(".prototype", "[$]", $sData);
  127. // Strings
  128. for ($nIndex = count($this->aStrings)-1; $nIndex >= 0; $nIndex--)
  129. $sData = str_replace( '"' . $this->aStrings[$nIndex] . '"', "_[" . $nIndex . ']', $sData);
  130. // Properties
  131. for ($nIndex = count($this->aStrings)-1; $nIndex >= 0; $nIndex--) {
  132. /*
  133. $sData = str_replace( '.' . $this->aStrings[$nIndex], "[_[" . $nIndex . ']]', $sData);
  134. */
  135. $sData = preg_replace( '/\.' .
  136. str_replace(
  137. array('/', '.', '$'),
  138. array('\/', '\.', '\$'),
  139. $this->aStrings[$nIndex]
  140. ). '(?!\w)/', "[_[" . $nIndex . ']]', $sData);
  141. // Debug
  142. if ($this->debug)
  143. echo $this->aStrings[$nIndex] . " [" . count(array_intersect(array_merge($aTempValues[1], $aTempProperties[1]), array($this->aStrings[$nIndex]))). "]\n";
  144. }
  145. // Debug
  146. if ($this->debug)
  147. echo "\n";
  148. $this->output = $sData;
  149. }
  150. function obfuscate() {
  151. // get or create obfuscated properties
  152. $nWString = array_search("String", $this->aStrings);
  153. if (!$nWString)
  154. $nWString = array_push($this->aStrings, "String") - 1;
  155. $nWMath = array_search("Math", $this->aStrings);
  156. if (!$nWMath)
  157. $nWMath = array_push($this->aStrings, "Math") - 1;
  158. $nWRegExp = array_search("RegExp", $this->aStrings);
  159. if (!$nWRegExp)
  160. $nWRegExp = array_push($this->aStrings, "RegExp") - 1;
  161. $nWFunction = array_search("Function", $this->aStrings);
  162. if (!$nWFunction)
  163. $nWFunction = array_push($this->aStrings, "Function") - 1;
  164. $nWlength = array_search("length", $this->aStrings);
  165. if (!$nWlength)
  166. $nWlength = array_push($this->aStrings, "length") - 1;
  167. $nWreplace = array_search("replace", $this->aStrings);
  168. if (!$nWreplace)
  169. $nWreplace = array_push($this->aStrings, "replace") - 1;
  170. $nWsplit = array_search("split", $this->aStrings);
  171. if (!$nWsplit)
  172. $nWsplit = array_push($this->aStrings, "split") - 1;
  173. $nWfromCharCode = array_search("fromCharCode", $this->aStrings);
  174. if (!$nWfromCharCode)
  175. $nWfromCharCode = array_push($this->aStrings, "fromCharCode") - 1;
  176. $nWcharCodeAt = array_search("charCodeAt", $this->aStrings);
  177. if (!$nWcharCodeAt)
  178. $nWcharCodeAt = array_push($this->aStrings, "charCodeAt") - 1;
  179. $nWfloor = array_search("floor", $this->aStrings);
  180. if (!$nWfloor)
  181. $nWfloor = array_push($this->aStrings, "floor") - 1;
  182. $output = $this->output;
  183. $sKeyWords = "";
  184. $nShift = 1;
  185. if (true) {
  186. $aKeyWords = array();
  187. $aKeyWords = array_merge($aKeyWords, array("in", "break", "case", "catch", "continue", "default", "delete", "else", "for", "function", "if", "instanceof", "new", "return", "throw", "typeof", "switch", "try", "var", "while", "with"));
  188. $aKeyWords = array_merge($aKeyWords, array("false", "null", "true"));
  189. $aKeyWords = array_merge($aKeyWords, array("arguments", "this", "window"));
  190. $aKeyWords = array_merge($aKeyWords, array("[_[", "]]", "[$]"));
  191. $aKeyWords = array_merge($aKeyWords, array("[]", "{}", "()", "&&", "||", "===", "==", "!!", "!==", "!=", "+=", "-=", "++", "--", "<=", ">="));
  192. // replace js keywords
  193. for ($nIndex = count($aKeyWords) - 1; $nIndex >= 0; $nIndex--)
  194. $output = str_replace($aKeyWords[$nIndex], ($nIndex % 10) . chr(122 - floor($nIndex/10)), $output);
  195. // encode keywords
  196. $sKeyWords = join(" ", $aKeyWords);
  197. $sKeyWords2 = "";
  198. for ($nIndex = strlen($sKeyWords) - 1; $nIndex >= 0; $nIndex--)
  199. $sKeyWords2 .= chr(ord(substr($sKeyWords, $nIndex, 1)) + $nShift);
  200. $sKeyWords = $sKeyWords2;
  201. }
  202. $m = $this->keyword[0];
  203. $u = $this->keyword[1];
  204. $n = $this->keyword[2];
  205. $g = $this->keyword[3];
  206. $e = $this->keyword[4];
  207. $d = $this->keyword[5];
  208. // create JS wrapper
  209. $sData = "(function({$m},{$u},{$n},{$g},{$e},{$d}){";
  210. if (true) {
  211. // decode js keywords
  212. $sData.= "for({$g}={$u}[{$d}[$nWlength]]-1;{$g}>=0;{$g}--)".
  213. "{$n}+={$e}[{$d}[$nWString]][{$d}[$nWfromCharCode]]({$u}[{$d}[$nWcharCodeAt]]({$g})-$nShift);";
  214. // restore js source
  215. $sData.= "{$u}={$n}[{$d}[$nWsplit]](' ');".
  216. "for({$g}={$u}[{$d}[$nWlength]]-1;{$g}>=0;{$g}--)".
  217. "{$m}={$m}[{$d}[$nWreplace]]({$e}[{$d}[$nWRegExp]]({$g}%10+({$e}[{$d}[$nWString]][{$d}[$nWfromCharCode]](122-{$e}[{$d}[$nWMath]][{$d}[$nWfloor]]({$g}/10))),'g'),{$u}[{$g}]);";
  218. }
  219. // execute source
  220. $sData .= "{$e}[{$d}[$nWFunction]]('_','$',{$m})({$d},{$d}[" . array_search("prototype", $this->aStrings) . "])";
  221. $sData .= "})(".
  222. "\"" . str_replace("\'", "'", addslashes($output)) . "\"," .
  223. "\"" . addslashes($sKeyWords) ."\",".
  224. "''," .
  225. "0," .
  226. "this,".
  227. "'" . join(" ", $this->aStrings) . "'.split(' ')".
  228. ")";
  229. $this->output = $sData;
  230. }
  231. function obfuscate2() {
  232. $output = $this->output;
  233. // Restore prototype to proper reference
  234. // $output = str_replace("[$]", "[_[0]]", $output);
  235. $sData = "(function($,_,_\$){"
  236. . str_replace("window", "_\$", $output)
  237. . "})('prototype','" . join(" ", $this->aStrings) . "'.split(' '),window)";
  238. $this->output = $sData;
  239. }
  240. function _normalizeArray($aTemp) {
  241. $aValuesTemp = array();
  242. for ($nIndex = count($aTemp) - 1; $nIndex >= 0; $nIndex--) {
  243. if (array_key_exists($aTemp[$nIndex], $aValuesTemp))
  244. $aValuesTemp[$aTemp[$nIndex]]++;
  245. else
  246. $aValuesTemp[$aTemp[$nIndex]] = 1;
  247. }
  248. arsort($aValuesTemp);
  249. // print_r($aValuesTemp);
  250. $aValues = array_keys($aValuesTemp);
  251. return $aValues;
  252. }
  253. var $reservedTokens = array("as", "do", "if", "in", "is", "for"/*, "let"*/, "var");
  254. var $alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  255. function createToken($nIndex) {
  256. $sToken = $nIndex < 52
  257. ? substr($this->alphabet, $nIndex, 1)
  258. : substr($this->alphabet, (int) ($nIndex / 52), 1) . substr($this->alphabet, $nIndex % 62, 1);
  259. $nPosition = array_search($sToken, $this->reservedTokens);
  260. return $nPosition ? "_" . chr(97 + $nPosition % 62) : $sToken;
  261. }
  262. }
  263. ?>