Commit 6f9fe6a0969ac16b347b83f386c0246bee421728

Authored by Edmar Moretti
1 parent f1e1a758

biblioteca packer movida para pacotes

classesjs/packer/class.JavaScriptPacker.php
... ... @@ -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   -<?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   -<?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   -<?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   -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