Commit 6f9fe6a0969ac16b347b83f386c0246bee421728

Authored by Edmar Moretti
1 parent f1e1a758

biblioteca packer movida para pacotes

classesjs/packer/class.JavaScriptPacker.php
@@ -1,736 +0,0 @@ @@ -1,736 +0,0 @@
1 -<?php  
2 -/* 7 December 2006. version 1.0  
3 - *  
4 - * This is the php version of the Dean Edwards JavaScript 's Packer,  
5 - * Based on :  
6 - *  
7 - * ParseMaster, version 1.0.2 (2005-08-19) Copyright 2005, Dean Edwards  
8 - * a multi-pattern parser.  
9 - * KNOWN BUG: erroneous behavior when using escapeChar with a replacement  
10 - * value that is a function  
11 - *  
12 - * packer, version 2.0.2 (2005-08-19) Copyright 2004-2005, Dean Edwards  
13 - *  
14 - * License: http://creativecommons.org/licenses/LGPL/2.1/  
15 - *  
16 - * Ported to PHP by Nicolas Martin.  
17 - *  
18 - * ----------------------------------------------------------------------  
19 - *  
20 - * examples of usage :  
21 - * $myPacker = new JavaScriptPacker($script, 62, true, false);  
22 - * $packed = $myPacker->pack();  
23 - *  
24 - * or  
25 - *  
26 - * $myPacker = new JavaScriptPacker($script, 'Normal', true, false);  
27 - * $packed = $myPacker->pack();  
28 - *  
29 - * or (default values)  
30 - *  
31 - * $myPacker = new JavaScriptPacker($script);  
32 - * $packed = $myPacker->pack();  
33 - *  
34 - *  
35 - * params of the constructor :  
36 - * $script: the JavaScript to pack, string.  
37 - * $encoding: level of encoding, int or string :  
38 - * 0,10,62,95 or 'None', 'Numeric', 'Normal', 'High ASCII'.  
39 - * default: 62.  
40 - * $fastDecode: include the fast decoder in the packed result, boolean.  
41 - * default : true.  
42 - * $specialChars: if you are flagged your private and local variables  
43 - * in the script, boolean.  
44 - * default: false.  
45 - *  
46 - * The pack() method return the compressed JavasScript, as a string.  
47 - *  
48 - * see http://dean.edwards.name/packer/usage/ for more information.  
49 - *  
50 - * Notes :  
51 - * # need PHP 5 . Tested with PHP 5.1.2  
52 - *  
53 - * # The packed result may be different than with the Dean Edwards  
54 - * version, but with the same length. The reason is that the PHP  
55 - * function usort to sort array don't necessarily preserve the  
56 - * original order of two equal member. The Javascript sort function  
57 - * in fact preserve this order (but that's not require by the  
58 - * ECMAScript standard). So the encoded keywords order can be  
59 - * different in the two results.  
60 - *  
61 - * # Be careful with the 'High ASCII' Level encoding if you use  
62 - * UTF-8 in your files...  
63 - */  
64 -  
65 -  
66 -class JavaScriptPacker {  
67 - // constants  
68 - const IGNORE = '$1';  
69 -  
70 - // validate parameters  
71 - private $_script = '';  
72 - private $_encoding = 62;  
73 - private $_fastDecode = true;  
74 - private $_specialChars = false;  
75 -  
76 - private $LITERAL_ENCODING = array(  
77 - 'None' => 0,  
78 - 'Numeric' => 10,  
79 - 'Normal' => 62,  
80 - 'High ASCII' => 95  
81 - );  
82 -  
83 - public function __construct($_script, $_encoding = 62, $_fastDecode = true, $_specialChars = false)  
84 - {  
85 - $this->_script = $_script . "\n";  
86 - if (array_key_exists($_encoding, $this->LITERAL_ENCODING))  
87 - $_encoding = $this->LITERAL_ENCODING[$_encoding];  
88 - $this->_encoding = min((int)$_encoding, 95);  
89 - $this->_fastDecode = $_fastDecode;  
90 - $this->_specialChars = $_specialChars;  
91 - }  
92 -  
93 - public function pack() {  
94 - $this->_addParser('_basicCompression');  
95 - if ($this->_specialChars)  
96 - $this->_addParser('_encodeSpecialChars');  
97 - if ($this->_encoding)  
98 - $this->_addParser('_encodeKeywords');  
99 -  
100 - // go!  
101 - return $this->_pack($this->_script);  
102 - }  
103 -  
104 - // apply all parsing routines  
105 - private function _pack($script) {  
106 - for ($i = 0; isset($this->_parsers[$i]); $i++) {  
107 - $script = call_user_func(array(&$this,$this->_parsers[$i]), $script);  
108 - }  
109 - return $script;  
110 - }  
111 -  
112 - // keep a list of parsing functions, they'll be executed all at once  
113 - private $_parsers = array();  
114 - private function _addParser($parser) {  
115 - $this->_parsers[] = $parser;  
116 - }  
117 -  
118 - // zero encoding - just removal of white space and comments  
119 - private function _basicCompression($script) {  
120 - $parser = new ParseMaster();  
121 - // make safe  
122 - $parser->escapeChar = '\\';  
123 - // protect strings  
124 - $parser->add('/\'[^\'\\n\\r]*\'/', self::IGNORE);  
125 - $parser->add('/"[^"\\n\\r]*"/', self::IGNORE);  
126 - // remove comments  
127 - $parser->add('/\\/\\/[^\\n\\r]*[\\n\\r]/', ' ');  
128 - $parser->add('/\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\//', ' ');  
129 - // protect regular expressions  
130 - $parser->add('/\\s+(\\/[^\\/\\n\\r\\*][^\\/\\n\\r]*\\/g?i?)/', '$2'); // IGNORE  
131 - $parser->add('/[^\\w\\x24\\/\'"*)\\?:]\\/[^\\/\\n\\r\\*][^\\/\\n\\r]*\\/g?i?/', self::IGNORE);  
132 - // remove: ;;; doSomething();  
133 - if ($this->_specialChars) $parser->add('/;;;[^\\n\\r]+[\\n\\r]/');  
134 - // remove redundant semi-colons  
135 - $parser->add('/\\(;;\\)/', self::IGNORE); // protect for (;;) loops  
136 - $parser->add('/;+\\s*([};])/', '$2');  
137 - // apply the above  
138 - $script = $parser->exec($script);  
139 -  
140 - // remove white-space  
141 - $parser->add('/(\\b|\\x24)\\s+(\\b|\\x24)/', '$2 $3');  
142 - $parser->add('/([+\\-])\\s+([+\\-])/', '$2 $3');  
143 - $parser->add('/\\s+/', '');  
144 - // done  
145 - return $parser->exec($script);  
146 - }  
147 -  
148 - private function _encodeSpecialChars($script) {  
149 - $parser = new ParseMaster();  
150 - // replace: $name -> n, $$name -> na  
151 - $parser->add('/((\\x24+)([a-zA-Z$_]+))(\\d*)/',  
152 - array('fn' => '_replace_name')  
153 - );  
154 - // replace: _name -> _0, double-underscore (__name) is ignored  
155 - $regexp = '/\\b_[A-Za-z\\d]\\w*/';  
156 - // build the word list  
157 - $keywords = $this->_analyze($script, $regexp, '_encodePrivate');  
158 - // quick ref  
159 - $encoded = $keywords['encoded'];  
160 -  
161 - $parser->add($regexp,  
162 - array(  
163 - 'fn' => '_replace_encoded',  
164 - 'data' => $encoded  
165 - )  
166 - );  
167 - return $parser->exec($script);  
168 - }  
169 -  
170 - private function _encodeKeywords($script) {  
171 - // escape high-ascii values already in the script (i.e. in strings)  
172 - if ($this->_encoding > 62)  
173 - $script = $this->_escape95($script);  
174 - // create the parser  
175 - $parser = new ParseMaster();  
176 - $encode = $this->_getEncoder($this->_encoding);  
177 - // for high-ascii, don't encode single character low-ascii  
178 - $regexp = ($this->_encoding > 62) ? '/\\w\\w+/' : '/\\w+/';  
179 - // build the word list  
180 - $keywords = $this->_analyze($script, $regexp, $encode);  
181 - $encoded = $keywords['encoded'];  
182 -  
183 - // encode  
184 - $parser->add($regexp,  
185 - array(  
186 - 'fn' => '_replace_encoded',  
187 - 'data' => $encoded  
188 - )  
189 - );  
190 - if (empty($script)) return $script;  
191 - else {  
192 - //$res = $parser->exec($script);  
193 - //$res = $this->_bootStrap($res, $keywords);  
194 - //return $res;  
195 - return $this->_bootStrap($parser->exec($script), $keywords);  
196 - }  
197 - }  
198 -  
199 - private function _analyze($script, $regexp, $encode) {  
200 - // analyse  
201 - // retreive all words in the script  
202 - $all = array();  
203 - preg_match_all($regexp, $script, $all);  
204 - $_sorted = array(); // list of words sorted by frequency  
205 - $_encoded = array(); // dictionary of word->encoding  
206 - $_protected = array(); // instances of "protected" words  
207 - $all = $all[0]; // simulate the javascript comportement of global match  
208 - if (!empty($all)) {  
209 - $unsorted = array(); // same list, not sorted  
210 - $protected = array(); // "protected" words (dictionary of word->"word")  
211 - $value = array(); // dictionary of charCode->encoding (eg. 256->ff)  
212 - $this->_count = array(); // word->count  
213 - $i = count($all); $j = 0; //$word = null;  
214 - // count the occurrences - used for sorting later  
215 - do {  
216 - --$i;  
217 - $word = '$' . $all[$i];  
218 - if (!isset($this->_count[$word])) {  
219 - $this->_count[$word] = 0;  
220 - $unsorted[$j] = $word;  
221 - // make a dictionary of all of the protected words in this script  
222 - // these are words that might be mistaken for encoding  
223 - //if (is_string($encode) && method_exists($this, $encode))  
224 - $values[$j] = call_user_func(array(&$this, $encode), $j);  
225 - $protected['$' . $values[$j]] = $j++;  
226 - }  
227 - // increment the word counter  
228 - $this->_count[$word]++;  
229 - } while ($i > 0);  
230 - // prepare to sort the word list, first we must protect  
231 - // words that are also used as codes. we assign them a code  
232 - // equivalent to the word itself.  
233 - // e.g. if "do" falls within our encoding range  
234 - // then we store keywords["do"] = "do";  
235 - // this avoids problems when decoding  
236 - $i = count($unsorted);  
237 - do {  
238 - $word = $unsorted[--$i];  
239 - if (isset($protected[$word]) /*!= null*/) {  
240 - $_sorted[$protected[$word]] = substr($word, 1);  
241 - $_protected[$protected[$word]] = true;  
242 - $this->_count[$word] = 0;  
243 - }  
244 - } while ($i);  
245 -  
246 - // sort the words by frequency  
247 - // Note: the javascript and php version of sort can be different :  
248 - // in php manual, usort :  
249 - // " If two members compare as equal,  
250 - // their order in the sorted array is undefined."  
251 - // so the final packed script is different of the Dean's javascript version  
252 - // but equivalent.  
253 - // the ECMAscript standard does not guarantee this behaviour,  
254 - // and thus not all browsers (e.g. Mozilla versions dating back to at  
255 - // least 2003) respect this.  
256 - usort($unsorted, array(&$this, '_sortWords'));  
257 - $j = 0;  
258 - // because there are "protected" words in the list  
259 - // we must add the sorted words around them  
260 - do {  
261 - if (!isset($_sorted[$i]))  
262 - $_sorted[$i] = substr($unsorted[$j++], 1);  
263 - $_encoded[$_sorted[$i]] = $values[$i];  
264 - } while (++$i < count($unsorted));  
265 - }  
266 - return array(  
267 - 'sorted' => $_sorted,  
268 - 'encoded' => $_encoded,  
269 - 'protected' => $_protected);  
270 - }  
271 -  
272 - private $_count = array();  
273 - private function _sortWords($match1, $match2) {  
274 - return $this->_count[$match2] - $this->_count[$match1];  
275 - }  
276 -  
277 - // build the boot function used for loading and decoding  
278 - private function _bootStrap($packed, $keywords) {  
279 - $ENCODE = $this->_safeRegExp('$encode\\($count\\)');  
280 -  
281 - // $packed: the packed script  
282 - $packed = "'" . $this->_escape($packed) . "'";  
283 -  
284 - // $ascii: base for encoding  
285 - $ascii = min(count($keywords['sorted']), $this->_encoding);  
286 - if ($ascii == 0) $ascii = 1;  
287 -  
288 - // $count: number of words contained in the script  
289 - $count = count($keywords['sorted']);  
290 -  
291 - // $keywords: list of words contained in the script  
292 - foreach ($keywords['protected'] as $i=>$value) {  
293 - $keywords['sorted'][$i] = '';  
294 - }  
295 - // convert from a string to an array  
296 - ksort($keywords['sorted']);  
297 - $keywords = "'" . implode('|',$keywords['sorted']) . "'.split('|')";  
298 -  
299 - $encode = ($this->_encoding > 62) ? '_encode95' : $this->_getEncoder($ascii);  
300 - $encode = $this->_getJSFunction($encode);  
301 - $encode = preg_replace('/_encoding/','$ascii', $encode);  
302 - $encode = preg_replace('/arguments\\.callee/','$encode', $encode);  
303 - $inline = '\\$count' . ($ascii > 10 ? '.toString(\\$ascii)' : '');  
304 -  
305 - // $decode: code snippet to speed up decoding  
306 - if ($this->_fastDecode) {  
307 - // create the decoder  
308 - $decode = $this->_getJSFunction('_decodeBody');  
309 - if ($this->_encoding > 62)  
310 - $decode = preg_replace('/\\\\w/', '[\\xa1-\\xff]', $decode);  
311 - // perform the encoding inline for lower ascii values  
312 - elseif ($ascii < 36)  
313 - $decode = preg_replace($ENCODE, $inline, $decode);  
314 - // special case: when $count==0 there are no keywords. I want to keep  
315 - // the basic shape of the unpacking funcion so i'll frig the code...  
316 - if ($count == 0)  
317 - $decode = preg_replace($this->_safeRegExp('($count)\\s*=\\s*1'), '$1=0', $decode, 1);  
318 - }  
319 -  
320 - // boot function  
321 - $unpack = $this->_getJSFunction('_unpack');  
322 - if ($this->_fastDecode) {  
323 - // insert the decoder  
324 - $this->buffer = $decode;  
325 - $unpack = preg_replace_callback('/\\{/', array(&$this, '_insertFastDecode'), $unpack, 1);  
326 - }  
327 - $unpack = preg_replace('/"/', "'", $unpack);  
328 - if ($this->_encoding > 62) { // high-ascii  
329 - // get rid of the word-boundaries for regexp matches  
330 - $unpack = preg_replace('/\'\\\\\\\\b\'\s*\\+|\\+\s*\'\\\\\\\\b\'/', '', $unpack);  
331 - }  
332 - if ($ascii > 36 || $this->_encoding > 62 || $this->_fastDecode) {  
333 - // insert the encode function  
334 - $this->buffer = $encode;  
335 - $unpack = preg_replace_callback('/\\{/', array(&$this, '_insertFastEncode'), $unpack, 1);  
336 - } else {  
337 - // perform the encoding inline  
338 - $unpack = preg_replace($ENCODE, $inline, $unpack);  
339 - }  
340 - // pack the boot function too  
341 - $unpackPacker = new JavaScriptPacker($unpack, 0, false, true);  
342 - $unpack = $unpackPacker->pack();  
343 -  
344 - // arguments  
345 - $params = array($packed, $ascii, $count, $keywords);  
346 - if ($this->_fastDecode) {  
347 - $params[] = 0;  
348 - $params[] = '{}';  
349 - }  
350 - $params = implode(',', $params);  
351 -  
352 - // the whole thing  
353 - return 'eval(' . $unpack . '(' . $params . "))\n";  
354 - }  
355 -  
356 - private $buffer;  
357 - private function _insertFastDecode($match) {  
358 - return '{' . $this->buffer . ';';  
359 - }  
360 - private function _insertFastEncode($match) {  
361 - return '{$encode=' . $this->buffer . ';';  
362 - }  
363 -  
364 - // mmm.. ..which one do i need ??  
365 - private function _getEncoder($ascii) {  
366 - return $ascii > 10 ? $ascii > 36 ? $ascii > 62 ?  
367 - '_encode95' : '_encode62' : '_encode36' : '_encode10';  
368 - }  
369 -  
370 - // zero encoding  
371 - // characters: 0123456789  
372 - private function _encode10($charCode) {  
373 - return $charCode;  
374 - }  
375 -  
376 - // inherent base36 support  
377 - // characters: 0123456789abcdefghijklmnopqrstuvwxyz  
378 - private function _encode36($charCode) {  
379 - return base_convert($charCode, 10, 36);  
380 - }  
381 -  
382 - // hitch a ride on base36 and add the upper case alpha characters  
383 - // characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ  
384 - private function _encode62($charCode) {  
385 - $res = '';  
386 - if ($charCode >= $this->_encoding) {  
387 - $res = $this->_encode62((int)($charCode / $this->_encoding));  
388 - }  
389 - $charCode = $charCode % $this->_encoding;  
390 -  
391 - if ($charCode > 35)  
392 - return $res . chr($charCode + 29);  
393 - else  
394 - return $res . base_convert($charCode, 10, 36);  
395 - }  
396 -  
397 - // use high-ascii values  
398 - // characters: ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ  
399 - private function _encode95($charCode) {  
400 - $res = '';  
401 - if ($charCode >= $this->_encoding)  
402 - $res = $this->_encode95($charCode / $this->_encoding);  
403 -  
404 - return $res . chr(($charCode % $this->_encoding) + 161);  
405 - }  
406 -  
407 - private function _safeRegExp($string) {  
408 - return '/'.preg_replace('/\$/', '\\\$', $string).'/';  
409 - }  
410 -  
411 - private function _encodePrivate($charCode) {  
412 - return "_" . $charCode;  
413 - }  
414 -  
415 - // protect characters used by the parser  
416 - private function _escape($script) {  
417 - return preg_replace('/([\\\\\'])/', '\\\$1', $script);  
418 - }  
419 -  
420 - // protect high-ascii characters already in the script  
421 - private function _escape95($script) {  
422 - return preg_replace_callback(  
423 - '/[\\xa1-\\xff]/',  
424 - array(&$this, '_escape95Bis'),  
425 - $script  
426 - );  
427 - }  
428 - private function _escape95Bis($match) {  
429 - return '\x'.((string)dechex(ord($match)));  
430 - }  
431 -  
432 -  
433 - private function _getJSFunction($aName) {  
434 - if (defined('self::JSFUNCTION'.$aName))  
435 - return constant('self::JSFUNCTION'.$aName);  
436 - else  
437 - return '';  
438 - }  
439 -  
440 - // JavaScript Functions used.  
441 - // Note : In Dean's version, these functions are converted  
442 - // with 'String(aFunctionName);'.  
443 - // This internal conversion complete the original code, ex :  
444 - // 'while (aBool) anAction();' is converted to  
445 - // 'while (aBool) { anAction(); }'.  
446 - // The JavaScript functions below are corrected.  
447 -  
448 - // unpacking function - this is the boot strap function  
449 - // data extracted from this packing routine is passed to  
450 - // this function when decoded in the target  
451 - // NOTE ! : without the ';' final.  
452 - const JSFUNCTION_unpack =  
453 -  
454 -'function($packed, $ascii, $count, $keywords, $encode, $decode) {  
455 - while ($count--) {  
456 - if ($keywords[$count]) {  
457 - $packed = $packed.replace(new RegExp(\'\\\\b\' + $encode($count) + \'\\\\b\', \'g\'), $keywords[$count]);  
458 - }  
459 - }  
460 - return $packed;  
461 -}';  
462 -/*  
463 -'function($packed, $ascii, $count, $keywords, $encode, $decode) {  
464 - while ($count--)  
465 - if ($keywords[$count])  
466 - $packed = $packed.replace(new RegExp(\'\\\\b\' + $encode($count) + \'\\\\b\', \'g\'), $keywords[$count]);  
467 - return $packed;  
468 -}';  
469 -*/  
470 -  
471 - // code-snippet inserted into the unpacker to speed up decoding  
472 - const JSFUNCTION_decodeBody =  
473 -//_decode = function() {  
474 -// does the browser support String.replace where the  
475 -// replacement value is a function?  
476 -  
477 -' if (!\'\'.replace(/^/, String)) {  
478 - // decode all the values we need  
479 - while ($count--) {  
480 - $decode[$encode($count)] = $keywords[$count] || $encode($count);  
481 - }  
482 - // global replacement function  
483 - $keywords = [function ($encoded) {return $decode[$encoded]}];  
484 - // generic match  
485 - $encode = function () {return \'\\\\w+\'};  
486 - // reset the loop counter - we are now doing a global replace  
487 - $count = 1;  
488 - }  
489 -';  
490 -//};  
491 -/*  
492 -' if (!\'\'.replace(/^/, String)) {  
493 - // decode all the values we need  
494 - while ($count--) $decode[$encode($count)] = $keywords[$count] || $encode($count);  
495 - // global replacement function  
496 - $keywords = [function ($encoded) {return $decode[$encoded]}];  
497 - // generic match  
498 - $encode = function () {return\'\\\\w+\'};  
499 - // reset the loop counter - we are now doing a global replace  
500 - $count = 1;  
501 - }';  
502 -*/  
503 -  
504 - // zero encoding  
505 - // characters: 0123456789  
506 - const JSFUNCTION_encode10 =  
507 -'function($charCode) {  
508 - return $charCode;  
509 -}';//;';  
510 -  
511 - // inherent base36 support  
512 - // characters: 0123456789abcdefghijklmnopqrstuvwxyz  
513 - const JSFUNCTION_encode36 =  
514 -'function($charCode) {  
515 - return $charCode.toString(36);  
516 -}';//;';  
517 -  
518 - // hitch a ride on base36 and add the upper case alpha characters  
519 - // characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ  
520 - const JSFUNCTION_encode62 =  
521 -'function($charCode) {  
522 - return ($charCode < _encoding ? \'\' : arguments.callee(parseInt($charCode / _encoding))) +  
523 - (($charCode = $charCode % _encoding) > 35 ? String.fromCharCode($charCode + 29) : $charCode.toString(36));  
524 -}';  
525 -  
526 - // use high-ascii values  
527 - // characters: ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ  
528 - const JSFUNCTION_encode95 =  
529 -'function($charCode) {  
530 - return ($charCode < _encoding ? \'\' : arguments.callee($charCode / _encoding)) +  
531 - String.fromCharCode($charCode % _encoding + 161);  
532 -}';  
533 -  
534 -}  
535 -  
536 -  
537 -class ParseMaster {  
538 - public $ignoreCase = false;  
539 - public $escapeChar = '';  
540 -  
541 - // constants  
542 - const EXPRESSION = 0;  
543 - const REPLACEMENT = 1;  
544 - const LENGTH = 2;  
545 -  
546 - // used to determine nesting levels  
547 - private $GROUPS = '/\\(/';//g  
548 - private $SUB_REPLACE = '/\\$\\d/';  
549 - private $INDEXED = '/^\\$\\d+$/';  
550 - private $TRIM = '/([\'"])\\1\\.(.*)\\.\\1\\1$/';  
551 - private $ESCAPE = '/\\\./';//g  
552 - private $QUOTE = '/\'/';  
553 - private $DELETED = '/\\x01[^\\x01]*\\x01/';//g  
554 -  
555 - public function add($expression, $replacement = '') {  
556 - // count the number of sub-expressions  
557 - // - add one because each pattern is itself a sub-expression  
558 - $length = 1 + preg_match_all($this->GROUPS, $this->_internalEscape((string)$expression), $out);  
559 -  
560 - // treat only strings $replacement  
561 - if (is_string($replacement)) {  
562 - // does the pattern deal with sub-expressions?  
563 - if (preg_match($this->SUB_REPLACE, $replacement)) {  
564 - // a simple lookup? (e.g. "$2")  
565 - if (preg_match($this->INDEXED, $replacement)) {  
566 - // store the index (used for fast retrieval of matched strings)  
567 - $replacement = (int)(substr($replacement, 1)) - 1;  
568 - } else { // a complicated lookup (e.g. "Hello $2 $1")  
569 - // build a function to do the lookup  
570 - $quote = preg_match($this->QUOTE, $this->_internalEscape($replacement))  
571 - ? '"' : "'";  
572 - $replacement = array(  
573 - 'fn' => '_backReferences',  
574 - 'data' => array(  
575 - 'replacement' => $replacement,  
576 - 'length' => $length,  
577 - 'quote' => $quote  
578 - )  
579 - );  
580 - }  
581 - }  
582 - }  
583 - // pass the modified arguments  
584 - if (!empty($expression)) $this->_add($expression, $replacement, $length);  
585 - else $this->_add('/^$/', $replacement, $length);  
586 - }  
587 -  
588 - public function exec($string) {  
589 - // execute the global replacement  
590 - $this->_escaped = array();  
591 -  
592 - // simulate the _patterns.toSTring of Dean  
593 - $regexp = '/';  
594 - foreach ($this->_patterns as $reg) {  
595 - $regexp .= '(' . substr($reg[self::EXPRESSION], 1, -1) . ')|';  
596 - }  
597 - $regexp = substr($regexp, 0, -1) . '/';  
598 - $regexp .= ($this->ignoreCase) ? 'i' : '';  
599 -  
600 - $string = $this->_escape($string, $this->escapeChar);  
601 - $string = preg_replace_callback(  
602 - $regexp,  
603 - array(  
604 - &$this,  
605 - '_replacement'  
606 - ),  
607 - $string  
608 - );  
609 - $string = $this->_unescape($string, $this->escapeChar);  
610 -  
611 - return preg_replace($this->DELETED, '', $string);  
612 - }  
613 -  
614 - public function reset() {  
615 - // clear the patterns collection so that this object may be re-used  
616 - $this->_patterns = array();  
617 - }  
618 -  
619 - // private  
620 - private $_escaped = array(); // escaped characters  
621 - private $_patterns = array(); // patterns stored by index  
622 -  
623 - // create and add a new pattern to the patterns collection  
624 - private function _add() {  
625 - $arguments = func_get_args();  
626 - $this->_patterns[] = $arguments;  
627 - }  
628 -  
629 - // this is the global replace function (it's quite complicated)  
630 - private function _replacement($arguments) {  
631 - if (empty($arguments)) return '';  
632 -  
633 - $i = 1; $j = 0;  
634 - // loop through the patterns  
635 - while (isset($this->_patterns[$j])) {  
636 - $pattern = $this->_patterns[$j++];  
637 - // do we have a result?  
638 - if (isset($arguments[$i]) && ($arguments[$i] != '')) {  
639 - $replacement = $pattern[self::REPLACEMENT];  
640 -  
641 - if (is_array($replacement) && isset($replacement['fn'])) {  
642 -  
643 - if (isset($replacement['data'])) $this->buffer = $replacement['data'];  
644 - return call_user_func(array(&$this, $replacement['fn']), $arguments, $i);  
645 -  
646 - } elseif (is_int($replacement)) {  
647 - return $arguments[$replacement + $i];  
648 -  
649 - }  
650 - $delete = ($this->escapeChar == '' ||  
651 - strpos($arguments[$i], $this->escapeChar) === false)  
652 - ? '' : "\x01" . $arguments[$i] . "\x01";  
653 - return $delete . $replacement;  
654 -  
655 - // skip over references to sub-expressions  
656 - } else {  
657 - $i += $pattern[self::LENGTH];  
658 - }  
659 - }  
660 - }  
661 -  
662 - private function _backReferences($match, $offset) {  
663 - $replacement = $this->buffer['replacement'];  
664 - $quote = $this->buffer['quote'];  
665 - $i = $this->buffer['length'];  
666 - while ($i) {  
667 - $replacement = str_replace('$'.$i--, $match[$offset + $i], $replacement);  
668 - }  
669 - return $replacement;  
670 - }  
671 -  
672 - private function _replace_name($match, $offset){  
673 - $length = strlen($match[$offset + 2]);  
674 - $start = $length - max($length - strlen($match[$offset + 3]), 0);  
675 - return substr($match[$offset + 1], $start, $length) . $match[$offset + 4];  
676 - }  
677 -  
678 - private function _replace_encoded($match, $offset) {  
679 - return $this->buffer[$match[$offset]];  
680 - }  
681 -  
682 -  
683 - // php : we cannot pass additional data to preg_replace_callback,  
684 - // and we cannot use &$this in create_function, so let's go to lower level  
685 - private $buffer;  
686 -  
687 - // encode escaped characters  
688 - private function _escape($string, $escapeChar) {  
689 - if ($escapeChar) {  
690 - $this->buffer = $escapeChar;  
691 - return preg_replace_callback(  
692 - '/\\' . $escapeChar . '(.)' .'/',  
693 - array(&$this, '_escapeBis'),  
694 - $string  
695 - );  
696 -  
697 - } else {  
698 - return $string;  
699 - }  
700 - }  
701 - private function _escapeBis($match) {  
702 - $this->_escaped[] = $match[1];  
703 - return $this->buffer;  
704 - }  
705 -  
706 - // decode escaped characters  
707 - private function _unescape($string, $escapeChar) {  
708 - if ($escapeChar) {  
709 - $regexp = '/'.'\\'.$escapeChar.'/';  
710 - $this->buffer = array('escapeChar'=> $escapeChar, 'i' => 0);  
711 - return preg_replace_callback  
712 - (  
713 - $regexp,  
714 - array(&$this, '_unescapeBis'),  
715 - $string  
716 - );  
717 -  
718 - } else {  
719 - return $string;  
720 - }  
721 - }  
722 - private function _unescapeBis() {  
723 - if (!empty($this->_escaped[$this->buffer['i']])) {  
724 - $temp = $this->_escaped[$this->buffer['i']];  
725 - } else {  
726 - $temp = '';  
727 - }  
728 - $this->buffer['i']++;  
729 - return $this->buffer['escapeChar'] . $temp;  
730 - }  
731 -  
732 - private function _internalEscape($string) {  
733 - return preg_replace($this->ESCAPE, '', $string);  
734 - }  
735 -}  
736 -?>  
classesjs/packer/class.JavaScriptPacker.php4
@@ -1,732 +0,0 @@ @@ -1,732 +0,0 @@
1 -<?php  
2 -/* 7 December 2006. version 1.0  
3 - *  
4 - * This is the php version of the Dean Edwards JavaScript 's Packer,  
5 - * Based on :  
6 - *  
7 - * ParseMaster, version 1.0.2 (2005-08-19) Copyright 2005, Dean Edwards  
8 - * a multi-pattern parser.  
9 - * KNOWN BUG: erroneous behavior when using escapeChar with a replacement  
10 - * value that is a function  
11 - *  
12 - * packer, version 2.0.2 (2005-08-19) Copyright 2004-2005, Dean Edwards  
13 - *  
14 - * License: http://creativecommons.org/licenses/LGPL/2.1/  
15 - *  
16 - * Ported to PHP by Nicolas Martin.  
17 - * modified by Mark Fabrizio Jr. to work with php 4  
18 - *  
19 - * ----------------------------------------------------------------------  
20 - *  
21 - * examples of usage :  
22 - * $myPacker = new JavaScriptPacker($script, 62, true, false);  
23 - * $packed = $myPacker->pack();  
24 - *  
25 - * or  
26 - *  
27 - * $myPacker = new JavaScriptPacker($script, 'Normal', true, false);  
28 - * $packed = $myPacker->pack();  
29 - *  
30 - * or (default values)  
31 - *  
32 - * $myPacker = new JavaScriptPacker($script);  
33 - * $packed = $myPacker->pack();  
34 - *  
35 - *  
36 - * params of the constructor :  
37 - * $script: the JavaScript to pack, string.  
38 - * $encoding: level of encoding, int or string :  
39 - * 0,10,62,95 or 'None', 'Numeric', 'Normal', 'High ASCII'.  
40 - * default: 62.  
41 - * $fastDecode: include the fast decoder in the packed result, boolean.  
42 - * default : true.  
43 - * $specialChars: if you are flagged your private and local variables  
44 - * in the script, boolean.  
45 - * default: false.  
46 - *  
47 - * The pack() method return the compressed JavasScript, as a string.  
48 - *  
49 - * see http://dean.edwards.name/packer/usage/ for more information.  
50 - *  
51 - * Notes :  
52 - * # [del]need PHP 5 . Tested with PHP 5.1.2[/del]  
53 - * this is a modified version for PHP 4  
54 - *  
55 - * # The packed result may be different than with the Dean Edwards  
56 - * version, but with the same length. The reason is that the PHP  
57 - * function usort to sort array don't necessarily preserve the  
58 - * original order of two equal member. The Javascript sort function  
59 - * in fact preserve this order (but that's not require by the  
60 - * ECMAScript standard). So the encoded keywords order can be  
61 - * different in the two results.  
62 - *  
63 - * # Be careful with the 'High ASCII' Level encoding if you use  
64 - * UTF-8 in your files...  
65 - */  
66 -  
67 - /*  
68 - * modified by Mark Fabrizio Jr. to work with php 4  
69 - */  
70 -  
71 -  
72 -class JavaScriptPacker {  
73 - var $IGNORE = '$1';  
74 -  
75 - // validate parameters  
76 - var $_script = '';  
77 - var $_encoding = 62;  
78 - var $_fastDecode = true;  
79 - var $_specialChars = false;  
80 -  
81 - var $LITERAL_ENCODING = array(  
82 - 'None' => 0,  
83 - 'Numeric' => 10,  
84 - 'Normal' => 62,  
85 - 'High ASCII' => 95  
86 - );  
87 -  
88 - function JavaScriptPacker($_script, $_encoding = 62, $_fastDecode = true, $_specialChars = false)  
89 - {  
90 - $this->_script = $_script . "\n";  
91 - if (array_key_exists($_encoding, $this->LITERAL_ENCODING))  
92 - $_encoding = $this->LITERAL_ENCODING[$_encoding];  
93 - $this->_encoding = min((int)$_encoding, 95);  
94 - $this->_fastDecode = $_fastDecode;  
95 - $this->_specialChars = $_specialChars;  
96 - }  
97 -  
98 - function pack() {  
99 - $this->_addParser('_basicCompression');  
100 - if ($this->_specialChars)  
101 - $this->_addParser('_encodeSpecialChars');  
102 - if ($this->_encoding)  
103 - $this->_addParser('_encodeKeywords');  
104 -  
105 - // go!  
106 - return $this->_pack($this->_script);  
107 - }  
108 -  
109 - // apply all parsing routines  
110 - function _pack($script) {  
111 - for ($i = 0; isset($this->_parsers[$i]); $i++) {  
112 - $script = call_user_func(array(&$this,$this->_parsers[$i]), $script);  
113 - }  
114 - return $script;  
115 - }  
116 -  
117 - // keep a list of parsing functions, they'll be executed all at once  
118 - var $_parsers = array();  
119 - function _addParser($parser) {  
120 - $this->_parsers[] = $parser;  
121 - }  
122 -  
123 - // zero encoding - just removal of white space and comments  
124 - function _basicCompression($script) {  
125 - $parser = new ParseMaster();  
126 - // make safe  
127 - $parser->escapeChar = '\\';  
128 - // protect strings  
129 - $parser->add('/\'[^\'\\n\\r]*\'/',$this->IGNORE);  
130 - $parser->add('/"[^"\\n\\r]*"/', $this->IGNORE);  
131 - // remove comments  
132 - $parser->add('/\\/\\/[^\\n\\r]*[\\n\\r]/', ' ');  
133 - $parser->add('/\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\//', ' ');  
134 - // protect regular expressions  
135 - $parser->add('/\\s+(\\/[^\\/\\n\\r\\*][^\\/\\n\\r]*\\/g?i?)/', '$2'); // IGNORE  
136 - $parser->add('/[^\\w\\x24\\/\'"*)\\?:]\\/[^\\/\\n\\r\\*][^\\/\\n\\r]*\\/g?i?/', $this->IGNORE);  
137 - // remove: ;;; doSomething();  
138 - if ($this->_specialChars) $parser->add('/;;;[^\\n\\r]+[\\n\\r]/');  
139 - // remove redundant semi-colons  
140 - $parser->add('/\\(;;\\)/', $this->IGNORE); // protect for (;;) loops  
141 - $parser->add('/;+\\s*([};])/', '$2');  
142 - // apply the above  
143 - $script = $parser->exec($script);  
144 -  
145 - // remove white-space  
146 - $parser->add('/(\\b|\\x24)\\s+(\\b|\\x24)/', '$2 $3');  
147 - $parser->add('/([+\\-])\\s+([+\\-])/', '$2 $3');  
148 - $parser->add('/\\s+/', '');  
149 - // done  
150 - return $parser->exec($script);  
151 - }  
152 -  
153 - function _encodeSpecialChars($script) {  
154 - $parser = new ParseMaster();  
155 - // replace: $name -> n, $$name -> na  
156 - $parser->add('/((\\x24+)([a-zA-Z$_]+))(\\d*)/',  
157 - array('fn' => '_replace_name')  
158 - );  
159 - // replace: _name -> _0, double-underscore (__name) is ignored  
160 - $regexp = '/\\b_[A-Za-z\\d]\\w*/';  
161 - // build the word list  
162 - $keywords = $this->_analyze($script, $regexp, '_encodePrivate');  
163 - // quick ref  
164 - $encoded = $keywords['encoded'];  
165 -  
166 - $parser->add($regexp,  
167 - array(  
168 - 'fn' => '_replace_encoded',  
169 - 'data' => $encoded  
170 - )  
171 - );  
172 - return $parser->exec($script);  
173 - }  
174 -  
175 - function _encodeKeywords($script) {  
176 - // escape high-ascii values already in the script (i.e. in strings)  
177 - if ($this->_encoding > 62)  
178 - $script = $this->_escape95($script);  
179 - // create the parser  
180 - $parser = new ParseMaster();  
181 - $encode = $this->_getEncoder($this->_encoding);  
182 - // for high-ascii, don't encode single character low-ascii  
183 - $regexp = ($this->_encoding > 62) ? '/\\w\\w+/' : '/\\w+/';  
184 - // build the word list  
185 - $keywords = $this->_analyze($script, $regexp, $encode);  
186 - $encoded = $keywords['encoded'];  
187 -  
188 - // encode  
189 - $parser->add($regexp,  
190 - array(  
191 - 'fn' => '_replace_encoded',  
192 - 'data' => $encoded  
193 - )  
194 - );  
195 - if (empty($script)) return $script;  
196 - else {  
197 - //$res = $parser->exec($script);  
198 - //$res = $this->_bootStrap($res, $keywords);  
199 - //return $res;  
200 - return $this->_bootStrap($parser->exec($script), $keywords);  
201 - }  
202 - }  
203 -  
204 - function _analyze($script, $regexp, $encode) {  
205 - // analyse  
206 - // retreive all words in the script  
207 - $all = array();  
208 - preg_match_all($regexp, $script, $all);  
209 - $_sorted = array(); // list of words sorted by frequency  
210 - $_encoded = array(); // dictionary of word->encoding  
211 - $_protected = array(); // instances of "protected" words  
212 - $all = $all[0]; // simulate the javascript comportement of global match  
213 - if (!empty($all)) {  
214 - $unsorted = array(); // same list, not sorted  
215 - $protected = array(); // "protected" words (dictionary of word->"word")  
216 - $value = array(); // dictionary of charCode->encoding (eg. 256->ff)  
217 - $this->_count = array(); // word->count  
218 - $i = count($all); $j = 0; //$word = null;  
219 - // count the occurrences - used for sorting later  
220 - do {  
221 - --$i;  
222 - $word = '$' . $all[$i];  
223 - if (!isset($this->_count[$word])) {  
224 - $this->_count[$word] = 0;  
225 - $unsorted[$j] = $word;  
226 - // make a dictionary of all of the protected words in this script  
227 - // these are words that might be mistaken for encoding  
228 - //if (is_string($encode) && method_exists($this, $encode))  
229 - $values[$j] = call_user_func(array(&$this, $encode), $j);  
230 - $protected['$' . $values[$j]] = $j++;  
231 - }  
232 - // increment the word counter  
233 - $this->_count[$word]++;  
234 - } while ($i > 0);  
235 - // prepare to sort the word list, first we must protect  
236 - // words that are also used as codes. we assign them a code  
237 - // equivalent to the word itself.  
238 - // e.g. if "do" falls within our encoding range  
239 - // then we store keywords["do"] = "do";  
240 - // this avoids problems when decoding  
241 - $i = count($unsorted);  
242 - do {  
243 - $word = $unsorted[--$i];  
244 - if (isset($protected[$word]) /*!= null*/) {  
245 - $_sorted[$protected[$word]] = substr($word, 1);  
246 - $_protected[$protected[$word]] = true;  
247 - $this->_count[$word] = 0;  
248 - }  
249 - } while ($i);  
250 -  
251 - // sort the words by frequency  
252 - // Note: the javascript and php version of sort can be different :  
253 - // in php manual, usort :  
254 - // " If two members compare as equal,  
255 - // their order in the sorted array is undefined."  
256 - // so the final packed script is different of the Dean's javascript version  
257 - // but equivalent.  
258 - // the ECMAscript standard does not guarantee this behaviour,  
259 - // and thus not all browsers (e.g. Mozilla versions dating back to at  
260 - // least 2003) respect this.  
261 - usort($unsorted, array(&$this, '_sortWords'));  
262 - $j = 0;  
263 - // because there are "protected" words in the list  
264 - // we must add the sorted words around them  
265 - do {  
266 - if (!isset($_sorted[$i]))  
267 - $_sorted[$i] = substr($unsorted[$j++], 1);  
268 - $_encoded[$_sorted[$i]] = $values[$i];  
269 - } while (++$i < count($unsorted));  
270 - }  
271 - return array(  
272 - 'sorted' => $_sorted,  
273 - 'encoded' => $_encoded,  
274 - 'protected' => $_protected);  
275 - }  
276 -  
277 - var $_count = array();  
278 - function _sortWords($match1, $match2) {  
279 - return $this->_count[$match2] - $this->_count[$match1];  
280 - }  
281 -  
282 - // build the boot function used for loading and decoding  
283 - function _bootStrap($packed, $keywords) {  
284 - $ENCODE = $this->_safeRegExp('$encode\\($count\\)');  
285 -  
286 - // $packed: the packed script  
287 - $packed = "'" . $this->_escape($packed) . "'";  
288 -  
289 - // $ascii: base for encoding  
290 - $ascii = min(count($keywords['sorted']), $this->_encoding);  
291 - if ($ascii == 0) $ascii = 1;  
292 -  
293 - // $count: number of words contained in the script  
294 - $count = count($keywords['sorted']);  
295 -  
296 - // $keywords: list of words contained in the script  
297 - foreach ($keywords['protected'] as $i=>$value) {  
298 - $keywords['sorted'][$i] = '';  
299 - }  
300 - // convert from a string to an array  
301 - ksort($keywords['sorted']);  
302 - $keywords = "'" . implode('|',$keywords['sorted']) . "'.split('|')";  
303 -  
304 - $encode = ($this->_encoding > 62) ? '_encode95' : $this->_getEncoder($ascii);  
305 - $encode = $this->_getJSFunction($encode);  
306 - $encode = preg_replace('/_encoding/','$ascii', $encode);  
307 - $encode = preg_replace('/arguments\\.callee/','$encode', $encode);  
308 - $inline = '\\$count' . ($ascii > 10 ? '.toString(\\$ascii)' : '');  
309 -  
310 - // $decode: code snippet to speed up decoding  
311 - if ($this->_fastDecode) {  
312 - // create the decoder  
313 - $decode = $this->_getJSFunction('_decodeBody');  
314 - if ($this->_encoding > 62)  
315 - $decode = preg_replace('/\\\\w/', '[\\xa1-\\xff]', $decode);  
316 - // perform the encoding inline for lower ascii values  
317 - elseif ($ascii < 36)  
318 - $decode = preg_replace($ENCODE, $inline, $decode);  
319 - // special case: when $count==0 there are no keywords. I want to keep  
320 - // the basic shape of the unpacking funcion so i'll frig the code...  
321 - if ($count == 0)  
322 - $decode = preg_replace($this->_safeRegExp('($count)\\s*=\\s*1'), '$1=0', $decode, 1);  
323 - }  
324 -  
325 - // boot function  
326 - $unpack = $this->_getJSFunction('_unpack');  
327 - if ($this->_fastDecode) {  
328 - // insert the decoder  
329 - $this->buffer = $decode;  
330 - $unpack = preg_replace_callback('/\\{/', array(&$this, '_insertFastDecode'), $unpack, 1);  
331 - }  
332 - $unpack = preg_replace('/"/', "'", $unpack);  
333 - if ($this->_encoding > 62) { // high-ascii  
334 - // get rid of the word-boundaries for regexp matches  
335 - $unpack = preg_replace('/\'\\\\\\\\b\'\s*\\+|\\+\s*\'\\\\\\\\b\'/', '', $unpack);  
336 - }  
337 - if ($ascii > 36 || $this->_encoding > 62 || $this->_fastDecode) {  
338 - // insert the encode function  
339 - $this->buffer = $encode;  
340 - $unpack = preg_replace_callback('/\\{/', array(&$this, '_insertFastEncode'), $unpack, 1);  
341 - } else {  
342 - // perform the encoding inline  
343 - $unpack = preg_replace($ENCODE, $inline, $unpack);  
344 - }  
345 - // pack the boot function too  
346 - $unpackPacker = new JavaScriptPacker($unpack, 0, false, true);  
347 - $unpack = $unpackPacker->pack();  
348 -  
349 - // arguments  
350 - $params = array($packed, $ascii, $count, $keywords);  
351 - if ($this->_fastDecode) {  
352 - $params[] = 0;  
353 - $params[] = '{}';  
354 - }  
355 - $params = implode(',', $params);  
356 -  
357 - // the whole thing  
358 - return 'eval(' . $unpack . '(' . $params . "))\n";  
359 - }  
360 -  
361 - var $buffer;  
362 - function _insertFastDecode($match) {  
363 - return '{' . $this->buffer . ';';  
364 - }  
365 - function _insertFastEncode($match) {  
366 - return '{$encode=' . $this->buffer . ';';  
367 - }  
368 -  
369 - // mmm.. ..which one do i need ??  
370 - function _getEncoder($ascii) {  
371 - return $ascii > 10 ? $ascii > 36 ? $ascii > 62 ?  
372 - '_encode95' : '_encode62' : '_encode36' : '_encode10';  
373 - }  
374 -  
375 - // zero encoding  
376 - // characters: 0123456789  
377 - function _encode10($charCode) {  
378 - return $charCode;  
379 - }  
380 -  
381 - // inherent base36 support  
382 - // characters: 0123456789abcdefghijklmnopqrstuvwxyz  
383 - function _encode36($charCode) {  
384 - return base_convert($charCode, 10, 36);  
385 - }  
386 -  
387 - // hitch a ride on base36 and add the upper case alpha characters  
388 - // characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ  
389 - function _encode62($charCode) {  
390 - $res = '';  
391 - if ($charCode >= $this->_encoding) {  
392 - $res = $this->_encode62((int)($charCode / $this->_encoding));  
393 - }  
394 - $charCode = $charCode % $this->_encoding;  
395 -  
396 - if ($charCode > 35)  
397 - return $res . chr($charCode + 29);  
398 - else  
399 - return $res . base_convert($charCode, 10, 36);  
400 - }  
401 -  
402 - // use high-ascii values  
403 - // characters: ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÃ?ÂÃÄÅÆÇÈÉÊËÌÃ?ÎÃ?Ã?ÑÒÓÔÕÖרÙÚÛÜÃ?Þßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ  
404 - function _encode95($charCode) {  
405 - $res = '';  
406 - if ($charCode >= $this->_encoding)  
407 - $res = $this->_encode95($charCode / $this->_encoding);  
408 -  
409 - return $res . chr(($charCode % $this->_encoding) + 161);  
410 - }  
411 -  
412 - function _safeRegExp($string) {  
413 - return '/'.preg_replace('/\$/', '\\\$', $string).'/';  
414 - }  
415 -  
416 - function _encodePrivate($charCode) {  
417 - return "_" . $charCode;  
418 - }  
419 -  
420 - // protect characters used by the parser  
421 - function _escape($script) {  
422 - return preg_replace('/([\\\\\'])/', '\\\$1', $script);  
423 - }  
424 -  
425 - // protect high-ascii characters already in the script  
426 - function _escape95($script) {  
427 - return preg_replace_callback(  
428 - '/[\\xa1-\\xff]/',  
429 - array(&$this, '_escape95Bis'),  
430 - $script  
431 - );  
432 - }  
433 - function _escape95Bis($match) {  
434 - return '\x'.((string)dechex(ord($match)));  
435 - }  
436 -  
437 -  
438 - function _getJSFunction($aName) {  
439 - $func = 'JSFUNCTION'.$aName;  
440 - if (isset($this->$func)){  
441 - return $this->$func;  
442 - }  
443 - else  
444 - return '';  
445 - }  
446 -  
447 - // JavaScript Functions used.  
448 - // Note : In Dean's version, these functions are converted  
449 - // with 'String(aFunctionName);'.  
450 - // This internal conversion complete the original code, ex :  
451 - // 'while (aBool) anAction();' is converted to  
452 - // 'while (aBool) { anAction(); }'.  
453 - // The JavaScript functions below are corrected.  
454 -  
455 - // unpacking function - this is the boot strap function  
456 - // data extracted from this packing routine is passed to  
457 - // this function when decoded in the target  
458 - // NOTE ! : without the ';' final.  
459 - var $JSFUNCTION_unpack = 'function($packed, $ascii, $count, $keywords, $encode, $decode) {  
460 - while ($count--) {  
461 - if ($keywords[$count]) {  
462 - $packed = $packed.replace(new RegExp(\'\\\\b\' + $encode($count) + \'\\\\b\', \'g\'), $keywords[$count]);  
463 - }  
464 - }  
465 - return $packed;  
466 -}';  
467 -/*  
468 -'function($packed, $ascii, $count, $keywords, $encode, $decode) {  
469 - while ($count--)  
470 - if ($keywords[$count])  
471 - $packed = $packed.replace(new RegExp(\'\\\\b\' + $encode($count) + \'\\\\b\', \'g\'), $keywords[$count]);  
472 - return $packed;  
473 -}';  
474 -*/  
475 -  
476 - // code-snippet inserted into the unpacker to speed up decoding  
477 - var $JSFUNCTION_decodeBody = ' if (!\'\'.replace(/^/, String)) {  
478 - // decode all the values we need  
479 - while ($count--) {  
480 - $decode[$encode($count)] = $keywords[$count] || $encode($count);  
481 - }  
482 - // global replacement function  
483 - $keywords = [function ($encoded) {return $decode[$encoded]}];  
484 - // generic match  
485 - $encode = function () {return \'\\\\w+\'};  
486 - // reset the loop counter - we are now doing a global replace  
487 - $count = 1;  
488 - }  
489 -';  
490 -//};  
491 -/*  
492 -' if (!\'\'.replace(/^/, String)) {  
493 - // decode all the values we need  
494 - while ($count--) $decode[$encode($count)] = $keywords[$count] || $encode($count);  
495 - // global replacement function  
496 - $keywords = [function ($encoded) {return $decode[$encoded]}];  
497 - // generic match  
498 - $encode = function () {return\'\\\\w+\'};  
499 - // reset the loop counter - we are now doing a global replace  
500 - $count = 1;  
501 - }';  
502 -*/  
503 -  
504 - // zero encoding  
505 - // characters: 0123456789  
506 - var $JSFUNCTION_encode10 = 'function($charCode) {  
507 - return $charCode;  
508 -}';//;';  
509 -  
510 - // inherent base36 support  
511 - // characters: 0123456789abcdefghijklmnopqrstuvwxyz  
512 - var $JSFUNCTION_encode36 = 'function($charCode) {  
513 - return $charCode.toString(36);  
514 -}';//;';  
515 -  
516 - // hitch a ride on base36 and add the upper case alpha characters  
517 - // characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ  
518 - var $JSFUNCTION_encode62 = 'function($charCode) {  
519 - return ($charCode < _encoding ? \'\' : arguments.callee(parseInt($charCode / _encoding))) +  
520 - (($charCode = $charCode % _encoding) > 35 ? String.fromCharCode($charCode + 29) : $charCode.toString(36));  
521 -}';  
522 -  
523 - // use high-ascii values  
524 - // characters: ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÃ?ÂÃÄÅÆÇÈÉÊËÌÃ?ÎÃ?Ã?ÑÒÓÔÕÖרÙÚÛÜÃ?Þßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ  
525 - var $JSFUNCTION_encode95 = 'function($charCode) {  
526 - return ($charCode < _encoding ? \'\' : arguments.callee($charCode / _encoding)) +  
527 - String.fromCharCode($charCode % _encoding + 161);  
528 -}';  
529 -  
530 -}  
531 -  
532 -  
533 -class ParseMaster {  
534 - var $ignoreCase = false;  
535 - var $escapeChar = '';  
536 -  
537 - // constants  
538 - var $EXPRESSION = 0;  
539 - var $REPLACEMENT = 1;  
540 - var $LENGTH = 2;  
541 -  
542 - // used to determine nesting levels  
543 - var $GROUPS = '/\\(/';//g  
544 - var $SUB_REPLACE = '/\\$\\d/';  
545 - var $INDEXED = '/^\\$\\d+$/';  
546 - var $TRIM = '/([\'"])\\1\\.(.*)\\.\\1\\1$/';  
547 - var $ESCAPE = '/\\\./';//g  
548 - var $QUOTE = '/\'/';  
549 - var $DELETED = '/\\x01[^\\x01]*\\x01/';//g  
550 -  
551 - function add($expression, $replacement = '') {  
552 - // count the number of sub-expressions  
553 - // - add one because each pattern is itself a sub-expression  
554 - $length = 1 + preg_match_all($this->GROUPS, $this->_internalEscape((string)$expression), $out);  
555 -  
556 - // treat only strings $replacement  
557 - if (is_string($replacement)) {  
558 - // does the pattern deal with sub-expressions?  
559 - if (preg_match($this->SUB_REPLACE, $replacement)) {  
560 - // a simple lookup? (e.g. "$2")  
561 - if (preg_match($this->INDEXED, $replacement)) {  
562 - // store the index (used for fast retrieval of matched strings)  
563 - $replacement = (int)(substr($replacement, 1)) - 1;  
564 - } else { // a complicated lookup (e.g. "Hello $2 $1")  
565 - // build a function to do the lookup  
566 - $quote = preg_match($this->QUOTE, $this->_internalEscape($replacement))  
567 - ? '"' : "'";  
568 - $replacement = array(  
569 - 'fn' => '_backReferences',  
570 - 'data' => array(  
571 - 'replacement' => $replacement,  
572 - 'length' => $length,  
573 - 'quote' => $quote  
574 - )  
575 - );  
576 - }  
577 - }  
578 - }  
579 - // pass the modified arguments  
580 - if (!empty($expression)) $this->_add($expression, $replacement, $length);  
581 - else $this->_add('/^$/', $replacement, $length);  
582 - }  
583 -  
584 - function exec($string) {  
585 - // execute the global replacement  
586 - $this->_escaped = array();  
587 -  
588 - // simulate the _patterns.toSTring of Dean  
589 - $regexp = '/';  
590 - foreach ($this->_patterns as $reg) {  
591 - $regexp .= '(' . substr($reg[$this->EXPRESSION], 1, -1) . ')|';  
592 - }  
593 - $regexp = substr($regexp, 0, -1) . '/';  
594 - $regexp .= ($this->ignoreCase) ? 'i' : '';  
595 -  
596 - $string = $this->_escape($string, $this->escapeChar);  
597 - $string = preg_replace_callback(  
598 - $regexp,  
599 - array(  
600 - &$this,  
601 - '_replacement'  
602 - ),  
603 - $string  
604 - );  
605 - $string = $this->_unescape($string, $this->escapeChar);  
606 -  
607 - return preg_replace($this->DELETED, '', $string);  
608 - }  
609 -  
610 - function reset() {  
611 - // clear the patterns collection so that this object may be re-used  
612 - $this->_patterns = array();  
613 - }  
614 -  
615 - // private  
616 - var $_escaped = array(); // escaped characters  
617 - var $_patterns = array(); // patterns stored by index  
618 -  
619 - // create and add a new pattern to the patterns collection  
620 - function _add() {  
621 - $arguments = func_get_args();  
622 - $this->_patterns[] = $arguments;  
623 - }  
624 -  
625 - // this is the global replace function (it's quite complicated)  
626 - function _replacement($arguments) {  
627 - if (empty($arguments)) return '';  
628 -  
629 - $i = 1; $j = 0;  
630 - // loop through the patterns  
631 - while (isset($this->_patterns[$j])) {  
632 - $pattern = $this->_patterns[$j++];  
633 - // do we have a result?  
634 - if (isset($arguments[$i]) && ($arguments[$i] != '')) {  
635 - $replacement = $pattern[$this->REPLACEMENT];  
636 -  
637 - if (is_array($replacement) && isset($replacement['fn'])) {  
638 -  
639 - if (isset($replacement['data'])) $this->buffer = $replacement['data'];  
640 - return call_user_func(array(&$this, $replacement['fn']), $arguments, $i);  
641 -  
642 - } elseif (is_int($replacement)) {  
643 - return $arguments[$replacement + $i];  
644 -  
645 - }  
646 - $delete = ($this->escapeChar == '' ||  
647 - strpos($arguments[$i], $this->escapeChar) === false)  
648 - ? '' : "\x01" . $arguments[$i] . "\x01";  
649 - return $delete . $replacement;  
650 -  
651 - // skip over references to sub-expressions  
652 - } else {  
653 - $i += $pattern[$this->LENGTH];  
654 - }  
655 - }  
656 - }  
657 -  
658 - function _backReferences($match, $offset) {  
659 - $replacement = $this->buffer['replacement'];  
660 - $quote = $this->buffer['quote'];  
661 - $i = $this->buffer['length'];  
662 - while ($i) {  
663 - $replacement = str_replace('$'.$i--, $match[$offset + $i], $replacement);  
664 - }  
665 - return $replacement;  
666 - }  
667 -  
668 - function _replace_name($match, $offset){  
669 - $length = strlen($match[$offset + 2]);  
670 - $start = $length - max($length - strlen($match[$offset + 3]), 0);  
671 - return substr($match[$offset + 1], $start, $length) . $match[$offset + 4];  
672 - }  
673 -  
674 - function _replace_encoded($match, $offset) {  
675 - return $this->buffer[$match[$offset]];  
676 - }  
677 -  
678 -  
679 - // php : we cannot pass additional data to preg_replace_callback,  
680 - // and we cannot use &$this in create_function, so let's go to lower level  
681 - var $buffer;  
682 -  
683 - // encode escaped characters  
684 - function _escape($string, $escapeChar) {  
685 - if ($escapeChar) {  
686 - $this->buffer = $escapeChar;  
687 - return preg_replace_callback(  
688 - '/\\' . $escapeChar . '(.)' .'/',  
689 - array(&$this, '_escapeBis'),  
690 - $string  
691 - );  
692 -  
693 - } else {  
694 - return $string;  
695 - }  
696 - }  
697 - function _escapeBis($match) {  
698 - $this->_escaped[] = $match[1];  
699 - return $this->buffer;  
700 - }  
701 -  
702 - // decode escaped characters  
703 - function _unescape($string, $escapeChar) {  
704 - if ($escapeChar) {  
705 - $regexp = '/'.'\\'.$escapeChar.'/';  
706 - $this->buffer = array('escapeChar'=> $escapeChar, 'i' => 0);  
707 - return preg_replace_callback  
708 - (  
709 - $regexp,  
710 - array(&$this, '_unescapeBis'),  
711 - $string  
712 - );  
713 -  
714 - } else {  
715 - return $string;  
716 - }  
717 - }  
718 - function _unescapeBis() {  
719 - if (!empty($this->_escaped[$this->buffer['i']])) {  
720 - $temp = $this->_escaped[$this->buffer['i']];  
721 - } else {  
722 - $temp = '';  
723 - }  
724 - $this->buffer['i']++;  
725 - return $this->buffer['escapeChar'] . $temp;  
726 - }  
727 -  
728 - function _internalEscape($string) {  
729 - return preg_replace($this->ESCAPE, '', $string);  
730 - }  
731 -}  
732 -?>  
classesjs/packer/example-file.php
@@ -1,34 +0,0 @@ @@ -1,34 +0,0 @@
1 -<?php  
2 -// you can pass this script to PHP CLI to convert your file.  
3 -  
4 -// adapt these 2 paths to your files.  
5 -$src = 'myScript-src.js';  
6 -$out = 'myScript.js';  
7 -  
8 -// or uncomment these lines to use the argc and argv passed by CLI :  
9 -/*  
10 -if ($argc >= 3) {  
11 - $src = $argv[1];  
12 - $out = $argv[2];  
13 -} else {  
14 - echo 'you must specify a source file and a result filename',"\n";  
15 - echo 'example :', "\n", 'php example-file.php myScript-src.js myPackedScript.js',"\n";  
16 - return;  
17 -}  
18 -*/  
19 -  
20 -require 'class.JavaScriptPacker.php';  
21 -  
22 -$script = file_get_contents($src);  
23 -  
24 -$t1 = microtime(true);  
25 -  
26 -$packer = new JavaScriptPacker($script, 'Normal', true, false);  
27 -$packed = $packer->pack();  
28 -  
29 -$t2 = microtime(true);  
30 -$time = sprintf('%.4f', ($t2 - $t1) );  
31 -echo 'script ', $src, ' packed in ' , $out, ', in ', $time, ' s.', "\n";  
32 -  
33 -file_put_contents($out, $packed);  
34 -?>  
classesjs/packer/example-inline.php
@@ -1,88 +0,0 @@ @@ -1,88 +0,0 @@
1 -<?php  
2 -  
3 -$treat = false;  
4 -if (isset($_POST['src'])) {  
5 - $script = $_POST['src'];  
6 - if (get_magic_quotes_gpc())  
7 - $script = stripslashes($script);  
8 - $encoding = (int)$_POST['ascii_encoding'];  
9 - $fast_decode = isset($_POST['fast_decode']) && $_POST['fast_decode'];  
10 - $special_char = isset($_POST['special_char'])&& $_POST['special_char'];  
11 -  
12 - require 'class.JavaScriptPacker.php';  
13 - $t1 = microtime(true);  
14 - $packer = new JavaScriptPacker($script, $encoding, $fast_decode, $special_char);  
15 - $packed = $packer->pack();  
16 - $t2 = microtime(true);  
17 -  
18 - $originalLength = strlen($script);  
19 - $packedLength = strlen($packed);  
20 - $ratio = number_format($packedLength / $originalLength, 3);  
21 - $time = sprintf('%.4f', ($t2 - $t1) );  
22 -  
23 - $treat = true;  
24 -}  
25 -?>  
26 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"  
27 - "http://www.w3.org/TR/html4/strict.dtd">  
28 -<html>  
29 -<head>  
30 -<title>JavaScript Packer in PHP</title>  
31 -<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">  
32 -<style type="text/css">  
33 -.result {  
34 - border: 1px blue dashed;  
35 - color: black;  
36 - background-color: #e5e5e5;  
37 - padding: 0.2em;  
38 -}  
39 -</style>  
40 -<script type="text/javascript">  
41 -function decode() {  
42 - var packed = document.getElementById('packed');  
43 - eval("packed.value=String" + packed.value.slice(4));  
44 -}  
45 -</script>  
46 -</head>  
47 -<body>  
48 - <form action="<?php echo $_SERVER['PHP_SELF']?>" method="post">  
49 - <div>  
50 - <h3>script to pack:</h3>  
51 - <textarea name="src" id="src" rows="10" cols="80"><?php if($treat) echo htmlspecialchars($script);?></textarea>  
52 - </div>  
53 - <!-- <fieldset> -->  
54 - <div>  
55 - <label for="ascii-encoding">Encoding:</label>  
56 - <select name="ascii_encoding" id="ascii-encoding">  
57 - <option value="0"<?php if ($treat && $encoding == 0) echo ' selected'?>>None</option>  
58 - <option value="10"<?php if ($treat && $encoding == 10) echo ' selected'?>>Numeric</option>  
59 - <option value="62"<?php if (!$treat) echo 'selected';if ($treat && $encoding == 62) echo ' selected';?>>Normal</option>  
60 - <option value="95"<?php if ($treat && $encoding == 95) echo ' selected'?>>High ASCII</option>  
61 - </select>  
62 - <label>  
63 - Fast Decode:  
64 - <input type="checkbox" name="fast_decode" id="fast-decode"<?php if (!$treat || $fast_decode) echo ' checked'?>>  
65 - </label>  
66 - <label>  
67 - Special Characters:  
68 - <input type="checkbox" name="special_char" id="special-char"<?php if ($treat && $special_char) echo ' checked'?>>  
69 - </label>  
70 - <input type="submit" value="Pack">  
71 - </div>  
72 - <!-- </fieldset> -->  
73 - </form>  
74 -  
75 - <?php if ($treat) {?>  
76 - <div id="result">  
77 - <h3>packed result:</h3>  
78 - <textarea id="packed" class="result" rows="10" cols="80" readonly="readonly"><?php echo htmlspecialchars($packed);?></textarea>  
79 - <p>  
80 - compression ratio:  
81 - <?php echo $originalLength, '/', $packedLength, ' = ',$ratio; ?>  
82 - <br>performed in <?php echo $time; ?> s.  
83 - </p>  
84 - <p><button type="button" onclick="decode()">decode</button></p>  
85 - </div>  
86 - <?php };//end if($treat)?>  
87 -</body>  
88 -</html>  
classesjs/packer/readme.txt
@@ -1,12 +0,0 @@ @@ -1,12 +0,0 @@
1 -PHP 5 :  
2 -use class.JavaScriptPacker.php (Tested under PHP 5.1.2, 5.1.3 et 5.1.4.)  
3 - - usage and comments in source.  
4 - - there is 2 examples in this archive for PHP 5,  
5 - 'example-file.php' and example-inline.php  
6 -  
7 -PHP 4 :  
8 -use class.JavaScriptPacker.php4, it's an adaptation for PHP4.  
9 -The examples in this archive will not work directly with PHP 4, they are  
10 -writed in PHP5, you'll need to adapt them. If some functions are missing in  
11 -PHP 4, you can find their equivalent here :  
12 -http://pear.php.net/package/PHP_Compat