WebP Express - Version 0.7.0

Version Description

This version added option to provide conversion service to other sites!

For more info, see the closed issues on the 0.7.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.7.0

=

Download this release

Release Info

Developer rosell.dk
Plugin Icon 128x128 WebP Express
Version 0.7.0
Comparing to
See all releases

Code changes from version 0.6.2 to 0.7.0

README.md CHANGED
@@ -5,18 +5,18 @@ Serve autogenerated WebP images instead of jpeg/png to browsers that supports We
5
  The plugin is available on the Wordpress codex ([here](https://wordpress.org/plugins/webp-express/)), and developed on github ([here](https://github.com/rosell-dk/webp-express/)).
6
 
7
  ## Description
8
-
9
- This plugin let's you take advantage of the WebP image format with only a little effort. Install, configure, test, forget - and enjoy the increased performance of your website.
10
 
11
  The plugin basically routes jpeg/png images to an image converter, or - if the image converter has already converted the image - directly to a converted image. The approach has the benefit that is works regardless of how an image found its way into your server - be it Media Library, Galleries, or even theme images referenced with CSS.
12
 
13
  The plugin builds on [WebPConvert](https://github.com/rosell-dk/webp-convert) and its "WebP On Demand" solution described [here](https://github.com/rosell-dk/webp-convert/blob/master/docs/webp-on-demand/webp-on-demand.md)
14
 
15
  #### Benefits
16
- - Much faster load time for images in blink based browsers such as Chrome and Opera (accounting for ~73% of all traffic, according to [caniuse.com](https://caniuse.com/webp)). The converted images are typically *less than half the size* (for jpeg), while maintaining the same quality. Bear in mind that for most web sites, images are responsible for the largest part of the waiting time.
 
17
  - Better user experience (whether performance goes from terrible to bad, or from good to impressive, it is a benefit)
18
  - Better ranking in Google searches (performance is taken into account by Google)
19
- - Less bandwidth consumption - makes a difference when abroad and in the parts of the world with slow and expensive internet connections.
20
 
21
 
22
  ## Installation
@@ -26,20 +26,30 @@ The plugin builds on [WebPConvert](https://github.com/rosell-dk/webp-convert) an
26
  3. Configure it (the plugin doesn't do anything until configured)
27
  4. Verify that it works
28
 
 
29
  You configure the plugin in *Settings > WebP Express*.
30
 
31
- WebPExpress uses [WebPConvert](https://github.com/rosell-dk/webp-convert) to convert images. This is how WebPConvert describes itself:
 
32
 
33
- *The current state of WebP conversion in PHP is this: There are several ways to do it, but they all require something of the server setup. What works on one shared host might not work on another. WebPConvert combines these methods by iterating over them (optionally in the desired order) until one of them is successful - or all of them fail.*
 
 
 
 
34
 
35
- These different converting methods are called *converters*.
 
36
 
37
- The best converter is *cwebp*. So the first thing you should do is test whether the cwebp converter is working. Simply click "test" next to the converter. If it doesn't work, you can disable that converter (or try to make it work, by changing the server setup).
38
- The next converter to try is *wpc*, which is equally good as cwebp in terms of quality / filesize ratio, but which is slower. wpc is an open source cloud service, which you will have to install on some other server. If this is too much work, continue to the next converter. In the converter settings, you can read about the individual converters. You can also head to the WebPConvert readme for more information.
 
 
39
 
 
40
  Once, you have a converter, that works, when you click the "test"-button, you are ready to test the whole stack, and the rewrite rules. To do this, first make sure to select something other than "Do not convert any images!" in *Image types to convert*. Next, click "Save settings". This will save settings, as well as update the *.htaccess*.
41
 
42
- If you are working in a browser that supports webp (ie Google Chrome), you will see a link "Convert test image (show debug)" after a successful save. Click that to test if it works. The screen should show a textual report of the conversion process. If it shows an image, it means that the *.htaccess* redirection isn't working. It may be that your server just needs some time. Some servers has set up caching.
43
 
44
  Note that the plugin does not change any HTML. In the HTML the image src is still set to ie "example.jpg". To verify that the plugin is working (without clicking the test button), do the following:
45
 
@@ -68,8 +78,7 @@ The plugin has not been tested in multisite configurations. It's on the roadmap.
68
  ## Limitations
69
 
70
  * The plugin does not work on Microsoft IIS server
71
- * The plugin has not been tested with multisite installation (it is on the roadmap!).
72
- * There might be compatability issues with other plugins. For example *.htaccess* rules from other plugins might interfere.
73
 
74
  ## Frequently Asked Questions
75
 
@@ -82,28 +91,9 @@ Chances are that the default setting of your CDN is not to forward any headers t
82
  The plugin takes care of setting the "Vary" HTTP header to "Accept" when routing WebP images. When the CDN sees this, it knows that the response varies, depending on the "Accept" header. The CDN is thus instructed not to cache the response on URL only, but also on the "Accept" header. This means that it will store an image for every accept header it meets. Luckily, there are (not that many variants for images)[https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values#Values_for_an_image], so it is not an issue.
83
 
84
  ### How do I donate?
85
- Putting this question in the "frequently" asked questions section is of course some mixture of humour, sarcasm and wishful thinking. In case there really is someone out there wanting to donate, you can simply write to me, and we can arrange. My contact information is available here https://www.bitwise-it.dk/contact. I have paypal and of course an ordinary bank account.
86
-
87
- ## Changes in 0.6.0
88
- This version added option for setting caching header, fixed a serious issue with *Imagick*, added a new converter, *Gmagick*, added a great deal of options to *Cwebp* and generally improved the interface.
89
-
90
- * Added option for caching
91
- * Fixed long standing and serious issue with Imagick converter. It no longer generates webp images in poor quality
92
- * Added gmagick as a new conversion method
93
- * WebPExpress now runs on newly released WebP-Convert 1.2.0
94
- * Added many new options for *cwebp*
95
- * You can now quickly see converter status by hovering over a converter
96
- * You can now choose between having quality auto-detected or not (if the server supports detecting quality).
97
- * If the server does not support detecting quality, the WPC converter will display a quality "auto" option
98
- * Added special intro message for those who has no working conversion methods
99
- * Added help texts for options
100
- * Settings are now saved, when changing converter options. Too many times, I found myself forgetting to save...
101
-
102
- For more info, see the closed issues on the 0.6.0 milestone on our github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.6.0
103
-
104
- # Roadmap
105
-
106
- * Share converter with other sites. Optionally provide conversion service for other sites, which will be able to connect to it using the "wpc" converter.
107
- * Test on multisite
108
- * Display whether the server is able to detect quality of jpegs or not
109
- * Make the fallback quality configurable (the quality to use, when quality of source file cannot be determined)
5
  The plugin is available on the Wordpress codex ([here](https://wordpress.org/plugins/webp-express/)), and developed on github ([here](https://github.com/rosell-dk/webp-express/)).
6
 
7
  ## Description
8
+ Almost 4 out of 5 mobile users use a browser that is able to display webp images. Yet, on most websites, they are served jpeg images, which are typically double the size of webp images for a given quality. What a waste of bandwidth! This plugin was created to help remedy that situation. With little effort, Wordpress admins can have their site serving autogenerated webp images to browsers that supports it, while still serving jpeg and png files to browsers that does not support webp.
 
9
 
10
  The plugin basically routes jpeg/png images to an image converter, or - if the image converter has already converted the image - directly to a converted image. The approach has the benefit that is works regardless of how an image found its way into your server - be it Media Library, Galleries, or even theme images referenced with CSS.
11
 
12
  The plugin builds on [WebPConvert](https://github.com/rosell-dk/webp-convert) and its "WebP On Demand" solution described [here](https://github.com/rosell-dk/webp-convert/blob/master/docs/webp-on-demand/webp-on-demand.md)
13
 
14
  #### Benefits
15
+ - Much faster load time for images in blink based browsers such as Chrome and Opera (overall accounting for ~73% of all traffic, and ~78% of mobile browsing trafic, according to [caniuse.com](https://caniuse.com/webp)).
16
+ - The converted images are typically *less than half the size* (for jpeg), while maintaining the same quality. Bear in mind that for most web sites, images are responsible for the largest part of the waiting time.
17
  - Better user experience (whether performance goes from terrible to bad, or from good to impressive, it is a benefit)
18
  - Better ranking in Google searches (performance is taken into account by Google)
19
+ - Less bandwidth consumption - makes a huge difference in the parts of the world where the internet is slow and costly (you know, ~80% of the world population lives under these circumstances).
20
 
21
 
22
  ## Installation
26
  3. Configure it (the plugin doesn't do anything until configured)
27
  4. Verify that it works
28
 
29
+ ### Configuring
30
  You configure the plugin in *Settings > WebP Express*.
31
 
32
+ #### Conversion methods
33
+ WebP Express has a bunch of methods available for converting images: Executing cwebp binary, Gd extension, Imagick extension, ewww cloud converter and remote WebP express. Each requires *something*. In many cases, one of the conversion methods will be available. You can quickly identify which converters are working - there is a green icon next to them. Hovering conversion methods that are not working will show you what is wrong.
34
 
35
+ In case no conversion methods are working out of the box, you have several options:
36
+ - You can install this plugin on another website, which supports a local conversion method and connect to that using the "Remote WebP Express" conversion method
37
+ - You can [purchase a key](https://ewww.io/plans/) for the ewww cloud converter. They do not charge credits for webp conversions, so all you ever have to pay is the one dollar start-up fee :)
38
+ - You can set up [webp-convert-cloud-service](https://github.com/rosell-dk/webp-convert-cloud-service) on another server and connect to that. Its open source.
39
+ - You can try to meet the server requirements of cwebp, gd, imagick or gmagick. Check out [this wiki page](https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters) on how to do that
40
 
41
+ ### The auto quality
42
+ If your server has imagick og gmagick installed, the plugin will be able to detect the quality of a jpeg, and use the same quality for the converted webp. You can tell if it does, by looking at the quality option. If it allows you to select "auto" quality, it is available, otherwise it is not, and you will only have the option to set a specific quality for all conversions. *Auto* should be chosen, if available, as this ensures that each conversion are converted with an appropriate quality. Say you have a jpeg with low quality (say 30). The best result, is achieved by converting it to the same quality. Converting it with high quality (say 80), will not get you better quality, only a larger file.
43
 
44
+ If you do not the "auto" option available:
45
+ - Install imagick or gmagick, if you can
46
+ - Use "Remote WebP Express" converter to connect to a site, that *does* have the auto option available
47
+ - If you have cwebp converter available, you can configure it to aim for a certain reduction, rather than using the quality parameter. Set this to for example 50%, or even 45%.
48
 
49
+ ### Verifying that it works.
50
  Once, you have a converter, that works, when you click the "test"-button, you are ready to test the whole stack, and the rewrite rules. To do this, first make sure to select something other than "Do not convert any images!" in *Image types to convert*. Next, click "Save settings". This will save settings, as well as update the *.htaccess*.
51
 
52
+ If you are working in a browser that supports webp (ie Google Chrome), you will see a link "Convert test image (show debug)" after a successful save. Click that to test if it works. The screen should show a textual report of the conversion process. If it shows an image, it means that the *.htaccess* redirection isn't working. It may be that your server just needs some time. Some servers has set up caching. It could also be that your images are handled by nginx.
53
 
54
  Note that the plugin does not change any HTML. In the HTML the image src is still set to ie "example.jpg". To verify that the plugin is working (without clicking the test button), do the following:
55
 
78
  ## Limitations
79
 
80
  * The plugin does not work on Microsoft IIS server
81
+ * The plugin has not been tested with multisite installation
 
82
 
83
  ## Frequently Asked Questions
84
 
91
  The plugin takes care of setting the "Vary" HTTP header to "Accept" when routing WebP images. When the CDN sees this, it knows that the response varies, depending on the "Accept" header. The CDN is thus instructed not to cache the response on URL only, but also on the "Accept" header. This means that it will store an image for every accept header it meets. Luckily, there are (not that many variants for images)[https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values#Values_for_an_image], so it is not an issue.
92
 
93
  ### How do I donate?
94
+ Putting this question in the "frequently" asked questions section is of course some mixture of humour, sarcasm and wishful thinking. In case there really is someone out there wanting to donate, you can simply write to me, and we can arrange. My contact information is available here https://www.bitwise-it.dk/contact. I have paypal, mobilepay and of course an ordinary bank account.
95
+
96
+ ## Changes in 0.7.0
97
+ This version added option to provide conversion service to other sites!
98
+
99
+ For more info, see the closed issues on the 0.7.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.7.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
README.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.bitwise-it.dk/contact
4
  Tags: webp, images, performance
5
  Requires at least: 4.0
6
  Tested up to: 4.9
7
- Stable tag: 0.6.2
8
  Requires PHP: 5.6
9
  License: GPLv3
10
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
@@ -13,7 +13,7 @@ Serve autogenerated WebP images instead of jpeg/png to browsers that supports We
13
 
14
  == Description ==
15
 
16
- This plugin let's you take advantage of the WebP image format with only a little effort. Install, configure, test, forget - and enjoy the increased performance of your website.
17
 
18
  The plugin basically routes jpeg/png images to an image converter, or - if the image converter has already converted the image - directly to a converted image. The approach has the benefit that is works regardless of how an image found its way into your server - be it Media Library, Galleries, or even theme images referenced with CSS.
19
 
@@ -33,34 +33,25 @@ The plugin builds on [WebPConvert](https://github.com/rosell-dk/webp-convert) an
33
  3. Configure it (the plugin doesn't do anything until configured)
34
  4. Verify that it works
35
 
36
- You configure the plugin in Settings > WebP Express.
 
37
 
38
- WebPExpress uses WebPConvert (https://github.com/rosell-dk/webp-convert) to convert images. This is how WebPConvert describes itself:
 
39
 
40
- "The current state of WebP conversion in PHP is this: There are several ways to do it, but they all require something of the server setup. What works on one shared host might not work on another. WebPConvert combines these methods by iterating over them (optionally in the desired order) until one of them is successful - or all of them fail."
 
 
 
 
41
 
42
- WebPConvert calls these different converting methods "converters".
 
43
 
44
- The best converter is cwebp. So the first thing you should do is test whether the cwebp converter is working. Simply click "test" next to the converter. If it doesn't work, you can disable that converter (or try to make it work, by changing the server setup).
45
-
46
- The next converter to try is wpc, which is equally good as cwebp in terms of quality / filesize ratio, but which is slower. wpc is an open source cloud service, which you will have to install on some other server. It is btw on the roadmap to have this plugin provide the same service. If installing wpc too much work, continue to the next converter. I will not go through all of them here; you can learn more by clicking on the "configure" button on a converter. You can also head to the WebPConvert project for more information.
47
-
48
- Once, you have a converter, that works, when you click the "test"-button, you are ready to test the whole stack, and the rewrite rules. To do this, first make sure to select something other than "Do not convert any images!" in "Image types to convert". Next, click "Save settings". This will save settings, as well as update the *.htaccess*.
49
-
50
- If you are working in a browser that supports webp (ie Google Chrome), you will see a link "Convert test image (show debug)" after a successful save. Click that to test if it works. The screen should show a textual report of the conversion process. If it shows an image, it means that the *.htaccess* redirection isn't working. It may be that your server just needs some time. Some servers has set up caching.
51
-
52
- Note that the plugin does not change any HTML. In the HTML the image src is still set to ie "example.jpg". To verify that the plugin is working (without clicking the test button), do the following:
53
-
54
- - Open the page in Google Chrome
55
- - Right-click the page and choose "Inspect"
56
- - Click the "Network" tab
57
- - Reload the page
58
- - Find a jpeg or png image in the list. In the "type" column, it should say "webp"
59
-
60
- In order to test that the image is not being reconverted every time, look at the Response headers of the image. There should be a "X-WebP-Convert-Status" header. It should say "Serving existing converted image" the first time, but "Serving existing converted image" on subsequent requests (WebP-Express is based upon [WebP Convert](https://github.com/rosell-dk/webp-convert)).
61
-
62
- You can also append ?debug after any image url, in order to run a conversion, and see the conversion report.
63
- Also, you append ?reconvert after an image url, you will force a reconversion of the image.
64
 
65
  ### Notes
66
 
@@ -92,7 +83,7 @@ https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_de
92
  - so it is not an issue.
93
 
94
  = How do I donate? =
95
- Putting this question in the "frequently" asked questions section is of course some mixture of humour, sarcasm and wishful thinking. In case there really is someone out there wanting to donate, you can simply write to me, and we can arrange. My contact information is available here https://www.bitwise-it.dk/contact. I have paypal and of course an ordinary bank account.
96
 
97
  == Screenshots ==
98
 
@@ -100,29 +91,12 @@ Putting this question in the "frequently" asked questions section is of course s
100
 
101
  == Changelog ==
102
 
103
- = 0.6.0 =
104
- This version added option for setting caching header, fixed a serious issue with *Imagick*, added a new converter, *Gmagick*, added a great deal of options to *Cwebp* and generally improved the interface.
105
-
106
- * Added option for caching
107
- * Fixed long standing and serious issue with Imagick converter. It no longer generates webp images in poor quality
108
- * Added gmagick as a new conversion method
109
- * WebPExpress now runs on newly released WebP-Convert 1.2.0
110
- * Added many new options for *cwebp*
111
- * You can now quickly see converter status by hovering over a converter
112
- * You can now choose between having quality auto-detected or not (if the server supports detecting quality).
113
- * If the server does not support detecting quality, the WPC converter will display a quality "auto" option
114
- * Added special intro message for those who has no working conversion methods
115
- * Added help texts for options
116
- * Settings are now saved, when changing converter options. Too many times, I found myself forgetting to save...
117
 
118
- For more info, see the closed issues on the 0.6.0 milestone on our github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.6.0
119
 
120
  == Upgrade Notice ==
121
 
122
- = 0.6.0 =
123
- Adding caching option, fixed imagick converter, added gmagick converter and more!
124
-
125
- == Roadmap ==
126
-
127
- * Share converter with other sites. Optionally provide conversion service for other sites, which will be able to connect to it using the "wpc" converter.
128
- * Support multisite setups
4
  Tags: webp, images, performance
5
  Requires at least: 4.0
6
  Tested up to: 4.9
7
+ Stable tag: 0.7.0
8
  Requires PHP: 5.6
9
  License: GPLv3
10
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
13
 
14
  == Description ==
15
 
16
+ Almost 4 out of 5 mobile users use a browser that is able to display webp images. Yet, on most websites, they are served jpeg images, which are typically double the size of webp images for a given quality. What a waste of bandwidth! This plugin was created to help remedy that situation. With little effort, Wordpress admins can have their site serving autogenerated webp images to browsers that supports it, while still serving jpeg and png files to browsers that does not support webp.
17
 
18
  The plugin basically routes jpeg/png images to an image converter, or - if the image converter has already converted the image - directly to a converted image. The approach has the benefit that is works regardless of how an image found its way into your server - be it Media Library, Galleries, or even theme images referenced with CSS.
19
 
33
  3. Configure it (the plugin doesn't do anything until configured)
34
  4. Verify that it works
35
 
36
+ ### Configuring
37
+ You configure the plugin in *Settings > WebP Express*.
38
 
39
+ #### Conversion methods
40
+ WebP Express has a bunch of methods available for converting images: Executing cwebp binary, Gd extension, Imagick extension, ewww cloud converter and remote WebP express. Each requires *something*. In many cases, one of the conversion methods will be available. You can quickly identify which converters are working - there is a green icon next to them. Hovering conversion methods that are not working will show you what is wrong.
41
 
42
+ In case no conversion methods are working out of the box, you have several options:
43
+ - You can install this plugin on another website, which supports a local conversion method and connect to that using the "Remote WebP Express" conversion method
44
+ - You can [purchase a key](https://ewww.io/plans/) for the ewww cloud converter. They do not charge credits for webp conversions, so all you ever have to pay is the one dollar start-up fee :)
45
+ - You can set up [webp-convert-cloud-service](https://github.com/rosell-dk/webp-convert-cloud-service) on another server and connect to that. Its open source.
46
+ - You can try to meet the server requirements of cwebp, gd, imagick or gmagick. Check out [this wiki page](https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters) on how to do that
47
 
48
+ ### The auto quality
49
+ If your server has imagick og gmagick installed, the plugin will be able to detect the quality of a jpeg, and use the same quality for the converted webp. You can tell if it does, by looking at the quality option. If it allows you to select "auto" quality, it is available, otherwise it is not, and you will only have the option to set a specific quality for all conversions. *Auto* should be chosen, if available, as this ensures that each conversion are converted with an appropriate quality. Say you have a jpeg with low quality (say 30). The best result, is achieved by converting it to the same quality. Converting it with high quality (say 80), will not get you better quality, only a larger file.
50
 
51
+ If you do not the "auto" option available:
52
+ - Install imagick or gmagick, if you can
53
+ - Use "Remote WebP Express" converter to connect to a site, that *does* have the auto option available
54
+ - If you have cwebp converter available, you can configure it to aim for a certain reduction, rather than using the quality parameter. Set this to for example 50%, or even 45%.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
  ### Notes
57
 
83
  - so it is not an issue.
84
 
85
  = How do I donate? =
86
+ Putting this question in the "frequently" asked questions section is of course some mixture of humour, sarcasm and wishful thinking. In case there really is someone out there wanting to donate, you can simply write to me, and we can arrange. My contact information is available here https://www.bitwise-it.dk/contact. I have paypal, mobilepay and of course an ordinary bank account.
87
 
88
  == Screenshots ==
89
 
91
 
92
  == Changelog ==
93
 
94
+ = 0.7.0 =
95
+ This version added option to provide conversion service to other sites!
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
+ For more info, see the closed issues on the 0.7.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.7.0
98
 
99
  == Upgrade Notice ==
100
 
101
+ = 0.7.0 =
102
+ This version added option to provide conversion service to other sites!
 
 
 
 
 
changelog.txt CHANGED
@@ -1,3 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 0.5.0 =
2
  This version works on many more setups than the previous. Also uses less resources and handles when images are changed.
3
 
1
+ = 0.6.0 =
2
+ This version added option for setting caching header, fixed a serious issue with *Imagick*, added a new converter, *Gmagick*, added a great deal of options to *Cwebp* and generally improved the interface.
3
+
4
+ * Added option for caching
5
+ * Fixed long standing and serious issue with Imagick converter. It no longer generates webp images in poor quality
6
+ * Added gmagick as a new conversion method
7
+ * WebPExpress now runs on newly released WebP-Convert 1.2.0
8
+ * Added many new options for *cwebp*
9
+ * You can now quickly see converter status by hovering over a converter
10
+ * You can now choose between having quality auto-detected or not (if the server supports detecting quality).
11
+ * If the server does not support detecting quality, the WPC converter will display a quality "auto" option
12
+ * Added special intro message for those who has no working conversion methods
13
+ * Added help texts for options
14
+ * Settings are now saved, when changing converter options. Too many times, I found myself forgetting to save...
15
+
16
+ For more info, see the closed issues on the 0.6.0 milestone on our github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.6.0
17
+
18
  = 0.5.0 =
19
  This version works on many more setups than the previous. Also uses less resources and handles when images are changed.
20
 
composer.json CHANGED
@@ -4,9 +4,14 @@
4
  {
5
  "type": "vcs",
6
  "url": "https://github.com/rosell-dk/webp-convert"
 
 
 
 
7
  }
8
  ],
9
  "require": {
10
- "rosell-dk/webp-convert": "dev-master"
 
11
  }
12
  }
4
  {
5
  "type": "vcs",
6
  "url": "https://github.com/rosell-dk/webp-convert"
7
+ },
8
+ {
9
+ "type": "vcs",
10
+ "url": "https://github.com/rosell-dk/webp-convert-cloud-service"
11
  }
12
  ],
13
  "require": {
14
+ "rosell-dk/webp-convert": "dev-master",
15
+ "rosell-dk/webp-convert-cloud-service": "dev-master"
16
  }
17
  }
lib/admin.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
 
3
  // When an update requires a migration, the number should be increased
4
  define('WEBPEXPRESS_MIGRATION_VERSION', '2');
@@ -45,5 +46,71 @@ add_filter('plugin_action_links_' . plugin_basename(WEBPEXPRESS_PLUGIN), functio
45
  $mylinks = array(
46
  '<a href="' . admin_url( 'options-general.php?page=webp_express_settings_page' ) . '">Settings</a>',
47
  );
48
- return array_merge( $links, $mylinks );
49
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
+ use \WebPExpress\State;
3
 
4
  // When an update requires a migration, the number should be increased
5
  define('WEBPEXPRESS_MIGRATION_VERSION', '2');
46
  $mylinks = array(
47
  '<a href="' . admin_url( 'options-general.php?page=webp_express_settings_page' ) . '">Settings</a>',
48
  );
49
+ return array_merge($links, $mylinks);
50
  });
51
+
52
+ add_action('wp_ajax_webpexpress_start_listening', 'webpexpress_start_listening');
53
+ function webpexpress_start_listening() {
54
+ include_once __DIR__ . '/classes/State.php';
55
+ State::setState('listening', true);
56
+ State::setState('request', null);
57
+ wp_die();
58
+ }
59
+
60
+ add_action('wp_ajax_webpexpress_stop_listening', 'webpexpress_stop_listening');
61
+ function webpexpress_stop_listening() {
62
+ include_once __DIR__ . '/classes/State.php';
63
+ State::setState('listening', false);
64
+ State::setState('request', null);
65
+ wp_die();
66
+ }
67
+
68
+ add_action('wp_ajax_webpexpress_get_request', 'webpexpress_get_request');
69
+ function webpexpress_get_request() {
70
+ include_once __DIR__ . '/classes/State.php';
71
+ echo json_encode(State::getState('request', null), JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK);
72
+ wp_die();
73
+ }
74
+
75
+ add_action('wp_ajax_webpexpress_request_access', 'webpexpress_request_access');
76
+ function webpexpress_request_access() {
77
+
78
+ $ch = curl_init();
79
+
80
+ curl_setopt_array(
81
+ $ch,
82
+ [
83
+ CURLOPT_URL => 'http://we0/wordpress/webp-express-server',
84
+ CURLOPT_HTTPHEADER => [
85
+ 'User-Agent: WebPConvert',
86
+ ],
87
+ CURLOPT_POSTFIELDS => [
88
+ 'action' => 'request-access',
89
+ 'label' => 'test',
90
+ 'key' => 'test-key'
91
+ ],
92
+ CURLOPT_RETURNTRANSFER => true,
93
+ CURLOPT_HEADER => false,
94
+ CURLOPT_SSL_VERIFYPEER => false
95
+ ]
96
+ );
97
+ $response = curl_exec($ch);
98
+ if (curl_errno($ch)) {
99
+ }
100
+
101
+ $returnObj = [
102
+ 'success' => true
103
+ ];
104
+ echo json_encode($returnObj, JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK);
105
+
106
+ wp_die();
107
+ }
108
+ /*
109
+ add_action('wp_ajax_webpexpress_accept_request', 'webpexpress_accept_request');
110
+ function webpexpress_accept_request() {
111
+ include_once __DIR__ . '/classes/State.php';
112
+
113
+ State::setState('listening', true);
114
+ State::setState('request', null);
115
+ wp_die();
116
+ }*/
lib/classes/Config.php CHANGED
@@ -157,6 +157,20 @@ class Config
157
  return false;
158
  }
159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  /**
161
  *
162
  * $rewriteRulesNeedsUpdate:
157
  return false;
158
  }
159
 
160
+
161
+ /**
162
+ * Save both configuration files, but do not update htaccess
163
+ * Returns success (boolean)
164
+ */
165
+ public static function saveConfigurationFileAndWodOptions($config)
166
+ {
167
+ if (!(self::saveConfigurationFile($config))) {
168
+ return false;
169
+ }
170
+ $options = self::generateWodOptionsFromConfigObj($config);
171
+ return (self::saveWodOptionsFile($options));
172
+ }
173
+
174
  /**
175
  *
176
  * $rewriteRulesNeedsUpdate:
lib/classes/Paths.php CHANGED
@@ -98,6 +98,9 @@ class Paths
98
 
99
  public static function getContentDirAbs()
100
  {
 
 
 
101
  return rtrim(WP_CONTENT_DIR, '/') . '/webp-express';
102
  }
103
 
@@ -284,6 +287,13 @@ APACHE
284
  return self::getPluginUrlPath() . '/wod/webp-on-demand.php';
285
  }
286
 
 
 
 
 
 
 
 
287
  /**
288
  * Calculate path to existing image, excluding
289
  * (relative to document root)
98
 
99
  public static function getContentDirAbs()
100
  {
101
+ if (!defined(WP_CONTENT_DIR)) {
102
+
103
+ }
104
  return rtrim(WP_CONTENT_DIR, '/') . '/webp-express';
105
  }
106
 
287
  return self::getPluginUrlPath() . '/wod/webp-on-demand.php';
288
  }
289
 
290
+ public static function getWebServiceUrl()
291
+ {
292
+ //return self::getPluginUrl() . '/wpc.php';
293
+ //return self::getHomeUrl() . '/webp-express-server';
294
+ return self::getHomeUrl() . '/webp-express-web-service';
295
+ }
296
+
297
  /**
298
  * Calculate path to existing image, excluding
299
  * (relative to document root)
lib/migrate/migrate.php CHANGED
@@ -41,4 +41,11 @@ if (!(State::getState('configured', false))) {
41
  // run migration 2
42
  include __DIR__ . '/migrate2.php';
43
  }
 
 
 
 
 
 
 
44
  }
41
  // run migration 2
42
  include __DIR__ . '/migrate2.php';
43
  }
44
+
45
+ /*
46
+ // We make sure to grab the option again - it might have been changed in the migration above
47
+ if (intval(get_option('webp-express-migration-version', 0)) == 2) {
48
+ // run migration 2
49
+ include __DIR__ . '/migrate3.php';
50
+ }*/
51
  }
lib/migrate/migrate3.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ namespace WebPExpress;
4
+
5
+ include_once __DIR__ . '/../classes/Config.php';
6
+ use \WebPExpress\Config;
7
+
8
+ include_once __DIR__ . '/../classes/Paths.php';
9
+ use \WebPExpress\Paths;
10
+
11
+ include_once __DIR__ . '/../classes/Messenger.php';
12
+ use \WebPExpress\Messenger;
13
+
14
+ include_once __DIR__ . '/../classes/TestRun.php';
15
+ use \WebPExpress\TestRun;
16
+
17
+ function webpexpress_migrate3() {
18
+
19
+ $changedSomething = false;
20
+ $config = Config::loadConfig();
21
+ if ($config !== false) {
22
+ if (isset($config['converters'])) {
23
+ foreach ($config['converters'] as &$converter) {
24
+ if (isset($converter['converter']) && ($converter['converter'] == 'wpc') && (isset($converter['options']))) {
25
+ if (isset($converter['options']['secret'])) {
26
+ $converter['options']['api-key'] = $converter['options']['secret'];
27
+ unset($converter['options']['secret']);
28
+ $converter['options']['api-version'] = 0;
29
+ } else {
30
+ $converter['options']['api-version'] = 1;
31
+ }
32
+
33
+ unset($converter['options']['url-2']);
34
+ unset($converter['options']['secret-2']);
35
+
36
+ $changedSomething = true;
37
+
38
+ }
39
+ }
40
+ if ($changedSomething) {
41
+ if (Config::saveConfigurationFileAndWodOptions($config)) {
42
+ Messenger::addMessage(
43
+ 'info',
44
+ 'WebP Express successfully migrated configuration file to 0.7.0 format'
45
+ );
46
+ } else {
47
+ Messenger::addMessage(
48
+ 'warning',
49
+ 'WebP Express could not migrated configuration files to 0.7.0 format, because it failed saving the files. ' .
50
+ 'If you use the wpc converter, you should change the configuration files manually (located in wp-content/webp-express/config). ' .
51
+ 'You should change "secret" to "api-key"'
52
+ );
53
+ return;
54
+ }
55
+ }
56
+ }
57
+ }
58
+
59
+ // PSST: When creating new migration files, remember to update WEBPEXPRESS_MIGRATION_VERSION in admin.php
60
+
61
+ update_option('webp-express-migration-version', '3');
62
+
63
+ }
64
+
65
+ webpexpress_migrate3();
66
+ */
lib/options/css/das-popup.css ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #das_overlay {
2
+ background: #000;
3
+ opacity: 0.7;
4
+ filter: alpha(opacity=70);
5
+ position: fixed;
6
+ top: 0;
7
+ right: 0;
8
+ bottom: 0;
9
+ left: 0;
10
+ z-index: 100051;
11
+ }
12
+
13
+ .das-popup {
14
+ position: fixed;
15
+ background-color: #fff;
16
+ z-index: 100052;
17
+ visibility: hidden;
18
+ text-align: left;
19
+ top: 50%;
20
+ left: 50%;
21
+ -webkit-box-shadow: 0 3px 6px rgba( 0, 0, 0, 0.3 );
22
+ box-shadow: 0 3px 6px rgba( 0, 0, 0, 0.3 );
23
+ padding: 20px;
24
+ }
lib/options/css/webp-express-options-page.css CHANGED
@@ -23,7 +23,7 @@
23
  #webpexpress_settings .form-table th {
24
  padding-top: 5px;
25
  padding-bottom: 5px;
26
- width: 180px;
27
  }
28
  #webpexpress_settings .form-table td {
29
  padding-top: 1px;
@@ -33,16 +33,19 @@
33
  }
34
 
35
  #converters li {
36
- cursor: move;
37
  border: 1px solid grey;
38
  box-shadow: 0 1px 1px rgba(0,0,0,.04);
39
  line-height: 1.4em;
40
  background-color: #fff;
41
- padding: 10px 10px 0;
42
- max-width: 465px;
43
- min-height: 30px;
44
  position: relative;
45
  font-size: 12px;
 
 
 
 
46
  }
47
  #converters li:hover {
48
  border-color: #000;
@@ -51,6 +54,9 @@
51
  #converters li.deactivated {
52
  border-color: #ccc;
53
  background-color: #f0f0f0;
 
 
 
54
  }
55
  #converters li.deactivated:hover {
56
  border-color: #999;
@@ -86,7 +92,7 @@
86
  }
87
  #converters li > .text {
88
  padding-left: 10px;
89
- width: 205px;
90
  }
91
 
92
  #converters li > a.btn {
@@ -108,12 +114,12 @@
108
  #converters li .status {
109
  font-size: 10px;
110
  position: absolute;
111
- right: 14px;
112
- bottom: 2px;
113
  }
114
 
115
  #converters li .status svg {
116
- padding: 5px;
117
  }
118
  #converters li svg#status_ok {
119
  color: #008000;
@@ -128,6 +134,13 @@
128
  color: #999999;
129
  }
130
 
 
 
 
 
 
 
 
131
 
132
  #converters li .popup,
133
  .help .popup {
@@ -174,10 +187,12 @@
174
  .converter-options label {
175
  min-width: 80px;
176
  display: inline-block;
 
 
177
  }
178
 
179
- .converter-options.wpc label {
180
- min-width: 100px;
181
  }
182
 
183
  .converter-options .info {
@@ -208,3 +223,121 @@
208
  font-family: sans-serif;
209
  position: relative;
210
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  #webpexpress_settings .form-table th {
24
  padding-top: 5px;
25
  padding-bottom: 5px;
26
+ width: 200px;
27
  }
28
  #webpexpress_settings .form-table td {
29
  padding-top: 1px;
33
  }
34
 
35
  #converters li {
 
36
  border: 1px solid grey;
37
  box-shadow: 0 1px 1px rgba(0,0,0,.04);
38
  line-height: 1.4em;
39
  background-color: #fff;
40
+ padding: 6px 10px 0;
41
+ max-width: 400px;
42
+ min-height: 26px;
43
  position: relative;
44
  font-size: 12px;
45
+ margin-bottom: 4px;
46
+ }
47
+ #converters li {
48
+ cursor: move;
49
  }
50
  #converters li:hover {
51
  border-color: #000;
54
  #converters li.deactivated {
55
  border-color: #ccc;
56
  background-color: #f0f0f0;
57
+ min-height: auto;
58
+ height: 22px;
59
+ padding-top: 3px;
60
  }
61
  #converters li.deactivated:hover {
62
  border-color: #999;
92
  }
93
  #converters li > .text {
94
  padding-left: 10px;
95
+ width: 160px;
96
  }
97
 
98
  #converters li > a.btn {
114
  #converters li .status {
115
  font-size: 10px;
116
  position: absolute;
117
+ right: 7px;
118
+ bottom: 3px;
119
  }
120
 
121
  #converters li .status svg {
122
+ padding: 0px;
123
  }
124
  #converters li svg#status_ok {
125
  color: #008000;
134
  color: #999999;
135
  }
136
 
137
+ #converters li.deactivated .status {
138
+ bottom: unset;
139
+ }
140
+ #converters li.deactivated .status svg {
141
+ width: 15px;
142
+ padding: 0;
143
+ }
144
 
145
  #converters li .popup,
146
  .help .popup {
187
  .converter-options label {
188
  min-width: 80px;
189
  display: inline-block;
190
+ padding-top: 2px;
191
+ vertical-align: top;
192
  }
193
 
194
+ .converter-options p {
195
+ padding: 0;
196
  }
197
 
198
  .converter-options .info {
223
  font-family: sans-serif;
224
  position: relative;
225
  }
226
+
227
+ /*
228
+ .converter-options.wpc #wpc_web_services_div > p {
229
+ margin-top: 0;
230
+ padding-top: 2px;
231
+ margin-bottom: 3px;
232
+ }
233
+ #wpc_web_services_div {
234
+ margin-bottom: 0px;
235
+ }*/
236
+
237
+ .converter-options.wpc label {
238
+ width: 110px;
239
+ display: inline-block;
240
+ }
241
+ .converter-options.wpc div {
242
+ margin-bottom: 5px;
243
+ }
244
+ #wpc_url {
245
+ min-width: 400px;
246
+ }
247
+ #wpc_change_api_key,
248
+ #wpc_set_api_key {
249
+ display:inline-block;
250
+ line-height:22px
251
+ }
252
+
253
+
254
+ #whitelist_table {
255
+ max-width: 400px;
256
+ width: 100%;
257
+ }
258
+ .whitelist td {
259
+ padding: 5px 0;
260
+ }
261
+ .whitelist td.quota input{
262
+ max-width: 40px;
263
+ }
264
+ .whitelist td.remove {
265
+ padding-left: 8px;
266
+ }
267
+ .whitelist td.remove a {
268
+ color: red;
269
+ font-size: 12px;
270
+ }
271
+ .whitelist td.whitelist-add-site {
272
+ text-align: left;
273
+ }
274
+
275
+ #password_helptext,
276
+ #whitelist_site_helptext,
277
+ #whitelist_quota_helptext {
278
+ display: none;
279
+ }
280
+
281
+ .whitelist-popup-content label {
282
+ min-width: 125px;
283
+ display: inline-block;
284
+ }
285
+ /*
286
+ .popup-content {
287
+ padding-top: 20px;
288
+ }
289
+ .popup-content > div {
290
+ margin: 10px 0;
291
+ }
292
+ */
293
+
294
+ #whitelist_div ul {
295
+ list-style: disc;
296
+ list-style-position: inside;
297
+ position: relative;
298
+ width: 400px;
299
+ max-width: 400px;
300
+ }
301
+
302
+ #whitelist_div .whitelist-links,
303
+ #wpc_web_services_div .wpc-links {
304
+ position: absolute;
305
+ right: 0;
306
+ text-align: right;
307
+ display: inline-block;
308
+ }
309
+ #whitelist_div .whitelist-links a,
310
+ #wpc_web_services_div .wpc-links a {
311
+ padding-left: 10px;
312
+ }
313
+
314
+ #whitelist_properties_popup label {
315
+ width: 110px;
316
+ display: inline-block;
317
+ }
318
+
319
+ #whitelist_change_api_key_div {
320
+ line-height: 35px;
321
+ }
322
+
323
+ .das-popup.mode-edit .hide-in-edit {
324
+ display: none;
325
+ }
326
+
327
+ .das-popup.mode-add .hide-in-add {
328
+ display: none;
329
+ }
330
+ /*
331
+ #wpc_web_services_div ul {
332
+ list-style: disc;
333
+ list-style-position: inside;
334
+ position: relative;
335
+ width: 300px;
336
+ max-width: 300px;
337
+ }
338
+
339
+ #wpc_properties_popup label {
340
+ width: 110px;
341
+ display: inline-block;
342
+ }
343
+ */
lib/options/enqueue_scripts.php CHANGED
@@ -6,27 +6,33 @@ use \WebPExpress\Paths;
6
  wp_register_script('sortable', plugins_url('js/sortable.min.js', __FILE__), [], '1.9.0');
7
  wp_enqueue_script('sortable');
8
 
9
- wp_register_script(
10
- 'webp-express-options-page',
11
- plugins_url('js/webp-express-options-page.js', __FILE__),
12
- ['sortable'],
13
- '0.6.0-2'
14
- );
15
- wp_enqueue_script('webp-express-options-page');
 
 
 
 
 
 
 
16
 
17
  if (function_exists('wp_add_inline_script')) {
18
  // wp_add_inline_script is available from Wordpress 4.5
19
- wp_add_inline_script('webp-express-options-page', 'window.webpExpressPaths = ' . json_encode(Paths::getUrlsAndPathsForTheJavascript()) . ';');
20
  } else {
21
  echo '<script>window.webpExpressPaths = ' . json_encode(Paths::getUrlsAndPathsForTheJavascript()) . ';</script>';
22
  }
23
 
24
- wp_register_style(
25
- 'webp-express-options-page-css',
26
- plugins_url('css/webp-express-options-page.css', __FILE__),
27
- null,
28
- '0.6.0-2'
29
- );
30
  wp_enqueue_style('webp-express-options-page-css');
31
 
 
 
 
32
  add_thickbox();
6
  wp_register_script('sortable', plugins_url('js/sortable.min.js', __FILE__), [], '1.9.0');
7
  wp_enqueue_script('sortable');
8
 
9
+ wp_register_script('daspopup', plugins_url('js/das-popup.js', __FILE__), [], '0.7.0-dev5');
10
+ wp_enqueue_script('daspopup');
11
+
12
+ wp_register_script('converters', plugins_url('js/converters.js', __FILE__), ['sortable','daspopup'], '0.7.0-dev21');
13
+ wp_enqueue_script('converters');
14
+
15
+ wp_register_script('whitelist', plugins_url('js/whitelist.js', __FILE__), ['daspopup'], '0.7.0-dev15');
16
+ wp_enqueue_script('whitelist');
17
+
18
+ //wp_register_script('api_keys', plugins_url('js/api-keys.js', __FILE__), ['daspopup'], '0.7.0-dev8');
19
+ //wp_enqueue_script('api_keys');
20
+
21
+ wp_register_script( 'page', plugins_url('js/page.js', __FILE__), [], '0.7.0-dev5');
22
+ wp_enqueue_script('page');
23
 
24
  if (function_exists('wp_add_inline_script')) {
25
  // wp_add_inline_script is available from Wordpress 4.5
26
+ wp_add_inline_script('converters', 'window.webpExpressPaths = ' . json_encode(Paths::getUrlsAndPathsForTheJavascript()) . ';');
27
  } else {
28
  echo '<script>window.webpExpressPaths = ' . json_encode(Paths::getUrlsAndPathsForTheJavascript()) . ';</script>';
29
  }
30
 
31
+ // Register styles
32
+ wp_register_style('webp-express-options-page-css', plugins_url('css/webp-express-options-page.css', __FILE__), null, '0.7.0-dev6');
 
 
 
 
33
  wp_enqueue_style('webp-express-options-page-css');
34
 
35
+ wp_register_style('das-popup-css', plugins_url('css/das-popup.css', __FILE__), null, '0.7.0-dev5');
36
+ wp_enqueue_style('das-popup-css');
37
+
38
  add_thickbox();
lib/options/js/authorized_sites_bak.js ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*function updateWhitelistInputValue() {
2
+ //var val = [];
3
+
4
+ document.getElementsByName('whitelist')[0].value = JSON.stringify(window.whitelist);
5
+ }
6
+
7
+ function setPassword(i) {
8
+ var password = window.prompt('Enter password' + i);
9
+
10
+ window.whitelist[i]['password_hashed'] = '';
11
+ window.whitelist[i]['new_password'] = password;
12
+
13
+ setWhitelistHTML();
14
+ }
15
+ */
16
+ function setAuthorizedSitesHTML() {
17
+ var s = '';
18
+
19
+ if (window.authorizedSites && window.authorizedSites.length > 0) {
20
+ s+='<table class="authorized_sites_list" >';
21
+ s+='<tr>';
22
+ s+='<th>Site<span id="whitelist_site_helptext2"></span></th>'
23
+ //s+='<th>Salt<span id="salt_helptext2"></span></th>'
24
+ //s+='<th>Limit<span id="whitelist_quota_helptext2"></span></th>'
25
+ s+='</tr>';
26
+ s=='</th></tr>';
27
+
28
+ for (var i=0; i<window.authorizedSites.length; i++) {
29
+ s+='<tr><td>';
30
+ s+=window.authorizedSites[i]['id']
31
+ s+='</td></tr>';
32
+ }
33
+ } else {
34
+ s+='<i>No sites have been authorized to use this server yet.</i>';
35
+ }
36
+ s+='</table>';
37
+ s+='<button type="button" class="button button-secondary" id="server_listen_btn" onclick="whitelistAdd()">Connect website</button>';
38
+
39
+ /*
40
+ s+='<tr><td colspan="3" class="whitelist-add-site">';
41
+ s+='<button type="button" class="button button-secondary" id="whitelist_add" onclick="whitelistAdd()">+ Add site</button>';
42
+ s+='</td></tr>';
43
+ s+='</table>';*/
44
+
45
+ document.getElementById('authorized_sites_div').innerHTML = s;
46
+
47
+ }
48
+
49
+ /*
50
+ function whitelistAdd() {
51
+ window.whitelist.push({
52
+ site: '',
53
+ password_hashed: '',
54
+ new_password: '',
55
+ //quota: 60
56
+ });
57
+ setWhitelistHTML();
58
+ }
59
+
60
+ function whitelistRemoveRow(i) {
61
+ window.whitelist.splice(i, 1);
62
+ setWhitelistHTML();
63
+ }
64
+ */
65
+
66
+ document.addEventListener('DOMContentLoaded', function() {
67
+ setAuthorizedSitesHTML();
68
+
69
+
70
+ });
lib/options/js/{webp-express-options-page.js → converters.js} RENAMED
@@ -20,12 +20,16 @@ function addMissingConvertersAndOptions() {
20
  var checkMe2 = window.converters[j]
21
  if (checkMe2['converter'] == checkMe['converter']) {
22
  found = true;
23
-
 
 
 
 
24
  if (checkMe['options']) {
25
  for (var optionName in checkMe['options']) {
26
  if (checkMe['options'].hasOwnProperty(optionName)) {
27
  if (!checkMe2['options']) {
28
- checkMe2['options'] = [];
29
  }
30
  if (!checkMe2['options'].hasOwnProperty(optionName)) {
31
  checkMe2['options'][optionName] = checkMe['options'][optionName];
@@ -39,16 +43,14 @@ function addMissingConvertersAndOptions() {
39
  window.converters.push(window.defaultConverters[i]);
40
  }
41
  }
42
- }
43
-
44
- function addMissingOptions() {
45
-
46
  }
47
 
48
  function getConversionMethodDescription(converterId) {
49
  var descriptions = {
50
  'cwebp': '<i>cwebp</i> binary',
51
- 'wpc': 'wpc cloud converter',
52
  'ewww': 'ewww cloud converter',
53
  'gd': 'Gd extension',
54
  'imagick': 'Imagick extension',
@@ -90,14 +92,15 @@ function generateConverterHTML(converter) {
90
 
91
  html += '<div class="status">';
92
  if (converter.working) {
93
- html += '<svg id="status_ok" width="21" height="21" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.000000 256.000000" preserveAspectRatio="xMidYMid meet">';
94
  html += '<g fill="currentcolor" stroke="none" transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"><path d="M1064 2545 c-406 -72 -744 -324 -927 -690 -96 -193 -127 -333 -127 -575 0 -243 33 -387 133 -585 177 -351 518 -606 907 -676 118 -22 393 -17 511 8 110 24 252 78 356 136 327 183 569 525 628 887 19 122 19 338 0 460 -81 498 -483 914 -990 1025 -101 22 -389 28 -491 10z m814 -745 c39 -27 73 -59 77 -70 9 -27 10 -25 -372 -590 -345 -510 -357 -524 -420 -512 -19 4 -98 74 -250 225 -123 121 -225 228 -228 238 -3 10 1 31 9 47 20 40 125 132 149 132 11 0 79 -59 162 -140 79 -77 146 -140 149 -140 3 0 38 48 78 108 95 143 465 678 496 720 35 46 64 42 150 -18z"/></g></svg>';
95
- html += '<div class="popup">' + converter['id'] + ' is operational</div>';
 
96
  } else {
97
  // + converter['id'] + ' is not operational<br>';
98
  //html += 'not operational. ';
99
  if (converter['error']) {
100
- html += '<svg id="status_not_ok" width="21" height="21" title="not operational" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500.000000 500.000000" preserveAspectRatio="xMidYMid meet">';
101
  html += '<g fill="currentcolor" stroke="none" transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"><path d="M2315 4800 c-479 -35 -928 -217 -1303 -527 -352 -293 -615 -702 -738 -1151 -104 -380 -104 -824 0 -1204 107 -389 302 -724 591 -1013 354 -354 785 -572 1279 -646 196 -30 476 -30 672 0 494 74 925 292 1279 646 354 354 571 784 646 1279 30 197 30 475 0 672 -75 495 -292 925 -646 1279 -289 289 -624 484 -1013 591 -228 62 -528 91 -767 74z m353 -511 c458 -50 874 -272 1170 -624 417 -497 536 -1174 308 -1763 -56 -145 -176 -367 -235 -434 -4 -4 -566 552 -1250 1236 l-1243 1243 94 60 c354 229 754 327 1156 282z m864 -3200 c-67 -59 -289 -179 -434 -235 -946 -366 -2024 172 -2322 1158 -47 155 -66 276 -73 453 -13 362 84 704 290 1023 l60 94 1243 -1243 c684 -684 1240 -1246 1236 -1250z"/></g></svg>';
102
  html += '<div class="popup">';
103
 
@@ -194,55 +197,10 @@ function setConvertersHTML() {
194
  updateInputValue();
195
  }
196
 
197
- function updateCacheControlCustomVisibility() {
198
- var cacheControlValue = document.getElementById('cache_control_select').value;
199
- var customEl = document.getElementById('cache_control_custom');
200
- if (cacheControlValue == 'custom') {
201
- customEl.setAttribute('type', 'text');
202
- } else {
203
- customEl.setAttribute('type', 'hidden');
204
- }
205
- }
206
-
207
- function updateQualityVisibility() {
208
- var qualityAutoEl = document.getElementById('quality_auto_select');
209
- if (!qualityAutoEl) {
210
- return;
211
- }
212
- var qualityAutoValue = qualityAutoEl.value;
213
- var maxQualityRowEl = document.getElementById('max_quality_row');
214
- var qualitySpecificRowEl = document.getElementById('quality_specific_row');
215
-
216
- //alert(qualityAutoValue);
217
- if (qualityAutoValue == 'auto_on') {
218
- maxQualityRowEl.style['display'] = 'table-row';
219
- qualitySpecificRowEl.style['display'] = 'none';
220
- } else {
221
- maxQualityRowEl.style['display'] = 'none';
222
- qualitySpecificRowEl.style['display'] = 'table-row';
223
- }
224
-
225
- }
226
-
227
  document.addEventListener('DOMContentLoaded', function() {
228
  //resetToDefaultConverters();
229
  addMissingConvertersAndOptions();
230
- addMissingOptions();
231
  setConvertersHTML();
232
- updateCacheControlCustomVisibility();
233
- updateQualityVisibility();
234
-
235
- document.getElementById('cache_control_select').addEventListener('change', function() {
236
- updateCacheControlCustomVisibility();
237
- });
238
-
239
- if (document.getElementById('quality_auto_select')) {
240
- document.getElementById('quality_auto_select').addEventListener('change', function() {
241
- updateQualityVisibility();
242
- });
243
- }
244
-
245
- //alert(sortable.toArray());
246
  });
247
 
248
  function wpe_addCloudConverter(converter) {
@@ -263,10 +221,14 @@ function setConverterOption(converter, optionName, value) {
263
  converter['options'][optionName] = value;
264
  }
265
 
266
- function wpcQualityChanged() {
267
- var q = document.getElementById('wpc_quality').value;
268
- document.getElementById('wpc_max_quality_div').style['display'] = (q == 'auto' ? 'block' : 'none');
 
 
269
  }
 
 
270
  function configureConverter(id) {
271
  var converter = window.convertersMap[id];
272
  window.currentlyEditing = id;
@@ -277,10 +239,60 @@ function configureConverter(id) {
277
  document.getElementById('ewww_key_2').value = getConverterOption(converter, 'key-2', '');
278
  break;
279
  case 'wpc':
 
280
  document.getElementById('wpc_url').value = getConverterOption(converter, 'url', '');
281
- document.getElementById('wpc_secret').value = getConverterOption(converter, 'secret', '');
282
- document.getElementById('wpc_url_2').value = getConverterOption(converter, 'url-2', '');
283
- document.getElementById('wpc_secret_2').value = getConverterOption(converter, 'secret-2', '');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  var q = getConverterOption(converter, 'quality', 'not_set');
285
  if (document.getElementById('wpc_quality')) {
286
  document.getElementById('wpc_quality').value = q;
@@ -316,9 +328,29 @@ function updateConverterOptions() {
316
  break;
317
  case 'wpc':
318
  setConverterOption(converter, 'url', document.getElementById('wpc_url').value);
319
- setConverterOption(converter, 'secret', document.getElementById('wpc_secret').value);
320
- setConverterOption(converter, 'url-2', document.getElementById('wpc_url_2').value);
321
- setConverterOption(converter, 'secret-2', document.getElementById('wpc_secret_2').value);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
 
323
  if (document.getElementById('wpc_quality')) {
324
  var q = document.getElementById('wpc_quality').value;
@@ -425,8 +457,173 @@ function activateConverter(id) {
425
  setConvertersHTML();
426
  }
427
 
428
- function addConverterClick() {
429
- // width=600&height=550&inlineId=add-cloud-converter-id
430
- var options = '#TB_inline?inlineId=add-cloud-converter-id';
431
- tb_show("Add converter", options);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  var checkMe2 = window.converters[j]
21
  if (checkMe2['converter'] == checkMe['converter']) {
22
  found = true;
23
+ // at a earilier point in time, we accidently added options as an
24
+ // empty array instead of an empty object. Correcting that!
25
+ if (checkMe2['options'] && checkMe2['options'].constructor === Array) {
26
+ checkMe2['options'] = {};
27
+ }
28
  if (checkMe['options']) {
29
  for (var optionName in checkMe['options']) {
30
  if (checkMe['options'].hasOwnProperty(optionName)) {
31
  if (!checkMe2['options']) {
32
+ checkMe2['options'] = {};
33
  }
34
  if (!checkMe2['options'].hasOwnProperty(optionName)) {
35
  checkMe2['options'][optionName] = checkMe['options'][optionName];
43
  window.converters.push(window.defaultConverters[i]);
44
  }
45
  }
46
+ console.log(window.converters);
47
+ console.log(window.defaultConverters);
 
 
48
  }
49
 
50
  function getConversionMethodDescription(converterId) {
51
  var descriptions = {
52
  'cwebp': '<i>cwebp</i> binary',
53
+ 'wpc': 'Remote WebP Express',
54
  'ewww': 'ewww cloud converter',
55
  'gd': 'Gd extension',
56
  'imagick': 'Imagick extension',
92
 
93
  html += '<div class="status">';
94
  if (converter.working) {
95
+ html += '<svg id="status_ok" width="19" height="19" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.000000 256.000000" preserveAspectRatio="xMidYMid meet">';
96
  html += '<g fill="currentcolor" stroke="none" transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"><path d="M1064 2545 c-406 -72 -744 -324 -927 -690 -96 -193 -127 -333 -127 -575 0 -243 33 -387 133 -585 177 -351 518 -606 907 -676 118 -22 393 -17 511 8 110 24 252 78 356 136 327 183 569 525 628 887 19 122 19 338 0 460 -81 498 -483 914 -990 1025 -101 22 -389 28 -491 10z m814 -745 c39 -27 73 -59 77 -70 9 -27 10 -25 -372 -590 -345 -510 -357 -524 -420 -512 -19 4 -98 74 -250 225 -123 121 -225 228 -228 238 -3 10 1 31 9 47 20 40 125 132 149 132 11 0 79 -59 162 -140 79 -77 146 -140 149 -140 3 0 38 48 78 108 95 143 465 678 496 720 35 46 64 42 150 -18z"/></g></svg>';
97
+ //html += '<div class="popup">' + converter['id'] + ' is operational</div>';
98
+ html += '<div class="popup">Operational</div>';
99
  } else {
100
  // + converter['id'] + ' is not operational<br>';
101
  //html += 'not operational. ';
102
  if (converter['error']) {
103
+ html += '<svg id="status_not_ok" width="19" height="19" title="not operational" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500.000000 500.000000" preserveAspectRatio="xMidYMid meet">';
104
  html += '<g fill="currentcolor" stroke="none" transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"><path d="M2315 4800 c-479 -35 -928 -217 -1303 -527 -352 -293 -615 -702 -738 -1151 -104 -380 -104 -824 0 -1204 107 -389 302 -724 591 -1013 354 -354 785 -572 1279 -646 196 -30 476 -30 672 0 494 74 925 292 1279 646 354 354 571 784 646 1279 30 197 30 475 0 672 -75 495 -292 925 -646 1279 -289 289 -624 484 -1013 591 -228 62 -528 91 -767 74z m353 -511 c458 -50 874 -272 1170 -624 417 -497 536 -1174 308 -1763 -56 -145 -176 -367 -235 -434 -4 -4 -566 552 -1250 1236 l-1243 1243 94 60 c354 229 754 327 1156 282z m864 -3200 c-67 -59 -289 -179 -434 -235 -946 -366 -2024 172 -2322 1158 -47 155 -66 276 -73 453 -13 362 84 704 290 1023 l60 94 1243 -1243 c684 -684 1240 -1246 1236 -1250z"/></g></svg>';
105
  html += '<div class="popup">';
106
 
197
  updateInputValue();
198
  }
199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  document.addEventListener('DOMContentLoaded', function() {
201
  //resetToDefaultConverters();
202
  addMissingConvertersAndOptions();
 
203
  setConvertersHTML();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  });
205
 
206
  function wpe_addCloudConverter(converter) {
221
  converter['options'][optionName] = value;
222
  }
223
 
224
+ function deleteConverterOption(converter, optionName) {
225
+ if (converter['options'] == undefined) {
226
+ converter['options'] = {};
227
+ }
228
+ delete converter['options'][optionName];
229
  }
230
+
231
+
232
  function configureConverter(id) {
233
  var converter = window.convertersMap[id];
234
  window.currentlyEditing = id;
239
  document.getElementById('ewww_key_2').value = getConverterOption(converter, 'key-2', '');
240
  break;
241
  case 'wpc':
242
+
243
  document.getElementById('wpc_url').value = getConverterOption(converter, 'url', '');
244
+
245
+ /* api key in configuration file can be:
246
+ - never set (null)
247
+ - set to be empty ('')
248
+ - set to be something.
249
+
250
+ If never set, we show a password input.
251
+ If set to empty, we also show a password input.
252
+ There is no need to differentiate. between never set and empty
253
+ If set to something, we show a link "Change"
254
+
255
+ in page.php, we remove the api key from javascript array.
256
+ if api key is non-empty, a "_api-key-non-empty" field is set.
257
+ */
258
+
259
+ document.getElementById('wpc_new_api_key').value = '';
260
+
261
+ if (getConverterOption(converter, '_api-key-non-empty', false)) {
262
+ // api key is set to something...
263
+ document.getElementById('wpc_change_api_key').style.display = 'inline';
264
+ document.getElementById('wpc_new_api_key').style.display = 'none';
265
+ } else {
266
+ // api key is empty (or not set)
267
+ document.getElementById('wpc_new_api_key').style.display = 'inline';
268
+ document.getElementById('wpc_change_api_key').style.display = 'none';
269
+ }
270
+
271
+ apiVersion = getConverterOption(converter, 'api-version', 0);
272
+ document.getElementById('wpc_api_version').value = apiVersion.toString();
273
+
274
+ if (apiVersion != 0) {
275
+ }
276
+
277
+ if (apiVersion == 0) {
278
+ document.getElementById('wpc_secret').value = getConverterOption(converter, 'secret', '');
279
+ } else {
280
+ // Only show api version dropdown if configured to run on old api
281
+ // There is no going back!
282
+ document.getElementById('wpc_api_version_div').style.display = 'none';
283
+ }
284
+
285
+ document.getElementById('wpc_crypt_api_key_in_transfer').checked = getConverterOption(converter, 'crypt-api-key-in-transfer', true);
286
+
287
+ wpcApiVersionChanged();
288
+
289
+ //document.getElementById('wpc_secret').value = getConverterOption(converter, 'secret', '');
290
+ //document.getElementById('wpc_url_2').value = getConverterOption(converter, 'url-2', '');
291
+ //document.getElementById('wpc_secret_2').value = getConverterOption(converter, 'secret-2', '');
292
+
293
+
294
+ //wpcUpdateWebServicesHTML();
295
+
296
  var q = getConverterOption(converter, 'quality', 'not_set');
297
  if (document.getElementById('wpc_quality')) {
298
  document.getElementById('wpc_quality').value = q;
328
  break;
329
  case 'wpc':
330
  setConverterOption(converter, 'url', document.getElementById('wpc_url').value);
331
+ //setConverterOption(converter, 'secret', document.getElementById('wpc_secret').value);
332
+ //setConverterOption(converter, 'url-2', document.getElementById('wpc_url_2').value);
333
+ //setConverterOption(converter, 'secret-2', document.getElementById('wpc_secret_2').value);*/
334
+
335
+ var apiVersion = document.getElementById('wpc_api_version').value;
336
+ setConverterOption(converter, 'api-version', apiVersion);
337
+
338
+ if (apiVersion == '0') {
339
+ setConverterOption(converter, 'secret', document.getElementById('wpc_secret').value);
340
+ } else {
341
+ deleteConverterOption(converter, 'secret');
342
+ setConverterOption(converter, 'crypt-api-key-in-transfer', document.getElementById('wpc_crypt_api_key_in_transfer').checked);
343
+ }
344
+
345
+ if (document.getElementById('wpc_new_api_key').style.display == 'inline') {
346
+ // password field is shown. Store the value
347
+ setConverterOption(converter, 'new-api-key', document.getElementById('wpc_new_api_key').value);
348
+ } else {
349
+ // password field is not shown. Remove "new-api-key" value, indicating there is no new value
350
+ //setConverterOption(converter, 'new-api-key', '');
351
+ deleteConverterOption(converter, 'new-api-key');
352
+ }
353
+
354
 
355
  if (document.getElementById('wpc_quality')) {
356
  var q = document.getElementById('wpc_quality').value;
457
  setConvertersHTML();
458
  }
459
 
460
+ /* WPC */
461
+ /* ------------- */
462
+
463
+ function wpcQualityChanged() {
464
+ var q = document.getElementById('wpc_quality').value;
465
+ document.getElementById('wpc_max_quality_div').style['display'] = (q == 'auto' ? 'block' : 'none');
466
+ }
467
+
468
+ function wpcShowAwaitingApprovalPopup() {
469
+ closeDasPopup();
470
+ openDasPopup('wpc_awaiting_approval_popup', 500, 350);
471
+
472
+ /*
473
+ window.pollRequestApprovalTid = window.setInterval(function() {
474
+ //openDasPopup('wpc_successfully_connected_popup', 500, 350);
475
+
476
+ }, 1500);*/
477
+
478
+ }
479
+
480
+ function wpcRequestAccess() {
481
+
482
+ var url = document.getElementById('wpc_request_access_url').value;
483
+ url = 'http://we0/wordpress/webp-express-server';
484
+
485
+ jQuery.post(window.ajaxurl, {
486
+ 'action': 'webpexpress_request_access',
487
+ }, function(response) {
488
+ if (response && (response.substr(0,1) == '{')) {
489
+ var r = JSON.parse(response);
490
+ if (r['success']) {
491
+ wpcShowAwaitingApprovalPopup()
492
+ } else {
493
+ alert(r['errorMessage']);
494
+ }
495
+ }
496
+ });
497
+ }
498
+
499
+ function openWpcConnectPopup() {
500
+ openDasPopup('wpc_connect_popup', 500, 350);
501
+ }
502
+
503
+ function wpcChangeApiKey() {
504
+ document.getElementById('wpc_new_api_key').style.display = 'inline';
505
+ document.getElementById('wpc_change_api_key').style.display = 'none';
506
+ }
507
+
508
+ function wpcApiVersionChanged() {
509
+ var apiVersion = parseInt(document.getElementById('wpc_api_version').value, 10);
510
+ if (apiVersion == 0) {
511
+ document.getElementById('wpc_crypt_api_key_in_transfer_div').style.display = 'none';
512
+ document.getElementById('wpc_api_key_label_1').style.display = 'inline-block';
513
+ document.getElementById('wpc_api_key_label_2').style.display = 'none';
514
+ document.getElementById('wpc_secret_div').style.display = 'block';
515
+ document.getElementById('wpc_api_key_div').style.display = 'none';
516
+ } else {
517
+ document.getElementById('wpc_crypt_api_key_in_transfer_div').style.display = 'block';
518
+ document.getElementById('wpc_api_key_label_1').style.display = 'none';
519
+ document.getElementById('wpc_api_key_label_2').style.display = 'inline-block';
520
+ document.getElementById('wpc_secret_div').style.display = 'none';
521
+ document.getElementById('wpc_api_key_div').style.display = 'block';
522
+ }
523
  }
524
+ /*
525
+ function wpcClearPropertiesForm() {
526
+ document.getElementById('wpc_label').value = '';
527
+ document.getElementById('wpc_url').value = '';
528
+ document.getElementById('wpc_api_key').value = '';
529
+ document.getElementById('wpc_crypt_api_key_in_transfer').checked = true;
530
+ }
531
+
532
+ function wpcRemoveEntry(i) {
533
+ var id = window.currentlyEditing;
534
+ var converter = window.convertersMap[id];
535
+
536
+ converter['options']['web-services'].splice(i, 1);
537
+ wpcUpdateWebServicesHTML();
538
+ }
539
+ function wpcUpdateWebServicesHTML() {
540
+ var id = window.currentlyEditing;
541
+ var converter = window.convertersMap[id];
542
+
543
+ //setConverterOption(converter, 'web-services', )
544
+ var s = '';
545
+
546
+ var webServices = getConverterOption(converter, 'web-services', []);
547
+
548
+ if (webServices.length == 0) {
549
+ s += '<p>Not connected to any web service yet</p>';
550
+ } else {
551
+ s += '<ul>';
552
+ for (var i=0; i<webServices.length; i++) {
553
+ s+='<li>';
554
+ s+=webServices[i].label;
555
+ s+='<div class="wpc-links">'
556
+ s+='<a href="javascript:wpcEditEntry(' + i + ')">edit</a>';
557
+ s+='<a href="javascript:wpcRemoveEntry(' + i + ')">remove</a>';
558
+ s+='</div>'
559
+ s+='</li>';
560
+ }
561
+ s += '</ul>';
562
+ }
563
+
564
+ document.getElementById('wpc_web_services_div').innerHTML = s;
565
+ }
566
+
567
+ function wpcAddEntry() {
568
+ var id = window.currentlyEditing;
569
+ var converter = window.convertersMap[id];
570
+
571
+ if (!converter['options']['web-services']) {
572
+ converter['options']['web-services'] = [];
573
+ }
574
+ converter['options']['web-services'].push(
575
+ {
576
+ 'label' : document.getElementById('wpc_label').value,
577
+ 'url' : document.getElementById('wpc_url').value,
578
+ 'new-api-key': document.getElementById('wpc_api_key').value,
579
+ 'crypt-api-key-in-transfer': document.getElementById('wpc_crypt_api_key_in_transfer').checked
580
+ }
581
+ )
582
+ wpcUpdateWebServicesHTML();
583
+ closeDasPopup();
584
+ }
585
+
586
+ function wpcUpdateEntry() {
587
+ var id = window.currentlyEditing;
588
+ var converter = window.convertersMap[id];
589
+ var i = parseInt(document.getElementById('wpc_i').value, 10);
590
+ var settings = converter['options']['web-services'][i];
591
+
592
+ // TODO: validate
593
+ settings['label'] = document.getElementById('wpc_label').value;
594
+ settings['url'] = document.getElementById('wpc_url').value;
595
+ settings['crypt-api-key-in-transfer'] = document.getElementById('wpc_crypt_api_key_in_transfer').checked;
596
+
597
+ wpcUpdateWebServicesHTML();
598
+ closeDasPopup();
599
+
600
+ }
601
+
602
+ function wpcEditEntry(i) {
603
+ var id = window.currentlyEditing;
604
+ var converter = window.convertersMap[id];
605
+ var settings = converter['options']['web-services'][i];
606
+
607
+ // todo: uid?
608
+ // TODO: api keys must be removed in page.php
609
+ // TODO: api-version
610
+ document.getElementById('wpc_i').value = i;
611
+ document.getElementById('wpc_label').value = settings['label'];
612
+ document.getElementById('wpc_url').value = settings['url'];
613
+ document.getElementById('wpc_new_api_key').value = '';
614
+ document.getElementById('wpc_crypt_api_key_in_transfer').checked = settings['crypt-api-key-in-transfer'];
615
+
616
+ document.getElementById('wpc_properties_popup').className = 'das-popup mode-edit';
617
+ openDasPopup('wpc_properties_popup', 500, 350);
618
+ }
619
+
620
+
621
+ function wpcAddManually() {
622
+ closeDasPopup();
623
+
624
+ wpcClearPropertiesForm();
625
+
626
+ document.getElementById('wpc_properties_popup').className = 'das-popup mode-add';
627
+ openDasPopup('wpc_properties_popup', 500, 350);
628
+
629
+ }*/
lib/options/js/das-popup.js ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function openDasPopup(id, w, h) {
2
+
3
+ // Create overlay, if it isn't already created
4
+ if (!document.getElementById('das_overlay')) {
5
+ var el = document.createElement('div');
6
+ el.setAttribute('id', 'das_overlay');
7
+ document.body.appendChild(el);
8
+ }
9
+
10
+ // Show overlay
11
+ document.getElementById('das_overlay').style['display'] = 'block';
12
+
13
+ // Set width and height on popup
14
+ var popupEl = document.getElementById(id);
15
+ popupEl.style['width'] = w + 'px';
16
+ popupEl.style['margin-left'] = -Math.floor(w/2) + 'px';
17
+ popupEl.style['height'] = h + 'px';
18
+ popupEl.style['margin-top'] = -Math.floor(h/2) + 'px';
19
+
20
+ // Show popup
21
+ popupEl.style['visibility'] = 'visible';
22
+ window.currentDasPopupId = id;
23
+ }
24
+
25
+ function closeDasPopup() {
26
+ if (document.getElementById('das_overlay')) {
27
+ document.getElementById('das_overlay').style['display'] = 'none';
28
+ }
29
+
30
+ if (window.currentDasPopupId) {
31
+ document.getElementById(window.currentDasPopupId).style['visibility'] = 'hidden';
32
+
33
+ }
34
+ }
35
+
36
+ document.onkeydown = function(evt) {
37
+ evt = evt || window.event;
38
+ var isEscape = false;
39
+ if ("key" in evt) {
40
+ isEscape = (evt.key == "Escape" || evt.key == "Esc");
41
+ } else {
42
+ isEscape = (evt.keyCode == 27);
43
+ }
44
+ if (isEscape) {
45
+ closeDasPopup();
46
+ }
47
+ };
lib/options/js/page.js ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ function updateCacheControlCustomVisibility() {
3
+ var cacheControlValue = document.getElementById('cache_control_select').value;
4
+ var customEl = document.getElementById('cache_control_custom');
5
+ if (cacheControlValue == 'custom') {
6
+ customEl.setAttribute('type', 'text');
7
+ } else {
8
+ customEl.setAttribute('type', 'hidden');
9
+ }
10
+ }
11
+
12
+ function updateQualityVisibility() {
13
+ var qualityAutoEl = document.getElementById('quality_auto_select');
14
+ if (!qualityAutoEl) {
15
+ return;
16
+ }
17
+ var qualityAutoValue = qualityAutoEl.value;
18
+ var maxQualityRowEl = document.getElementById('max_quality_row');
19
+ var qualitySpecificRowEl = document.getElementById('quality_specific_row');
20
+
21
+ //alert(qualityAutoValue);
22
+ if (qualityAutoValue == 'auto_on') {
23
+ maxQualityRowEl.style['display'] = 'table-row';
24
+ qualitySpecificRowEl.style['display'] = 'none';
25
+ } else {
26
+ maxQualityRowEl.style['display'] = 'none';
27
+ qualitySpecificRowEl.style['display'] = 'table-row';
28
+ }
29
+
30
+ }
31
+
32
+ function updateServerSettingsVisibility() {
33
+ var enabledEl = document.getElementById('web_service_enabled');
34
+ if (!enabledEl) {
35
+ return;
36
+ }
37
+ var enabled = enabledEl.checked;
38
+ //document.getElementById('whitelist_row').style['display'] = (enabled ? 'table-row' : 'none');
39
+ //document.getElementById('server_url').style['display'] = (enabled ? 'table-row' : 'none');
40
+ document.getElementById('whitelist_div').style['display'] = (enabled ? 'block' : 'none');
41
+ }
42
+
43
+ document.addEventListener('DOMContentLoaded', function() {
44
+ //resetToDefaultConverters();
45
+ updateCacheControlCustomVisibility();
46
+ updateQualityVisibility();
47
+ updateServerSettingsVisibility();
48
+
49
+ document.getElementById('cache_control_select').addEventListener('change', function() {
50
+ updateCacheControlCustomVisibility();
51
+ });
52
+
53
+ if (document.getElementById('quality_auto_select')) {
54
+ document.getElementById('quality_auto_select').addEventListener('change', function() {
55
+ updateQualityVisibility();
56
+ });
57
+ }
58
+
59
+ document.getElementById('web_service_enabled').addEventListener('change', function() {
60
+ updateServerSettingsVisibility();
61
+ });
62
+
63
+ // Dot animation
64
+ window.setInterval(function() {
65
+ var dotElms = document.getElementsByClassName('animated-dots');
66
+ for (var i=0; i<dotElms.length; i++) {
67
+ var el = dotElms[i];
68
+ if (el.innerText == '....') {
69
+ el.innerText = '';
70
+ } else {
71
+ el.innerText += '.';
72
+ }
73
+ }
74
+ }, 500);
75
+
76
+ //alert(sortable.toArray());
77
+ });
lib/options/js/whitelist.js ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function updateWhitelistInputValue() {
2
+ document.getElementById('whitelist').value = JSON.stringify(window.whitelist);
3
+ }
4
+
5
+ function whitelistStartPolling() {
6
+
7
+ jQuery.post(window.ajaxurl, {
8
+ 'action': 'webpexpress_start_listening',
9
+ }, function(response) {
10
+ window.whitelistTid = window.setInterval(function() {
11
+ jQuery.post(window.ajaxurl, {
12
+ 'action': 'webpexpress_get_request',
13
+ }, function(response) {
14
+ if (response && (response.substr(0,1) == '{')) {
15
+ var r = JSON.parse(response);
16
+ window.webpexpress_incoming_request = r;
17
+ //console.log(r);
18
+ window.clearInterval(window.whitelistTid);
19
+ closeDasPopup();
20
+
21
+ // Show request
22
+ openDasPopup('whitelist_accept_request', 300, 200);
23
+
24
+ var s = '';
25
+ s += 'Website: ' + r['label'] + '<br>';
26
+ s += 'IP: ' + r['ip'] + '<br>';
27
+
28
+ document.getElementById('request_details').innerHTML = s;
29
+ } else {
30
+ console.log('Got this from the server: ' + response);
31
+ }
32
+ }
33
+ );
34
+ }, 2000);
35
+ }
36
+ );
37
+ }
38
+
39
+ function whitelistCancelListening() {
40
+ /*
41
+ jQuery.post(window.ajaxurl, {
42
+ 'action': 'webpexpress_stop_listening',
43
+ }, function(response) {}
44
+ );
45
+ */
46
+ }
47
+
48
+ function whitelistCreateUid() {
49
+ var timestamp = (new Date()).getTime();
50
+ var randomNumber = Math.floor(Math.random() * 10000);
51
+ return (timestamp * 10000 + randomNumber).toString(36);
52
+ }
53
+
54
+ /*
55
+ function whitelistAcceptRequest() {
56
+ whitelistCancelListening();
57
+ closeDasPopup();
58
+
59
+ var r = window.webpexpress_incoming_request;
60
+ window.whitelist.push({
61
+ uid: whitelistCreateUid(),
62
+ label: r['label'],
63
+ 'new-api-key': r['api-key'],
64
+ ip: r['ip'],
65
+ // new_password: '',
66
+ //quota: 60
67
+ });
68
+ updateWhitelistInputValue();
69
+ whitelistSetHTML();
70
+ }
71
+
72
+ function whitelistDenyRequest() {
73
+ whitelistCancelListening();
74
+ closeDasPopup();
75
+ }*/
76
+
77
+ function whitelistAddSite() {
78
+ whitelistStartPolling();
79
+ openDasPopup('whitelist_listen_popup', 400, 300);
80
+ }
81
+
82
+ function whitelistRemoveEntry(i) {
83
+ window.whitelist.splice(i, 1);
84
+ whitelistSetHTML();
85
+ }
86
+ function whitelistSetHTML() {
87
+ updateWhitelistInputValue();
88
+ var s = '';
89
+
90
+ if (window.whitelist && window.whitelist.length > 0) {
91
+ s+='<br><i>Authorized web sites:</i>';
92
+ s+='<ul>';
93
+ for (var i=0; i<window.whitelist.length; i++) {
94
+ s+='<li>';
95
+ s+=window.whitelist[i]['label'];
96
+ s+='<div class="whitelist-links">'
97
+ s+='<a href="javascript:whitelistEditEntry(' + i + ')">edit</a>';
98
+ s+='<a href="javascript:whitelistRemoveEntry(' + i + ')">remove</a>';
99
+ s+='</div>'
100
+ s+='</li>';
101
+ }
102
+ s+='</ul>';
103
+ } else {
104
+ s+='<p style="margin:12px 0"><i>No sites have been authorized to use the web service yet.</i></p>';
105
+ }
106
+ s+='<button type="button" class="button button-secondary" id="server_listen_btn" onclick="whitelistAddManually()">+ Authorize website</button>';
107
+
108
+ document.getElementById('whitelist_div').innerHTML = s;
109
+
110
+ }
111
+
112
+ function whitelistClearWhitelistEntryForm() {
113
+ document.getElementById('whitelist_label').value = '';
114
+ document.getElementById('whitelist_ip').value = '';
115
+ document.getElementById('whitelist_api_key').value = '';
116
+ document.getElementById('whitelist_require_api_key_to_be_crypted_in_transfer').checked = true;
117
+ }
118
+
119
+ function whitelistAddWhitelistEntry() {
120
+
121
+ if (document.getElementById('whitelist_label').value == '') {
122
+ alert('Label must be filled out');
123
+ return;
124
+ }
125
+ if (document.getElementById('whitelist_ip').value == '') {
126
+ alert('IP must be filled out. To allow any IP, enter "*"');
127
+ return;
128
+ }
129
+ // TODO: Validate IP syntax
130
+ if (document.getElementById('whitelist_api_key').value == '') {
131
+ alert('API key must be filled in');
132
+ return;
133
+ }
134
+ window.whitelist.push({
135
+ uid: whitelistCreateUid(),
136
+ label: document.getElementById('whitelist_label').value,
137
+ ip: document.getElementById('whitelist_ip').value,
138
+ 'new-api-key': document.getElementById('whitelist_api_key').value,
139
+ 'require-api-key-to-be-crypted-in-transfer': document.getElementById('whitelist_require_api_key_to_be_crypted_in_transfer').checked,
140
+ // new_password: '',
141
+ //quota: 60
142
+ });
143
+ updateWhitelistInputValue();
144
+ whitelistSetHTML();
145
+
146
+ closeDasPopup();
147
+ }
148
+
149
+ function whitelistAddManually() {
150
+ // alert('not implemented yet');
151
+ whitelistClearWhitelistEntryForm();
152
+
153
+ document.getElementById('whitelist_properties_popup').className = 'das-popup mode-add';
154
+
155
+ // whitelistCancelListening();
156
+ // closeDasPopup();
157
+ openDasPopup('whitelist_properties_popup', 400, 300);
158
+ }
159
+
160
+ function whitelistChangeApiKey() {
161
+ document.getElementById('whitelist_api_key').value = prompt('Enter new api key');
162
+ }
163
+
164
+ function whitelistUpdateWhitelistEntry() {
165
+ var i = parseInt(document.getElementById('whitelist_i').value, 10);
166
+
167
+ window.whitelist[i]['uid'] = document.getElementById('whitelist_uid').value;
168
+ window.whitelist[i]['label'] = document.getElementById('whitelist_label').value;
169
+ window.whitelist[i]['ip'] = document.getElementById('whitelist_ip').value;
170
+
171
+ if (document.getElementById('whitelist_api_key').value != '') {
172
+ window.whitelist[i]['new-api-key'] = document.getElementById('whitelist_api_key').value;
173
+ }
174
+ window.whitelist[i]['require-api-key-to-be-crypted-in-transfer'] = document.getElementById('whitelist_require_api_key_to_be_crypted_in_transfer').checked;
175
+ whitelistSetHTML();
176
+ closeDasPopup();
177
+ }
178
+
179
+ function whitelistEditEntry(i) {
180
+ var entry = window.whitelist[i];
181
+ whitelistClearWhitelistEntryForm();
182
+
183
+ document.getElementById('whitelist_properties_popup').className = 'das-popup mode-edit';
184
+
185
+ document.getElementById('whitelist_uid').value = entry['uid'];
186
+ document.getElementById('whitelist_i').value = i;
187
+ document.getElementById('whitelist_label').value = entry['label'];
188
+ document.getElementById('whitelist_ip').value = entry['ip'];
189
+ document.getElementById('whitelist_api_key').value = '';
190
+ document.getElementById('whitelist_require_api_key_to_be_crypted_in_transfer').checked = entry['require-api-key-to-be-crypted-in-transfer'];
191
+
192
+ openDasPopup('whitelist_properties_popup', 400, 300);
193
+ }
194
+
195
+ document.addEventListener('DOMContentLoaded', function() {
196
+ updateWhitelistInputValue();
197
+ whitelistSetHTML();
198
+ });
lib/options/js/whitelist_old.js ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function updateWhitelistInputValue() {
2
+ //var val = [];
3
+
4
+ document.getElementsByName('whitelist')[0].value = JSON.stringify(window.whitelist);
5
+ }
6
+
7
+ function openPasswordPopup(i) {
8
+ window.currentWhitelistPassword = i;
9
+ document.getElementById('whitelist_enter_password').value = '';
10
+ document.getElementById('whitelist_hash_password').checked = false;
11
+
12
+ var options = '#TB_inline?inlineId=whitelist_enter_password_popup&width=400&height=300';
13
+ tb_show("Enter password", options);
14
+
15
+ }
16
+ function setPassword() {
17
+
18
+ var i = window.currentWhitelistPassword;
19
+ var password = document.getElementById('whitelist_enter_password').value;
20
+ var hashPassword = document.getElementById('whitelist_hash_password').checked;
21
+
22
+ //var password = window.prompt('Enter password');
23
+
24
+ window.whitelist[i]['password'] = '';
25
+ window.whitelist[i]['new_password'] = password;
26
+ window.whitelist[i]['hash_new_password'] = hashPassword;
27
+
28
+ setWhitelistHTML();
29
+ tb_remove();
30
+ }
31
+
32
+ function setWhitelistHTML() {
33
+ var s = '';
34
+ s+='<table class="whitelist" id="whitelist_table">';
35
+ s+='<tr>';
36
+ s+='<th>Site<span id="whitelist_site_helptext2"></span></th>'
37
+ s+='<th>Password<span id="password_helptext2"></span></th>'
38
+ //s+='<th>Salt<span id="salt_helptext2"></span></th>'
39
+ //s+='<th>Limit<span id="whitelist_quota_helptext2"></span></th>'
40
+ s+='</tr>';
41
+ s=='</th></tr>';
42
+ if (window.whitelist) {
43
+ for (var i=0; i<window.whitelist.length; i++) {
44
+ s+='<tr>';
45
+ s+='<td><input type="text" size="15" id="whitelist-site-' + i + '" placeholder="hostname or IP"></input></td>';
46
+ //s+='<td><input type="text" size="10" id="whitelist-password-' + i + '"></input></td>';
47
+
48
+ s+='<td><a href="javascript:openPasswordPopup(' + i + ')">Click to ' +
49
+ ((window.whitelist[i]['password'] || window.whitelist[i]['new_password']) ? 'change' : 'set')
50
+ + '</td>';
51
+ //s+='<td>' + (window.whitelist[i]['salt'] || '') + '</td>';
52
+
53
+ //s+='<td class="quota"><nobr><input type="text" size="3" id="whitelist-quota-' + i + '"></input><i> per hour</i></nobr></td>';
54
+ //s+='<td class="buttons"><button type="button" class="button button-secondary" onclick="whitelistRemoveRow(' + i + ')">remove</button></td>';
55
+ s+='<td class="remove"><a href="javascript:whitelistRemoveRow(' + i + ')">remove row</a></td>';
56
+ s+='</tr>';
57
+ }
58
+ }
59
+ s+='<tr><td colspan="3" class="whitelist-add-site">';
60
+ s+='<button type="button" class="button button-secondary" id="whitelist_add" onclick="whitelistAddSite()">+ Add site</button>';
61
+ s+='</td></tr>';
62
+ s+='</table>';
63
+
64
+ document.getElementById('whitelist_div').innerHTML = s;
65
+
66
+ if (window.whitelist) {
67
+ for (var i=0; i<window.whitelist.length; i++) {
68
+ document.getElementById('whitelist-site-' + i).value = window.whitelist[i]['site'];
69
+ //document.getElementById('whitelist-password-hashed' + i).value = window.whitelist[i]['password_hashed'];
70
+ //document.getElementById('whitelist-quota-' + i).value = window.whitelist[i]['quota'];
71
+ }
72
+ }
73
+ updateWhitelistInputValue();
74
+
75
+ document.getElementById('password_helptext2').innerHTML = document.getElementById('password_helptext').innerHTML;
76
+ document.getElementById('whitelist_site_helptext2').innerHTML = document.getElementById('whitelist_site_helptext').innerHTML;
77
+ //document.getElementById('whitelist_quota_helptext2').innerHTML = document.getElementById('whitelist_quota_helptext').innerHTML;
78
+
79
+ }
80
+
81
+ function whitelistStartPolling() {
82
+
83
+ jQuery.post(window.ajaxurl, {
84
+ 'action': 'webpexpress_start_listening',
85
+ }, function(response) {
86
+ window.whitelistTid = window.setInterval(function() {
87
+ jQuery.post(window.ajaxurl, {
88
+ 'action': 'webpexpress_get_request',
89
+ }, function(response) {
90
+ if (response && (response.substr(0,1) == '{')) {
91
+ var r = JSON.parse(response);
92
+ window.webpexpress_incoming_request = r;
93
+ //console.log(r);
94
+ window.clearInterval(window.whitelistTid);
95
+ closeDasPopup();
96
+
97
+ // Show request
98
+ openDasPopup('whitelist_accept_request', 300, 200);
99
+
100
+ var s = '';
101
+ s += 'Website: ' + r['website'] + '<br>';
102
+ s += 'IP: ' + r['ip'] + '<br>';
103
+
104
+ document.getElementById('request_details').innerHTML = s;
105
+ } else {
106
+ console.log('Got this from the server: ' + response);
107
+ }
108
+ }
109
+ );
110
+ }, 2000);
111
+ }
112
+ );
113
+ }
114
+
115
+ function whitelistCancelListening() {
116
+ jQuery.post(window.ajaxurl, {
117
+ 'action': 'webpexpress_stop_listening',
118
+ }, function(response) {}
119
+ );
120
+ closeDasPopup();
121
+ }
122
+
123
+ function whitelistAcceptRequest() {
124
+ whitelistCancelListening();
125
+
126
+ var r = window.webpexpress_incoming_request;
127
+ window.whitelist.push({
128
+ id: r['website'],
129
+ new_password: r['password'],
130
+ // new_password: '',
131
+ //quota: 60
132
+ });
133
+ setWhitelistHTML();
134
+ }
135
+
136
+ function whitelistDenyRequest() {
137
+ whitelistCancelListening();
138
+ }
139
+
140
+ function whitelistAddSite() {
141
+ whitelistStartPolling();
142
+ openDasPopup('whitelist_listen_popup', 400, 300);
143
+ }
144
+
145
+ function whitelistAdd() {
146
+ }
147
+
148
+ function whitelistRemoveRow(i) {
149
+ window.whitelist.splice(i, 1);
150
+ setWhitelistHTML();
151
+ }
152
+
153
+ document.addEventListener('DOMContentLoaded', function() {
154
+
155
+ window.setInterval(function() {
156
+ var el = document.getElementById('animated_dots');
157
+ if (el.innerText == '....') {
158
+ el.innerText = '';
159
+ } else {
160
+ el.innerText += '.';
161
+ }
162
+ }, 500);
163
+
164
+ setWhitelistHTML();
165
+
166
+ document.getElementById('whitelist_div').addEventListener("input", function(e){
167
+ console.log(e);
168
+ for (var i=0; i<window.whitelist.length; i++) {
169
+ window.whitelist[i]['site'] = document.getElementById('whitelist-site-' + i).value;
170
+ //window.whitelist[i]['password_hashed'] = document.getElementById('whitelist-password-hashed' + i).value;
171
+ //window.whitelist[i]['quota'] = document.getElementById('whitelist-quota-' + i).value;
172
+ }
173
+ updateWhitelistInputValue();
174
+ });
175
+
176
+ document.getElementById('whitelist_table').addEventListener("change", function(e){
177
+ // Clean up
178
+ for (var i=0; i<window.whitelist.length; i++) {
179
+ var s = document.getElementById('whitelist-site-' + i).value;
180
+ var s2 = s.replace(/^https?:\/\//, '');
181
+ if (s2 != s) {
182
+ e.target.value = s2;
183
+ window.whitelist[i][0] = s2;
184
+ updateWhitelistInputValue();
185
+ }
186
+ }
187
+ });
188
+
189
+ });
lib/options/page-welcome.php CHANGED
@@ -30,6 +30,7 @@ if ($weKnowThereAreNoWorkingConverters) {
30
  echo '<p>Unfortunately none of the local conversion methods are available on your server. ' .
31
  'but do not despear! - You have options!' .
32
  '<ol style="list-style-position:outside">' .
 
33
  '<li>You can purchase a key for the <a target="_blank" href="https://ewww.io/plans/">ewww cloud converter</a>. They do not charge credits for webp conversions, so all you ever have to pay is the one dollar start-up fee :)</li>' .
34
  '<li>You can set up a <a target="_blank" href="https://github.com/rosell-dk/webp-convert-cloud-service">webp-convert-cloud-service</a> on another server and connect to that. Its open source.</li>' .
35
  '<li>You can try to meet the server requirements of cwebp, gd, imagick or gmagick. Check out <a target="_blank" href="https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters">this wiki page</a> on how to do that</li>' .
30
  echo '<p>Unfortunately none of the local conversion methods are available on your server. ' .
31
  'but do not despear! - You have options!' .
32
  '<ol style="list-style-position:outside">' .
33
+ '<li>You can install this plugin on another website, which supports a local conversion method and connect to that using the "Remote WebP Express" conversion method' .
34
  '<li>You can purchase a key for the <a target="_blank" href="https://ewww.io/plans/">ewww cloud converter</a>. They do not charge credits for webp conversions, so all you ever have to pay is the one dollar start-up fee :)</li>' .
35
  '<li>You can set up a <a target="_blank" href="https://github.com/rosell-dk/webp-convert-cloud-service">webp-convert-cloud-service</a> on another server and connect to that. Its open source.</li>' .
36
  '<li>You can try to meet the server requirements of cwebp, gd, imagick or gmagick. Check out <a target="_blank" href="https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters">this wiki page</a> on how to do that</li>' .
lib/options/page.php CHANGED
@@ -36,6 +36,13 @@ if (!current_user_can('manage_options')) {
36
 
37
  <?php
38
 
 
 
 
 
 
 
 
39
  //update_option('webp-express-migration-version', '1');
40
 
41
  // Test converters
@@ -74,6 +81,20 @@ $defaultConfig = [
74
  'max-quality' => 80,
75
  'quality-specific' => 70,
76
  'metadata' => 'none',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  ];
78
 
79
  $defaultConverters = ConvertersHelper::$defaultConverters;
@@ -90,6 +111,30 @@ $config = array_merge($defaultConfig, $config);
90
  if ($config['converters'] == null) {
91
  $config['converters'] = [];
92
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
  if (count($config['converters']) == 0) {
95
  // This is first time visit!
@@ -144,18 +189,31 @@ if ($testResult) {
144
  if ($working) {
145
  Messenger::printMessage(
146
  'info',
147
- 'Hurray! - The <i>' . $converterId . '</i> conversion method is working now!'
148
  );
149
  } else {
150
  Messenger::printMessage(
151
  'warning',
152
- 'Sad news. The <i>' . $converterId . '</i> conversion method is not working anymore. What happened?'
153
  );
154
  }
155
  }
156
  $converter['working'] = $working;
157
  if ($hasError) {
158
- $converter['error'] = $testResult['errors'][$converterId];
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  } else {
160
  unset($converter['error']);
161
  }
@@ -173,6 +231,9 @@ $webpexpress_settings_nonce = wp_create_nonce('webpexpress_settings_nonce');
173
  </p>
174
 
175
  <?php
 
 
 
176
  echo '<form id="webpexpress_settings" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" method="post" >';
177
  ?>
178
  <input type="hidden" name="action" value="webpexpress_settings_submit">
@@ -248,7 +309,7 @@ if ($canDetectQuality) {
248
  echo helpIcon('All converted images will be encoded with this quality');
249
  } else {
250
  echo helpIcon('All converted images will be encoded with this quality. ' .
251
- 'For the wpc converter, you will however have the option to use override this, and use ' .
252
  '"auto". If you install imagick or gmagick, quality can have "auto" for all convertion methods. '
253
  );
254
  }
@@ -257,88 +318,20 @@ echo '</th><td>';
257
  echo '<input type="text" size=3 id="quality_specific" name="quality-specific" value="' . $qualitySpecific . '">';
258
  echo '</td></tr>';
259
 
260
-
261
-
262
-
263
- // echo '<tr><td colspan=2><p>Converted jpeg images will get same quality as original, but not more than this setting. Something between 70-85 is recommended for most websites.</p></td></tr>';
264
-
265
- // method
266
- //echo '<p>When higher values are used, the encoder will spend more time inspecting additional encoding possibilities and decide on the quality gain. Supported by cwebp, wpc and imagick</p>';
267
-
268
- // Cache-Control
269
  // --------------------
270
- //$maxQuality = get_option('webp_express_max_quality');
271
- $cacheControl = $config['cache-control'];
272
- $cacheControlCustom = $config['cache-control-custom'];
273
-
274
- echo '<tr><th scope="row">Caching';
275
- echo helpIcon(
276
- 'Controls the cache-control header for the converted image. ' .
277
- 'This header is only sent when a converted image is successfully delivered (either existing, or new ' .
278
- 'conversion). In case of failure, headers will be sent to prevent caching.');
279
- echo '</th><td>';
280
- echo '<select id="cache_control_select" name="cache-control">';
281
- echo '<option value="no-header"' . ($cacheControl == 'no-header' ? ' selected' : '') . '>Do not set Cache-Control header</option>';
282
- echo '<option value="one-second"' . ($cacheControl == 'one-second' ? ' selected' : '') . '>One second</option>';
283
- echo '<option value="one-minute"' . ($cacheControl == 'one-minute' ? ' selected' : '') . '>One minute</option>';
284
- echo '<option value="one-hour"' . ($cacheControl == 'one-hour' ? ' selected' : '') . '>One hour</option>';
285
- echo '<option value="one-day"' . ($cacheControl == 'one-day' ? ' selected' : '') . '>One day</option>';
286
- echo '<option value="one-week"' . ($cacheControl == 'one-week' ? ' selected' : '') . '>One week</option>';
287
- echo '<option value="one-month"' . ($cacheControl == 'one-month' ? ' selected' : '') . '>One month</option>';
288
- echo '<option value="one-year"' . ($cacheControl == 'one-year' ? ' selected' : '') . '>One year</option>';
289
- echo '<option value="custom"' . ($cacheControl == 'custom' ? ' selected' : '') . '>Custom Cache-Control header</option>';
290
- echo '</select><br>';
291
- echo '<input type="text" id="cache_control_custom" name="cache-control-custom" value="' . $cacheControlCustom . '">';
292
- echo '</td></tr>';
293
 
 
 
 
294
 
295
- // Metadata
296
- // --------------------
297
- //$maxQuality = get_option('webp_express_max_quality');
298
- $metadata = $config['metadata'];
299
-
300
- echo '<tr><th scope="row">Metadata';
301
- echo helpIcon('Decide what to do with image metadata, such as Exif. Note that this setting is not supported by the "Gd" conversion method, as it is not possible to copy the metadata with the Gd extension');
302
  echo '</th><td>';
303
 
304
- echo '<select name="metadata">';
305
- echo '<option value="none"' . ($metadata == 'none' ? ' selected' : '') . '>No metadata in webp</option>';
306
- echo '<option value="all"' . ($metadata == 'all' ? ' selected' : '') . '>Copy all metadata to webp</option>';
307
- echo '</select>';
308
- echo '</td></tr>';
309
- // echo '<tr><td colspan=2><p>Converted jpeg images will get same quality as original, but not more than this setting. Something between 70-85 is recommended for most websites.</p></td></tr>';
310
-
311
- // method
312
- //echo '<p>When higher values are used, the encoder will spend more time inspecting additional encoding possibilities and decide on the quality gain. Supported by cwebp, wpc and imagick</p>';
313
-
314
- // Response on failure
315
- // --------------------
316
- echo '<tr><th scope="row">Response on failure';
317
- echo helpIcon('Determines what to serve in case the image conversion should fail.');
318
- echo '</th><td>';
319
-
320
- //$fail = get_option('webp_express_failure_response');
321
- $fail = $config['fail'];
322
- echo '<select name="fail">';
323
- echo '<option value="original"' . ($fail == 'original' ? ' selected' : '') . '>Original image</option>';
324
- echo '<option value="404"' . ($fail == '404' ? ' selected' : '') . '>404</option>';
325
- echo '<option value="report"' . ($fail == 'report' ? ' selected' : '') . '>Error report (in plain text)</option>';
326
- echo '<option value="report-as-image"' . ($fail == 'report-as-image' ? ' selected' : '') . '>Error report as image</option>';
327
- echo '</select>';
328
- echo '</td></tr>';
329
- // echo '<tr><td colspan=2>Determines what the converter should serve, in case the image conversion should fail. For production servers, recommended value is "Original image". For development servers, choose anything you like, but that</td></tr>';
330
-
331
-
332
- echo '</tbody></table>';
333
-
334
- // Converters
335
- // --------------------
336
-
337
  $converters = $config['converters'];
338
  echo '<script>window.converters = ' . json_encode($converters) . '</script>';
339
  echo '<script>window.defaultConverters = ' . json_encode($defaultConverters) . '</script>';
340
 
341
- echo "<input type='text' name='converters' value='' style='visibility:hidden' />";
342
 
343
  // https://premium.wpmudev.org/blog/handling-form-submissions/
344
 
@@ -371,17 +364,18 @@ http://php.net/manual/en/function.set-include-path.php
371
  //echo 'All se bools: ' . print_r($output6, true) . '. Return code:' . $returnCode5;
372
  */
373
 
374
- echo '<h2>Conversion methods to try</h2>';
375
  $dragIcon = '<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="17px" height="17px" viewBox="0 0 100.000000 100.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,100.000000) scale(0.100000,-0.100000)" fill="#444444" stroke="none"><path d="M415 920 l-80 -80 165 0 165 0 -80 80 c-44 44 -82 80 -85 80 -3 0 -41 -36 -85 -80z"/><path d="M0 695 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M0 500 l0 -40 500 0 500 0 0 40 0 40 -500 0 -500 0 0 -40z"/><path d="M0 305 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M418 78 l82 -83 82 83 83 82 -165 0 -165 0 83 -82z"/></g></svg>';
376
 
377
- echo '<p><i>Drag to reorder. The conversion method on top will first be tried. ';
378
  echo 'Should it fail, the next will be used, etc.<br>';
379
  echo 'To learn more about the conversion methods, ';
380
  echo '<a target="_blank" href="https://github.com/rosell-dk/webp-convert/blob/master/docs/converters.md">Go here</a></i></p>';
 
381
  // https://github.com/RubaXa/Sortable
382
 
383
  // Empty list of converters. The list will be populated by the javascript
384
- echo '<ul id="converters"></ul>';
385
  ?>
386
  <div id="cwebp" style="display:none;">
387
  <div class="cwebp converter-options">
@@ -497,25 +491,155 @@ echo '<ul id="converters"></ul>';
497
  <!-- <a href="javascript: tb_remove();">close</a> -->
498
  </div>
499
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
500
  <div id="wpc" style="display:none;">
501
  <div class="wpc converter-options">
502
- <h3>WebPConvert Cloud Service (WPC)</h3>
503
- wpc is an open source cloud converter based on <a href="https://github.com/rosell-dk/webp-convert" target="_blank">WebPConvert</a>.
504
- You will need to install the WPC library on a server (or have someone do it for you).
505
- <a href="https://github.com/rosell-dk/webp-convert-cloud-service" target="blank">Visit WPC on github</a>.
506
- (PS: It is planned to integrate wpc into <i>WebP Express</i>, making it very easy to share the capability to convert with your other sites)
 
 
 
 
 
 
507
  <h3>Options</h3>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
508
  <div>
509
- <label for="wpc_url">URL</label>
510
- <input type="text" id="wpc_url" placeholder="Url to your WPC instance">
 
 
 
511
  </div>
512
 
513
- <div>
514
- <label for="wpc_secret">Secret</label>
515
- <input type="text" id="wpc_secret" placeholder="Secret (must match secret on server side)">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
516
  </div>
 
 
 
 
 
 
 
 
 
517
  <?php
518
- if ($canDetectQuality) { ?>
519
  <div>
520
  <label for="wpc_quality">
521
  Quality
@@ -537,21 +661,233 @@ echo '<ul id="converters"></ul>';
537
  <input type="text" size=3 id="wpc_max_quality">
538
  </div>
539
  <?php } ?>
540
- <br>
541
- <h4>Fallback (optional)</h4>
542
- <p>In case the first is down, the fallback will be used.</p>
543
- <div>
544
- <label for="wpc_url_2">URL</label>
545
- <input type="text" id="wpc_url_2" placeholder="Url to your other WPC instance">
546
- </div>
547
- <div>
548
- <label for="wpc_secret_2">Secret</label>
549
- <input type="text" id="wpc_secret_2" placeholder="Secret (must match secret on server side)">
550
- </div>
551
- <br>
552
  <button onclick="updateConverterOptions()" class="button button-primary" type="button">Update and save settings</button>
553
  </div>
554
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
555
 
556
  <table>
557
  <tr>
36
 
37
  <?php
38
 
39
+ function webpexpress_converterName($converterId) {
40
+ if ($converterId == 'wpc') {
41
+ return 'Remote WebP Express';
42
+ }
43
+ return $converterId;
44
+ }
45
+
46
  //update_option('webp-express-migration-version', '1');
47
 
48
  // Test converters
81
  'max-quality' => 80,
82
  'quality-specific' => 70,
83
  'metadata' => 'none',
84
+ 'web-service' => [
85
+ 'enabled' => false,
86
+ 'whitelist' => [
87
+ /*[
88
+ 'uid' => '', // for internal purposes
89
+ 'label' => '', // ie website name. It is just for display
90
+ 'ip' => '', // restrict to these ips. * pattern is allowed.
91
+ 'api-key' => '', // Api key for the entry. Not neccessarily unique for the entry
92
+ //'quota' => 60
93
+ ]
94
+ */
95
+ ]
96
+
97
+ ]
98
  ];
99
 
100
  $defaultConverters = ConvertersHelper::$defaultConverters;
111
  if ($config['converters'] == null) {
112
  $config['converters'] = [];
113
  }
114
+ if (!isset($config['web-service'])) {
115
+ $config['web-service'] = [];
116
+ }
117
+ if (!isset($config['web-service']['whitelist'])) {
118
+ $config['web-service']['whitelist'] = [];
119
+ }
120
+
121
+ // Remove keys in whitelist (so they cannot easily be picked up by examining the html)
122
+ foreach ($config['web-service']['whitelist'] as &$whitelistEntry) {
123
+ unset($whitelistEntry['api-key']);
124
+ }
125
+
126
+ // Remove keys from WPC converters
127
+ foreach ($config['converters'] as &$converter) {
128
+ if (isset($converter['converter']) && ($converter['converter'] == 'wpc')) {
129
+ if (isset($converter['options']['api-key'])) {
130
+ if ($converter['options']['api-key'] != '') {
131
+ $converter['options']['_api-key-non-empty'] = true;
132
+ }
133
+ unset($converter['options']['api-key']);
134
+ }
135
+ }
136
+ }
137
+
138
 
139
  if (count($config['converters']) == 0) {
140
  // This is first time visit!
189
  if ($working) {
190
  Messenger::printMessage(
191
  'info',
192
+ 'Hurray! - The <i>' . webpexpress_converterName($converterId) . '</i> conversion method is working now!'
193
  );
194
  } else {
195
  Messenger::printMessage(
196
  'warning',
197
+ 'Sad news. The <i>' . webpexpress_converterName($converterId) . '</i> conversion method is not working anymore. What happened?'
198
  );
199
  }
200
  }
201
  $converter['working'] = $working;
202
  if ($hasError) {
203
+ $error = $testResult['errors'][$converterId];
204
+ if ($converterId == 'wpc') {
205
+ if (preg_match('/Missing URL/', $error)) {
206
+ $error = 'Not configured';
207
+ }
208
+ if ($error == 'No remote host has been set up') {
209
+ $error = 'Not configured';
210
+ }
211
+
212
+ if (preg_match('/cloud service is not enabled/', $error)) {
213
+ $error = 'The server is not enabled. Click the "Enable web service" on WebP Express settings on the site you are trying to connect to.';
214
+ }
215
+ }
216
+ $converter['error'] = $error;
217
  } else {
218
  unset($converter['error']);
219
  }
231
  </p>
232
 
233
  <?php
234
+
235
+
236
+
237
  echo '<form id="webpexpress_settings" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" method="post" >';
238
  ?>
239
  <input type="hidden" name="action" value="webpexpress_settings_submit">
309
  echo helpIcon('All converted images will be encoded with this quality');
310
  } else {
311
  echo helpIcon('All converted images will be encoded with this quality. ' .
312
+ 'For the Remote WebP Express converter, you will however have the option to use override this, and use ' .
313
  '"auto". If you install imagick or gmagick, quality can have "auto" for all convertion methods. '
314
  );
315
  }
318
  echo '<input type="text" size=3 id="quality_specific" name="quality-specific" value="' . $qualitySpecific . '">';
319
  echo '</td></tr>';
320
 
321
+ // Converters
 
 
 
 
 
 
 
 
322
  // --------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
 
324
+ echo '<tr><th scope="row">Conversion method';
325
+ echo helpIcon('Drag to reorder. The conversion method on top will first be tried. ' .
326
+ 'Should it fail, the next will be used, etc. To learn more about the conversion methods, <a target="_blank" href="https://github.com/rosell-dk/webp-convert/blob/master/docs/converters.md">Go here</a>');
327
 
 
 
 
 
 
 
 
328
  echo '</th><td>';
329
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  $converters = $config['converters'];
331
  echo '<script>window.converters = ' . json_encode($converters) . '</script>';
332
  echo '<script>window.defaultConverters = ' . json_encode($defaultConverters) . '</script>';
333
 
334
+ echo "<input type='text' name='converters' value='' style='visibility:hidden; height:0' />";
335
 
336
  // https://premium.wpmudev.org/blog/handling-form-submissions/
337
 
364
  //echo 'All se bools: ' . print_r($output6, true) . '. Return code:' . $returnCode5;
365
  */
366
 
367
+ //echo '<h2>Conversion methods to try</h2>';
368
  $dragIcon = '<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="17px" height="17px" viewBox="0 0 100.000000 100.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,100.000000) scale(0.100000,-0.100000)" fill="#444444" stroke="none"><path d="M415 920 l-80 -80 165 0 165 0 -80 80 c-44 44 -82 80 -85 80 -3 0 -41 -36 -85 -80z"/><path d="M0 695 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M0 500 l0 -40 500 0 500 0 0 40 0 40 -500 0 -500 0 0 -40z"/><path d="M0 305 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M418 78 l82 -83 82 83 83 82 -165 0 -165 0 83 -82z"/></g></svg>';
369
 
370
+ /*echo '<p><i>Drag to reorder. The conversion method on top will first be tried. ';
371
  echo 'Should it fail, the next will be used, etc.<br>';
372
  echo 'To learn more about the conversion methods, ';
373
  echo '<a target="_blank" href="https://github.com/rosell-dk/webp-convert/blob/master/docs/converters.md">Go here</a></i></p>';
374
+ */
375
  // https://github.com/RubaXa/Sortable
376
 
377
  // Empty list of converters. The list will be populated by the javascript
378
+ echo '<ul id="converters" style="margin-top: -13px"></ul>';
379
  ?>
380
  <div id="cwebp" style="display:none;">
381
  <div class="cwebp converter-options">
491
  <!-- <a href="javascript: tb_remove();">close</a> -->
492
  </div>
493
  </div>
494
+ <!--
495
+ <div id="wpc_successfully_connected_popup" class="das-popup">
496
+ <h3>Your request has been approved</h3>
497
+ All you need now is to save settings (both places)
498
+ <button onclick="closeDasPopup()" class="button button-primary" type="button" style="position:absolute; bottom:20px">Close</button>
499
+ </div>
500
+ <div id="wpc_awaiting_approval_popup" class="das-popup">
501
+ <h3>Avaiting approval<span class="animated-dots">...</span></h3>
502
+ In the remote WebP Express settings, the screen should now show "Incoming request".
503
+ Click the "Grant access" button there, and then return here.
504
+ </div>
505
+ <div id="wpc_connect_popup" class="das-popup">
506
+ <h3>Request access to web service</h3>
507
+ <div style="font-size:90%">
508
+ Before requesting access, the website you want to request access to must be <i>listening</i>
509
+ for requests. If you control that website, open a new tab and do the following. Otherwise,
510
+ make sure the admin does the following:
511
+ <ol>
512
+ <li>Log in to the Wordpress site you want to connect to.</li>
513
+ <li>In WebP Express settings, make sure that "enable web service?" is checked.</li>
514
+ <li>Click "+ Authorize new website"</li>
515
+ <li>An URL will display, which you must copy to the field below:</li>
516
+ </ol>
517
+ Paste URL here:<br>
518
+ <input id="wpc_request_access_url" style="width:100%">
519
+ </div>
520
+ <div style="position:absolute; bottom:20px; line-height:28px">
521
+ <button onclick="wpcRequestAccess()" class="button button-primary" type="button">Request access</button>
522
+ &nbsp;or&nbsp;
523
+ <button onclick="wpcAddManually()" class="button button-secondary" type="button">Add manually</button>
524
+ </div>
525
+ </div>
526
+ <div id="wpc_properties_popup" class="das-popup">
527
+ <h3 class="hide-in-edit">Add connection to web service</h3>
528
+ <h3 class="hide-in-add">Edit connection to web service</h3>
529
+ <input type="hidden" id="wpc_i">
530
+ <div>
531
+ <label for="wpc_label">
532
+ Label
533
+ <?php echo helpIcon('The label is purely for your own reference'); ?>
534
+ </label>
535
+ <input id="wpc_label" type="text">
536
+ </div>
537
+ <div>
538
+ <label for="wpc_url">
539
+ URL
540
+ <?php echo helpIcon('The endpoint of the web service.'); ?>
541
+ </label>
542
+ <input id="wpc_url" type="text">
543
+ </div>
544
+ <div>
545
+ <label for="wpc_api_key">
546
+ Api key
547
+ <?php echo helpIcon('The API key is set up on the remote. Copy that.'); ?>
548
+ </label>
549
+ <input id="wpc_api_key" type="password" class="hide-in-edit">
550
+ <a href="javascript:wpcChangeApiKey()" class="hide-in-add" style="display:inline-block;line-height:34px">Change api key</a>
551
+ </div>
552
+ <div>
553
+ <label for="wpc_crypt_api_key_in_transfer">
554
+ Crypt api key in transfer?
555
+ <?php echo helpIcon('If checked, the api key will be crypted in requests. Crypting the api-key protects it from being stolen during transfer.'); ?>
556
+ </label>
557
+ <input id="wpc_crypt_api_key_in_transfer" type="checkbox">
558
+ </div>
559
+ <button id="wpc_properties_add_button" onclick="wpcAddEntry()" class="hide-in-edit button button-primary" type="button" style="position:absolute; bottom:20px">
560
+ Add
561
+ </button>
562
+ <button id="wpc_properties_update_button" onclick="wpcUpdateEntry()" class="hide-in-add button button-primary" type="button" style="position:absolute; bottom:20px">
563
+ Update
564
+ </button>
565
+ </div>
566
+ -->
567
  <div id="wpc" style="display:none;">
568
  <div class="wpc converter-options">
569
+ <h3>Remote WebP Express</h3>
570
+ Use a WebP Express installed on another Wordpress site to convert. Remote WepP Express is based
571
+ on <a href="https://github.com/rosell-dk/webp-convert-cloud-service" target="blank">WPC</a>,
572
+ and you can use it to connect to WPC as well.
573
+
574
+ <?php
575
+ if ((!extension_loaded('curl')) || (!function_exists('curl_init'))) {
576
+ echo '<p><b style="color:red">Your server does not have curl installed. Curl is required!</b></p>';
577
+ }
578
+ ?>
579
+
580
  <h3>Options</h3>
581
+ <!--
582
+ <div>
583
+ <label for="wpc_web_services">Web Services</label>
584
+ <div style="display:inline-block">
585
+ <div id="wpc_web_services_div"></div>
586
+ <button type="button" id="wpc_web_services_request" onclick="openWpcConnectPopup()" class="button button-secondary" >Add web service</button>
587
+ </div>
588
+ </div>
589
+ -->
590
+
591
+ <div id="wpc_api_version_div">
592
+ <label for="wpc_api_version">
593
+ Api version
594
+ <?php echo helpIcon('Select 2, if connecting to a remote webp-express. Api 1 was never used with this plugin, and should only be used to connect to webp-convert-cloud-service running api version 1'); ?>
595
+ </label>
596
+ <select id="wpc_api_version" onchange="wpcApiVersionChanged()">
597
+ <option value="0">0</option>
598
+ <option value="1">1</option>
599
+ </select>
600
+ </div>
601
+
602
  <div>
603
+ <label for="wpc_url">
604
+ URL
605
+ <?php echo helpIcon('The endpoint of the web service. Copy it from the remote setup.'); ?>
606
+ </label>
607
+ <input type="text" id="wpc_url" placeholder="Url to your Remote WebP Express">
608
  </div>
609
 
610
+ <div id="wpc_secret_div">
611
+ <label for="wpc_secret">
612
+ Secret
613
+ <?php echo helpIcon('Must match the one set up in webp-convert-cloud-service v0.1'); ?>
614
+ </label>
615
+ <input type="text" id="wpc_secret" placeholder="">
616
+ </div>
617
+
618
+ <div id="wpc_api_key_div">
619
+ <label id="wpc_api_key_label_1" for="wpc_api_key">
620
+ Secret
621
+ <?php echo helpIcon('The secret set up on the wpc server. Copy that.'); ?>
622
+ </label>
623
+ <label id="wpc_api_key_label_2" for="wpc_api_key">
624
+ Api key
625
+ <?php echo helpIcon('The API key is set up on the remote. Copy that.'); ?>
626
+ </label>
627
+ <input id="wpc_new_api_key" type="password">
628
+ <a id="wpc_change_api_key" href="javascript:wpcChangeApiKey()">
629
+ Click to change
630
+ </a>
631
  </div>
632
+
633
+ <div id="wpc_crypt_api_key_in_transfer_div">
634
+ <label for="wpc_crypt_api_key_in_transfer">
635
+ Crypt api key in transfer?
636
+ <?php echo helpIcon('If checked, the api key will be crypted in requests. Crypting the api-key protects it from being stolen during transfer.'); ?>
637
+ </label>
638
+ <input id="wpc_crypt_api_key_in_transfer" type="checkbox">
639
+ </div>
640
+
641
  <?php
642
+ if (!$canDetectQuality) { ?>
643
  <div>
644
  <label for="wpc_quality">
645
  Quality
661
  <input type="text" size=3 id="wpc_max_quality">
662
  </div>
663
  <?php } ?>
664
+ <p>
665
+ <b>Psst. The IP of your website is: <?php echo $_SERVER['SERVER_ADDR']; ?>.</b>
666
+ </p>
 
 
 
 
 
 
 
 
 
667
  <button onclick="updateConverterOptions()" class="button button-primary" type="button">Update and save settings</button>
668
  </div>
669
  </div>
670
+ </td></tr>
671
+ <?php
672
+
673
+ // echo '<tr><td colspan=2><p>Converted jpeg images will get same quality as original, but not more than this setting. Something between 70-85 is recommended for most websites.</p></td></tr>';
674
+
675
+ // method
676
+ //echo '<p>When higher values are used, the encoder will spend more time inspecting additional encoding possibilities and decide on the quality gain. Supported by cwebp, wpc and imagick</p>';
677
+
678
+ // Cache-Control
679
+ // --------------------
680
+ //$maxQuality = get_option('webp_express_max_quality');
681
+ $cacheControl = $config['cache-control'];
682
+ $cacheControlCustom = $config['cache-control-custom'];
683
+
684
+ echo '<tr><th scope="row">Caching';
685
+ echo helpIcon(
686
+ 'Controls the cache-control header for the converted image. ' .
687
+ 'This header is only sent when a converted image is successfully delivered (either existing, or new ' .
688
+ 'conversion). In case of failure, headers will be sent to prevent caching.');
689
+ echo '</th><td>';
690
+ echo '<select id="cache_control_select" name="cache-control">';
691
+ echo '<option value="no-header"' . ($cacheControl == 'no-header' ? ' selected' : '') . '>Do not set Cache-Control header</option>';
692
+ echo '<option value="one-second"' . ($cacheControl == 'one-second' ? ' selected' : '') . '>One second</option>';
693
+ echo '<option value="one-minute"' . ($cacheControl == 'one-minute' ? ' selected' : '') . '>One minute</option>';
694
+ echo '<option value="one-hour"' . ($cacheControl == 'one-hour' ? ' selected' : '') . '>One hour</option>';
695
+ echo '<option value="one-day"' . ($cacheControl == 'one-day' ? ' selected' : '') . '>One day</option>';
696
+ echo '<option value="one-week"' . ($cacheControl == 'one-week' ? ' selected' : '') . '>One week</option>';
697
+ echo '<option value="one-month"' . ($cacheControl == 'one-month' ? ' selected' : '') . '>One month</option>';
698
+ echo '<option value="one-year"' . ($cacheControl == 'one-year' ? ' selected' : '') . '>One year</option>';
699
+ echo '<option value="custom"' . ($cacheControl == 'custom' ? ' selected' : '') . '>Custom Cache-Control header</option>';
700
+ echo '</select><br>';
701
+ echo '<input type="text" id="cache_control_custom" name="cache-control-custom" value="' . $cacheControlCustom . '">';
702
+ echo '</td></tr>';
703
+
704
+
705
+ // Metadata
706
+ // --------------------
707
+ //$maxQuality = get_option('webp_express_max_quality');
708
+ $metadata = $config['metadata'];
709
+
710
+ echo '<tr><th scope="row">Metadata';
711
+ echo helpIcon('Decide what to do with image metadata, such as Exif. Note that this setting is not supported by the "Gd" conversion method, as it is not possible to copy the metadata with the Gd extension');
712
+ echo '</th><td>';
713
+
714
+ echo '<select name="metadata">';
715
+ echo '<option value="none"' . ($metadata == 'none' ? ' selected' : '') . '>No metadata in webp</option>';
716
+ echo '<option value="all"' . ($metadata == 'all' ? ' selected' : '') . '>Copy all metadata to webp</option>';
717
+ echo '</select>';
718
+ echo '</td></tr>';
719
+ // echo '<tr><td colspan=2><p>Converted jpeg images will get same quality as original, but not more than this setting. Something between 70-85 is recommended for most websites.</p></td></tr>';
720
+
721
+ // method
722
+ //echo '<p>When higher values are used, the encoder will spend more time inspecting additional encoding possibilities and decide on the quality gain. Supported by cwebp, wpc and imagick</p>';
723
+
724
+ // Response on failure
725
+ // --------------------
726
+ echo '<tr><th scope="row">Response on failure';
727
+ echo helpIcon('Determines what to serve in case the image conversion should fail.');
728
+ echo '</th><td>';
729
+
730
+ //$fail = get_option('webp_express_failure_response');
731
+ $fail = $config['fail'];
732
+ echo '<select name="fail">';
733
+ echo '<option value="original"' . ($fail == 'original' ? ' selected' : '') . '>Original image</option>';
734
+ echo '<option value="404"' . ($fail == '404' ? ' selected' : '') . '>404</option>';
735
+ echo '<option value="report"' . ($fail == 'report' ? ' selected' : '') . '>Error report (in plain text)</option>';
736
+ echo '<option value="report-as-image"' . ($fail == 'report-as-image' ? ' selected' : '') . '>Error report as image</option>';
737
+ echo '</select>';
738
+ echo '</td></tr>';
739
+ // echo '<tr><td colspan=2>Determines what the converter should serve, in case the image conversion should fail. For production servers, recommended value is "Original image". For development servers, choose anything you like, but that</td></tr>';
740
+
741
+ //echo '</tbody></table>';
742
+
743
+
744
+ // Web Service
745
+ // --------------------
746
+
747
+ $whitelist = $config['web-service']['whitelist'];
748
+ echo '<script>window.whitelist = ' . json_encode($whitelist) . '</script>';
749
+ echo '<tr id="share"><th scope="row">Enable web service?';
750
+ echo helpIcon('Enabling the web service will allow selected sites to convert webp-images through this site (more options will appear, if you enable)');
751
+ echo '</th><td>';
752
+
753
+ echo '<input type="checkbox" id="web_service_enabled" name="web-service-enabled" value="true" ' . ($config['web-service']['enabled'] ? 'checked="checked"' : '') . '">';
754
+ echo "<input type='text' name='whitelist' id='whitelist' value='' style='visibility:hidden; height:0' />";
755
+
756
+ ?>
757
+ <div id="whitelist_div"></div>
758
+ <!--
759
+ <div id="whitelist_listen_popup" class="das-popup">
760
+ <h3>Listening for a request<span class="animated-dots">...</span></h3>
761
+ <div style="font-size:90%">
762
+ Send the instructions below to the one that controls the website that you want to grant access.
763
+ If you control that website, simply open up a new tab and perform the following:
764
+ <ol>
765
+ <li>Log in to the website you want to use the web service</li>
766
+ <li>In WebP Express settings, find the <i>Remote WebP Express</i> conversion method and click <i>configure</i></li>
767
+ <li>Click "Make request"</li>
768
+ <li>Enter this url: <b><?php echo Paths::getWebServiceUrl(); ?></b></li>
769
+ </ol>
770
+ This popup will close once the above is completed<br><br>
771
+ </div>
772
+ <div style="display: inline-block;vertical-align:middle; line-height:27px;">
773
+ <button onclick="whitelistCancelListening()" class="button button-secondary" type="button">
774
+ Give up
775
+ </button>
776
+ or
777
+ <button onclick="whitelistAddManually()" class="button button-secondary" type="button">
778
+ Add manually
779
+ </button>
780
+ </div>
781
+ </div>
782
+ -->
783
+ <div id="whitelist_properties_popup" class="das-popup">
784
+ <h3 class="hide-in-edit">Authorize website</h3>
785
+ <h3 class="hide-in-add">Edit authorized website</h3>
786
+ <input type="hidden" id="whitelist_uid">
787
+ <input type="hidden" id="whitelist_i">
788
+ <div>
789
+ <label for="whitelist_label">
790
+ Label
791
+ <?php echo helpIcon('The label is purely for your own reference'); ?>
792
+ </label>
793
+ <input id="whitelist_label" type="text">
794
+ </div>
795
+ <div>
796
+ <label for="whitelist_ip">
797
+ IP
798
+ <?php echo helpIcon('IP to allow access to service. You can use *, ie "212.91.*", or even "*"'); ?>
799
+ </label>
800
+ <input id="whitelist_ip" type="text">
801
+ </div>
802
+ <div>
803
+ <label for="whitelist_api_key">
804
+ Api key
805
+ <?php echo helpIcon('Who says api keys must be dull-looking meaningless sequences of random ' .
806
+ 'characters? Here you get to shape your key to your liking. Enter any phrase you want'); ?>
807
+ </label>
808
+ <input id="whitelist_api_key" type="password" class="hide-in-edit">
809
+ <a href="javascript:whitelistChangeApiKey()" class="hide-in-add" style="line-height:34px">Change api key</a>
810
+ </div>
811
+ <div>
812
+ <label for="whitelist_require_api_key_to_be_crypted_in_transfer">
813
+ Require api-key to be crypted in transfer?
814
+ <?php echo helpIcon('If checked, the web service will only accept crypted api keys. Crypting the api-key protects it from being stolen during transfer. On a few older server setups, clients do not have the capability to crypt'); ?>
815
+ </label>
816
+ <input id="whitelist_require_api_key_to_be_crypted_in_transfer" type="checkbox">
817
+ </div>
818
+ <p style="margin-top: 15px">Psst: The endpoint of the web service is: <b><?php echo Paths::getWebServiceUrl() ?></b></p>
819
+
820
+ <button id="whitelist_properties_add_button" onclick="whitelistAddWhitelistEntry()" class="hide-in-edit button button-primary" type="button" style="position:absolute; bottom:20px">
821
+ Add
822
+ </button>
823
+ <button id="whitelist_properties_update_button" onclick="whitelistUpdateWhitelistEntry()" class="hide-in-add button button-primary" type="button" style="position:absolute; bottom:20px">
824
+ Update
825
+ </button>
826
+ </div>
827
+ <!--
828
+ <div id="whitelist_accept_request" class="das-popup">
829
+ <h3>Incoming request!</h3>
830
+ <div id="request_details"></div>
831
+ <button onclick="whitelistAcceptRequest()" class="button button-primary" type="button" style="position:absolute; bottom:20px">Grant access</button>
832
+ <button onclick="whitelistDenyRequest()" class="button button-secondary" type="button" style="position:absolute; bottom:20px;right:20px">Deny</button>
833
+ </div>-->
834
+
835
+ <?php
836
+ echo '</td></tr>';
837
+
838
+
839
+ // WPC - whitelist
840
+ // --------------------
841
+ /*
842
+ echo '<tr id="whitelist_row"><th scope="row">Whitelist';
843
+
844
+ $whitelist = $config['server']['whitelist'];
845
+
846
+ echo '<script>window.whitelist = ' . json_encode($whitelist) . '</script>';
847
+ echo helpIcon('Specify which sites that may use the conversion service.');
848
+ echo '</th><td>';
849
+ */
850
+ ?>
851
+ <!--
852
+ <div id="whitelist_enter_password_popup" style="display:none">
853
+ <div class="whitelist-popup-content">
854
+ <div>
855
+ <label for="whitelist_password">New password</label>
856
+ <input type="password" id="whitelist_enter_password">
857
+ </div>
858
+ <div>
859
+ <label for="whitelist_hash_password">Scramble password?</label>
860
+ <input type="checkbox" id="whitelist_hash_password">
861
+ </div><br>
862
+ <i>Note: If you choose "scramble password", the password will be scrambled.
863
+ This protects others from discovering what you wrote as password.
864
+ It however still allows people with read access to the file system of your website to get the scrambled
865
+ password and use that to connect with.
866
+ </i>
867
+ <br><br>
868
+ <button onclick="setPassword()" class="button button-primary" type="button">Set password</button>
869
+
870
+ </div>
871
+ </div>
872
+ -->
873
+ <?php
874
+ /*
875
+ echo '<div id="whitelist_div"></div>';
876
+ echo "<input type='text' name='whitelist' value='' style='visibility:hidden; height:0' />"; //
877
+ //echo gethostbyaddr('212.97.134.33');
878
+ //echo gethostbyname('www.rosell.dk');
879
+ echo '<div id="password_helptext">' . helpIcon('You may have to leave blank, if the site in question doesnt have the md5() function available.<br><br>' .
880
+ 'md5 is needed because the password is not transmitted directly, but used to create a ' .
881
+ 'unique hash for the image being converted. So if someone intercepts, they will only get the hash, not the password. And that ' .
882
+ 'hash will only work for that specific image.') . '</div>';visibility:
883
+ echo '<div id="whitelist_site_helptext">' . helpIcon('Enter IP or domain (ie www.example.com). You may use * as a wildcard.') . '</div>';
884
+ //echo '<div id="whitelist_quota_helptext">' . helpIcon('Maximum conversions per hour for this site') . '</div>';
885
+
886
+ echo '</td></tr>';
887
+ */
888
+
889
+ ?>
890
+ </tbody></table>
891
 
892
  <table>
893
  <tr>
lib/options/submit.php CHANGED
@@ -13,6 +13,81 @@ use \WebPExpress\Messenger;
13
  include_once __DIR__ . '/../classes/Paths.php';
14
  use \WebPExpress\Paths;
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  // https://premium.wpmudev.org/blog/handling-form-submissions/
18
  // checkout https://codex.wordpress.org/Function_Reference/sanitize_meta
@@ -32,6 +107,10 @@ $config = [
32
  'forward-query-string' => true,
33
  'image-types' => sanitize_text_field($_POST['image-types']),
34
  'metadata' => sanitize_text_field($_POST['metadata']),
 
 
 
 
35
  ];
36
 
37
  $auto = (isset($_POST['quality-auto']) && $_POST['quality-auto'] == 'auto_on');
@@ -50,6 +129,73 @@ foreach ($config['converters'] as &$converter) {
50
  unset ($converter['id']);
51
  }
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  $result = Config::saveConfigurationAndHTAccess($config, isset($_POST['force']));
54
 
55
  /*
13
  include_once __DIR__ . '/../classes/Paths.php';
14
  use \WebPExpress\Paths;
15
 
16
+ /**
17
+ * Generate valid salt for blowfish, using string that
18
+ * may contain invalid characters.
19
+ * The string supplied should preferably be at least 22 chars, but may be less
20
+ */
21
+ function webp_express_generateBlowfishSalt($string) {
22
+ // http://php.net/manual/en/function.crypt.php
23
+
24
+ // Salt may only contain the following characters: "./0-9A-Za-z"
25
+ $salt = preg_replace('/([^a-zA-Z0-9.\\/])/', '', $string);
26
+
27
+ // Salt must be at least 22 chars
28
+ while (strlen($salt) < 22) {
29
+ $salt .= strtoupper($salt);
30
+ }
31
+
32
+ // It seems salt may be more than 22. But not sure. We trim
33
+ $salt = substr($salt, 0, 22);
34
+
35
+ return $salt;
36
+ }
37
+
38
+ function webp_express_hashItForMe($password) {
39
+
40
+ if (CRYPT_BLOWFISH == 1) {
41
+ $salt = webp_express_generateBlowfishSalt('./aATesting.123');
42
+ $crypted = crypt($password, '$2y$10$' . $salt . '$');
43
+
44
+ // No reason to store the first 28 character.
45
+ // The first 6 are always "$2y$10$". The next 22 is the salt, which we cannot allow to be
46
+ // random, because...
47
+
48
+ // Hm. perhaps, instead of a whitelist, we could have a list of authorized clients
49
+ // Procedure:
50
+ /*
51
+ On server:
52
+ - Click "Listen for requests".
53
+ That opens a dialog showing the URL that it is listening on
54
+
55
+ On client:
56
+ - Click "Send request". That opens a prompt for the URL
57
+ - Enter URL
58
+ - Client sends a request including a autogenerated password (crypted?).
59
+ The salt is included in the crypted password (crypt() output)
60
+ Blowfish is specified.
61
+ Perhaps also a callback URL, so client can display message upon connection.
62
+ But a "test connection" link would probably suffice
63
+
64
+ On server:
65
+ - The request is displayed (polling, including the client domain / IP
66
+ - Click "Accept" next to the request.
67
+ - The request is added to the authorized list (IP, domain? and the crypted password)
68
+ - The client
69
+
70
+ On client:
71
+ - When request
72
+ */
73
+ return substr($crypted, 28);
74
+ }
75
+
76
+ /*
77
+ $salt = 'banana';
78
+ // TODO: Lets use the server URL (at the time of password creation) as salt
79
+ // This will work, even if site changes URL (not if new sites are connecting,
80
+ // to same though)
81
+
82
+ if (function_exists('md5')) {
83
+ return md5($password . $salt);
84
+ }
85
+ */
86
+ // No, we cannot use password_hash.
87
+ // We need something that returns the same hash on server and client.
88
+ // So we need to specify salt, and ensure it is the same
89
+ //password_hash($entry['new_password'], PASSWORD_DEFAULT);
90
+ }
91
 
92
  // https://premium.wpmudev.org/blog/handling-form-submissions/
93
  // checkout https://codex.wordpress.org/Function_Reference/sanitize_meta
107
  'forward-query-string' => true,
108
  'image-types' => sanitize_text_field($_POST['image-types']),
109
  'metadata' => sanitize_text_field($_POST['metadata']),
110
+ 'web-service' => [
111
+ 'enabled' => isset($_POST['web-service-enabled']),
112
+ 'whitelist' => json_decode(wp_unslash($_POST['whitelist']), true)
113
+ ]
114
  ];
115
 
116
  $auto = (isset($_POST['quality-auto']) && $_POST['quality-auto'] == 'auto_on');
129
  unset ($converter['id']);
130
  }
131
 
132
+ $oldConfig = Config::loadConfig();
133
+
134
+ // Set existing api keys in web service (we removed them from the json array, for security purposes)
135
+ if ($oldConfig !== false) {
136
+ if (isset($oldConfig['web-service']['whitelist'])) {
137
+ foreach ($oldConfig['web-service']['whitelist'] as $existingWhitelistEntry) {
138
+ foreach ($config['web-service']['whitelist'] as &$whitelistEntry) {
139
+ if ($whitelistEntry['uid'] == $existingWhitelistEntry['uid']) {
140
+ $whitelistEntry['api-key'] = $existingWhitelistEntry['api-key'];
141
+ }
142
+ }
143
+ }
144
+ }
145
+ }
146
+
147
+ // Set new api keys in web service
148
+ foreach ($config['web-service']['whitelist'] as &$whitelistEntry) {
149
+ if (!empty($whitelistEntry['new-api-key'])) {
150
+ $whitelistEntry['api-key'] = $whitelistEntry['new-api-key'];
151
+ unset($whitelistEntry['new-api-key']);
152
+ }
153
+ }
154
+
155
+ // Get existing wpc api key from old config
156
+ $existingWpcApiKey = '';
157
+ if ($oldConfig !== false) {
158
+ foreach ($oldConfig['converters'] as &$converter) {
159
+ if (isset($converter['converter']) && ($converter['converter'] == 'wpc')) {
160
+ if (isset($converter['options']['api-key'])) {
161
+ $existingWpcApiKey = $converter['options']['api-key'];
162
+ }
163
+ }
164
+ }
165
+ }
166
+
167
+ // Set wpc api key in new config
168
+ // - either to the existing, or to a new
169
+ foreach ($config['converters'] as &$converter) {
170
+ if (isset($converter['converter']) && ($converter['converter'] == 'wpc')) {
171
+ unset($converter['options']['_api-key-non-empty']);
172
+ if (isset($converter['options']['new-api-key'])) {
173
+ $converter['options']['api-key'] = $converter['options']['new-api-key'];
174
+ unset($converter['options']['new-api-key']);
175
+ } else {
176
+ $converter['options']['api-key'] = $existingWpcApiKey;
177
+ }
178
+
179
+ }
180
+ }
181
+
182
+ // create password hashes for new passwords
183
+ /*
184
+ foreach ($config['server']['whitelist'] as &$entry) {
185
+ if (!empty($entry['new_password'])) {
186
+
187
+ if ($entry['hash_new_password']) {
188
+ $entry['password'] = webp_express_hashItForMe($entry['new_password']);
189
+ } else {
190
+ $entry['password'] = $entry['new_password'];
191
+ }
192
+
193
+ unset($entry['hash_new_password']);
194
+ unset($entry['new_password']);
195
+ }
196
+ }
197
+ */
198
+
199
  $result = Config::saveConfigurationAndHTAccess($config, isset($_POST['force']));
200
 
201
  /*
lib/wpc.php ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ //ini_set('display_errors', 1);
4
+ //error_reporting(E_ALL);
5
+
6
+ //require_once( dirname( dirname( __FILE__ ) ) . '/wp-load.php' );
7
+
8
+ include_once __DIR__ . '/classes/Config.php';
9
+ use \WebPExpress\Config;
10
+
11
+ include_once __DIR__ . '/classes/Paths.php';
12
+ use \WebPExpress\Paths;
13
+
14
+ include_once __DIR__ . '/classes/State.php';
15
+ use \WebPExpress\State;
16
+
17
+ require_once __DIR__ . '/../vendor/autoload.php';
18
+ use WebPConvert\WebPConvert;
19
+
20
+
21
+ const ERROR_SERVER_SETUP = 0;
22
+ const ERROR_NOT_ALLOWED = 1;
23
+ const ERROR_RUNTIME = 2;
24
+
25
+ $action = (isset($_POST['action']) ? $_POST['action'] : 'convert');
26
+
27
+ if ($action == 'request-access') {
28
+ if (!(State::getState('listening', false))) {
29
+ exitWithError(ERROR_NOT_ALLOWED, 'Server is not listening for requests');
30
+ } else {
31
+ State::setState('request', [
32
+ 'label' => isset($_POST['label']) ? $_POST['label'] : 'unknown',
33
+ 'key' => isset($_POST['key']) ? $_POST['key'] : 'prut2',
34
+ 'ip' => $_SERVER['REMOTE_ADDR'],
35
+ 'timestamp' => time(),
36
+ ]);
37
+ $returnObject = [
38
+ 'success' => 1,
39
+ ];
40
+ echo json_encode($returnObject);
41
+ die();
42
+ }
43
+ }
44
+
45
+
46
+
47
+ function exitWithError($errorCode, $msg)
48
+ {
49
+ $returnObject = [
50
+ 'success' => 0,
51
+ 'errorCode' => $errorCode,
52
+ 'errorMessage' => $msg,
53
+ ];
54
+ echo json_encode($returnObject);
55
+ exit;
56
+ }
57
+
58
+ $config = Config::loadConfig();
59
+ if ($config === false) {
60
+ if (Config::isConfigFileThere()) {
61
+ exitWithError(ERROR_SERVER_SETUP, 'config file could not be loaded.');
62
+ } else {
63
+ exitWithError(ERROR_SERVER_SETUP, 'config file could not be loaded (its not there): ' . Paths::getConfigFileName());
64
+ }
65
+ }
66
+
67
+ if (!isset($config['wpc'])) {
68
+ exitWithError(ERROR_SERVER_SETUP, 'cloud service is not configured');
69
+ }
70
+
71
+ $wpcOptions = $config['wpc'];
72
+
73
+ if (!isset($wpcOptions['enabled']) || $wpcOptions['enabled'] == false) {
74
+ exitWithError(ERROR_SERVER_SETUP, 'cloud service is not enabled');
75
+ }
76
+
77
+ $whitelisted = false;
78
+ $password = '';
79
+
80
+ /**
81
+ * Note about the whitelist:
82
+ * It is not unspoofable. But it does not have to be either.
83
+ * The extra layer of "security" is added to avoid massive misuse in case that the password
84
+ * is leaked. Massive misuse would be if the password where to spread in internet forums, and
85
+ * anyone could easily use it. With the whitelist, the password is not enough, you would also
86
+ * be needing to know an entry on the whitelist. This could of course also be leaked. But you
87
+ * would also need to do the spoofing. This additional step is probably more than most people
88
+ * would bother to go through.
89
+ */
90
+ function testWhitelistEntry($sitePattern) {
91
+ if ($sitePattern == '*') {
92
+ return true;
93
+ }
94
+ $regEx = '/^' . str_replace('*', '.*', $sitePattern) . '$/';
95
+
96
+ $ip = $_SERVER['REMOTE_ADDR'];
97
+ if (preg_match($regEx, $ip)) {
98
+ return true;
99
+ }
100
+
101
+ // If sitePattern looks like a full IP pattern, exit now,
102
+ // so the other methods cant be misused with spoofing.
103
+ // ^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$
104
+ if (preg_match('/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/', $sitePattern)) {
105
+ return false;
106
+ }
107
+ // Also test a nearly full IP pattern.
108
+ // As domain names may now start with numbers, theoretically, we could have a domain
109
+ // called 123.127.com, and the user might also have 123.127.net, and therefore add
110
+ // a rule '123.127.*'.
111
+ if (preg_match('/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.?\\*$/', $sitePattern)) {
112
+ return false;
113
+ }
114
+
115
+ // ^(\d{1,3}(\.)?){1,4}\*?$ works in regexr.com, but not here...
116
+
117
+ if (isset($_SERVER['REMOTE_HOST'])) {
118
+ // REMOTE_HOST is only available if Apache has been configured
119
+ // with HostnameLookups = On (in apache.conf).
120
+ // It seldom is, as it is not the default, and it is expensive,as at least one
121
+ // DNS lookup will be made per request.
122
+ // Anyway, here we are, and we have it.
123
+ if (preg_match($regEx, $_SERVER['REMOTE_HOST'])) {
124
+ return true;
125
+ }
126
+ }
127
+
128
+ // I know, it can easily be spoofed, simply by changing the source code.
129
+ // However, encrypting it would not help, as the bandit would already be
130
+ // knowing the secret.
131
+ // - And $_SERVER['REMOTE_HOST'] is seldom available, and often misleading
132
+ // on shared hosts
133
+ if (isset($_POST['servername'])) {
134
+ $domain = $_POST['servername'];
135
+ if (preg_match($regEx, $_POST['servername'])) {
136
+ return true;
137
+ }
138
+ }
139
+
140
+ return false;
141
+ }
142
+
143
+ foreach ($wpcOptions['whitelist'] as $entry) {
144
+ if (testWhitelistEntry($entry['site'])) {
145
+ $whitelisted = true;
146
+ $password = $entry['password'];
147
+ break;
148
+ }
149
+ }
150
+
151
+ if (!$whitelisted) {
152
+ if (isset($_SERVER['REMOTE_HOST']) && (!empty($_SERVER['REMOTE_HOST']))) {
153
+ if (isset($_POST['servername'])) {
154
+ exitWithError(ERROR_NOT_ALLOWED, 'Neither your domain (' . $_POST['servername'] . '), the domain of your webhost (' . $_SERVER['REMOTE_HOST'] . ') or your IP (' . $_SERVER['REMOTE_ADDR'] . ') is on the whitelist');
155
+ } else {
156
+ exitWithError(ERROR_NOT_ALLOWED, 'Neither the domain of your webhost (' . $_SERVER['REMOTE_HOST'] . ') or your IP (' . $_SERVER['REMOTE_ADDR'] . ') is on the whitelist');
157
+ }
158
+ } else {
159
+ if (isset($_POST['servername'])) {
160
+ exitWithError(ERROR_NOT_ALLOWED, 'Neither your domain (' . $_POST['servername'] . ') or your IP (' . $_SERVER['REMOTE_ADDR'] . ') is on the whitelist');
161
+ } else {
162
+ exitWithError(ERROR_NOT_ALLOWED, 'Your IP (' . $_SERVER['REMOTE_ADDR'] . ') is not on the whitelist');
163
+ }
164
+ }
165
+ }
166
+
167
+ $uploaddir = Paths::getCacheDirAbs() . '/wpc';
168
+
169
+ if (!is_dir($uploaddir)) {
170
+ if (!@mkdir($uploaddir, 0775, true)) {
171
+ exitWithError(ERROR_SERVER_SETUP, 'Could not create folder for converted files: ' . $uploaddir);
172
+ }
173
+ @chmod($uploaddir, 0775);
174
+ }
175
+
176
+
177
+ if (!isset($_POST['hash'])) {
178
+ exitWithError(ERROR_NOT_ALLOWED, 'Restricted access. Hash required, but missing');
179
+ }
180
+
181
+ if (!isset($_FILES['file']['error'])) {
182
+ exitWithError(ERROR_RUNTIME, 'Invalid parameters');
183
+ }
184
+
185
+ if (is_array($_FILES['file']['error'])) {
186
+ exitWithError(ERROR_RUNTIME, 'Cannot convert multiple files');
187
+ }
188
+
189
+ switch ($_FILES['file']['error']) {
190
+ case UPLOAD_ERR_OK:
191
+ break;
192
+ case UPLOAD_ERR_NO_FILE:
193
+ exitWithError(ERROR_RUNTIME, 'No file sent');
194
+ case UPLOAD_ERR_INI_SIZE:
195
+ case UPLOAD_ERR_FORM_SIZE:
196
+ exitWithError(ERROR_RUNTIME, 'Exceeded filesize limit.');
197
+ default:
198
+ exitWithError(ERROR_RUNTIME, 'Unknown error.');
199
+ }
200
+
201
+ if ($_FILES['file']['size'] == 0) {
202
+ exitWithError(ERROR_NOT_ALLOWED, 'File size is zero. Perhaps exceeded filesize limit?');
203
+ }
204
+ // Undefined | Multiple Files | $_FILES Corruption Attack
205
+ // If this request falls under any of them, treat it invalid.
206
+ /*if ($_FILES['file']['size'] > 1000000) {
207
+ throw new RuntimeException('Exceeded filesize limit.');
208
+ }*/
209
+
210
+ // DO NOT TRUST $_FILES['upfile']['mime'] VALUE !!
211
+ // Check MIME Type by yourself.
212
+ $finfo = new finfo(FILEINFO_MIME_TYPE);
213
+ if (false === $ext = array_search(
214
+ $finfo->file($_FILES['file']['tmp_name']),
215
+ array(
216
+ 'jpg' => 'image/jpeg',
217
+ 'png' => 'image/png',
218
+ 'gif' => 'image/gif',
219
+ ),
220
+ true
221
+ )) {
222
+ exitWithError(ERROR_NOT_ALLOWED, 'Invalid file format.');
223
+ }
224
+
225
+ $uploadfile = $uploaddir . '/' . sha1_file($_FILES['file']['tmp_name']) . '.' . $ext;
226
+ //echo $uploadfile;
227
+ if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
228
+ // File is valid, and was successfully uploaded
229
+
230
+ $source = $uploadfile;
231
+
232
+ if (!empty($password)) {
233
+ $hash = md5(md5_file($source) . $password);
234
+
235
+ if ($hash != $_POST['hash']) {
236
+ exitWithError(ERROR_NOT_ALLOWED, 'Wrong password.');
237
+ }
238
+ }
239
+
240
+ $destination = $uploadfile . '.webp';
241
+
242
+ // Merge in options in $_POST, overwriting those in config.yaml
243
+ $convertOptionsInPost = (array) json_decode($_POST['options']);
244
+ $options = Config::generateWodOptionsFromConfigObj($config);
245
+ $convertOptions = array_merge($options, $convertOptionsInPost);
246
+
247
+ try {
248
+ if (WebPConvert::convert($source, $destination, $convertOptions)) {
249
+ header('Content-type: application/octet-stream');
250
+ echo file_get_contents($destination);
251
+
252
+ unlink($source);
253
+ unlink($destination);
254
+ } else {
255
+ echo 'no converters could convert the image';
256
+ }
257
+ } catch (\Exception $e) {
258
+ echo 'failed!';
259
+ echo $e->getMessage();
260
+ }
261
+ } else {
262
+ // Possible file upload attack!
263
+ exitWithError(ERROR_SERVER_SETUP, 'Failed to move uploaded file');
264
+
265
+ //echo 'Failed to move uploaded file';
266
+ }
test/test-run.php CHANGED
@@ -105,6 +105,7 @@ $options['converters'] = [[
105
 
106
  function testRun($converter, $source, $destination, $options) {
107
 
 
108
  try {
109
  $success = WebPConvert::convert($source, $destination, $options, new EchoLogger());
110
  } catch (\Exception $e) {
105
 
106
  function testRun($converter, $source, $destination, $options) {
107
 
108
+ $success = false;
109
  try {
110
  $success = WebPConvert::convert($source, $destination, $options, new EchoLogger());
111
  } catch (\Exception $e) {
web-service/wpc.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ //require '../vendor/rosell-dk/webp-convert/build/webp-on-demand-1.inc';
4
+ require __DIR__ . '/../vendor/autoload.php';
5
+ use \WebPConvertCloudService\WebPConvertCloudService;
6
+
7
+ include_once __DIR__ . '../../lib/classes/Config.php';
8
+ use \WebPExpress\Config;
9
+
10
+ include_once __DIR__ . '../../lib/classes/Paths.php';
11
+ use \WebPExpress\Paths;
12
+
13
+ include_once __DIR__ . '/../lib/classes/Config.php';
14
+
15
+
16
+ // Patch together $options object for wpc...
17
+ $options = [];
18
+
19
+ $config = Config::loadConfig();
20
+ if ($config === false) {
21
+ if (Config::isConfigFileThere()) {
22
+ WebPConvertCloudService::exitWithError(WebPConvertCloudService::ERROR_CONFIGURATION, 'config file could not be loaded.');
23
+ } else {
24
+ WebPConvertCloudService::exitWithError(WebPConvertCloudService::ERROR_CONFIGURATION, 'config file could not be loaded (its not there): ' . Paths::getConfigFileName());
25
+ }
26
+ }
27
+
28
+ if (!isset($config['web-service'])) {
29
+ WebPConvertCloudService::exitWithError(WebPConvertCloudService::ERROR_ACCESS_DENIED, 'Web Service is not configured');
30
+ }
31
+
32
+ $webServiceConfig = $config['web-service'];
33
+
34
+ if (!$webServiceConfig['enabled']) {
35
+ WebPConvertCloudService::exitWithError(WebPConvertCloudService::ERROR_ACCESS_DENIED, 'Web Service is not enabled');
36
+ }
37
+
38
+ $options['destination-dir'] = Paths::getCacheDirAbs() . '/wpc';
39
+ $options['access'] = [
40
+ //'allowed-ips' => ['127.0.0.1'],
41
+ 'whitelist' => $webServiceConfig['whitelist']
42
+ ];
43
+
44
+ /*
45
+ $options['access'] = [
46
+ 'whitelist' => [
47
+ [
48
+ 'label' => 'testing',
49
+ 'ip' => '127.0.0.1',
50
+ 'api-key' => 'my dog is white',
51
+ 'require-api-key-to-be-hashed-in-transfer' => false,
52
+ ]
53
+ ]
54
+ ]; */
55
+
56
+ $options['webp-convert'] = Config::generateWodOptionsFromConfigObj($config);
57
+
58
+ WebPConvertCloudService::handleRequest($options);
webp-express.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WebP Express
4
  * Plugin URI: https://github.com/rosell-dk/webp-express
5
  * Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
6
- * Version: 0.6.2
7
  * Author: Bjørn Rosell
8
  * Author URI: https://www.bitwise-it.dk
9
  * License: GPL2
@@ -19,3 +19,21 @@ define('WEBPEXPRESS_PLUGIN_DIR', __DIR__);
19
  if (is_admin()) {
20
  include __DIR__ . '/lib/admin.php';
21
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  * Plugin Name: WebP Express
4
  * Plugin URI: https://github.com/rosell-dk/webp-express
5
  * Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
6
+ * Version: 0.7.0
7
  * Author: Bjørn Rosell
8
  * Author URI: https://www.bitwise-it.dk
9
  * License: GPL2
19
  if (is_admin()) {
20
  include __DIR__ . '/lib/admin.php';
21
  }
22
+
23
+ //add_action( 'wp_ajax_foobar', 'my_ajax_foobar_handler' );
24
+
25
+
26
+ function webp_express_process_post() {
27
+ // strip query string
28
+ $requestUriNoQS = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
29
+
30
+ if (!preg_match('/webp-express-web-service$/', $requestUriNoQS)) {
31
+ return;
32
+ }
33
+ //include __DIR__ . '/lib/wpc.php';
34
+ include __DIR__ . '/web-service/wpc.php';
35
+ die();
36
+ }
37
+ add_action( 'init', 'webp_express_process_post' );
38
+
39
+ //add_action( 'template_redirect', 'webp_express_template_redirect' );