Version Description
- Support for WP-CLI commands and PHP > 5.5 (though please upgrade, props @robertpeake)
- Better information regarding Cloudflare
- Better failure on domains for scanner
- Better IP detection
- Break apart settings for faster saving
Download this release
Release Info
Developer | Ipstenu |
Plugin | Varnish HTTP Purge |
Version | 4.0.2 |
Comparing to | |
See all releases |
Code changes from version 4.0.1 to 4.0.2
- readme.txt +8 -1
- varnish-http-purge.php +4 -4
- varnish-status.php +103 -39
- wp-cli.php +4 -8
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: Ipstenu, mikeschroder, techpriester
|
|
3 |
Tags: varnish, purge, cache
|
4 |
Requires at least: 4.0
|
5 |
Tested up to: 4.7
|
6 |
-
Stable tag: 4.0.
|
7 |
|
8 |
Automatically purge Varnish Cache when content on your site is modified.
|
9 |
|
@@ -209,6 +209,13 @@ Yes I do, and yes and no. This plugin is installed by default for _all_ DreamPre
|
|
209 |
|
210 |
== Changelog ==
|
211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
= 4.0.1 =
|
213 |
* Fix typo (on -> one)
|
214 |
* Correct permissions on Multisite (props @phh - resolves #27 #28)
|
3 |
Tags: varnish, purge, cache
|
4 |
Requires at least: 4.0
|
5 |
Tested up to: 4.7
|
6 |
+
Stable tag: 4.0.2
|
7 |
|
8 |
Automatically purge Varnish Cache when content on your site is modified.
|
9 |
|
209 |
|
210 |
== Changelog ==
|
211 |
|
212 |
+
= 4.0.2 =
|
213 |
+
* Support for WP-CLI commands and PHP > 5.5 (though please upgrade, props @robertpeake)
|
214 |
+
* Better information regarding Cloudflare
|
215 |
+
* Better failure on domains for scanner
|
216 |
+
* Better IP detection
|
217 |
+
* Break apart settings for faster saving
|
218 |
+
|
219 |
= 4.0.1 =
|
220 |
* Fix typo (on -> one)
|
221 |
* Correct permissions on Multisite (props @phh - resolves #27 #28)
|
varnish-http-purge.php
CHANGED
@@ -3,16 +3,16 @@
|
|
3 |
Plugin Name: Varnish HTTP Purge
|
4 |
Plugin URI: https://halfelf.org/plugins/varnish-http-purge/
|
5 |
Description: Automatically purge Varnish Cache when content on your site is modified.
|
6 |
-
Version: 4.0.
|
7 |
Author: Mika Epstein
|
8 |
Author URI: https://halfelf.org/
|
9 |
License: http://www.apache.org/licenses/LICENSE-2.0
|
10 |
Text Domain: varnish-http-purge
|
11 |
Network: true
|
12 |
|
13 |
-
Copyright 2013-2016: Mika A. Epstein (email: ipstenu@halfelf.org)
|
14 |
|
15 |
-
Original Author: Leon Weidauer ( http:/www.lnwdr.de/ )
|
16 |
|
17 |
This file is part of Varnish HTTP Purge, a plugin for WordPress.
|
18 |
|
@@ -461,4 +461,4 @@ if ( defined('WP_CLI') && WP_CLI ) {
|
|
461 |
*
|
462 |
* @since 4.0
|
463 |
*/
|
464 |
-
include_once( 'varnish-status.php' );
|
3 |
Plugin Name: Varnish HTTP Purge
|
4 |
Plugin URI: https://halfelf.org/plugins/varnish-http-purge/
|
5 |
Description: Automatically purge Varnish Cache when content on your site is modified.
|
6 |
+
Version: 4.0.2
|
7 |
Author: Mika Epstein
|
8 |
Author URI: https://halfelf.org/
|
9 |
License: http://www.apache.org/licenses/LICENSE-2.0
|
10 |
Text Domain: varnish-http-purge
|
11 |
Network: true
|
12 |
|
13 |
+
Copyright 2013-2016: Mika A. Epstein (email: ipstenu@halfelf.org)
|
14 |
|
15 |
+
Original Author: Leon Weidauer ( http:/www.lnwdr.de/ )
|
16 |
|
17 |
This file is part of Varnish HTTP Purge, a plugin for WordPress.
|
18 |
|
461 |
*
|
462 |
* @since 4.0
|
463 |
*/
|
464 |
+
include_once( 'varnish-status.php' );
|
varnish-status.php
CHANGED
@@ -44,7 +44,8 @@ class VarnishStatus {
|
|
44 |
*/
|
45 |
function admin_init() {
|
46 |
// Register Settings
|
47 |
-
$this->
|
|
|
48 |
}
|
49 |
|
50 |
/**
|
@@ -57,16 +58,24 @@ class VarnishStatus {
|
|
57 |
}
|
58 |
|
59 |
/**
|
60 |
-
* Register Admin Settings
|
61 |
*
|
62 |
* @since 4.0
|
63 |
*/
|
64 |
-
function
|
65 |
-
register_setting( 'varnish-http-purge', '
|
66 |
-
register_setting( 'varnish-http-purge', 'vhp_varnish_url', array( &$this, 'varnish_url_sanitize' ) );
|
67 |
|
68 |
-
add_settings_section( 'varnish-url-settings-section', __('
|
69 |
-
add_settings_field( 'varnish_url', __('Check
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
add_settings_section( 'varnish-ip-settings-section', __('Configure Custom Varnish IP', 'varnish-http-purge'), array( &$this, 'options_callback_ip'), 'varnish-ip-settings' );
|
72 |
add_settings_field( 'varnish_ip', __('Set Varnish IP', 'varnish-http-purge'), array( &$this, 'varnish_ip_callback'), 'varnish-ip-settings', 'varnish-ip-settings-section' );
|
@@ -125,6 +134,9 @@ class VarnishStatus {
|
|
125 |
* @since 4.0
|
126 |
*/
|
127 |
function options_callback_url() {
|
|
|
|
|
|
|
128 |
$icon_awesome = '<span class="dashicons dashicons-heart" style="color:#008000;"></span>';
|
129 |
$icon_good = '<span class="dashicons dashicons-thumbs-up" style="color:#008000;"></span>';
|
130 |
$icon_warning = '<span class="dashicons dashicons-warning" style="color:#FF9933"></span>';
|
@@ -148,14 +160,35 @@ class VarnishStatus {
|
|
148 |
// Basic checks that should stop a scan
|
149 |
if( is_wp_error($response) ) {
|
150 |
$preflight = false;
|
151 |
-
$failure_to_launch = __('This request cannot be performed
|
|
|
152 |
}
|
153 |
if( wp_remote_retrieve_response_code($response) == '404' ) {
|
154 |
$preflight = false;
|
155 |
$failure_to_launch = __('This URL is a 404. Please check your typing and try again.', 'varnish-http-purge');
|
156 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
?>
|
158 |
|
|
|
|
|
159 |
<table class="wp-list-table widefat fixed posts">
|
160 |
<?php
|
161 |
|
@@ -184,7 +217,27 @@ class VarnishStatus {
|
|
184 |
<td><?php _e( 'We did not find Varnish active for this domain.', 'varnish-http-purge' ); ?></td>
|
185 |
</tr><?php
|
186 |
}
|
187 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
// Cloudflare
|
189 |
if ( strpos( $headers['Server'] ,'cloudflare') !== false ) {
|
190 |
?><tr>
|
@@ -342,12 +395,7 @@ class VarnishStatus {
|
|
342 |
function varnish_url_callback() {
|
343 |
$url = esc_url( VarnishPurger::the_home_url() );
|
344 |
$varnishurl = get_option( 'vhp_varnish_url', $url );
|
345 |
-
?>
|
346 |
-
<input type="text" id="vhp_varnish_url" name="vhp_varnish_url" value="<?php echo $varnishurl; ?>" size="50" />
|
347 |
-
<label for="vhp_varnish_url">
|
348 |
-
<?php printf( __( 'Example: <code>%s</code>', 'varnish-http-purge' ), esc_url( VarnishPurger::the_home_url() ) ); ?>
|
349 |
-
</label>
|
350 |
-
<?php
|
351 |
}
|
352 |
|
353 |
/*
|
@@ -360,21 +408,21 @@ class VarnishStatus {
|
|
360 |
<div class="wrap">
|
361 |
|
362 |
<h1><?php _e( 'Is Varnish Working?', 'varnish-http-purge' ); ?></h1>
|
363 |
-
|
364 |
-
<p><?php _e( 'While it would be impossible to detect all possible conflicts, this Status Page will perform a check of the most common issues that prevent Varnish from caching your site properly.', 'varnish-http-purge' ); ?></p>
|
365 |
|
366 |
<?php settings_errors(); ?>
|
367 |
|
368 |
<form action="options.php" method="POST" ><?php
|
369 |
-
settings_fields( 'varnish-http-purge' );
|
370 |
-
|
371 |
do_settings_sections( 'varnish-url-settings' );
|
372 |
submit_button( 'Check URL', 'primary');
|
|
|
373 |
|
|
|
374 |
// Only available if _not_ multisite
|
375 |
if ( !is_multisite() ) {
|
|
|
376 |
do_settings_sections( 'varnish-ip-settings' );
|
377 |
-
submit_button( 'Save IP', '
|
378 |
}
|
379 |
?></form>
|
380 |
|
@@ -389,12 +437,20 @@ class VarnishStatus {
|
|
389 |
* @since 4.0
|
390 |
*/
|
391 |
function varnish_ip_sanitize( $input ) {
|
392 |
-
|
393 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
394 |
$output = filter_var( $input, FILTER_VALIDATE_IP);
|
395 |
-
}
|
396 |
-
|
397 |
-
|
398 |
return $output;
|
399 |
}
|
400 |
|
@@ -407,22 +463,30 @@ class VarnishStatus {
|
|
407 |
function varnish_url_sanitize( $input ) {
|
408 |
|
409 |
$baseurl_host = parse_url( esc_url( VarnishPurger::the_home_url() ), PHP_URL_HOST );
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
$
|
415 |
-
|
416 |
-
|
417 |
-
|
|
|
|
|
|
|
|
|
418 |
}
|
419 |
-
|
420 |
-
if (
|
421 |
-
$
|
422 |
-
}
|
423 |
-
$
|
|
|
424 |
$set_message = 'You cannot scan URLs on other domains.';
|
425 |
-
|
|
|
|
|
|
|
426 |
}
|
427 |
|
428 |
add_settings_error( 'vhp_varnish_url', 'varnish-url', $set_message, $set_type );
|
44 |
*/
|
45 |
function admin_init() {
|
46 |
// Register Settings
|
47 |
+
$this->register_settings_url();
|
48 |
+
$this->register_settings_ip();
|
49 |
}
|
50 |
|
51 |
/**
|
58 |
}
|
59 |
|
60 |
/**
|
61 |
+
* Register Admin Settings URL
|
62 |
*
|
63 |
* @since 4.0
|
64 |
*/
|
65 |
+
function register_settings_url() {
|
66 |
+
register_setting( 'varnish-http-purge-url', 'vhp_varnish_url', array( &$this, 'varnish_url_sanitize' ) );
|
|
|
67 |
|
68 |
+
add_settings_section( 'varnish-url-settings-section', __('Check Varnish Status', 'varnish-http-purge'), array( &$this, 'options_callback_url'), 'varnish-url-settings' );
|
69 |
+
add_settings_field( 'varnish_url', __('Check A URL On Your Site:', 'varnish-http-purge'), array( &$this, 'varnish_url_callback'), 'varnish-url-settings', 'varnish-url-settings-section' );
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Register Admin Settings IP
|
74 |
+
*
|
75 |
+
* @since 4.0.2
|
76 |
+
*/
|
77 |
+
function register_settings_ip() {
|
78 |
+
register_setting( 'varnish-http-purge-ip', 'vhp_varnish_ip', array( &$this, 'varnish_ip_sanitize' ) );
|
79 |
|
80 |
add_settings_section( 'varnish-ip-settings-section', __('Configure Custom Varnish IP', 'varnish-http-purge'), array( &$this, 'options_callback_ip'), 'varnish-ip-settings' );
|
81 |
add_settings_field( 'varnish_ip', __('Set Varnish IP', 'varnish-http-purge'), array( &$this, 'varnish_ip_callback'), 'varnish-ip-settings', 'varnish-ip-settings-section' );
|
134 |
* @since 4.0
|
135 |
*/
|
136 |
function options_callback_url() {
|
137 |
+
|
138 |
+
?><p><?php _e( 'While it would be impossible to detect all possible conflicts, this Status Page will perform a check of the most common issues that prevent Varnish from caching your site properly.', 'varnish-http-purge' ); ?></p><?php
|
139 |
+
|
140 |
$icon_awesome = '<span class="dashicons dashicons-heart" style="color:#008000;"></span>';
|
141 |
$icon_good = '<span class="dashicons dashicons-thumbs-up" style="color:#008000;"></span>';
|
142 |
$icon_warning = '<span class="dashicons dashicons-warning" style="color:#FF9933"></span>';
|
160 |
// Basic checks that should stop a scan
|
161 |
if( is_wp_error($response) ) {
|
162 |
$preflight = false;
|
163 |
+
$failure_to_launch = __('This request cannot be performed: ', 'varnish-http-purge');
|
164 |
+
$failure_to_launch .= $response->get_error_message();
|
165 |
}
|
166 |
if( wp_remote_retrieve_response_code($response) == '404' ) {
|
167 |
$preflight = false;
|
168 |
$failure_to_launch = __('This URL is a 404. Please check your typing and try again.', 'varnish-http-purge');
|
169 |
}
|
170 |
+
|
171 |
+
// Get the IP address so we can check things later
|
172 |
+
if ( isset( $headers['X-Forwarded-For'] ) && filter_var( $headers['X-Forwarded-For'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
|
173 |
+
$remote_ip = $headers['X-Forwarded-For'];
|
174 |
+
} elseif ( isset( $headers['HTTP_X_FORWARDED_FOR'] ) && filter_var( $headers['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 )
|
175 |
+
) {
|
176 |
+
$remote_ip = $headers['HTTP_X_FORWARDED_FOR'];
|
177 |
+
} else {
|
178 |
+
$remote_ip = false;
|
179 |
+
}
|
180 |
+
|
181 |
+
// Get the Varnish IP
|
182 |
+
if ( VHP_VARNISH_IP != false ) {
|
183 |
+
$varniship = VHP_VARNISH_IP;
|
184 |
+
} else {
|
185 |
+
$varniship = get_option('vhp_varnish_ip');
|
186 |
+
}
|
187 |
+
|
188 |
?>
|
189 |
|
190 |
+
<h4><?php printf( __( 'Results for %s', 'varnish-http-purge' ), $varnishurl ); ?></h4>
|
191 |
+
|
192 |
<table class="wp-list-table widefat fixed posts">
|
193 |
<?php
|
194 |
|
217 |
<td><?php _e( 'We did not find Varnish active for this domain.', 'varnish-http-purge' ); ?></td>
|
218 |
</tr><?php
|
219 |
}
|
220 |
+
|
221 |
+
// Remote IP (i.e. Yo Dawg, I heard you like proxies
|
222 |
+
?><tr><?php
|
223 |
+
if ( $remote_ip == false && !empty( $varniship) ) {
|
224 |
+
?>
|
225 |
+
<td width="40px"><?php echo $icon_bad; ?></td>
|
226 |
+
<td><?php printf( __( 'You have a Varnish IP set but you don\'t appear to be using a proxy like Cloudflare or Sucuri. Please <a href="%s">erase your Varnish IP</a>', 'varnish-http-purge' ), '#configure' ); ?></td>
|
227 |
+
<?php
|
228 |
+
} elseif ( $remote_ip !== false && $remote_ip !== $varniship ) {
|
229 |
+
?>
|
230 |
+
<td width="40px"><?php echo $icon_bad; ?></td>
|
231 |
+
<td><?php printf( __( 'You\'re using a Custom Varnish IP that doesn\'t appear to match your server IP address. Please make sure you\'ve <a href="%s">properly configured it</a> according to your webhost\'s specifications.', 'varnish-http-purge' ), '#configure' ); ?></td>
|
232 |
+
<?php
|
233 |
+
} else {
|
234 |
+
?>
|
235 |
+
<td width="40px"><?php echo $icon_good; ?></td>
|
236 |
+
<td><?php printf( __( 'Your sever IP setup looks just fine. If you are using a proxy (like Sucuri or Cloudflare or Fastly) please double check that configuration and make sure to add a <a href="%s">custom Varnish IP</a> .', 'varnish-http-purge' ), '#configure' ); ?></td>
|
237 |
+
<?php
|
238 |
+
}
|
239 |
+
?></tr><?php
|
240 |
+
|
241 |
// Cloudflare
|
242 |
if ( strpos( $headers['Server'] ,'cloudflare') !== false ) {
|
243 |
?><tr>
|
395 |
function varnish_url_callback() {
|
396 |
$url = esc_url( VarnishPurger::the_home_url() );
|
397 |
$varnishurl = get_option( 'vhp_varnish_url', $url );
|
398 |
+
?><input type="text" id="vhp_varnish_url" name="vhp_varnish_url" value="<?php echo $varnishurl; ?>" size="50" /><?php
|
|
|
|
|
|
|
|
|
|
|
399 |
}
|
400 |
|
401 |
/*
|
408 |
<div class="wrap">
|
409 |
|
410 |
<h1><?php _e( 'Is Varnish Working?', 'varnish-http-purge' ); ?></h1>
|
|
|
|
|
411 |
|
412 |
<?php settings_errors(); ?>
|
413 |
|
414 |
<form action="options.php" method="POST" ><?php
|
415 |
+
settings_fields( 'varnish-http-purge-url' );
|
|
|
416 |
do_settings_sections( 'varnish-url-settings' );
|
417 |
submit_button( 'Check URL', 'primary');
|
418 |
+
?></form>
|
419 |
|
420 |
+
<form action="options.php" method="POST" ><?php
|
421 |
// Only available if _not_ multisite
|
422 |
if ( !is_multisite() ) {
|
423 |
+
settings_fields( 'varnish-http-purge-ip' );
|
424 |
do_settings_sections( 'varnish-ip-settings' );
|
425 |
+
submit_button( 'Save IP', 'secondary');
|
426 |
}
|
427 |
?></form>
|
428 |
|
437 |
* @since 4.0
|
438 |
*/
|
439 |
function varnish_ip_sanitize( $input ) {
|
440 |
+
|
441 |
+
$output = '';
|
442 |
+
$set_message = 'You have entered an invalid IP address.';
|
443 |
+
$set_type = 'error';
|
444 |
+
|
445 |
+
if ( empty($input) ) {
|
446 |
+
return; // do nothing
|
447 |
+
} elseif ( filter_var( $input, FILTER_VALIDATE_IP) ) {
|
448 |
+
$set_message = 'IP Updated.';
|
449 |
+
$set_type = 'updated';
|
450 |
$output = filter_var( $input, FILTER_VALIDATE_IP);
|
451 |
+
}
|
452 |
+
|
453 |
+
add_settings_error( 'vhp_varnish_url', 'varnish-url', $set_message, $set_type );
|
454 |
return $output;
|
455 |
}
|
456 |
|
463 |
function varnish_url_sanitize( $input ) {
|
464 |
|
465 |
$baseurl_host = parse_url( esc_url( VarnishPurger::the_home_url() ), PHP_URL_HOST );
|
466 |
+
$output = esc_url( VarnishPurger::the_home_url() );
|
467 |
+
$set_type = 'error';
|
468 |
+
|
469 |
+
if ( !empty($input) ) {
|
470 |
+
$parsed_input = parse_url($input);
|
471 |
+
if ( empty($parsed_input['scheme']) ) {
|
472 |
+
$schema_input = 'http://';
|
473 |
+
if ( is_ssl() ) {
|
474 |
+
$schema_input = 'https://';
|
475 |
+
}
|
476 |
+
$input = $schema_input . ltrim($input, '/');
|
477 |
+
}
|
478 |
}
|
479 |
+
|
480 |
+
if ( empty($input) ) {
|
481 |
+
$set_message = 'You must enter a URL from your own domain to scan.';
|
482 |
+
} elseif ( !filter_var( $input, FILTER_VALIDATE_URL) ) {
|
483 |
+
$set_message = 'You have entered an invalid URL address.';
|
484 |
+
} elseif ( $baseurl_host !== parse_url( $input, PHP_URL_HOST ) ) {
|
485 |
$set_message = 'You cannot scan URLs on other domains.';
|
486 |
+
} else {
|
487 |
+
$output = filter_var( $input, FILTER_VALIDATE_URL);
|
488 |
+
$set_message = 'Scanning New URL...';
|
489 |
+
$set_type = 'updated';
|
490 |
}
|
491 |
|
492 |
add_settings_error( 'vhp_varnish_url', 'varnish-url', $set_message, $set_type );
|
wp-cli.php
CHANGED
@@ -40,7 +40,7 @@ class WP_CLI_Varnish_Purge_Command extends WP_CLI_Command {
|
|
40 |
*
|
41 |
* wp varnish purge http://example.com/wp-content/themes/twentyeleventy/style.css
|
42 |
*
|
43 |
-
* wp
|
44 |
*
|
45 |
* wp varnish purge http://example.com/wp-content/themes/ --wildcard
|
46 |
*
|
@@ -54,25 +54,21 @@ class WP_CLI_Varnish_Purge_Command extends WP_CLI_Command {
|
|
54 |
$cli_version = WP_CLI_VERSION;
|
55 |
|
56 |
// Set the URL/path
|
57 |
-
list( $url ) = $args;
|
58 |
|
59 |
// If wildcard is set, or the URL argument is empty
|
60 |
// then treat this as a full purge
|
|
|
61 |
if ( isset( $assoc_args['wildcard'] ) || empty($url) ) {
|
62 |
$pregex = '/?vhp-regex';
|
63 |
$wild = ".*";
|
64 |
-
} else {
|
65 |
-
$pregex = $wild = '';
|
66 |
}
|
67 |
|
68 |
wp_create_nonce('vhp-flush-cli');
|
69 |
|
70 |
// Make sure the URL is a URL:
|
71 |
if ( !empty($url) ) {
|
72 |
-
|
73 |
-
if ( empty( esc_url( $url ) ) ) {
|
74 |
-
$url = $this->varnish_purge->the_home_url() . $url;
|
75 |
-
}
|
76 |
} else {
|
77 |
$url = $this->varnish_purge->the_home_url();
|
78 |
}
|
40 |
*
|
41 |
* wp varnish purge http://example.com/wp-content/themes/twentyeleventy/style.css
|
42 |
*
|
43 |
+
* wp varnish purge "/wp-content/themes/twentysixty/style.css"
|
44 |
*
|
45 |
* wp varnish purge http://example.com/wp-content/themes/ --wildcard
|
46 |
*
|
54 |
$cli_version = WP_CLI_VERSION;
|
55 |
|
56 |
// Set the URL/path
|
57 |
+
if ( !empty($args) ) { list( $url ) = $args; }
|
58 |
|
59 |
// If wildcard is set, or the URL argument is empty
|
60 |
// then treat this as a full purge
|
61 |
+
$pregex = $wild = '';
|
62 |
if ( isset( $assoc_args['wildcard'] ) || empty($url) ) {
|
63 |
$pregex = '/?vhp-regex';
|
64 |
$wild = ".*";
|
|
|
|
|
65 |
}
|
66 |
|
67 |
wp_create_nonce('vhp-flush-cli');
|
68 |
|
69 |
// Make sure the URL is a URL:
|
70 |
if ( !empty($url) ) {
|
71 |
+
$url = $this->varnish_purge->the_home_url() . esc_url( $url );
|
|
|
|
|
|
|
72 |
} else {
|
73 |
$url = $this->varnish_purge->the_home_url();
|
74 |
}
|