PluginProbe
NETSENSAI Shield / trunk
NETSENSAI Shield vtrunk
1.6.1 trunk 1.1 1.2 1.3 1.4 1.4.1 1.4.2 1.4.3 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.6.0
netsensai-shield / includes / disable_xml_rpc.php

disable_xml_rpc.php in NETSENSAI Shield trunk, at includes/disable_xml_rpc.php

149 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Exit if accessed directly.
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 /**
8 * Return whether an option value represents a checked WordPress checkbox.
9 *
10 * @param mixed $value Option value.
11 * @return bool
12 */
13 function ns_shield_htaccess_option_is_enabled( $value ) {
14 return true === $value || 1 === $value || '1' === $value;
15 }
16
17 /**
18 * Store and return a .htaccess synchronization result for later admin feedback.
19 *
20 * @param string $option Result option name.
21 * @param bool $success Whether the operation succeeded.
22 * @param string $code Machine-readable result code.
23 * @return array
24 */
25 function ns_shield_htaccess_sync_result( $option, $success, $code ) {
26 $result = array(
27 'success' => (bool) $success,
28 'code' => sanitize_key( $code ),
29 'time' => time(),
30 );
31
32 update_option( $option, $result, false );
33
34 return $result;
35 }
36
37 /**
38 * Synchronize one WordPress-managed .htaccess marker section.
39 *
40 * insert_with_markers() locks the file while updating its own marker section,
41 * leaving WordPress, administrator, and other-plugin rules untouched.
42 *
43 * @param string $marker Marker name without BEGIN or END.
44 * @param string[] $lines Lines to insert, or an empty array to clear them.
45 * @param string $result_option Option used to store the diagnostic result.
46 * @return array
47 */
48 function ns_shield_sync_htaccess_marker( $marker, $lines, $result_option ) {
49 $htaccess_file = ABSPATH . '.htaccess';
50
51 if ( ! file_exists( $htaccess_file ) ) {
52 return ns_shield_htaccess_sync_result( $result_option, false, 'htaccess_missing' );
53 }
54
55 if ( ! wp_is_writable( $htaccess_file ) ) {
56 return ns_shield_htaccess_sync_result( $result_option, false, 'htaccess_not_writable' );
57 }
58
59 if ( ! function_exists( 'insert_with_markers' ) ) {
60 require_once ABSPATH . 'wp-admin/includes/misc.php';
61 }
62
63 if ( ! function_exists( 'insert_with_markers' ) ) {
64 return ns_shield_htaccess_sync_result( $result_option, false, 'markers_unavailable' );
65 }
66
67 if ( ! insert_with_markers( $htaccess_file, $marker, $lines ) ) {
68 return ns_shield_htaccess_sync_result( $result_option, false, 'htaccess_write_failed' );
69 }
70
71 return ns_shield_htaccess_sync_result( $result_option, true, 'updated' );
72 }
73
74 /**
75 * Disable XML-RPC at runtime without touching .htaccess.
76 *
77 * @return void
78 */
79 function ns_shield_disable_xml_rpc() {
80 if ( ! ns_shield_htaccess_option_is_enabled( get_option( 'ns_shield_xml_rpc', false ) ) ) {
81 return;
82 }
83
84 add_filter( 'xmlrpc_enabled', '__return_false' );
85
86 if ( isset( $_SERVER['REQUEST_URI'] ) && false !== strpos( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'xmlrpc.php' ) ) {
87 header( 'HTTP/1.1 403 Forbidden' );
88 $user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '';
89 if ( false !== stripos( $user_agent, 'curl' ) ) {
90 exit( 'Protected by Netsensai Shield' );
91 }
92
93 exit( 'XML-RPC is disabled on this site.' );
94 }
95 }
96 add_action( 'init', 'ns_shield_disable_xml_rpc' );
97
98 /**
99 * Synchronize the XML-RPC marker section after an option save.
100 *
101 * @param mixed $value New option value.
102 * @return array
103 */
104 function ns_shield_sync_xml_rpc_htaccess( $value ) {
105 $lines = ns_shield_htaccess_option_is_enabled( $value )
106 ? array(
107 '<Files xmlrpc.php>',
108 ' order deny,allow',
109 ' deny from all',
110 '</Files>',
111 )
112 : array();
113
114 return ns_shield_sync_htaccess_marker(
115 'NETSENSAI SHIELD XML-RPC',
116 $lines,
117 'ns_shield_xml_rpc_htaccess_sync_result'
118 );
119 }
120
121 /**
122 * Synchronize after the option is first added.
123 *
124 * @param string $option Option name.
125 * @param mixed $value New option value.
126 * @return void
127 */
128 function ns_shield_xml_rpc_option_added( $option, $value ) {
129 ns_shield_sync_xml_rpc_htaccess( $value );
130 }
131 add_action( 'add_option_ns_shield_xml_rpc', 'ns_shield_xml_rpc_option_added', 10, 2 );
132
133 /**
134 * Synchronize only after the option value actually changes.
135 *
136 * @param mixed $old_value Previous option value.
137 * @param mixed $value New option value.
138 * @param string $option Option name.
139 * @return void
140 */
141 function ns_shield_xml_rpc_option_updated( $old_value, $value, $option ) {
142 if ( ns_shield_htaccess_option_is_enabled( $old_value ) === ns_shield_htaccess_option_is_enabled( $value ) ) {
143 return;
144 }
145
146 ns_shield_sync_xml_rpc_htaccess( $value );
147 }
148 add_action( 'update_option_ns_shield_xml_rpc', 'ns_shield_xml_rpc_option_updated', 10, 3 );
149