1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19

20
/**
21
 * Encodes files using Zeng Guard Encoder
22
 *
23
 * @author  Petr Rybak <petr@rynawe.net>
24
 * @package phing.tasks.ext.zendguard
25
 * @since   2.4.3
26
 */
27
class ZendGuardEncodeTask extends MatchingTask
28
{
29
    protected $filesets = [];
30
    protected $encodeCommand;
31

32
    /**
33
     * TASK PROPERTIES
34
     *
35
     * See http://static.zend.com/topics/Zend-Guard-User-Guidev5x.pdf
36
     * for more information on how to use ZendGuard
37
     */
38
    /**
39
     * Permanently deletes (see warning below) the original source files specified in the
40
     * SourceInputPath and saves the encoded files in its place.
41
     * This option has no option parameter.
42
     * When this option is use, do not use the output_file parameter.
43
     *
44
     * Warning:
45
     * To avoid permanent loss of non-encoded scripts, make a backup. Deleted files
46
     * cannot be restored or recovered and will be permanently deleted with this option.
47
     * If you are unsure about deleting the source files, use the ––rename-source option
48
     * instead
49
     *
50
     * @var bool
51
     */
52
    protected $deleteSource = true;
53
    /**
54
     * Move the original source file to <input_file>.<renameSourceExt> and save the encoded file in its
55
     * place.
56
     *
57
     * If specified deleteSource will be automatically disabled.
58
     *
59
     * @var string
60
     */
61
    protected $renameSourceExt = null;
62
    /**
63
     * Turns short PHP tag (“<?” ) recognition either on or off.
64
     * On or off must be specified as an argument when using this option.
65
     * The default, when option is not used in the command-line, is - on
66
     *
67
     * @var bool
68
     */
69
    protected $shortTags = true;
70
    /**
71
     * Turn ASP tag (“<%” ) recognition on/off. (default: off). On or off must be specified
72
     * as an argument when using this option.
73
     * The default, when this option is not used in the command-line, is - off
74
     *
75
     * @var bool
76
     */
77
    protected $aspTags = false;
78
    /**
79
     * Disables the PHP-compatible header that is added to the top of every encoded file
80
     * by default. Encoded files generated with this option will not display a meaningful
81
     * error when loaded by PHP that doesn't have the Zend Optimizer properly installed.
82
     * Using this option saves approximately 1.5KB for every encoded file. Do not use it
83
     * unless disk space constraints are critica
84
     *
85
     * @var bool
86
     */
87
    protected $noHeader = false;
88
    /**
89
     * If cryptography should be used to encode the source code
90
     *
91
     * @var bool
92
     */
93
    protected $useCrypto = false;
94
    /**
95
     * Force cooperation with other encoded files only. This option generates files that
96
     * work exclusively with associated encoded files. Associated encoded files are
97
     * those generated by the same company. Files that do not share the same encoded
98
     * company association cannot call these files
99
     *
100
     * @var bool
101
     */
102
    protected $encodedOnly = false;
103
    /**
104
     * Allow encoding previously encoded files. (NOT recommended!)
105
     *
106
     * @var bool
107
     */
108
    protected $forceEncode = false;
109
    /**
110
     * Make an encoded file to expire on the given date. Date is in yyyy-mm-dd format.
111
     *
112
     * @var string
113
     */
114
    protected $expires = null;
115
    /**
116
     * Level of obfuscation. Defaults to 0 (no obfuscation).
117
     *
118
     * @var int
119
     */
120
    protected $obfuscationLevel = 0;
121
    /**
122
     * Optimization mask. (default value: [+++++++])
123
     * opt_mask is an integer representing a bit-mask.
124
     * The default value enables all of the optimization passes.
125
     * Each optimization pass of the Zend Optimizer can be turned on or off based on
126
     * the mask entered
127
     *
128
     * @var int
129
     */
130
    protected $optMask = null;
131
    /**
132
     * Path to the zend encoder binary
133
     *
134
     * @var string
135
     */
136
    protected $zendEncoderPath = null;
137
    /**
138
     * Path to private key for licensing
139
     *
140
     * @var string
141
     */
142
    protected $privateKeyPath = null;
143
    /**
144
     * Enable licensing.
145
     * If enabled, productName must be defined.
146
     *
147
     * @var bool
148
     */
149
    protected $licenseProduct = false;
150
    /**
151
     * If true the ownership, permissions and timestamps
152
     * of the encoded files won't be preserved.
153
     *
154
     * @var bool
155
     */
156
    protected $ignoreFileModes = false;
157
    /**
158
     * Enable signing
159
     * If enabled, productName must be defined.
160
     *
161
     * @var bool
162
     */
163
    protected $signProduct = false;
164
    /**
165
     * Product name. Must be defined if licenseProduct
166
     * or signProduct is set to 1
167
     *
168
     * @var string
169
     */
170
    protected $productName = null;
171
    /**
172
     * Embed the information in the specified file into the header of the encoded file
173
     * (overrides noHeader)
174
     *
175
     * @var string
176
     */
177
    protected $prologFile = null;
178

179
    /**
180
     * TASK PROPERTIES SETTERS
181
     *
182
     * @param $value
183
     */
184 0
    public function setZendEncoderPath($value)
185
    {
186 0
        $this->zendEncoderPath = $value;
187
    }
188

189
    /**
190
     * @param $value
191
     */
192 0
    public function setPrivateKeyPath($value)
193
    {
194 0
        $this->privateKeyPath = $value;
195
    }
196

197
    /**
198
     * @param $value
199
     */
200 0
    public function setShortTags(bool $value)
201
    {
202 0
        $this->shortTags = $value;
203
    }
204

205
    /**
206
     * @param $value
207
     */
208 0
    public function setAspTags(bool $value)
209
    {
210 0
        $this->aspTags = $value;
211
    }
212

213
    /**
214
     * @param $value
215
     */
216 0
    public function setDeleteSource(bool $value)
217
    {
218 0
        $this->shortTags = $value;
219
    }
220

221
    /**
222
     * @param $value
223
     */
224 0
    public function setUseCrypto(bool $value)
225
    {
226 0
        $this->useCrypto = $value;
227
    }
228

229
    /**
230
     * @param $value
231
     */
232 0
    public function setObfuscationLevel($value)
233
    {
234 0
        $this->obfuscationLevel = (int) $value;
235
    }
236

237
    /**
238
     * @param $value
239
     */
240 0
    public function setLicenseProduct(bool $value)
241
    {
242 0
        $this->licenseProduct = $value;
243
    }
244

245
    /**
246
     * @param $value
247
     */
248 0
    public function setPrologFile($value)
249
    {
250 0
        $this->prologFile = $value;
251
    }
252

253
    /**
254
     * @param $value
255
     */
256 0
    public function setSignProduct(bool $value)
257
    {
258 0
        $this->signProduct = $value;
259
    }
260

261
    /**
262
     * @param $value
263
     */
264 0
    public function setForceEncode(bool $value)
265
    {
266 0
        $this->forceEncode = $value;
267
    }
268

269
    /**
270
     * @param $value
271
     */
272 0
    public function setEncodedOnly(bool $value)
273
    {
274 0
        $this->encodedOnly = $value;
275
    }
276

277
    /**
278
     * @param $value
279
     */
280 0
    public function setIgnoreFileModes(bool $value)
281
    {
282 0
        $this->ignoreFileModes = $value;
283
    }
284

285
    /**
286
     * @param $value
287
     */
288 0
    public function setExpires($value)
289
    {
290 0
        $this->expires = $value;
291
    }
292

293
    /**
294
     * @param $value
295
     */
296 0
    public function setProductName($value)
297
    {
298 0
        $this->productName = $value;
299
    }
300

301
    /**
302
     * @param $value
303
     */
304 0
    public function setOptMask($value)
305
    {
306 0
        $this->optMask = (int) $value;
307
    }
308

309
    /**
310
     * @param $value
311
     */
312 0
    public function setRenameSourceExt($value)
313
    {
314 0
        $this->renameSourceExt = $value;
315
    }
316

317
    /**
318
     * @param $value
319
     */
320 0
    public function setNoHeader(bool $value)
321
    {
322 0
        $this->noHeader = $value;
323
    }
324

325
    /**
326
     * Add a new fileset.
327
     *
328
     * @return FileSet
329
     */
330 0
    public function createFileSet()
331
    {
332 0
        $this->fileset = new ZendGuardFileSet();
333 0
        $this->filesets[] = $this->fileset;
334

335 0
        return $this->fileset;
336
    }
337

338
    /**
339
     * Verifies that the configuration is correct
340
     *
341
     * @throws BuildException
342
     */
343 0
    protected function verifyConfiguration()
344
    {
345
        // Check that the zend encoder path is specified
346 0
        if (empty($this->zendEncoderPath)) {
347 0
            throw new BuildException("Zend Encoder path must be specified");
348
        }
349

350
        // verify that the zend encoder binary exists
351 0
        if (!file_exists($this->zendEncoderPath)) {
352 0
            throw new BuildException("Zend Encoder not found on path " . $this->zendEncoderPath);
353
        }
354

355
        // if either sign or license is required the private key path needs to be defined
356
        // and the file has to exist and product name has to be specified
357 0
        if ($this->signProduct || $this->licenseProduct) {
358 0
            if (empty($this->privateKeyPath)) {
359 0
                throw new BuildException("Licensing or signing requested but privateKeyPath not provided.");
360
            }
361 0
            if (!is_readable($this->privateKeyPath)) {
362 0
                throw new BuildException("Licensing or signing requested but private key path doesn't exist or is unreadable.");
363
            }
364 0
            if (empty($this->productName)) {
365 0
                throw new BuildException("Licensing or signing requested but product name not provided.");
366
            }
367
        }
368

369
        // verify prolog file exists
370 0
        if (!empty($this->prologFile)) {
371 0
            if (!file_exists($this->prologFile)) {
372 0
                throw new BuildException("The prolog file doesn't exist: " . $this->prologFile);
373
            }
374
        }
375
    }
376

377
    /**
378
     * Do the work
379
     *
380
     * @throws BuildException
381
     */
382 0
    public function main()
383
    {
384 0
        $this->verifyConfiguration();
385 0
        $this->prepareEncoderCommand();
386

387
        try {
388 0
            if (empty($this->filesets)) {
389 0
                throw new BuildException(
390 0
                    "You must supply nested fileset.",
391 0
                    $this->getLocation()
392
                );
393
            }
394

395 0
            $encodedFilesCounter = 0;
396

397 0
            foreach ($this->filesets as $fs) {
398
                /* @var $fs FileSet */
399

400
                /* @var $fsBasedir PhingFile */
401 0
                $fsBasedir = $fs->getDir($this->project)->getAbsolutePath();
402

403 0
                $files = $fs->getIterator(false);
404

405 0
                foreach ($files as $file) {
406 0
                    $f = new PhingFile($fsBasedir, $file);
407

408 0
                    if ($f->isFile()) {
409 0
                        $path = $f->getAbsolutePath();
410

411 0
                        $this->log("Encoding " . $path, Project::MSG_VERBOSE);
412 0
                        $this->encodeFile($path);
413

414 0
                        $encodedFilesCounter++;
415
                    }
416
                }
417
            }
418

419 0
            $this->log("Encoded files: " . $encodedFilesCounter);
420 0
        } catch (IOException $ioe) {
421 0
            $msg = "Problem encoding files: " . $ioe->getMessage();
422 0
            throw new BuildException($msg, $ioe, $this->getLocation());
423
        }
424
    }
425

426
    /**
427
     * Prepares the main part of the command that will be
428
     * used to encode the given file(s).
429
     */
430 0
    protected function prepareEncoderCommand()
431
    {
432 0
        $command = $this->zendEncoderPath . " ";
433

434 0
        if (!empty($this->renameSourceExt)) {
435 0
            $command .= " --rename-source " . $this->renameSourceExt . " ";
436 0
        } elseif ($this->deleteSource) {
437
            // delete source
438 0
            $command .= " --delete-source ";
439
        }
440

441
        // short tags
442 0
        $command .= " --short-tags " . (($this->shortTags) ? 'on' : 'off') . " ";
443

444
        // asp tags
445 0
        $command .= " --asp-tags " . (($this->aspTags) ? 'on' : 'off') . " ";
446

447
        // use crypto
448 0
        if ($this->useCrypto) {
449 0
            $command .= " --use-crypto ";
450
        }
451

452
        // ignore file modes
453 0
        if ($this->ignoreFileModes) {
454 0
            $command .= " --ignore-file-modes ";
455
        }
456

457
        // force encode
458 0
        if ($this->forceEncode) {
459 0
            $command .= " --force-encode ";
460
        }
461

462
        // expires
463 0
        if (!empty($this->expires)) {
464 0
            $command .= " --expires " . $this->expires . " ";
465
        }
466

467
        // insert prolog file name or no-header
468 0
        if (!empty($this->prologFile)) {
469 0
            $command .= " --prolog-filename " . $this->prologFile . " ";
470 0
        } elseif ($this->noHeader) {
471
            // no-header
472 0
            $command .= " --no-header ";
473
        }
474

475
        // obfuscation level
476 0
        if ($this->obfuscationLevel > 0) {
477 0
            $command .= " --obfuscation-level " . $this->obfuscationLevel . " ";
478
        }
479

480
        // encoded only
481 0
        if ($this->encodedOnly) {
482 0
            $command .= " --encoded-only ";
483
        }
484

485
        // opt mask
486 0
        if (null !== $this->optMask) {
487 0
            $command .= " --optimizations " . $this->optMask . " ";
488
        }
489

490
        // Signing or licensing
491 0
        if ($this->signProduct) {
492 0
            $command .= " --sign-product " . $this->productName . " --private-key " . $this->privateKeyPath . " ";
493 0
        } elseif ($this->licenseProduct) {
494 0
            $command .= " --license-product " . $this->productName . " --private-key " . $this->privateKeyPath . " ";
495
        }
496

497
        // add a blank space
498 0
        $command .= " ";
499

500 0
        $this->encodeCommand = $command;
501
    }
502

503
    /**
504
     * Encodes a file using currently defined Zend Guard settings
505
     *
506
     * @param  string $filePath Path to the encoded file
507
     * @throws BuildException
508
     * @return bool
509
     */
510 0
    protected function encodeFile($filePath)
511
    {
512 0
        $command = $this->encodeCommand . $filePath . ' 2>&1';
513

514 0
        $this->log('Running: ' . $command, Project::MSG_VERBOSE);
515

516 0
        $tmp = exec($command, $output, $return_var);
517 0
        if ($return_var !== 0) {
518 0
            throw new BuildException("Encoding failed. \n Msg: " . $tmp . " \n Encode command: " . $command);
519
        }
520

521 0
        return true;
522
    }
523
}

Read our documentation on viewing source code .

Loading