ShortPixel Image Optimizer - Version 4.6.0

Version Description

  • add a filter option to the Other Media table
  • fixes in order to comply with WP plugin guidelines
Download this release

Release Info

Developer ShortPixel
Plugin Icon 128x128 ShortPixel Image Optimizer
Version 4.6.0
Comparing to
See all releases

Code changes from version 4.5.5 to 4.6.0

JSON/JSON.php DELETED
@@ -1,824 +0,0 @@
1
- <?php
2
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
-
4
- /**
5
- * Converts to and from JSON format.
6
- *
7
- * JSON (JavaScript Object Notation) is a lightweight data-interchange
8
- * format. It is easy for humans to read and write. It is easy for machines
9
- * to parse and generate. It is based on a subset of the JavaScript
10
- * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
11
- * This feature can also be found in Python. JSON is a text format that is
12
- * completely language independent but uses conventions that are familiar
13
- * to programmers of the C-family of languages, including C, C++, C#, Java,
14
- * JavaScript, Perl, TCL, and many others. These properties make JSON an
15
- * ideal data-interchange language.
16
- *
17
- * This package provides a simple encoder and decoder for JSON notation. It
18
- * is intended for use with client-side Javascript applications that make
19
- * use of HTTPRequest to perform server communication functions - data can
20
- * be encoded into JSON notation for use in a client-side javascript, or
21
- * decoded from incoming Javascript requests. JSON format is native to
22
- * Javascript, and can be directly eval()'ed with no further parsing
23
- * overhead
24
- *
25
- * All strings should be in ASCII or UTF-8 format!
26
- *
27
- * LICENSE: Redistribution and use in source and binary forms, with or
28
- * without modification, are permitted provided that the following
29
- * conditions are met: Redistributions of source code must retain the
30
- * above copyright notice, this list of conditions and the following
31
- * disclaimer. Redistributions in binary form must reproduce the above
32
- * copyright notice, this list of conditions and the following disclaimer
33
- * in the documentation and/or other materials provided with the
34
- * distribution.
35
- *
36
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
37
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
39
- * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
40
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
41
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
42
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
45
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46
- * DAMAGE.
47
- *
48
- * @category
49
- * @package Services_JSON
50
- * @author Michal Migurski <mike-json@teczno.com>
51
- * @author Matt Knapp <mdknapp[at]gmail[dot]com>
52
- * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
53
- * @copyright 2005 Michal Migurski
54
- * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
55
- * @license http://www.opensource.org/licenses/bsd-license.php
56
- * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
57
- */
58
-
59
- /**
60
- * Marker constant for Services_JSON::decode(), used to flag stack state
61
- */
62
- define('SERVICES_JSON_SLICE', 1);
63
-
64
- /**
65
- * Marker constant for Services_JSON::decode(), used to flag stack state
66
- */
67
- define('SERVICES_JSON_IN_STR', 2);
68
-
69
- /**
70
- * Marker constant for Services_JSON::decode(), used to flag stack state
71
- */
72
- define('SERVICES_JSON_IN_ARR', 3);
73
-
74
- /**
75
- * Marker constant for Services_JSON::decode(), used to flag stack state
76
- */
77
- define('SERVICES_JSON_IN_OBJ', 4);
78
-
79
- /**
80
- * Marker constant for Services_JSON::decode(), used to flag stack state
81
- */
82
- define('SERVICES_JSON_IN_CMT', 5);
83
-
84
- /**
85
- * Behavior switch for Services_JSON::decode()
86
- */
87
- define('SERVICES_JSON_LOOSE_TYPE', 16);
88
-
89
- /**
90
- * Behavior switch for Services_JSON::decode()
91
- */
92
- define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
93
-
94
- /**
95
- * Converts to and from JSON format.
96
- *
97
- * Brief example of use:
98
- *
99
- * <code>
100
- * // create a new instance of Services_JSON
101
- * $json = new Services_JSON();
102
- *
103
- * // convert a complexe value to JSON notation, and send it to the browser
104
- * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
105
- * $output = $json->encode($value);
106
- *
107
- * print($output);
108
- * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
109
- *
110
- * // accept incoming POST data, assumed to be in JSON notation
111
- * $input = file_get_contents('php://input', 1000000);
112
- * $value = $json->decode($input);
113
- * </code>
114
- */
115
- class Services_JSON
116
- {
117
- /**
118
- * constructs a new JSON instance
119
- *
120
- * @param int $use object behavior flags; combine with boolean-OR
121
- *
122
- * possible values:
123
- * - SERVICES_JSON_LOOSE_TYPE: loose typing.
124
- * "{...}" syntax creates associative arrays
125
- * instead of objects in decode().
126
- * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
127
- * Values which can't be encoded (e.g. resources)
128
- * appear as NULL instead of throwing errors.
129
- * By default, a deeply-nested resource will
130
- * bubble up with an error, so all return values
131
- * from encode() should be checked with isError()
132
- */
133
- function __construct($use = 0)
134
- {
135
- $this->use = $use;
136
- }
137
-
138
- /* Handling older constructor */
139
- function Services_JSON($use = 0) {
140
- $this->__construct();
141
- }
142
-
143
-
144
- /**
145
- * convert a string from one UTF-16 char to one UTF-8 char
146
- *
147
- * Normally should be handled by mb_convert_encoding, but
148
- * provides a slower PHP-only method for installations
149
- * that lack the multibye string extension.
150
- *
151
- * @param string $utf16 UTF-16 character
152
- * @return string UTF-8 character
153
- * @access private
154
- */
155
- function utf162utf8($utf16)
156
- {
157
- // oh please oh please oh please oh please oh please
158
- if(function_exists('mb_convert_encoding')) {
159
- return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
160
- }
161
-
162
- $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
163
-
164
- switch(true) {
165
- case ((0x7F & $bytes) == $bytes):
166
- // this case should never be reached, because we are in ASCII range
167
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
168
- return chr(0x7F & $bytes);
169
-
170
- case (0x07FF & $bytes) == $bytes:
171
- // return a 2-byte UTF-8 character
172
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
173
- return chr(0xC0 | (($bytes >> 6) & 0x1F))
174
- . chr(0x80 | ($bytes & 0x3F));
175
-
176
- case (0xFFFF & $bytes) == $bytes:
177
- // return a 3-byte UTF-8 character
178
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
179
- return chr(0xE0 | (($bytes >> 12) & 0x0F))
180
- . chr(0x80 | (($bytes >> 6) & 0x3F))
181
- . chr(0x80 | ($bytes & 0x3F));
182
- }
183
-
184
- // ignoring UTF-32 for now, sorry
185
- return '';
186
- }
187
-
188
- /**
189
- * convert a string from one UTF-8 char to one UTF-16 char
190
- *
191
- * Normally should be handled by mb_convert_encoding, but
192
- * provides a slower PHP-only method for installations
193
- * that lack the multibye string extension.
194
- *
195
- * @param string $utf8 UTF-8 character
196
- * @return string UTF-16 character
197
- * @access private
198
- */
199
- function utf82utf16($utf8)
200
- {
201
- // oh please oh please oh please oh please oh please
202
- if(function_exists('mb_convert_encoding')) {
203
- return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
204
- }
205
-
206
- switch(strlen($utf8)) {
207
- case 1:
208
- // this case should never be reached, because we are in ASCII range
209
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
210
- return $utf8;
211
-
212
- case 2:
213
- // return a UTF-16 character from a 2-byte UTF-8 char
214
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
215
- return chr(0x07 & (ord($utf8{0}) >> 2))
216
- . chr((0xC0 & (ord($utf8{0}) << 6))
217
- | (0x3F & ord($utf8{1})));
218
-
219
- case 3:
220
- // return a UTF-16 character from a 3-byte UTF-8 char
221
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
222
- return chr((0xF0 & (ord($utf8{0}) << 4))
223
- | (0x0F & (ord($utf8{1}) >> 2)))
224
- . chr((0xC0 & (ord($utf8{1}) << 6))
225
- | (0x7F & ord($utf8{2})));
226
- }
227
-
228
- // ignoring UTF-32 for now, sorry
229
- return '';
230
- }
231
-
232
- /**
233
- * encodes an arbitrary variable into JSON format
234
- *
235
- * @param mixed $var any number, boolean, string, array, or object to be encoded.
236
- * see argument 1 to Services_JSON() above for array-parsing behavior.
237
- * if var is a strng, note that encode() always expects it
238
- * to be in ASCII or UTF-8 format!
239
- *
240
- * @return mixed JSON string representation of input var or an error if a problem occurs
241
- * @access public
242
- */
243
- function encode($var)
244
- {
245
- switch (gettype($var)) {
246
- case 'boolean':
247
- return $var ? 'true' : 'false';
248
-
249
- case 'NULL':
250
- return 'null';
251
-
252
- case 'integer':
253
- return (int) $var;
254
-
255
- case 'double':
256
- case 'float':
257
- return (float) $var;
258
-
259
- case 'string':
260
- // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
261
- $ascii = '';
262
- $strlen_var = strlen($var);
263
-
264
- /*
265
- * Iterate over every character in the string,
266
- * escaping with a slash or encoding to UTF-8 where necessary
267
- */
268
- for ($c = 0; $c < $strlen_var; ++$c) {
269
-
270
- $ord_var_c = ord($var{$c});
271
-
272
- switch (true) {
273
- case $ord_var_c == 0x08:
274
- $ascii .= '\b';
275
- break;
276
- case $ord_var_c == 0x09:
277
- $ascii .= '\t';
278
- break;
279
- case $ord_var_c == 0x0A:
280
- $ascii .= '\n';
281
- break;
282
- case $ord_var_c == 0x0C:
283
- $ascii .= '\f';
284
- break;
285
- case $ord_var_c == 0x0D:
286
- $ascii .= '\r';
287
- break;
288
-
289
- case $ord_var_c == 0x22:
290
- case $ord_var_c == 0x2F:
291
- case $ord_var_c == 0x5C:
292
- // double quote, slash, slosh
293
- $ascii .= '\\'.$var{$c};
294
- break;
295
-
296
- case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
297
- // characters U-00000000 - U-0000007F (same as ASCII)
298
- $ascii .= $var{$c};
299
- break;
300
-
301
- case (($ord_var_c & 0xE0) == 0xC0):
302
- // characters U-00000080 - U-000007FF, mask 110XXXXX
303
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
304
- $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
305
- $c += 1;
306
- $utf16 = $this->utf82utf16($char);
307
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
308
- break;
309
-
310
- case (($ord_var_c & 0xF0) == 0xE0):
311
- // characters U-00000800 - U-0000FFFF, mask 1110XXXX
312
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
313
- $char = pack('C*', $ord_var_c,
314
- ord($var{$c + 1}),
315
- ord($var{$c + 2}));
316
- $c += 2;
317
- $utf16 = $this->utf82utf16($char);
318
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
319
- break;
320
-
321
- case (($ord_var_c & 0xF8) == 0xF0):
322
- // characters U-00010000 - U-001FFFFF, mask 11110XXX
323
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
324
- $char = pack('C*', $ord_var_c,
325
- ord($var{$c + 1}),
326
- ord($var{$c + 2}),
327
- ord($var{$c + 3}));
328
- $c += 3;
329
- $utf16 = $this->utf82utf16($char);
330
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
331
- break;
332
-
333
- case (($ord_var_c & 0xFC) == 0xF8):
334
- // characters U-00200000 - U-03FFFFFF, mask 111110XX
335
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
336
- $char = pack('C*', $ord_var_c,
337
- ord($var{$c + 1}),
338
- ord($var{$c + 2}),
339
- ord($var{$c + 3}),
340
- ord($var{$c + 4}));
341
- $c += 4;
342
- $utf16 = $this->utf82utf16($char);
343
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
344
- break;
345
-
346
- case (($ord_var_c & 0xFE) == 0xFC):
347
- // characters U-04000000 - U-7FFFFFFF, mask 1111110X
348
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
349
- $char = pack('C*', $ord_var_c,
350
- ord($var{$c + 1}),
351
- ord($var{$c + 2}),
352
- ord($var{$c + 3}),
353
- ord($var{$c + 4}),
354
- ord($var{$c + 5}));
355
- $c += 5;
356
- $utf16 = $this->utf82utf16($char);
357
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
358
- break;
359
- }
360
- }
361
-
362
- return '"'.$ascii.'"';
363
-
364
- case 'array':
365
- /*
366
- * As per JSON spec if any array key is not an integer
367
- * we must treat the the whole array as an object. We
368
- * also try to catch a sparsely populated associative
369
- * array with numeric keys here because some JS engines
370
- * will create an array with empty indexes up to
371
- * max_index which can cause memory issues and because
372
- * the keys, which may be relevant, will be remapped
373
- * otherwise.
374
- *
375
- * As per the ECMA and JSON specification an object may
376
- * have any string as a property. Unfortunately due to
377
- * a hole in the ECMA specification if the key is a
378
- * ECMA reserved word or starts with a digit the
379
- * parameter is only accessible using ECMAScript's
380
- * bracket notation.
381
- */
382
-
383
- // treat as a JSON object
384
- if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
385
- $properties = array_map(array($this, 'name_value'),
386
- array_keys($var),
387
- array_values($var));
388
-
389
- foreach($properties as $property) {
390
- if(Services_JSON::isError($property)) {
391
- return $property;
392
- }
393
- }
394
-
395
- return '{' . join(',', $properties) . '}';
396
- }
397
-
398
- // treat it like a regular array
399
- $elements = array_map(array($this, 'encode'), $var);
400
-
401
- foreach($elements as $element) {
402
- if(Services_JSON::isError($element)) {
403
- return $element;
404
- }
405
- }
406
-
407
- return '[' . join(',', $elements) . ']';
408
-
409
- case 'object':
410
- $vars = get_object_vars($var);
411
-
412
- $properties = array_map(array($this, 'name_value'),
413
- array_keys($vars),
414
- array_values($vars));
415
-
416
- foreach($properties as $property) {
417
- if(Services_JSON::isError($property)) {
418
- return $property;
419
- }
420
- }
421
-
422
- return '{' . join(',', $properties) . '}';
423
-
424
- default:
425
- return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
426
- ? 'null'
427
- : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
428
- }
429
- }
430
-
431
- /**
432
- * array-walking function for use in generating JSON-formatted name-value pairs
433
- *
434
- * @param string $name name of key to use
435
- * @param mixed $value reference to an array element to be encoded
436
- *
437
- * @return string JSON-formatted name-value pair, like '"name":value'
438
- * @access private
439
- */
440
- function name_value($name, $value)
441
- {
442
- $encoded_value = $this->encode($value);
443
-
444
- if(Services_JSON::isError($encoded_value)) {
445
- return $encoded_value;
446
- }
447
-
448
- return $this->encode(strval($name)) . ':' . $encoded_value;
449
- }
450
-
451
- /**
452
- * reduce a string by removing leading and trailing comments and whitespace
453
- *
454
- * @param $str string string value to strip of comments and whitespace
455
- *
456
- * @return string string value stripped of comments and whitespace
457
- * @access private
458
- */
459
- function reduce_string($str)
460
- {
461
- $str = preg_replace(array(
462
-
463
- // eliminate single line comments in '// ...' form
464
- '#^\s*//(.+)$#m',
465
-
466
- // eliminate multi-line comments in '/* ... */' form, at start of string
467
- '#^\s*/\*(.+)\*/#Us',
468
-
469
- // eliminate multi-line comments in '/* ... */' form, at end of string
470
- '#/\*(.+)\*/\s*$#Us'
471
-
472
- ), '', $str);
473
-
474
- // eliminate extraneous space
475
- return trim($str);
476
- }
477
-
478
- /**
479
- * decodes a JSON string into appropriate variable
480
- *
481
- * @param string $str JSON-formatted string
482
- *
483
- * @return mixed number, boolean, string, array, or object
484
- * corresponding to given JSON input string.
485
- * See argument 1 to Services_JSON() above for object-output behavior.
486
- * Note that decode() always returns strings
487
- * in ASCII or UTF-8 format!
488
- * @access public
489
- */
490
- function decode($str)
491
- {
492
- $str = $this->reduce_string($str);
493
-
494
- switch (strtolower($str)) {
495
- case 'true':
496
- return true;
497
-
498
- case 'false':
499
- return false;
500
-
501
- case 'null':
502
- return null;
503
-
504
- default:
505
- $m = array();
506
-
507
- if (is_numeric($str)) {
508
- // Lookie-loo, it's a number
509
-
510
- // This would work on its own, but I'm trying to be
511
- // good about returning integers where appropriate:
512
- // return (float)$str;
513
-
514
- // Return float or int, as appropriate
515
- return ((float)$str == (integer)$str)
516
- ? (integer)$str
517
- : (float)$str;
518
-
519
- } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
520
- // STRINGS RETURNED IN UTF-8 FORMAT
521
- $delim = substr($str, 0, 1);
522
- $chrs = substr($str, 1, -1);
523
- $utf8 = '';
524
- $strlen_chrs = strlen($chrs);
525
-
526
- for ($c = 0; $c < $strlen_chrs; ++$c) {
527
-
528
- $substr_chrs_c_2 = substr($chrs, $c, 2);
529
- $ord_chrs_c = ord($chrs{$c});
530
-
531
- switch (true) {
532
- case $substr_chrs_c_2 == '\b':
533
- $utf8 .= chr(0x08);
534
- ++$c;
535
- break;
536
- case $substr_chrs_c_2 == '\t':
537
- $utf8 .= chr(0x09);
538
- ++$c;
539
- break;
540
- case $substr_chrs_c_2 == '\n':
541
- $utf8 .= chr(0x0A);
542
- ++$c;
543
- break;
544
- case $substr_chrs_c_2 == '\f':
545
- $utf8 .= chr(0x0C);
546
- ++$c;
547
- break;
548
- case $substr_chrs_c_2 == '\r':
549
- $utf8 .= chr(0x0D);
550
- ++$c;
551
- break;
552
-
553
- case $substr_chrs_c_2 == '\\"':
554
- case $substr_chrs_c_2 == '\\\'':
555
- case $substr_chrs_c_2 == '\\\\':
556
- case $substr_chrs_c_2 == '\\/':
557
- if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
558
- ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
559
- $utf8 .= $chrs{++$c};
560
- }
561
- break;
562
-
563
- case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
564
- // single, escaped unicode character
565
- $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
566
- . chr(hexdec(substr($chrs, ($c + 4), 2)));
567
- $utf8 .= $this->utf162utf8($utf16);
568
- $c += 5;
569
- break;
570
-
571
- case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
572
- $utf8 .= $chrs{$c};
573
- break;
574
-
575
- case ($ord_chrs_c & 0xE0) == 0xC0:
576
- // characters U-00000080 - U-000007FF, mask 110XXXXX
577
- //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
578
- $utf8 .= substr($chrs, $c, 2);
579
- ++$c;
580
- break;
581
-
582
- case ($ord_chrs_c & 0xF0) == 0xE0:
583
- // characters U-00000800 - U-0000FFFF, mask 1110XXXX
584
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
585
- $utf8 .= substr($chrs, $c, 3);
586
- $c += 2;
587
- break;
588
-
589
- case ($ord_chrs_c & 0xF8) == 0xF0:
590
- // characters U-00010000 - U-001FFFFF, mask 11110XXX
591
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
592
- $utf8 .= substr($chrs, $c, 4);
593
- $c += 3;
594
- break;
595
-
596
- case ($ord_chrs_c & 0xFC) == 0xF8:
597
- // characters U-00200000 - U-03FFFFFF, mask 111110XX
598
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
599
- $utf8 .= substr($chrs, $c, 5);
600
- $c += 4;
601
- break;
602
-
603
- case ($ord_chrs_c & 0xFE) == 0xFC:
604
- // characters U-04000000 - U-7FFFFFFF, mask 1111110X
605
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
606
- $utf8 .= substr($chrs, $c, 6);
607
- $c += 5;
608
- break;
609
-
610
- }
611
-
612
- }
613
-
614
- return $utf8;
615
-
616
- } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
617
- // array, or object notation
618
-
619
- if ($str{0} == '[') {
620
- $stk = array(SERVICES_JSON_IN_ARR);
621
- $arr = array();
622
- } else {
623
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
624
- $stk = array(SERVICES_JSON_IN_OBJ);
625
- $obj = array();
626
- } else {
627
- $stk = array(SERVICES_JSON_IN_OBJ);
628
- $obj = new stdClass();
629
- }
630
- }
631
-
632
- array_push($stk, array('what' => SERVICES_JSON_SLICE,
633
- 'where' => 0,
634
- 'delim' => false));
635
-
636
- $chrs = substr($str, 1, -1);
637
- $chrs = $this->reduce_string($chrs);
638
-
639
- if ($chrs == '') {
640
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
641
- return $arr;
642
-
643
- } else {
644
- return $obj;
645
-
646
- }
647
- }
648
-
649
- //print("\nparsing {$chrs}\n");
650
-
651
- $strlen_chrs = strlen($chrs);
652
-
653
- for ($c = 0; $c <= $strlen_chrs; ++$c) {
654
-
655
- $top = end($stk);
656
- $substr_chrs_c_2 = substr($chrs, $c, 2);
657
-
658
- if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
659
- // found a comma that is not inside a string, array, etc.,
660
- // OR we've reached the end of the character list
661
- $slice = substr($chrs, $top['where'], ($c - $top['where']));
662
- array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
663
- //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
664
-
665
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
666
- // we are in an array, so just push an element onto the stack
667
- array_push($arr, $this->decode($slice));
668
-
669
- } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
670
- // we are in an object, so figure
671
- // out the property name and set an
672
- // element in an associative array,
673
- // for now
674
- $parts = array();
675
-
676
- if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
677
- // "name":value pair
678
- $key = $this->decode($parts[1]);
679
- $val = $this->decode($parts[2]);
680
-
681
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
682
- $obj[$key] = $val;
683
- } else {
684
- $obj->$key = $val;
685
- }
686
- } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
687
- // name:value pair, where name is unquoted
688
- $key = $parts[1];
689
- $val = $this->decode($parts[2]);
690
-
691
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
692
- $obj[$key] = $val;
693
- } else {
694
- $obj->$key = $val;
695
- }
696
- }
697
-
698
- }
699
-
700
- } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
701
- // found a quote, and we are not inside a string
702
- array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
703
- //print("Found start of string at {$c}\n");
704
-
705
- } elseif (($chrs{$c} == $top['delim']) &&
706
- ($top['what'] == SERVICES_JSON_IN_STR) &&
707
- ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
708
- // found a quote, we're in a string, and it's not escaped
709
- // we know that it's not escaped becase there is _not_ an
710
- // odd number of backslashes at the end of the string so far
711
- array_pop($stk);
712
- //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
713
-
714
- } elseif (($chrs{$c} == '[') &&
715
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
716
- // found a left-bracket, and we are in an array, object, or slice
717
- array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
718
- //print("Found start of array at {$c}\n");
719
-
720
- } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
721
- // found a right-bracket, and we're in an array
722
- array_pop($stk);
723
- //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
724
-
725
- } elseif (($chrs{$c} == '{') &&
726
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
727
- // found a left-brace, and we are in an array, object, or slice
728
- array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
729
- //print("Found start of object at {$c}\n");
730
-
731
- } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
732
- // found a right-brace, and we're in an object
733
- array_pop($stk);
734
- //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
735
-
736
- } elseif (($substr_chrs_c_2 == '/*') &&
737
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
738
- // found a comment start, and we are in an array, object, or slice
739
- array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
740
- $c++;
741
- //print("Found start of comment at {$c}\n");
742
-
743
- } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
744
- // found a comment end, and we're in one now
745
- array_pop($stk);
746
- $c++;
747
-
748
- for ($i = $top['where']; $i <= $c; ++$i)
749
- $chrs = substr_replace($chrs, ' ', $i, 1);
750
-
751
- //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
752
-
753
- }
754
-
755
- }
756
-
757
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
758
- return $arr;
759
-
760
- } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
761
- return $obj;
762
-
763
- }
764
-
765
- }
766
- }
767
- }
768
-
769
- /**
770
- * @todo Ultimately, this should just call PEAR::isError()
771
- */
772
- function isError($data, $code = null)
773
- {
774
- if (class_exists('pear')) {
775
- return PEAR::isError($data, $code);
776
- } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
777
- is_subclass_of($data, 'services_json_error'))) {
778
- return true;
779
- }
780
-
781
- return false;
782
- }
783
- }
784
-
785
- if (class_exists('PEAR_Error')) {
786
-
787
- class Services_JSON_Error extends PEAR_Error
788
- {
789
- function __construct($message = 'unknown error', $code = null,
790
- $mode = null, $options = null, $userinfo = null)
791
- {
792
- parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
793
- }
794
-
795
- /* Handling older constructor */
796
- function Services_JSON_Error($message = 'unknown error', $code = null,
797
- $mode = null, $options = null, $userinfo = null) {
798
- $this->__construct();
799
- }
800
- }
801
-
802
- } else {
803
-
804
- /**
805
- * @todo Ultimately, this class shall be descended from PEAR_Error
806
- */
807
- class Services_JSON_Error
808
- {
809
- function __construct($message = 'unknown error', $code = null,
810
- $mode = null, $options = null, $userinfo = null)
811
- {
812
-
813
- }
814
-
815
- /* Handling older constructor */
816
- function Services_JSON_Error($message = 'unknown error', $code = null,
817
- $mode = null, $options = null, $userinfo = null) {
818
- $this->__construct();
819
- }
820
-
821
- }
822
- }
823
-
824
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
JSON/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- Redistribution and use in source and binary forms, with or without
2
- modification, are permitted provided that the following conditions are
3
- met:
4
-
5
- Redistributions of source code must retain the above copyright notice,
6
- this list of conditions and the following disclaimer.
7
-
8
- Redistributions in binary form must reproduce the above copyright
9
- notice, this list of conditions and the following disclaimer in the
10
- documentation and/or other materials provided with the distribution.
11
-
12
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
13
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
15
- NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
16
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
18
- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19
- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21
- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
class/db/shortpixel-custom-meta-dao.php CHANGED
@@ -205,7 +205,7 @@ class ShortPixelCustomMetaDao {
205
  $folder = new ShortPixelFolder(array("path" => $addedFolder), $this->excludePatterns);
206
  try {
207
  $folder->setFileCount($folder->countFiles());
208
- } catch(SpFileRightsException $ex) {
209
  return $ex->getMessage();
210
  }
211
  if(ShortPixelMetaFacade::isMediaSubfolder($folder->getPath())) {
@@ -232,7 +232,7 @@ class ShortPixelCustomMetaDao {
232
  $addedPath = $folder->getPath();
233
  if($addedPath) {
234
  //first check if it does contain the Backups Folder - we don't allow that
235
- if(ShortPixelFolder::checkFolderIsSubfolder(SP_BACKUP_FOLDER, $addedPath)) {
236
  return __('This folder contains the ShortPixel Backups. Please select a different folder.','shortpixel-image-optimiser');
237
  }
238
  $customFolderPaths = array_map(array('ShortPixelFolder','path'), $this->getFolders());
@@ -312,15 +312,18 @@ class ShortPixelCustomMetaDao {
312
  $this->db->query($sql);
313
  }
314
 
315
- public function getPaginatedMetas($hasNextGen, $count, $page, $orderby = false, $order = false) {
316
  $sql = "SELECT sm.id, sm.name, sm.path folder, "
317
  . ($hasNextGen ? "CASE WHEN ng.gid IS NOT NULL THEN 'NextGen' ELSE 'Custom' END media_type, " : "'Custom' media_type, ")
318
  . "sm.status, sm.compression_type, sm.keep_exif, sm.cmyk2rgb, sm.resize, sm.resize_width, sm.resize_height, sm.message "
319
  . "FROM {$this->db->getPrefix()}shortpixel_meta sm "
320
  . "INNER JOIN {$this->db->getPrefix()}shortpixel_folders sf on sm.folder_id = sf.id "
321
  . ($hasNextGen ? "LEFT JOIN {$this->db->getPrefix()}ngg_gallery ng on sf.path = ng.path " : " ")
322
- . "WHERE sf.status <> -1 "
323
- . ($orderby ? "ORDER BY $orderby $order " : "")
 
 
 
324
  . "LIMIT $count OFFSET " . ($page - 1) * $count;
325
 
326
  //die($sql);
@@ -350,10 +353,14 @@ class ShortPixelCustomMetaDao {
350
  return isset($res[0]->recCount) ? $res[0]->recCount : null;
351
  }
352
 
353
- public function getCustomMetaCount() {
354
  $sql = "SELECT COUNT(sm.id) recCount FROM {$this->db->getPrefix()}shortpixel_meta sm "
355
  . "INNER JOIN {$this->db->getPrefix()}shortpixel_folders sf on sm.folder_id = sf.id "
356
  . "WHERE sf.status <> -1 AND sm.status <> 3";
 
 
 
 
357
  $res = $this->db->query($sql);
358
  return isset($res[0]->recCount) ? $res[0]->recCount : 0;
359
  }
205
  $folder = new ShortPixelFolder(array("path" => $addedFolder), $this->excludePatterns);
206
  try {
207
  $folder->setFileCount($folder->countFiles());
208
+ } catch(ShortPixelFileRightsException $ex) {
209
  return $ex->getMessage();
210
  }
211
  if(ShortPixelMetaFacade::isMediaSubfolder($folder->getPath())) {
232
  $addedPath = $folder->getPath();
233
  if($addedPath) {
234
  //first check if it does contain the Backups Folder - we don't allow that
235
+ if(ShortPixelFolder::checkFolderIsSubfolder(SHORTPIXEL_BACKUP_FOLDER, $addedPath)) {
236
  return __('This folder contains the ShortPixel Backups. Please select a different folder.','shortpixel-image-optimiser');
237
  }
238
  $customFolderPaths = array_map(array('ShortPixelFolder','path'), $this->getFolders());
312
  $this->db->query($sql);
313
  }
314
 
315
+ public function getPaginatedMetas($hasNextGen, $filters, $count, $page, $orderby = false, $order = false) {
316
  $sql = "SELECT sm.id, sm.name, sm.path folder, "
317
  . ($hasNextGen ? "CASE WHEN ng.gid IS NOT NULL THEN 'NextGen' ELSE 'Custom' END media_type, " : "'Custom' media_type, ")
318
  . "sm.status, sm.compression_type, sm.keep_exif, sm.cmyk2rgb, sm.resize, sm.resize_width, sm.resize_height, sm.message "
319
  . "FROM {$this->db->getPrefix()}shortpixel_meta sm "
320
  . "INNER JOIN {$this->db->getPrefix()}shortpixel_folders sf on sm.folder_id = sf.id "
321
  . ($hasNextGen ? "LEFT JOIN {$this->db->getPrefix()}ngg_gallery ng on sf.path = ng.path " : " ")
322
+ . "WHERE sf.status <> -1 ";
323
+ foreach($filters as $field => $value) {
324
+ $sql .= " AND sm.$field " . $value->operator . " ". $value->value . " ";
325
+ }
326
+ $sql .= ($orderby ? "ORDER BY $orderby $order " : "")
327
  . "LIMIT $count OFFSET " . ($page - 1) * $count;
328
 
329
  //die($sql);
353
  return isset($res[0]->recCount) ? $res[0]->recCount : null;
354
  }
355
 
356
+ public function getCustomMetaCount($filters = array()) {
357
  $sql = "SELECT COUNT(sm.id) recCount FROM {$this->db->getPrefix()}shortpixel_meta sm "
358
  . "INNER JOIN {$this->db->getPrefix()}shortpixel_folders sf on sm.folder_id = sf.id "
359
  . "WHERE sf.status <> -1 AND sm.status <> 3";
360
+ foreach($filters as $field => $value) {
361
+ $sql .= " AND sm.$field " . $value->operator . " ". $value->value . " ";
362
+ }
363
+
364
  $res = $this->db->query($sql);
365
  return isset($res[0]->recCount) ? $res[0]->recCount : 0;
366
  }
class/db/shortpixel-meta-facade.php CHANGED
@@ -269,7 +269,7 @@ class ShortPixelMetaFacade {
269
  throw new Exception("Post metadata is corrupt (No attachment URL)");
270
  }
271
  if ( !parse_url($attURL, PHP_URL_SCHEME) ) {//no absolute URLs used -> we implement a hack
272
- return get_site_url() . $attURL;//get the file URL
273
  }
274
  else {
275
  return $attURL;//get the file URL
@@ -418,7 +418,7 @@ class ShortPixelMetaFacade {
418
  public static function pathToWebPath($path) {
419
  //$upl = wp_upload_dir();
420
  //return str_replace($upl["basedir"], $upl["baseurl"], $path);
421
- return self::replaceHomePath($path, site_url()."/");
422
  }
423
 
424
  public static function pathToRootRelative($path) {
269
  throw new Exception("Post metadata is corrupt (No attachment URL)");
270
  }
271
  if ( !parse_url($attURL, PHP_URL_SCHEME) ) {//no absolute URLs used -> we implement a hack
272
+ return self::getHomeUrl() . $attURL;//get the file URL
273
  }
274
  else {
275
  return $attURL;//get the file URL
418
  public static function pathToWebPath($path) {
419
  //$upl = wp_upload_dir();
420
  //return str_replace($upl["basedir"], $upl["baseurl"], $path);
421
+ return self::replaceHomePath($path, self::getHomeUrl()."/");
422
  }
423
 
424
  public static function pathToRootRelative($path) {
class/front/img-to-picture-webp.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
  /**
3
- * Class ImgToPictureWebp - convert an <img> tag to a <picture> tag and add the webp versions of the images
4
  * thanks to the Responsify WP plugin for some of the code
5
  */
6
 
7
- class ImgToPictureWebp {
8
 
9
  public static function convert($content) {
10
  // Don't do anything with the RSS feed.
1
  <?php
2
  /**
3
+ * Class ShortPixelImgToPictureWebp - convert an <img> tag to a <picture> tag and add the webp versions of the images
4
  * thanks to the Responsify WP plugin for some of the code
5
  */
6
 
7
+ class ShortPixelImgToPictureWebp {
8
 
9
  public static function convert($content) {
10
  // Don't do anything with the RSS feed.
class/model/shortpixel-folder.php CHANGED
@@ -76,7 +76,7 @@ class ShortPixelFolder extends ShortPixelEntity{
76
  }
77
  $ignore = array('.','..');
78
  if(!is_writable($path)) {
79
- throw new SpFileRightsException(sprintf(__('Folder %s is not writeable. Please check permissions and try again.','shortpixel-image-optimiser'),$path));
80
  }
81
  $files = scandir($path);
82
  foreach($files as $t) {
@@ -149,7 +149,7 @@ class ShortPixelFolder extends ShortPixelEntity{
149
  protected static function getFolderContentsChangeDateRecursive($path, $mtime, $refMtime) {
150
  $ignore = array('.','..');
151
  if(!is_writable($path)) {
152
- throw new SpFileRightsException(sprintf(__('Folder %s is not writeable. Please check permissions and try again.','shortpixel-image-optimiser'),$path));
153
  }
154
  $files = scandir($path);
155
  $mtime = max($mtime, filemtime($path));
76
  }
77
  $ignore = array('.','..');
78
  if(!is_writable($path)) {
79
+ throw new ShortPixelFileRightsException(sprintf(__('Folder %s is not writeable. Please check permissions and try again.','shortpixel-image-optimiser'),$path));
80
  }
81
  $files = scandir($path);
82
  foreach($files as $t) {
149
  protected static function getFolderContentsChangeDateRecursive($path, $mtime, $refMtime) {
150
  $ignore = array('.','..');
151
  if(!is_writable($path)) {
152
+ throw new ShortPixelFileRightsException(sprintf(__('Folder %s is not writeable. Please check permissions and try again.','shortpixel-image-optimiser'),$path));
153
  }
154
  $files = scandir($path);
155
  $mtime = max($mtime, filemtime($path));
class/model/sp-file-rights-exception.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class SpFileRightsException extends Exception {
4
 
5
  }
6
 
1
  <?php
2
 
3
+ class ShortPixelFileRightsException extends Exception {
4
 
5
  }
6
 
class/shortpixel-tools.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
 
3
  class ShortPixelTools {
4
- public static function parseJSON($data) {
5
  if ( function_exists('json_decode') ) {
6
  $data = json_decode( $data );
7
  } else {
@@ -10,7 +10,7 @@ class ShortPixelTools {
10
  $data = $json->decode( $data );
11
  }
12
  return $data;
13
- }
14
 
15
  public static function snakeToCamel($snake_case) {
16
  return str_replace(' ', '', ucwords(str_replace('_', ' ', $snake_case)));
1
  <?php
2
 
3
  class ShortPixelTools {
4
+ /* public static function parseJSON($data) {
5
  if ( function_exists('json_decode') ) {
6
  $data = json_decode( $data );
7
  } else {
10
  $data = $json->decode( $data );
11
  }
12
  return $data;
13
+ }*/
14
 
15
  public static function snakeToCamel($snake_case) {
16
  return str_replace(' ', '', ucwords(str_replace('_', ' ', $snake_case)));
class/view/shortpixel-list-table.php CHANGED
@@ -175,12 +175,20 @@ class ShortPixelListTable extends WP_List_Table {
175
  // If no order, default to asc
176
  $order = ( ! empty($_GET['order'] ) ) ? $_GET['order'] : 'desc';
177
 
178
- $this->items = $this->spMetaDao->getPaginatedMetas($this->hasNextGen, $perPage, $currentPage, $orderby, $order);
179
  return $this->items;
180
  }
181
 
 
 
 
 
 
 
 
 
182
  public function record_count() {
183
- return $this->spMetaDao->getCustomMetaCount();
184
  }
185
 
186
  public function action_optimize_image( $id ) {
175
  // If no order, default to asc
176
  $order = ( ! empty($_GET['order'] ) ) ? $_GET['order'] : 'desc';
177
 
178
+ $this->items = $this->spMetaDao->getPaginatedMetas($this->hasNextGen, $this->getFilter(), $perPage, $currentPage, $orderby, $order);
179
  return $this->items;
180
  }
181
 
182
+ protected function getFilter() {
183
+ $filter = array();
184
+ if(isset($_GET["s"]) && strlen($_GET["s"])) {
185
+ $filter['path'] = (object)array("operator" => "like", "value" =>"'%" . esc_sql($_GET["s"]) . "%'");
186
+ }
187
+ return $filter;
188
+ }
189
+
190
  public function record_count() {
191
+ return $this->spMetaDao->getCustomMetaCount($this->getFilter());
192
  }
193
 
194
  public function action_optimize_image( $id ) {
class/wp-short-pixel.php CHANGED
@@ -25,7 +25,7 @@ class WPShortPixel {
25
 
26
  $isAdminUser = current_user_can( 'manage_options' );
27
 
28
- $this->_affiliateSufix = (strlen(SP_AFFILIATE_CODE)) ? "/affiliate/" . SP_AFFILIATE_CODE : "";
29
  $this->_settings = new WPShortPixelSettings();
30
  $this->_apiInterface = new ShortPixelAPI($this->_settings);
31
  $this->hasNextGen = ShortPixelNextGenAdapter::hasNextGen();
@@ -143,7 +143,7 @@ class WPShortPixel {
143
  public static function shortPixelActivatePlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
144
  {
145
  self::shortPixelDeactivatePlugin();
146
- if(SP_RESET_ON_ACTIVATE === true && WP_DEBUG === true) { //force reset plugin counters, only on specific occasions and on test environments
147
  WPShortPixelSettings::debugResetOptions();
148
 
149
  $settings = new WPShortPixelSettings();
@@ -515,7 +515,7 @@ class WPShortPixel {
515
  }
516
 
517
  public function bulkRestore(){
518
- global $wpdb, $MAX_EXECUTION_TIME;
519
 
520
  $startQueryID = $crtStartQueryID = $this->prioQ->getStartBulkId();
521
  $endQueryID = $this->prioQ->getStopBulkId();
@@ -525,8 +525,8 @@ class WPShortPixel {
525
  }
526
 
527
  $startTime = time();
528
- $maxTime = (is_numeric($MAX_EXECUTION_TIME) && $MAX_EXECUTION_TIME > 10 ? $MAX_EXECUTION_TIME - 5 : 25);
529
- $maxResults = SP_MAX_RESULTS_QUERY * 2;
530
  $restored = array();
531
 
532
  //$ind = 0;
@@ -578,13 +578,13 @@ class WPShortPixel {
578
  WHERE ( post_id <= $crtStartQueryID AND post_id >= $endQueryID )
579
  AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )
580
  ORDER BY post_id DESC
581
- LIMIT " . SP_MAX_RESULTS_QUERY;
582
  $resultsPostMeta = $wpdb->get_results($queryPostMeta);
583
  */
584
- $resultsPostMeta = WpShortPixelMediaLbraryAdapter::getPostMetaSlice($crtStartQueryID, $endQueryID, SP_MAX_RESULTS_QUERY);
585
 
586
  if ( empty($resultsPostMeta) ) {
587
- $crtStartQueryID -= SP_MAX_RESULTS_QUERY;
588
  $startQueryID = $crtStartQueryID;
589
  $this->prioQ->setStartBulkId($startQueryID);
590
  continue;
@@ -836,7 +836,7 @@ class WPShortPixel {
836
  }
837
 
838
  if(strlen($thumb) && $this->_settings->backupImages && $this->_settings->processThumbnails) {
839
- $backupUrl = content_url() . "/" . SP_UPLOADS_NAME . "/" . SP_BACKUP . "/";
840
  //$urlBkPath = $this->_apiInterface->returnSubDir(get_attached_file($ID));
841
  $urlBkPath = ShortPixelMetaFacade::returnSubDir($meta->getPath(), ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
842
  $bkThumb = $backupUrl . $urlBkPath . $thumb;
@@ -863,7 +863,7 @@ class WPShortPixel {
863
  } else {
864
  $result["Thumb"] = $thumb = $rootUrl . $meta->getWebPath();
865
  if($this->_settings->backupImages) {
866
- $result["BkThumb"] = str_replace($rootUrl, $rootUrl. "/" . basename(dirname(dirname(SP_BACKUP_FOLDER))) . "/" . SP_UPLOADS_NAME . "/" . SP_BACKUP . "/", $thumb);
867
  }
868
  }
869
  $this->setBulkInfo($itemId, $result);
@@ -873,7 +873,7 @@ class WPShortPixel {
873
  }
874
  }
875
  elseif ($result["Status"] == ShortPixelAPI::STATUS_ERROR) {
876
- if($meta->getRetries() > MAX_ERR_RETRIES) {
877
  if(! $this->prioQ->remove($itemId) ){
878
  $this->advanceBulk($meta->getId());
879
  }
@@ -1108,22 +1108,22 @@ class WPShortPixel {
1108
  $SubDir = ShortPixelMetaFacade::returnSubDir($file, ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
1109
  $SubDirOld = ShortPixelMetaFacade::returnSubDirOld($file, ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
1110
 
1111
- if ( !file_exists(SP_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file))
1112
- && !file_exists(SP_BACKUP_FOLDER . '/' . date("Y") . "/" . date("m") . "/" . ShortPixelAPI::MB_basename($file)) ) {
1113
  $SubDir = $SubDirOld; //maybe the folder was saved with the old method that returned the full path if the wp-content was not inside the root of the site.
1114
  }
1115
- if ( !file_exists(SP_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file))
1116
- && !file_exists(SP_BACKUP_FOLDER . '/' . date("Y") . "/" . date("m") . "/" . ShortPixelAPI::MB_basename($file)) ) {
1117
  $SubDir = trailingslashit(substr(dirname($file), 1)); //try this too
1118
  }
1119
  //sometimes the month of original file and backup can differ
1120
- if ( !file_exists(SP_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file)) ) {
1121
  $SubDir = date("Y") . "/" . date("m") . "/";
1122
- if( !file_exists(SP_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file)) ) {
1123
  return false;
1124
  }
1125
  }
1126
- return SP_BACKUP_FOLDER . '/' . $SubDir;
1127
  }
1128
 
1129
  public function getBackupFolderAny($file, $thumbs) {
@@ -1253,7 +1253,7 @@ class WPShortPixel {
1253
 
1254
  $file = $meta->getPath();
1255
  $fullSubDir = str_replace(get_home_path(), "", dirname($file)) . '/';
1256
- $bkFile = SP_BACKUP_FOLDER . '/' . $fullSubDir . ShortPixelAPI::MB_basename($file);
1257
 
1258
  if(file_exists($bkFile)) {
1259
  @rename($bkFile, $file);
@@ -1368,11 +1368,11 @@ class WPShortPixel {
1368
  try {
1369
  $SubDir = ShortPixelMetaFacade::returnSubDir($file, ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
1370
 
1371
- @unlink(SP_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file));
1372
 
1373
  if ( !empty($meta['file']) )
1374
  {
1375
- $filesPath = SP_BACKUP_FOLDER . '/' . $SubDir;//base BACKUP path
1376
  //remove thumbs thumbnails
1377
  if(isset($meta["sizes"])) {
1378
  foreach($meta["sizes"] as $size => $imageData) {
@@ -1474,6 +1474,10 @@ class WPShortPixel {
1474
  <div id="post-body" class="metabox-holder columns-2">
1475
  <div id="post-body-content">
1476
  <div class="meta-box-sortables ui-sortable">
 
 
 
 
1477
  <form method="post" class="shortpixel-table">
1478
  <?php
1479
  $customMediaListTable->display();
@@ -1625,7 +1629,7 @@ class WPShortPixel {
1625
  }
1626
 
1627
  public function emptyBackup(){
1628
- if(file_exists(SP_BACKUP_FOLDER)) {
1629
 
1630
  //extract all images from DB in an array. of course
1631
  $attachments = null;
@@ -1637,19 +1641,19 @@ class WPShortPixel {
1637
 
1638
 
1639
  //delete the actual files on disk
1640
- $this->deleteDir(SP_BACKUP_FOLDER);//call a recursive function to empty files and sub-dirs in backup dir
1641
  }
1642
  }
1643
 
1644
  public function backupFolderIsEmpty() {
1645
- return count(scandir(SP_BACKUP_FOLDER)) > 2 ? false : true;
1646
  }
1647
 
1648
  public function getBackupSize() {
1649
  if ( !current_user_can( 'manage_options' ) ) {
1650
  wp_die(__('You do not have sufficient permissions to access this page.','shortpixel-image-optimiser'));
1651
  }
1652
- die(self::formatBytes(self::folderSize(SP_BACKUP_FOLDER)));
1653
  }
1654
 
1655
  public function browseContent() {
@@ -1708,7 +1712,7 @@ class WPShortPixel {
1708
  $handle = new ShortPixelMetaFacade($_POST['id']);
1709
  $meta = $handle->getMeta();
1710
  $rawMeta = $handle->getRawMeta();
1711
- $backupUrl = content_url() . "/" . SP_UPLOADS_NAME . "/" . SP_BACKUP . "/";
1712
  $uploadsUrl = ShortPixelMetaFacade::getHomeUrl();
1713
  $urlBkPath = ShortPixelMetaFacade::returnSubDir($meta->getPath(), ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
1714
  $ret['origUrl'] = $backupUrl . $urlBkPath . $meta->getName();
@@ -1751,7 +1755,7 @@ class WPShortPixel {
1751
  }
1752
  //echo ("mt: " . $mt);
1753
  //die(var_dump($folder));
1754
- } catch(SpFileRightsException $ex) {
1755
  if(is_array($notice)) {
1756
  if($notice['status'] == 'error') {
1757
  $notice['msg'] .= " " . $ex->getMessage();
@@ -1856,10 +1860,10 @@ class WPShortPixel {
1856
  }
1857
  $this->_settings->verifiedKey = true;
1858
  //test that the "uploads" have the right rights and also we can create the backup dir for ShortPixel
1859
- if ( !file_exists(SP_BACKUP_FOLDER) && !@mkdir(SP_BACKUP_FOLDER, 0777, true) )
1860
  $notice = array("status" => "error",
1861
  "msg" => sprintf(__("There is something preventing us to create a new folder for backing up your original files.<BR>Please make sure that folder <b>%s</b> has the necessary write and read rights.",'shortpixel-image-optimiser'),
1862
- WP_CONTENT_DIR . '/' . SP_UPLOADS_NAME ));
1863
  } else {
1864
  if(isset($_POST['validate'])) {
1865
  //display notification
@@ -2038,7 +2042,7 @@ class WPShortPixel {
2038
 
2039
  $requestURL = $this->_settings->httpProto . '://api.shortpixel.com/v2/api-status.php';
2040
  $args = array(
2041
- 'timeout'=> SP_VALIDATE_MAX_TIMEOUT,
2042
  'body' => array('key' => $apiKey)
2043
  );
2044
  $argsStr = "?key=".$apiKey;
@@ -2124,7 +2128,7 @@ class WPShortPixel {
2124
  }
2125
 
2126
  $data = $response['body'];
2127
- $data = ShortPixelTools::parseJSON($data);
2128
 
2129
  if(empty($data)) { return $defaultData; }
2130
 
@@ -2511,18 +2515,18 @@ class WPShortPixel {
2511
  }
2512
 
2513
  public function migrateBackupFolder() {
2514
- $oldBackupFolder = WP_CONTENT_DIR . '/' . SP_BACKUP;
2515
 
2516
  if(file_exists($oldBackupFolder)) { //if old backup folder does not exist then there is nothing to do
2517
 
2518
- if(!file_exists(SP_BACKUP_FOLDER)) {
2519
  //we check that the backup folder exists, if not we create it so we can copy into it
2520
- if(!mkdir(SP_BACKUP_FOLDER, 0777, true)) return;
2521
  }
2522
 
2523
  $scannedDirectory = array_diff(scandir($oldBackupFolder), array('..', '.'));
2524
  foreach($scannedDirectory as $file) {
2525
- @rename($oldBackupFolder.'/'.$file, SP_BACKUP_FOLDER.'/'.$file);
2526
  }
2527
  $scannedDirectory = array_diff(scandir($oldBackupFolder), array('..', '.'));
2528
  if(empty($scannedDirectory)) {
@@ -2530,22 +2534,22 @@ class WPShortPixel {
2530
  }
2531
  }
2532
  //now if the backup folder does not contain the uploads level, create it
2533
- if( !is_dir(SP_BACKUP_FOLDER . '/' . SP_UPLOADS_NAME )
2534
- && !is_dir(SP_BACKUP_FOLDER . '/' . basename(WP_CONTENT_DIR))) {
2535
- @rename(SP_BACKUP_FOLDER, SP_BACKUP_FOLDER."_tmp");
2536
- @mkdir(SP_BACKUP_FOLDER);
2537
- @rename(SP_BACKUP_FOLDER."_tmp", SP_BACKUP_FOLDER.'/'.SP_UPLOADS_NAME);
2538
- if(!file_exists(SP_BACKUP_FOLDER)) {//just in case..
2539
- @rename(SP_BACKUP_FOLDER."_tmp", SP_BACKUP_FOLDER);
2540
  }
2541
  }
2542
  //then create the wp-content level if not present
2543
- if(!is_dir(SP_BACKUP_FOLDER . '/' . basename(WP_CONTENT_DIR))) {
2544
- @rename(SP_BACKUP_FOLDER, SP_BACKUP_FOLDER."_tmp");
2545
- @mkdir(SP_BACKUP_FOLDER);
2546
- @rename(SP_BACKUP_FOLDER."_tmp", SP_BACKUP_FOLDER.'/' . basename(WP_CONTENT_DIR));
2547
- if(!file_exists(SP_BACKUP_FOLDER)) {//just in case..
2548
- @rename(SP_BACKUP_FOLDER."_tmp", SP_BACKUP_FOLDER);
2549
  }
2550
  }
2551
  return;
25
 
26
  $isAdminUser = current_user_can( 'manage_options' );
27
 
28
+ $this->_affiliateSufix = (strlen(SHORTPIXEL_AFFILIATE_CODE)) ? "/affiliate/" . SHORTPIXEL_AFFILIATE_CODE : "";
29
  $this->_settings = new WPShortPixelSettings();
30
  $this->_apiInterface = new ShortPixelAPI($this->_settings);
31
  $this->hasNextGen = ShortPixelNextGenAdapter::hasNextGen();
143
  public static function shortPixelActivatePlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
144
  {
145
  self::shortPixelDeactivatePlugin();
146
+ if(SHORTPIXEL_RESET_ON_ACTIVATE === true && WP_DEBUG === true) { //force reset plugin counters, only on specific occasions and on test environments
147
  WPShortPixelSettings::debugResetOptions();
148
 
149
  $settings = new WPShortPixelSettings();
515
  }
516
 
517
  public function bulkRestore(){
518
+ global $wpdb;
519
 
520
  $startQueryID = $crtStartQueryID = $this->prioQ->getStartBulkId();
521
  $endQueryID = $this->prioQ->getStopBulkId();
525
  }
526
 
527
  $startTime = time();
528
+ $maxTime = (is_numeric(SHORTPIXEL_MAX_EXECUTION_TIME) && SHORTPIXEL_MAX_EXECUTION_TIME > 10 ? SHORTPIXEL_MAX_EXECUTION_TIME - 5 : 25);
529
+ $maxResults = SHORTPIXEL_MAX_RESULTS_QUERY * 2;
530
  $restored = array();
531
 
532
  //$ind = 0;
578
  WHERE ( post_id <= $crtStartQueryID AND post_id >= $endQueryID )
579
  AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )
580
  ORDER BY post_id DESC
581
+ LIMIT " . SHORTPIXEL_MAX_RESULTS_QUERY;
582
  $resultsPostMeta = $wpdb->get_results($queryPostMeta);
583
  */
584
+ $resultsPostMeta = WpShortPixelMediaLbraryAdapter::getPostMetaSlice($crtStartQueryID, $endQueryID, SHORTPIXEL_MAX_RESULTS_QUERY);
585
 
586
  if ( empty($resultsPostMeta) ) {
587
+ $crtStartQueryID -= SHORTPIXEL_MAX_RESULTS_QUERY;
588
  $startQueryID = $crtStartQueryID;
589
  $this->prioQ->setStartBulkId($startQueryID);
590
  continue;
836
  }
837
 
838
  if(strlen($thumb) && $this->_settings->backupImages && $this->_settings->processThumbnails) {
839
+ $backupUrl = content_url() . "/" . SHORTPIXEL_UPLOADS_NAME . "/" . SHORTPIXEL_BACKUP . "/";
840
  //$urlBkPath = $this->_apiInterface->returnSubDir(get_attached_file($ID));
841
  $urlBkPath = ShortPixelMetaFacade::returnSubDir($meta->getPath(), ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
842
  $bkThumb = $backupUrl . $urlBkPath . $thumb;
863
  } else {
864
  $result["Thumb"] = $thumb = $rootUrl . $meta->getWebPath();
865
  if($this->_settings->backupImages) {
866
+ $result["BkThumb"] = str_replace($rootUrl, $rootUrl. "/" . basename(dirname(dirname(SHORTPIXEL_BACKUP_FOLDER))) . "/" . SHORTPIXEL_UPLOADS_NAME . "/" . SHORTPIXEL_BACKUP . "/", $thumb);
867
  }
868
  }
869
  $this->setBulkInfo($itemId, $result);
873
  }
874
  }
875
  elseif ($result["Status"] == ShortPixelAPI::STATUS_ERROR) {
876
+ if($meta->getRetries() > SHORTPIXEL_MAX_ERR_RETRIES) {
877
  if(! $this->prioQ->remove($itemId) ){
878
  $this->advanceBulk($meta->getId());
879
  }
1108
  $SubDir = ShortPixelMetaFacade::returnSubDir($file, ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
1109
  $SubDirOld = ShortPixelMetaFacade::returnSubDirOld($file, ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
1110
 
1111
+ if ( !file_exists(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file))
1112
+ && !file_exists(SHORTPIXEL_BACKUP_FOLDER . '/' . date("Y") . "/" . date("m") . "/" . ShortPixelAPI::MB_basename($file)) ) {
1113
  $SubDir = $SubDirOld; //maybe the folder was saved with the old method that returned the full path if the wp-content was not inside the root of the site.
1114
  }
1115
+ if ( !file_exists(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file))
1116
+ && !file_exists(SHORTPIXEL_BACKUP_FOLDER . '/' . date("Y") . "/" . date("m") . "/" . ShortPixelAPI::MB_basename($file)) ) {
1117
  $SubDir = trailingslashit(substr(dirname($file), 1)); //try this too
1118
  }
1119
  //sometimes the month of original file and backup can differ
1120
+ if ( !file_exists(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file)) ) {
1121
  $SubDir = date("Y") . "/" . date("m") . "/";
1122
+ if( !file_exists(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file)) ) {
1123
  return false;
1124
  }
1125
  }
1126
+ return SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir;
1127
  }
1128
 
1129
  public function getBackupFolderAny($file, $thumbs) {
1253
 
1254
  $file = $meta->getPath();
1255
  $fullSubDir = str_replace(get_home_path(), "", dirname($file)) . '/';
1256
+ $bkFile = SHORTPIXEL_BACKUP_FOLDER . '/' . $fullSubDir . ShortPixelAPI::MB_basename($file);
1257
 
1258
  if(file_exists($bkFile)) {
1259
  @rename($bkFile, $file);
1368
  try {
1369
  $SubDir = ShortPixelMetaFacade::returnSubDir($file, ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
1370
 
1371
+ @unlink(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file));
1372
 
1373
  if ( !empty($meta['file']) )
1374
  {
1375
+ $filesPath = SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir;//base BACKUP path
1376
  //remove thumbs thumbnails
1377
  if(isset($meta["sizes"])) {
1378
  foreach($meta["sizes"] as $size => $imageData) {
1474
  <div id="post-body" class="metabox-holder columns-2">
1475
  <div id="post-body-content">
1476
  <div class="meta-box-sortables ui-sortable">
1477
+ <form method="get">
1478
+ <input type="hidden" name="page" value="wp-short-pixel-custom" />
1479
+ <?php $customMediaListTable->search_box("Search", "sp_search_file"); ?>
1480
+ </form>
1481
  <form method="post" class="shortpixel-table">
1482
  <?php
1483
  $customMediaListTable->display();
1629
  }
1630
 
1631
  public function emptyBackup(){
1632
+ if(file_exists(SHORTPIXEL_BACKUP_FOLDER)) {
1633
 
1634
  //extract all images from DB in an array. of course
1635
  $attachments = null;
1641
 
1642
 
1643
  //delete the actual files on disk
1644
+ $this->deleteDir(SHORTPIXEL_BACKUP_FOLDER);//call a recursive function to empty files and sub-dirs in backup dir
1645
  }
1646
  }
1647
 
1648
  public function backupFolderIsEmpty() {
1649
+ return count(scandir(SHORTPIXEL_BACKUP_FOLDER)) > 2 ? false : true;
1650
  }
1651
 
1652
  public function getBackupSize() {
1653
  if ( !current_user_can( 'manage_options' ) ) {
1654
  wp_die(__('You do not have sufficient permissions to access this page.','shortpixel-image-optimiser'));
1655
  }
1656
+ die(self::formatBytes(self::folderSize(SHORTPIXEL_BACKUP_FOLDER)));
1657
  }
1658
 
1659
  public function browseContent() {
1712
  $handle = new ShortPixelMetaFacade($_POST['id']);
1713
  $meta = $handle->getMeta();
1714
  $rawMeta = $handle->getRawMeta();
1715
+ $backupUrl = content_url() . "/" . SHORTPIXEL_UPLOADS_NAME . "/" . SHORTPIXEL_BACKUP . "/";
1716
  $uploadsUrl = ShortPixelMetaFacade::getHomeUrl();
1717
  $urlBkPath = ShortPixelMetaFacade::returnSubDir($meta->getPath(), ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
1718
  $ret['origUrl'] = $backupUrl . $urlBkPath . $meta->getName();
1755
  }
1756
  //echo ("mt: " . $mt);
1757
  //die(var_dump($folder));
1758
+ } catch(ShortPixelFileRightsException $ex) {
1759
  if(is_array($notice)) {
1760
  if($notice['status'] == 'error') {
1761
  $notice['msg'] .= " " . $ex->getMessage();
1860
  }
1861
  $this->_settings->verifiedKey = true;
1862
  //test that the "uploads" have the right rights and also we can create the backup dir for ShortPixel
1863
+ if ( !file_exists(SHORTPIXEL_BACKUP_FOLDER) && !@mkdir(SHORTPIXEL_BACKUP_FOLDER, 0777, true) )
1864
  $notice = array("status" => "error",
1865
  "msg" => sprintf(__("There is something preventing us to create a new folder for backing up your original files.<BR>Please make sure that folder <b>%s</b> has the necessary write and read rights.",'shortpixel-image-optimiser'),
1866
+ WP_CONTENT_DIR . '/' . SHORTPIXEL_UPLOADS_NAME ));
1867
  } else {
1868
  if(isset($_POST['validate'])) {
1869
  //display notification
2042
 
2043
  $requestURL = $this->_settings->httpProto . '://api.shortpixel.com/v2/api-status.php';
2044
  $args = array(
2045
+ 'timeout'=> SHORTPIXEL_VALIDATE_MAX_TIMEOUT,
2046
  'body' => array('key' => $apiKey)
2047
  );
2048
  $argsStr = "?key=".$apiKey;
2128
  }
2129
 
2130
  $data = $response['body'];
2131
+ $data = json_decode($data);
2132
 
2133
  if(empty($data)) { return $defaultData; }
2134
 
2515
  }
2516
 
2517
  public function migrateBackupFolder() {
2518
+ $oldBackupFolder = WP_CONTENT_DIR . '/' . SHORTPIXEL_BACKUP;
2519
 
2520
  if(file_exists($oldBackupFolder)) { //if old backup folder does not exist then there is nothing to do
2521
 
2522
+ if(!file_exists(SHORTPIXEL_BACKUP_FOLDER)) {
2523
  //we check that the backup folder exists, if not we create it so we can copy into it
2524
+ if(!mkdir(SHORTPIXEL_BACKUP_FOLDER, 0777, true)) return;
2525
  }
2526
 
2527
  $scannedDirectory = array_diff(scandir($oldBackupFolder), array('..', '.'));
2528
  foreach($scannedDirectory as $file) {
2529
+ @rename($oldBackupFolder.'/'.$file, SHORTPIXEL_BACKUP_FOLDER.'/'.$file);
2530
  }
2531
  $scannedDirectory = array_diff(scandir($oldBackupFolder), array('..', '.'));
2532
  if(empty($scannedDirectory)) {
2534
  }
2535
  }
2536
  //now if the backup folder does not contain the uploads level, create it
2537
+ if( !is_dir(SHORTPIXEL_BACKUP_FOLDER . '/' . SHORTPIXEL_UPLOADS_NAME )
2538
+ && !is_dir(SHORTPIXEL_BACKUP_FOLDER . '/' . basename(WP_CONTENT_DIR))) {
2539
+ @rename(SHORTPIXEL_BACKUP_FOLDER, SHORTPIXEL_BACKUP_FOLDER."_tmp");
2540
+ @mkdir(SHORTPIXEL_BACKUP_FOLDER);
2541
+ @rename(SHORTPIXEL_BACKUP_FOLDER."_tmp", SHORTPIXEL_BACKUP_FOLDER.'/'.SHORTPIXEL_UPLOADS_NAME);
2542
+ if(!file_exists(SHORTPIXEL_BACKUP_FOLDER)) {//just in case..
2543
+ @rename(SHORTPIXEL_BACKUP_FOLDER."_tmp", SHORTPIXEL_BACKUP_FOLDER);
2544
  }
2545
  }
2546
  //then create the wp-content level if not present
2547
+ if(!is_dir(SHORTPIXEL_BACKUP_FOLDER . '/' . basename(WP_CONTENT_DIR))) {
2548
+ @rename(SHORTPIXEL_BACKUP_FOLDER, SHORTPIXEL_BACKUP_FOLDER."_tmp");
2549
+ @mkdir(SHORTPIXEL_BACKUP_FOLDER);
2550
+ @rename(SHORTPIXEL_BACKUP_FOLDER."_tmp", SHORTPIXEL_BACKUP_FOLDER.'/' . basename(WP_CONTENT_DIR));
2551
+ if(!file_exists(SHORTPIXEL_BACKUP_FOLDER)) {//just in case..
2552
+ @rename(SHORTPIXEL_BACKUP_FOLDER."_tmp", SHORTPIXEL_BACKUP_FOLDER);
2553
  }
2554
  }
2555
  return;
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: ShortPixel
3
  Tags: compress, image, compression, optimize, image optimizer, image compression, resize, compress pdf, compress jpg, compress png, image compression
4
  Requires at least: 3.2.0
5
  Tested up to: 4.8
6
- Stable tag: 4.5.5
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -222,6 +222,10 @@ The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Co
222
 
223
  == Changelog ==
224
 
 
 
 
 
225
  = 4.5.5 =
226
  * max thumbs constant - no more than this number of thumbs will be optimized in one pass
227
  * fix problem with webp <picture> tag when using Fusion Builder
3
  Tags: compress, image, compression, optimize, image optimizer, image compression, resize, compress pdf, compress jpg, compress png, image compression
4
  Requires at least: 3.2.0
5
  Tested up to: 4.8
6
+ Stable tag: 4.6.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
222
 
223
  == Changelog ==
224
 
225
+ = 4.6.0 =
226
+ * add a filter option to the Other Media table
227
+ * fixes in order to comply with WP plugin guidelines
228
+
229
  = 4.5.5 =
230
  * max thumbs constant - no more than this number of thumbs will be optimized in one pass
231
  * fix problem with webp <picture> tag when using Fusion Builder
shortpixel-debug.php CHANGED
@@ -1,5 +1,5 @@
1
  <?php
2
- function process_error_backtrace($errno, $errstr, $errfile, $errline, $errcontext) {
3
  if(!(error_reporting() & $errno))
4
  return;
5
  switch($errno) {
@@ -43,5 +43,5 @@ function process_error_backtrace($errno, $errstr, $errfile, $errline, $errcontex
43
  }
44
 
45
  if(WP_DEBUG === true) {
46
- set_error_handler('process_error_backtrace');
47
  }
1
  <?php
2
+ function shortpixel_process_error_backtrace($errno, $errstr, $errfile, $errline, $errcontext) {
3
  if(!(error_reporting() & $errno))
4
  return;
5
  switch($errno) {
43
  }
44
 
45
  if(WP_DEBUG === true) {
46
+ set_error_handler('shortpixel_process_error_backtrace');
47
  }
shortpixel_api.php CHANGED
@@ -121,7 +121,7 @@ class ShortPixelAPI {
121
  */
122
  public function parseResponse($response) {
123
  $data = $response['body'];
124
- $data = ShortPixelTools::parseJSON($data);
125
  return (array)$data;
126
  }
127
 
@@ -167,9 +167,9 @@ class ShortPixelAPI {
167
  }
168
  $apiRetries = $this->_settings->apiRetries;
169
 
170
- if( time() - $startTime > MAX_EXECUTION_TIME)
171
  {//keeps track of time
172
- if ( $apiRetries > MAX_API_RETRIES )//we tried to process this time too many times, giving up...
173
  {
174
  $itemHandler->incrementRetries(1, self::ERR_TIMEOUT, __('Timed out while processing.','shortpixel-image-optimiser'));
175
  $this->_settings->apiRetries = 0; //fai added to solve a bug?
@@ -237,7 +237,7 @@ class ShortPixelAPI {
237
 
238
  $itemHandler->incrementRetries($incR, $err["Code"], $err["Message"]);
239
  $meta = $itemHandler->getMeta();
240
- if($meta->getRetries() >= MAX_FAIL_RETRIES) {
241
  $meta->setStatus($APIresponse[0]->Status->Code);
242
  $meta->setMessage($APIresponse[0]->Status->Message);
243
  $itemHandler->updateMeta($meta);
@@ -426,20 +426,20 @@ class ShortPixelAPI {
426
  {
427
  $source = $PATHs; //array with final paths for these files
428
 
429
- if( !file_exists(SP_BACKUP_FOLDER) && !@mkdir(SP_BACKUP_FOLDER, 0777, true) ) {//creates backup folder if it doesn't exist
430
  return array("Status" => self::STATUS_FAIL, "Message" => __('Backup folder does not exist and it cannot be created','shortpixel-image-optimiser'));
431
  }
432
  //create subdir in backup folder if needed
433
- @mkdir( SP_BACKUP_FOLDER . '/' . $fullSubDir, 0777, true);
434
 
435
  foreach ( $source as $fileID => $filePATH )//create destination files array
436
  {
437
- $destination[$fileID] = SP_BACKUP_FOLDER . '/' . $fullSubDir . self::MB_basename($source[$fileID]);
438
  }
439
- //die("IZ BACKUP: " . SP_BACKUP_FOLDER . '/' . $SubDir . var_dump($destination));
440
 
441
  //now that we have original files and where we should back them up we attempt to do just that
442
- if(is_writable(SP_BACKUP_FOLDER))
443
  {
444
  foreach ( $destination as $fileID => $filePATH )
445
  {
121
  */
122
  public function parseResponse($response) {
123
  $data = $response['body'];
124
+ $data = json_decode($data);
125
  return (array)$data;
126
  }
127
 
167
  }
168
  $apiRetries = $this->_settings->apiRetries;
169
 
170
+ if( time() - $startTime > SHORTPIXEL_MAX_EXECUTION_TIME2)
171
  {//keeps track of time
172
+ if ( $apiRetries > SHORTPIXEL_MAX_API_RETRIES )//we tried to process this time too many times, giving up...
173
  {
174
  $itemHandler->incrementRetries(1, self::ERR_TIMEOUT, __('Timed out while processing.','shortpixel-image-optimiser'));
175
  $this->_settings->apiRetries = 0; //fai added to solve a bug?
237
 
238
  $itemHandler->incrementRetries($incR, $err["Code"], $err["Message"]);
239
  $meta = $itemHandler->getMeta();
240
+ if($meta->getRetries() >= SHORTPIXEL_MAX_FAIL_RETRIES) {
241
  $meta->setStatus($APIresponse[0]->Status->Code);
242
  $meta->setMessage($APIresponse[0]->Status->Message);
243
  $itemHandler->updateMeta($meta);
426
  {
427
  $source = $PATHs; //array with final paths for these files
428
 
429
+ if( !file_exists(SHORTPIXEL_BACKUP_FOLDER) && !@mkdir(SHORTPIXEL_BACKUP_FOLDER, 0777, true) ) {//creates backup folder if it doesn't exist
430
  return array("Status" => self::STATUS_FAIL, "Message" => __('Backup folder does not exist and it cannot be created','shortpixel-image-optimiser'));
431
  }
432
  //create subdir in backup folder if needed
433
+ @mkdir( SHORTPIXEL_BACKUP_FOLDER . '/' . $fullSubDir, 0777, true);
434
 
435
  foreach ( $source as $fileID => $filePATH )//create destination files array
436
  {
437
+ $destination[$fileID] = SHORTPIXEL_BACKUP_FOLDER . '/' . $fullSubDir . self::MB_basename($source[$fileID]);
438
  }
439
+ //die("IZ BACKUP: " . SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . var_dump($destination));
440
 
441
  //now that we have original files and where we should back them up we attempt to do just that
442
+ if(is_writable(SHORTPIXEL_BACKUP_FOLDER))
443
  {
444
  foreach ( $destination as $fileID => $filePATH )
445
  {
wp-shortpixel.php CHANGED
@@ -3,49 +3,48 @@
3
  * Plugin Name: ShortPixel Image Optimizer
4
  * Plugin URI: https://shortpixel.com/
5
  * Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="options-general.php?page=wp-shortpixel" target="_blank">Settings &gt; ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
6
- * Version: 4.5.5
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  * Text Domain: shortpixel-image-optimiser
10
  * Domain Path: /lang
11
  */
12
 
13
- define('SP_RESET_ON_ACTIVATE', false); //if true TODO set false
14
  //define('SHORTPIXEL_DEBUG', true);
15
 
16
  define('SHORTPIXEL_PLUGIN_FILE', __FILE__);
17
 
18
- define('SP_AFFILIATE_CODE', '');
19
 
20
- define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "4.5.5");
21
- define('SP_MAX_TIMEOUT', 10);
22
- define('SP_VALIDATE_MAX_TIMEOUT', 15);
23
- define('SP_BACKUP', 'ShortpixelBackups');
24
- define('MAX_API_RETRIES', 50);
25
- define('MAX_ERR_RETRIES', 5);
26
- define('MAX_FAIL_RETRIES', 3);
27
  define('SHORTPIXEL_MAX_THUMBS', 100);
28
 
29
- $MAX_EXECUTION_TIME = ini_get('max_execution_time');
30
 
31
  require_once(ABSPATH . 'wp-admin/includes/file.php');
32
 
33
  $sp__uploads = wp_upload_dir();
34
- define('SP_UPLOADS_BASE', $sp__uploads['basedir']);
35
- define('SP_UPLOADS_NAME', basename(is_main_site() ? SP_UPLOADS_BASE : dirname(dirname(SP_UPLOADS_BASE))));
36
- define('SP_UPLOADS_BASE_REL', str_replace(get_home_path(),"", $sp__uploads['basedir']));
37
- $sp__backupBase = is_main_site() ? SP_UPLOADS_BASE : dirname(dirname(SP_UPLOADS_BASE));
38
- define('SP_BACKUP_FOLDER', $sp__backupBase . '/' . SP_BACKUP);
39
 
40
  /*
41
- if ( is_numeric($MAX_EXECUTION_TIME) && $MAX_EXECUTION_TIME > 10 )
42
- define('MAX_EXECUTION_TIME', $MAX_EXECUTION_TIME - 5 ); //in seconds
43
  else
44
- define('MAX_EXECUTION_TIME', 25 );
45
  */
46
 
47
- define('MAX_EXECUTION_TIME', 2 );
48
- define("SP_MAX_RESULTS_QUERY", 6);
49
 
50
  function shortpixelInit() {
51
  global $pluginInstance;
@@ -67,7 +66,7 @@ function shortpixelInit() {
67
  }
68
  }
69
 
70
- function handleImageUploadHook($meta, $ID = null) {
71
  global $pluginInstance;
72
  if(!isset($pluginInstance)) {
73
  require_once('wp-shortpixel-req.php');
@@ -76,7 +75,7 @@ function handleImageUploadHook($meta, $ID = null) {
76
  return $pluginInstance->handleMediaLibraryImageUpload($meta, $ID);
77
  }
78
 
79
- function shortpixelNggAdd($image) {
80
  global $pluginInstance;
81
  if(!isset($pluginInstance)) {
82
  require_once('wp-shortpixel-req.php');
@@ -96,12 +95,11 @@ function shortPixelDeactivatePlugin () {
96
  }
97
 
98
  //Picture generation, hooked on the_content filter
99
- function spConvertImgToPictureAddWebp($content) {
100
  require_once('class/front/img-to-picture-webp.php');
101
- //require_once('class/responsive-image.php');
102
- return ImgToPictureWebp::convert($content) . "<!-- PICTURE TAGS BY SHORTPIXEL -->";
103
  }
104
- function spAddPictureJs() {
105
  // Don't do anything with the RSS feed.
106
  if ( is_feed() || is_admin() ) { return; }
107
 
@@ -116,23 +114,22 @@ function spAddPictureJs() {
116
  . '}'
117
  . '</script>';
118
  }
119
- //function spAddPicturefillJs() {
120
- // wp_enqueue_script( 'picturefill', plugins_url('/res/js/picturefill.min.js', __FILE__), null, null, true);
121
- //}
122
  if ( get_option('wp-short-pixel-create-webp-markup')) {
123
- add_filter( 'the_content', 'spConvertImgToPictureAddWebp', 10000 ); // priority big, so it will be executed last
124
- add_action( 'wp_head', 'spAddPictureJs');
 
125
  // add_action( 'wp_enqueue_scripts', 'spAddPicturefillJs' );
126
  }
127
 
128
 
129
  if ( !function_exists( 'vc_action' ) || vc_action() !== 'vc_inline' ) { //handle incompatibility with Visual Composer
130
  add_action( 'init', 'shortpixelInit');
131
- add_action('ngg_added_new_image', 'shortpixelNggAdd');
132
 
133
  $autoMediaLibrary = get_option('wp-short-pixel-auto-media-library');
134
  if($autoMediaLibrary) {
135
- add_filter( 'wp_generate_attachment_metadata', 'handleImageUploadHook', 10, 2 );
136
  }
137
 
138
  register_activation_hook( __FILE__, 'shortPixelActivatePlugin' );
3
  * Plugin Name: ShortPixel Image Optimizer
4
  * Plugin URI: https://shortpixel.com/
5
  * Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="options-general.php?page=wp-shortpixel" target="_blank">Settings &gt; ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
6
+ * Version: 4.6.0
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  * Text Domain: shortpixel-image-optimiser
10
  * Domain Path: /lang
11
  */
12
 
13
+ define('SHORTPIXEL_RESET_ON_ACTIVATE', false); //if true TODO set false
14
  //define('SHORTPIXEL_DEBUG', true);
15
 
16
  define('SHORTPIXEL_PLUGIN_FILE', __FILE__);
17
 
18
+ define('SHORTPIXEL_AFFILIATE_CODE', '');
19
 
20
+ define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "4.6.0");
21
+ define('SHORTPIXEL_MAX_TIMEOUT', 10);
22
+ define('SHORTPIXEL_VALIDATE_MAX_TIMEOUT', 15);
23
+ define('SHORTPIXEL_BACKUP', 'ShortpixelBackups');
24
+ define('SHORTPIXEL_MAX_API_RETRIES', 50);
25
+ define('SHORTPIXEL_MAX_ERR_RETRIES', 5);
26
+ define('SHORTPIXEL_MAX_FAIL_RETRIES', 3);
27
  define('SHORTPIXEL_MAX_THUMBS', 100);
28
 
29
+ define('SHORTPIXEL_MAX_EXECUTION_TIME', ini_get('max_execution_time'));
30
 
31
  require_once(ABSPATH . 'wp-admin/includes/file.php');
32
 
33
  $sp__uploads = wp_upload_dir();
34
+ define('SHORTPIXEL_UPLOADS_BASE', $sp__uploads['basedir']);
35
+ define('SHORTPIXEL_UPLOADS_NAME', basename(is_main_site() ? SHORTPIXEL_UPLOADS_BASE : dirname(dirname(SHORTPIXEL_UPLOADS_BASE))));
36
+ $sp__backupBase = is_main_site() ? SHORTPIXEL_UPLOADS_BASE : dirname(dirname(SHORTPIXEL_UPLOADS_BASE));
37
+ define('SHORTPIXEL_BACKUP_FOLDER', $sp__backupBase . '/' . SHORTPIXEL_BACKUP);
 
38
 
39
  /*
40
+ if ( is_numeric(SHORTPIXEL_MAX_EXECUTION_TIME) && SHORTPIXEL_MAX_EXECUTION_TIME > 10 )
41
+ define('SHORTPIXEL_MAX_EXECUTION_TIME', SHORTPIXEL_MAX_EXECUTION_TIME - 5 ); //in seconds
42
  else
43
+ define('SHORTPIXEL_MAX_EXECUTION_TIME', 25 );
44
  */
45
 
46
+ define('SHORTPIXEL_MAX_EXECUTION_TIME2', 2 );
47
+ define("SHORTPIXEL_MAX_RESULTS_QUERY", 6);
48
 
49
  function shortpixelInit() {
50
  global $pluginInstance;
66
  }
67
  }
68
 
69
+ function shortPixelHandleImageUploadHook($meta, $ID = null) {
70
  global $pluginInstance;
71
  if(!isset($pluginInstance)) {
72
  require_once('wp-shortpixel-req.php');
75
  return $pluginInstance->handleMediaLibraryImageUpload($meta, $ID);
76
  }
77
 
78
+ function shortPixelNggAdd($image) {
79
  global $pluginInstance;
80
  if(!isset($pluginInstance)) {
81
  require_once('wp-shortpixel-req.php');
95
  }
96
 
97
  //Picture generation, hooked on the_content filter
98
+ function shortPixelConvertImgToPictureAddWebp($content) {
99
  require_once('class/front/img-to-picture-webp.php');
100
+ return ShortPixelImgToPictureWebp::convert($content) . "<!-- PICTURE TAGS BY SHORTPIXEL -->";
 
101
  }
102
+ function shortPixelAddPictureJs() {
103
  // Don't do anything with the RSS feed.
104
  if ( is_feed() || is_admin() ) { return; }
105
 
114
  . '}'
115
  . '</script>';
116
  }
117
+
 
 
118
  if ( get_option('wp-short-pixel-create-webp-markup')) {
119
+ add_filter( 'the_content', 'shortPixelConvertImgToPictureAddWebp', 10000 ); // priority big, so it will be executed last
120
+ add_filter( 'post_thumbnail_html', 'shortPixelConvertImgToPictureAddWebp');
121
+ add_action( 'wp_head', 'shortPixelAddPictureJs');
122
  // add_action( 'wp_enqueue_scripts', 'spAddPicturefillJs' );
123
  }
124
 
125
 
126
  if ( !function_exists( 'vc_action' ) || vc_action() !== 'vc_inline' ) { //handle incompatibility with Visual Composer
127
  add_action( 'init', 'shortpixelInit');
128
+ add_action('ngg_added_new_image', 'shortPixelNggAdd');
129
 
130
  $autoMediaLibrary = get_option('wp-short-pixel-auto-media-library');
131
  if($autoMediaLibrary) {
132
+ add_filter( 'wp_generate_attachment_metadata', 'shortPixelHandleImageUploadHook', 10, 2 );
133
  }
134
 
135
  register_activation_hook( __FILE__, 'shortPixelActivatePlugin' );