1<?php
2/**
3 * $Id: b72d02e8f0d73e9a0533c249bcee161beeca5fb0 $
4 *
5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 *
17 * This software consists of voluntary contributions made by many individuals
18 * and is licensed under the LGPL. For more information please see
19 * <http://phing.info>.
20 */
21
22require_once 'phing/Task.php';
23require_once 'phing/tasks/ext/ioncube/IoncubeComment.php';
24
25/**
26 * Invokes the ionCube Encoder (PHP4 or PHP5)
27 *
28 * @author Michiel Rook <mrook@php.net>
29 * @author Andrew Eddie <andrew.eddie@jamboworks.com>
30 * @author Domenico Sgarbossa <sbraaaa@yahoo.it>
31 * @version $Id: b72d02e8f0d73e9a0533c249bcee161beeca5fb0 $
32 * @package phing.tasks.ext.ioncube
33 * @since 2.2.0
34 */
35class IoncubeEncoderTask extends Task
36{
37    private $ionSwitches = array();
38
39    private $ionOptions = array();
40
41    private $ionOptionsXS = array();
42
43    private $comments = array();
44
45    private $encoderName = 'ioncube_encoder';
46
47    private $fromDir = '';
48
49    private $ioncubePath = '/usr/local/ioncube';
50
51    private $phpVersion = '5';
52
53    private $targetOption = '';
54
55    private $toDir = '';
56
57    private $showCommandLine = false;
58
59    /**
60     * Sets whether to show command line before it is executed
61     */
62    function setShowCommandLine($value)
63    {
64        $this->showCommandLine = $value;
65    }
66
67    /**
68     * Adds a comment to be used in encoded files
69     */
70    function addComment(IoncubeComment $comment)
71    {
72        $this->comments[] = $comment;
73    }
74
75    /**
76     * Sets the allowed server
77     */
78    function setAllowedServer($value)
79    {
80        $this->ionOptionsXS['allowed-server'] = $value;
81    }
82
83    /**
84     * Returns the allowed server setting
85     */
86    function getAllowedServer()
87    {
88        return $this->ionOptionsXS['allowed-server'];
89    }
90
91    /**
92     * Sets the binary option
93     */
94    function setBinary($value)
95    {
96        $this->ionSwitches['binary'] = $value;
97    }
98
99    /**
100     * Returns the binary option
101     */
102    function getBinary()
103    {
104        return $this->ionSwitches['binary'];
105    }
106
107    /**
108     * Sets files or folders to copy (separated by space)
109     */
110    function setCopy($value)
111    {
112        $this->ionOptionsXS['copy'] = $value;
113    }
114
115    /**
116     * Returns the copy setting
117     */
118    function getCopy()
119    {
120        return $this->ionOptionsXS['copy'];
121    }
122
123    /**
124     * Sets additional file patterns, files or directories to encode,
125     * or to reverse the effect of copy (separated by space)
126     */
127    function setEncode($value)
128    {
129        $this->ionOptionsXS['encode'] = $value;
130    }
131
132    /**
133     * Returns the encode setting
134     */
135    function getEncode()
136    {
137        return $this->ionOptionsXS['encode'];
138    }
139
140    /**
141     * Sets regexps of additional files to encrypt (separated by space)
142     */
143    function setEncrypt($value)
144    {
145        $this->ionOptionsXS['encrypt'] = $value;
146    }
147
148    /**
149     * Returns regexps of additional files to encrypt (separated by space)
150     */
151    function getEncrypt()
152    {
153        return $this->ionOptionsXS['encrypt'];
154    }
155
156    /**
157     * Sets a period after which the files expire
158     */
159    function setExpirein($value)
160    {
161        $this->ionOptions['expire-in'] = $value;
162    }
163
164    /**
165     * Returns the expireIn setting
166     */
167    function getExpirein()
168    {
169        return $this->ionOptions['expire-in'];
170    }
171
172    /**
173     * Sets a YYYY-MM-DD date to expire the files
174     */
175    function setExpireon($value)
176    {
177        $this->ionOptions['expire-on'] = $value;
178    }
179
180    /**
181     * Returns the expireOn setting
182     */
183    function getExpireon()
184    {
185        return $this->ionOptions['expire-on'];
186    }
187
188    /**
189     * Sets the source directory
190     */
191    function setFromDir($value)
192    {
193        $this->fromDir = $value;
194    }
195
196    /**
197     * Returns the source directory
198     */
199    function getFromDir()
200    {
201        return $this->fromDir;
202    }
203
204    /**
205     * Set files and directories to ignore entirely and exclude from the target directory
206     * (separated by space).
207     */
208    function setIgnore($value)
209    {
210        $this->ionOptionsXS['ignore'] = $value;
211    }
212
213    /**
214     * Returns the ignore setting
215     */
216    function getIgnore()
217    {
218        return $this->ionOptionsXS['ignore'];
219    }
220
221    /**
222     * Sets the path to the ionCube encoder
223     */
224    function setIoncubePath($value)
225    {
226        $this->ioncubePath = $value;
227    }
228
229    /**
230     * Returns the path to the ionCube encoder
231     */
232    function getIoncubePath()
233    {
234        return $this->ioncubePath;
235    }
236
237    /**
238     * Set files and directories not to be ignored (separated by space).
239     */
240    function setKeep($value)
241    {
242        $this->ionOptionsXS['keep'] = $value;
243    }
244
245    /**
246     * Returns the ignore setting
247     */
248    function getKeep()
249    {
250        return $this->ionOptionsXS['keep'];
251    }
252
253    /**
254     * Sets the path to the license file to use
255     */
256    function setLicensePath($value)
257    {
258        $this->ionOptions['with-license'] = $value;
259    }
260
261    /**
262     * Returns the path to the license file to use
263     */
264    function getLicensePath()
265    {
266        return $this->ionOptions['with-license'];
267    }
268
269    /**
270     * Sets the no-doc-comments option
271     */
272    function setNoDocComments($value)
273    {
274        $this->ionSwitches['no-doc-comment'] = $value;
275    }
276
277    /**
278     * Returns the no-doc-comments option
279     */
280    function getNoDocComments()
281    {
282        return $this->ionSwitches['no-doc-comment'];
283    }
284
285    /**
286     * Sets the obfuscate option
287     */
288    function setObfuscate($value)
289    {
290        $this->ionOptionsXS['obfuscate'] = $value;
291    }
292
293    /**
294     * Returns the optimize option
295     */
296    function getObfuscate()
297    {
298        return $this->ionOptionsXS['obfuscate'];
299    }
300
301    /**
302     * Sets the obfuscation key (required if using the obfuscate option)
303     */
304    function setObfuscationKey($value)
305    {
306        $this->ionOptions['obfuscation-key'] = $value;
307    }
308
309    /**
310     * Returns the optimize option
311     */
312    function getObfuscationKey()
313    {
314        return $this->ionOptions['obfuscation-key'];
315    }
316
317    /**
318     * Sets the optimize option
319     */
320    function setOptimize($value)
321    {
322        $this->ionOptions['optimize'] = $value;
323    }
324
325    /**
326     * Returns the optimize option
327     */
328    function getOptimize()
329    {
330        return $this->ionOptions['optimize'];
331    }
332
333    /**
334     * Sets the passphrase to use when encoding files
335     */
336    function setPassPhrase($value)
337    {
338        $this->ionOptions['passphrase'] = $value;
339    }
340
341    /**
342     * Returns the passphrase to use when encoding files
343     */
344    function getPassPhrase()
345    {
346        return $this->ionOptions['passphrase'];
347    }
348
349    /**
350     * Sets the version of PHP to use (defaults to 5)
351     */
352    function setPhpVersion($value)
353    {
354        $this->phpVersion = $value;
355    }
356
357    /**
358     * Returns the version of PHP to use (defaults to 5)
359     */
360    function getPhpVersion()
361    {
362        return $this->phpVersion;
363    }
364
365    /**
366     * Sets the target directory
367     */
368    function setToDir($value)
369    {
370        $this->toDir = $value;
371    }
372
373    /**
374     * Returns the target directory
375     */
376    function getToDir()
377    {
378        return $this->toDir;
379    }
380
381    /**
382     * Sets the without-runtime-loader-support option
383     */
384    function setWithoutRuntimeLoaderSupport($value)
385    {
386        $this->ionSwitches['without-runtime-loader-support'] = $value;
387    }
388
389    /**
390     * Returns the without-runtime-loader-support option
391     */
392    function getWithoutRuntimeLoaderSupport()
393    {
394        return $this->ionSwitches['without-runtime-loader-support'];
395    }
396
397    /**
398     * Sets the no-short-open-tags option
399     */
400    function setNoShortOpenTags($value)
401    {
402        $this->ionSwitches['no-short-open-tags'] = $value;
403    }
404
405    /**
406     * Returns the no-short-open-tags option
407     */
408    function getNoShortOpenTags()
409    {
410        return $this->ionSwitches['no-short-open-tags'];
411    }
412
413    /**
414     * Sets the ignore-deprecated-warnings option
415     */
416    function setIgnoreDeprecatedWarnings($value)
417    {
418        $this->ionSwitches['ignore-deprecated-warnings'] = $value;
419    }
420
421    /**
422     * Returns the ignore-deprecated-warnings option
423     */
424    function getIgnoreDeprecatedWarnings()
425    {
426        return $this->ionSwitches['ignore-deprecated-warnings'];
427    }
428
429    /**
430     * Sets the ignore-strict-warnings option
431     */
432    function setIgnoreStrictWarnings($value)
433    {
434        $this->ionSwitches['ignore-strict-warnings'] = $value;
435    }
436
437    /**
438     * Returns the ignore-strict-warnings option
439     */
440    function getIgnoreStrictWarnings()
441    {
442        return $this->ionSwitches['ignore-strict-warnings'];
443    }
444
445    /**
446     * Sets the allow-encoding-into-source option
447     */
448    function setAllowEncodingIntoSource($value)
449    {
450        $this->ionSwitches['allow-encoding-into-source'] = $value;
451    }
452
453    /**
454     * Returns the allow-encoding-into-source option
455     */
456    function getAllowEncodingIntoSource()
457    {
458        return $this->ionSwitches['allow-encoding-into-source'];
459    }
460
461    /**
462     * Sets the message-if-no-loader option
463     */
464    function setMessageIfNoLoader($value)
465    {
466        $this->ionOptions['message-if-no-loader'] = $value;
467    }
468
469    /**
470     * Returns the message-if-no-loader option
471     */
472    function getMessageIfNoLoader()
473    {
474        return $this->ionOptions['message-if-no-loader'];
475    }
476
477    /**
478     * Sets the action-if-no-loader option
479     */
480    function setActionIfNoLoader($value)
481    {
482        $this->ionOptions['action-if-no-loader'] = $value;
483    }
484
485    /**
486     * Returns the action-if-no-loader option
487     */
488    function getActionIfNoLoader()
489    {
490        return $this->ionOptions['action-if-no-loader'];
491    }
492
493    /**
494     * Sets the option to use when encoding target directory already exists (defaults to none)
495     */
496    function setTargetOption($targetOption)
497    {
498        $this->targetOption = $targetOption;
499    }
500
501    /**
502     * Returns he option to use when encoding target directory already exists (defaults to none)
503     */
504    function getTargetOption()
505    {
506        return $this->targetOption;
507    }
508
509    /**
510     * Sets the callback-file option
511     */
512    function setCallbackFile($value)
513    {
514        $this->ionOptions['callback-file'] = $value;
515    }
516
517    /**
518     * Returns the callback-file option
519     */
520    function getCallbackFile()
521    {
522        return $this->ionOptions['callback-file'];
523    }
524
525    /**
526     * Sets the obfuscation-exclusions-file option
527     */
528    function setObfuscationExclusionFile($value)
529    {
530        $this->ionOptions['obfuscation-exclusion-file'] = $value;
531    }
532
533    /**
534     * Returns the obfuscation-exclusions-file option
535     */
536    function getObfuscationExclusionFile()
537    {
538        return $this->ionOptions['obfuscation-exclusion-file'];
539    }
540
541    /**
542     * The main entry point
543     *
544     * @throws BuildException
545     */
546    function main()
547    {
548        $arguments = $this->constructArguments();
549
550        if (in_array($this->phpVersion, array(5, 53))) {
551            $encoderName = $this->encoderName . $this->phpVersion;
552        } else {
553            $encoderName = $this->encoderName;
554        }
555        $encoder = new PhingFile($this->ioncubePath, $encoderName);
556
557        $this->log("Running ionCube Encoder...");
558
559        if ($this->showCommandLine)
560        {
561            $this->log("Command line: ".$encoder->__toString() . ' ' . $arguments);
562        }
563
564        exec($encoder->__toString() . ' ' . $arguments . " 2>&1", $output, $return);
565
566        if ($return != 0)
567        {
568            throw new BuildException("Could not execute ionCube Encoder: " . implode(' ', $output));
569        }
570    }
571
572    /**
573     * Constructs an argument string for the ionCube encoder
574     */
575    private function constructArguments()
576    {
577        $arguments = '';
578
579        foreach ($this->ionSwitches as $name => $value)
580        {
581            if ($value)
582            {
583                $arguments.= "--$name ";
584            }
585        }
586
587        foreach ($this->ionOptions as $name => $value)
588        {
589            /**
590             * action-if-no-loader value is a php source snippet so it is
591	         * better to handle it this way to prevent quote problems!
592	         */
593            if ($name == 'action-if-no-loader')
594            {
595                $arguments.= "--$name \"$value\" ";
596            }
597            else
598            {
599                $arguments.= "--$name '$value' ";
600            }
601        }
602
603        foreach ($this->ionOptionsXS as $name => $value)
604        {
605            foreach (explode(' ', $value) as $arg)
606            {
607                $arguments.= "--$name '$arg' ";
608            }
609        }
610
611        foreach ($this->comments as $comment)
612        {
613            $arguments.= "--add-comment '" . $comment->getValue() . "' ";
614        }
615
616        if (!empty($this->targetOption))
617        {
618            switch ($this->targetOption)
619            {
620                case "replace":
621                case "merge":
622                case "update":
623                case "rename":
624                {
625                    $arguments.= "--" . $this->targetOption . "-target ";
626                } break;
627
628                default:
629                {
630                    throw new BuildException("Unknown target option '" . $this->targetOption . "'");
631                } break;
632            }
633        }
634
635        if ($this->fromDir != '')
636        {
637            $arguments .= $this->fromDir . ' ';
638        }
639
640        if ($this->toDir != '')
641        {
642            $arguments .= "-o " . $this->toDir . ' ';
643        }
644
645        return $arguments;
646    }
647}
648