Acunetix WP Security - Version 4.0

Version Description

Download this release

Release Info

Developer Acunetix
Plugin Icon wp plugin Acunetix WP Security
Version 4.0
Comparing to
See all releases

Code changes from version 3.1.0 to 4.0

Files changed (104) hide show
  1. backups/index.php +0 -1
  2. css/acx-wp-dashboard.css +0 -17
  3. css/wsd.css +0 -329
  4. images/acunetix.png +0 -0
  5. images/agent-green.png +0 -0
  6. images/agent-red.png +0 -0
  7. images/facebook.gif +0 -0
  8. images/loading45.gif +0 -0
  9. images/wsd-logo-small.png +0 -0
  10. images/wsd-logo.png +0 -0
  11. inc/admin/db.php +0 -60
  12. inc/admin/plugin_options.php +0 -64
  13. inc/admin/pwtool.php +0 -49
  14. inc/admin/scanner.php +0 -37
  15. inc/admin/security.php +0 -30
  16. inc/admin/support.php +0 -74
  17. inc/admin/templates/db-backup.php +0 -91
  18. inc/admin/templates/db-change-prefix.php +0 -143
  19. inc/admin/templates/footer.php +0 -17
  20. inc/admin/templates/header.php +0 -11
  21. index.php +65 -0
  22. js/json.js +0 -482
  23. js/md5.js +0 -201
  24. js/remove_wp_version.js +0 -3
  25. js/scripts.js +0 -27
  26. js/wsd.js +0 -188
  27. libs/functions.php +0 -584
  28. libs/json.php +0 -806
  29. libs/recaptchalib.php +0 -277
  30. libs/wpssUtil.php +0 -167
  31. libs/wsd.php +0 -835
  32. readme.txt +144 -70
  33. res/backups/index.php +1 -0
  34. res/css/acx-styles-extra.css +1 -0
  35. res/css/blog.css +66 -0
  36. res/css/index.php +1 -0
  37. res/css/styles.alerts.css +54 -0
  38. res/css/styles.base.css +31 -0
  39. res/css/styles.general.css +196 -0
  40. res/css/styles.status.css +38 -0
  41. res/images/ajax-loader.gif +0 -0
  42. res/images/alert-info-critical.png +0 -0
  43. res/images/alert-info-icon.png +0 -0
  44. res/images/alerts-page-ico.png +0 -0
  45. images/wpss_icon_small_combined.png → res/images/arrow-black-icon.png +0 -0
  46. res/images/blog/featured-slider-bg.jpg +0 -0
  47. res/images/blog/ico-facebook.png +0 -0
  48. res/images/blog/ico-twitter.png +0 -0
  49. res/images/blog/index.php +1 -0
  50. res/images/blog/logo.png +0 -0
  51. images/wpss_icon_large.png → res/images/checkbox.png +0 -0
  52. {images → res/images}/close-button.png +0 -0
  53. res/images/green-check-icon.png +0 -0
  54. res/images/icon-info.png +0 -0
  55. res/images/index.php +1 -0
  56. res/images/indicator-blue.png +0 -0
  57. res/images/indicator-green.png +0 -0
  58. res/images/indicator-red.png +0 -0
  59. res/images/indicator-yellow.png +0 -0
  60. images/wsd-logo-small-list.png → res/images/logo-small.png +0 -0
  61. res/images/logo.png +0 -0
  62. {images → res/images}/rss.png +0 -0
  63. res/images/tooltips/index.php +1 -0
  64. res/images/tooltips/tt_bottom.gif +0 -0
  65. res/images/tooltips/tt_top.gif +0 -0
  66. res/inc/WsdCheck.php +286 -0
  67. res/inc/WsdInfo.php +317 -0
  68. res/inc/WsdLiveTraffic.php +223 -0
  69. res/inc/WsdPlugin.php +380 -0
  70. res/inc/WsdScheduler.php +115 -0
  71. res/inc/WsdSecurity.php +726 -0
  72. res/inc/WsdUtil.php +601 -0
  73. res/inc/WsdWatch.php +67 -0
  74. res/inc/alerts.php +64 -0
  75. res/inc/index.php +1 -0
  76. res/inc/wss-functions.php +36 -0
  77. res/index.php +1 -0
  78. res/js/index.php +1 -0
  79. res/js/wsd-util.js +25 -0
  80. res/js/wsdplugin_glossary_tooltip.js +78 -0
  81. res/languages/index.php +1 -0
  82. res/pages/about.php +57 -0
  83. res/pages/blog.php +113 -0
  84. res/pages/dashboard.php +134 -0
  85. res/pages/database.php +61 -0
  86. res/pages/index.php +1 -0
  87. res/pages/live_traffic.php +272 -0
  88. res/pages/scanner.php +39 -0
  89. res/pages/settings.php +168 -0
  90. res/pages/tpl/box-available-backups.php +26 -0
  91. res/pages/tpl/box-banners.php +9 -0
  92. res/pages/tpl/box-database-backup.php +57 -0
  93. res/pages/tpl/box-database-change-prefix.php +243 -0
  94. res/pages/tpl/box-scan-results-file.php +108 -0
  95. res/pages/tpl/box-scan-results-wp.php +13 -0
  96. res/pages/tpl/box-server-results.php +3 -0
  97. res/pages/tpl/index.php +1 -0
  98. screenshot-1.jpg +0 -0
  99. screenshot-2.jpg +0 -0
  100. screenshot-3.jpg +0 -0
  101. screenshot-4.jpg +0 -0
  102. securityscan.php +0 -268
  103. uninstall.php +0 -12
  104. wss-settings.php +74 -0
backups/index.php DELETED
@@ -1 +0,0 @@
1
- <?php /*[ Only to prevent directory listing ]*/ ?>
 
css/acx-wp-dashboard.css DELETED
@@ -1,17 +0,0 @@
1
- /*
2
- * manage the rss box on dashboard
3
- */
4
-
5
- #acx_plugin_dashboard_widget h3.hndle{
6
- background: url('../images/wsd-logo-small.png') no-repeat 5px 50%;
7
- padding-left: 35px; padding-top: 10px;
8
- }
9
- #acx_plugin_dashboard_widget h4 {
10
- margin: 0 0; font-size: 1.2em;
11
- /* background: url('../images/arrow-black-icon.png') no-repeat left center;
12
- background: url('../images/wsd-logo-small-list.png') no-repeat left center;
13
- padding-left: 20px;*/
14
- }
15
- #acx_plugin_dashboard_widget p { margin: 3px 0; }
16
-
17
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
css/wsd.css DELETED
@@ -1,329 +0,0 @@
1
- /********************************************************
2
- * BEGIN >> General styling
3
- */
4
- p.wsd-error-summary {
5
- background-color: #F9EFAC;
6
- border: 1px dotted #f00;
7
- color: #DC143C;
8
- padding: 5px 10px;
9
- margin: 10px;
10
- font-weight: bold;
11
- cursor: default;
12
- }
13
-
14
- span.wsd-error-summary-detail {
15
- color: #000;
16
- font-weight: normal;
17
- font-size: 11px;
18
- cursor: default;
19
- }
20
-
21
-
22
- p.wsd-success-summary {
23
- background-color: #90EE90;
24
- border: 1px dotted #f00;
25
- color: #000;
26
- padding: 5px 10px;
27
- margin: 10px;
28
- font-weight: bold;
29
- cursor: default;
30
- }
31
-
32
- span.wsd-success-summary-detail {
33
- color: #000;
34
- font-weight: normal;
35
- font-size: 11px;
36
- cursor: default;
37
- }
38
-
39
-
40
- p.wsd-login-notice {
41
- font-weight: bold;
42
- color: #000;
43
- margin-top: -10px;
44
- margin-bottom: 20px;
45
- }
46
-
47
- .wsd-inside {
48
- padding: 10px;
49
- font-family: Verdana, Arial, sans-serif !important;
50
- font-size: 100% !important;
51
- }
52
-
53
- p.wsd-error-summary a, .wsd-inside a {
54
- color: #CC0000;
55
- text-decoration: none;
56
- }
57
-
58
- p.wsd-error-summary a:hover, .wsd-inside a:hover {
59
- color: #CC0000;
60
- text-decoration: underline;
61
- }
62
-
63
- /********************************************************
64
- * BEGIN >> Login form styling
65
- */
66
- #wsd_login_form {
67
- margin: 0px;
68
- }
69
-
70
- #wsd_login_form .wsd-login-section {
71
- display: block;
72
- float: left;
73
- width: 100%;
74
- margin-bottom: 5px;
75
- }
76
-
77
- #wsd_login_form .wsd-login-section label {
78
- display: block;
79
- float: left;
80
- width: 70px;
81
- padding-top: 6px;
82
- }
83
-
84
- #wsd_login_form .wsd-login-section input {
85
- display: block;
86
- width: 200px;
87
- float: left;
88
- }
89
-
90
- #wsd_login_form #wsd-login {
91
- clear: left;
92
- margin-left: 70px;
93
- }
94
-
95
-
96
-
97
- /********************************************************
98
- * BEGIN >> Registration form styling
99
- */
100
- #wsd_new_user_form {
101
- margin: 0px;
102
- }
103
-
104
- #wsd_new_user_form .wsd-new-user-section {
105
- display: block;
106
- float: left;
107
- width: 100%;
108
- margin-bottom: 5px;
109
- }
110
-
111
- #wsd_new_user_form .wsd-new-user-section label {
112
- display: block;
113
- float: left;
114
- width: 120px;
115
- padding-top: 6px;
116
- }
117
-
118
- #wsd_new_user_form .wsd-new-user-section input {
119
- display: block;
120
- width: 200px;
121
- float: left;
122
- }
123
-
124
- #wsd_new_user_form #wsd-login {
125
- clear: left;
126
- margin-left: 70px;
127
- }
128
-
129
-
130
-
131
- /********************************************************
132
- * BEGIN >> Initial scan widget styling
133
- */
134
- #wsd-information-scan-list {
135
- list-style-type: disc;
136
- margin: 10px;
137
- padding-left: 20px;
138
- }
139
-
140
-
141
-
142
- #wsd-initial-scan { }
143
-
144
- #wsd-initial-scan .wsd-initial-scan-section {
145
- line-height: 1.4em;
146
- display: block;
147
- color: #090;
148
- }
149
-
150
-
151
- /********************************************************
152
- * BEGIN >> Target update form styling
153
- */
154
- #wsd_target_id_form {
155
- width: 100%;
156
- }
157
-
158
- #wsd_target_id_form #targetid {
159
- width: 300px;
160
- }
161
-
162
-
163
-
164
- /********************************************************
165
- * BEGIN >> Status content styling
166
- */
167
- div#wsd-target-status-holder {
168
- overflow: hidden;
169
- }
170
-
171
- p.wsd-target-status-title {
172
- font-weight: bold;
173
- }
174
-
175
- div.wsd-target-status-section {
176
- display: block;
177
- float: left;
178
- margin-right: 5px;
179
- }
180
-
181
- span.wsd-target-status-section-label {
182
- display: block;
183
- padding: 5px 4px;
184
- float: left;
185
- color: #999999
186
- }
187
-
188
- span.wsd-target-status-section-enabled {
189
- display: block;
190
- padding: 5px 0px;
191
- background-color: #0f0;
192
- color: #000;
193
- float: left;
194
- width: 50px;
195
- height: 24px;
196
- border-radius: 3px;
197
- -moz-border-radius: 3px;
198
- -webkit-border-radius: 3px;
199
- text-align: center;
200
- font-weight: bold;
201
-
202
- background: url('../images/agent-green.png') no-repeat scroll left top transparent;
203
- }
204
-
205
- span.wsd-target-status-section-disabled {
206
- display: block;
207
- padding: 5px 0px;
208
- background-color: #f00;
209
- color: #fff;
210
- float: left;
211
- width: 50px;
212
- height: 24px;
213
- border-radius: 3px;
214
- -moz-border-radius: 3px;
215
- -webkit-border-radius: 3px;
216
- text-align: center;
217
- font-weight: bold;
218
-
219
- background: url('../images/agent-red.png') no-repeat scroll left top transparent;
220
- }
221
-
222
-
223
-
224
-
225
- /********************************************************
226
- * BEGIN >> Password meter styling
227
- */
228
- #wsd_new_user_form label.password-meter {
229
- display: none;
230
- -webkit-border-radius: 3px;
231
- -moz-border-radius: 3px;
232
- font-weight: bolder;
233
- border-radius: 3px;
234
- text-align: center;
235
- font-size: 12px;
236
- color: #000;
237
- width: 80px;
238
- margin-left: 20px;
239
- padding: 4px;
240
- cursor: default;
241
- }
242
-
243
-
244
- /*
245
- * 3.0.2
246
- */
247
- .scanpass { color: #090; }
248
-
249
- .mrt_wpss_note {
250
- text-align: center;
251
- color: grey;
252
- margin-top: 20px;
253
- margin-bottom: 20px;
254
- }
255
-
256
- .wpss_icon {
257
- background: url(../images/wsd-logo.png) no-repeat left center;
258
- margin-top: 10px !important;
259
- padding: 5px 0 3px 50px !important;
260
- }
261
-
262
- .wsd_user_notify {
263
- border: solid 1px #fc0; background: #ffc;
264
- padding: 5px 5px;
265
- font-size: 100%;
266
- }
267
- .wsd_user_information {
268
- border: solid 1px #324FB2; background: #E5EAF0;
269
- padding: 5px 5px;
270
- font-size: 100%;
271
- }
272
- .wsd_user_success {
273
- border: solid 1px #030; background: #090;
274
- padding: 5px 5px;
275
- font-size: 100%;
276
- color: #fff;
277
- }
278
- .wsd_info_list {
279
- list-style-type: disc;
280
- list-style-position: outside;
281
- margin: 0 0 10px 25px;
282
- }
283
- div.wsd_user_information, div.wsd_user_notify, div.wsd_user_success { margin: 1em 0 !important; }
284
-
285
- #Words { overflow: hidden; min-height: 1px; margin: 0 0 0 0 !important; padding: 0 0 0 0 !important; }
286
- #Words p { float: left; display: block; width: 150px; line-height: normal !important; padding: 0 0 0 0; margin: 6px 0 0 0 !important; }
287
- #Words p.indicator { height: 4px; }
288
- #Words p.indicator-1 { background: #f00;}
289
- #Words p.indicator-2 { background: #990000; }
290
- #Words p.indicator-3 { background: #990099; }
291
- #Words p.indicator-4 { background: #000099; }
292
- #Words p.indicator-5 { background: #0000ff; }
293
- #Words p.indicator-6 { background: #ffffff; }
294
- #Words p+p {margin: 0 0 0 5px !important; padding: 0 0 0 0 !important; line-height: normal !important;}
295
- #wsd_pwdtool { margin-top: 10px; }
296
-
297
- .wsd_commonList {
298
- list-style-type: none;
299
- margin: 0 0 10px 0;
300
- padding-left: 0;
301
- }
302
- .wsd_commonList li {
303
- font-style: italic !important;
304
- background: url('../images/wsd-logo-small-list.png') no-repeat 0 50%;
305
- padding: 2px 0 2px 20px !important;
306
- }
307
-
308
- .wsd-inside p, .wsd-inside ul, .wsd-inside ol, .wsd-inside blockquote, .wsd-inside input, .wsd-inside select {
309
- font-size: 100%;
310
- }
311
-
312
- .wsd-inside, .wsd-inside p, .wsd-inside li, .wsd-inside dl, .wsd-inside dd, .wsd-inside dt {
313
- line-height: normal !important;
314
- }
315
-
316
- #wsd_db_wrapper .inner-sidebar1 { margin: 10px 10px 0 10px; }
317
- #wsd_db_wrapper, #wsd_db_wrapper .metabox-holder {overflow:hidden; min-height:1px; }
318
- #wsd_permissions_table { margin: 15px 0; }
319
- #wsd_permissions_table th,
320
- #wsd_permissions_table td { text-align: left; }
321
- #wsd_permissions_table td { padding: 1px 7px;}
322
- #wsd_tables_list_block { clear: both;}
323
-
324
- .wsd_cursor_help { cursor: help; border-bottom: dotted 1px #000; }
325
-
326
-
327
-
328
-
329
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
images/acunetix.png DELETED
Binary file
images/agent-green.png DELETED
Binary file
images/agent-red.png DELETED
Binary file
images/facebook.gif DELETED
Binary file
images/loading45.gif DELETED
Binary file
images/wsd-logo-small.png DELETED
Binary file
images/wsd-logo.png DELETED
Binary file
inc/admin/db.php DELETED
@@ -1,60 +0,0 @@
1
- <?php
2
- function mrt_sub3()
3
- {
4
- // Show header
5
- mrt_wpss_menu_head('WP - Database Security');
6
-
7
- $wsd_wpConfigFile = ABSPATH.'wp-config.php';
8
-
9
- // internal flag
10
- $canLoadPage = false;
11
- if (wsd_wpConfigCheckPermissions($wsd_wpConfigFile)) {
12
- $canLoadPage = true;
13
- }
14
- ?>
15
- <p class="wsd_user_notify">
16
- <strong>Important</strong>: Make a backup of your database before using this tool!
17
- </p>
18
- <?php
19
- if (!$canLoadPage) {
20
- // Display the error message
21
- echo wsd_eInfo('
22
- The <strong>wp-config.php</strong> file MUST be writable in order to perform this action.
23
- You have to manually change permissions for this file.');
24
- }
25
- ?>
26
-
27
-
28
- <?php /*[ BEGIN PAGE DATABASE ]*/ ?>
29
- <div id="wsd_db_wrapper">
30
- <?php
31
- /* Display the Database backup page */
32
- echo wsd_getTemplate('db-backup');
33
- ?>
34
-
35
- <br/>
36
- <div style="clear:both;"></div>
37
-
38
- <?php
39
- /* Stop here if the wp-config file is not writable or if we cannot change its permissions */
40
- if ($canLoadPage)
41
- {
42
- // Display the Change Database Table prefix page
43
- echo wsd_getTemplate('db-change-prefix',array(
44
- 'wsd_wpConfigFile' => $wsd_wpConfigFile,
45
- 'old_prefix' => $GLOBALS['table_prefix'],
46
- 'new_prefix' => (empty($_POST['newPrefixInput']) ? '' : $_POST['newPrefixInput']),
47
- 'isPostBack' => (($_SERVER['REQUEST_METHOD'] == 'POST') ? true : false)
48
- ));
49
- }
50
- ?>
51
- </div>
52
- <?php /*[ END PAGE DATABASE ]*/ ?>
53
-
54
- <p style="height:200px;"></p>
55
-
56
- <?php
57
- // Show footer
58
- mrt_wpss_menu_footer();
59
- }//function mrt_sub3
60
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/admin/plugin_options.php DELETED
@@ -1,64 +0,0 @@
1
- <?php
2
- function mrt_sub4(){
3
-
4
- mrt_wpss_menu_head('Plugin options');
5
-
6
- ?>
7
-
8
- <div class="metabox-holder">
9
- <div class="postbox" style="width: 60%;">
10
- <h3 class="hndle"><span><?php echo __('Plugin options');?></span></h3>
11
- <div class="inside">
12
- <p></p>
13
- <?php
14
- //# 10/04/2011
15
- $_checked = false;
16
- if ($_SERVER['REQUEST_METHOD'] == 'POST')
17
- {
18
- if($_POST['show_rss_widget'] == 'on'){
19
- update_option('WSD-RSS-WGT-DISPLAY', 'yes');
20
- $_checked = true;
21
- }
22
- else {
23
- update_option('WSD-RSS-WGT-DISPLAY', 'no');
24
- $_checked = false;
25
- }
26
- }
27
- $wsdRssWidgetVisible = get_option('WSD-RSS-WGT-DISPLAY');
28
- if (empty($wsdRssWidgetVisible) || $wsdRssWidgetVisible=='yes') {
29
- add_option('WSD-RSS-WGT-DISPLAY', 'yes');
30
- $_checked = true;
31
- }
32
- else {
33
- if (strtolower($wsdRssWidgetVisible) == 'no') {
34
- $_checked = false;
35
- }
36
- }
37
- //@++
38
- ?>
39
- <div class="acx-section-box">
40
-
41
- <form id="plugin_options_form" method="post">
42
- <div>
43
- <input type="checkbox" name="show_rss_widget" id="show_rss_widget" <?php echo ($_checked ? 'checked="checked"' : '');?> />
44
- <label for="show_rss_widget"><?php echo __("Show the WebsiteDefender News dashboard widget");?></label>
45
- </div>
46
-
47
- <div>
48
- <p style="margin-top: 25px">
49
- <input type="submit" class="button-primary" value="<?php echo __('Update');?>"/>
50
- </p>
51
- </div>
52
- </form>
53
-
54
- </div>
55
- <p></p>
56
- </div>
57
- </div>
58
- </div>
59
-
60
-
61
- <?php
62
- mrt_wpss_menu_footer();
63
-
64
- } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/admin/pwtool.php DELETED
@@ -1,49 +0,0 @@
1
- <?php
2
- function mrt_sub1(){
3
-
4
- mrt_wpss_menu_head('WP - Password Tools');
5
-
6
- ?>
7
-
8
- <div class="metabox-holder">
9
- <div class="postbox" style="width: 60%;">
10
- <h3 class="hndle"><span><?php echo __('Password Strength Tool');?></span></h3>
11
- <div class="inside">
12
- <p></p>
13
- <table id="wsd_pwdtool">
14
- <tr valign="top">
15
- <td>
16
- <form name="commandForm">
17
- Type password: <input type="password" size="30" maxlength="50" name="password" onkeyup="testPassword(this.value);" value="" />
18
- <br/>
19
- <span style="color:#808080">Minimum 6 Characters</span>
20
- </form>
21
- </td>
22
- <td style="padding-left: 6px;">
23
- <span>Password Strength:</span>
24
- <div id="Words">
25
- <p class="indicator"></p>
26
- <p><strong>Begin Typing</strong></p>
27
- </div>
28
- </td>
29
- </tr>
30
- </table>
31
- <p></p>
32
- </div>
33
- </div>
34
- </div>
35
-
36
- <div>
37
- <?php
38
- echo "<br /><strong>Strong Password Generator</strong><br />";
39
- echo "Strong Password: " . '<span style="color:#f00;">' . make_password(15) . "</span>";
40
- ?>
41
- </div>
42
- <br/><br/>
43
- <p style="margin-top: 75px;"></p>
44
- <hr align="left" size="2" width="612px" />
45
-
46
- <?php
47
- mrt_wpss_menu_footer();
48
-
49
- } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/admin/scanner.php DELETED
@@ -1,37 +0,0 @@
1
- <?php
2
- function mrt_sub0(){
3
-
4
- mrt_wpss_menu_head('WP - Security Scan');?>
5
-
6
- <div class="metabox-holder">
7
- <div class="postbox">
8
- <h3 class="hndle"><span><?php echo __('Directory Info');?></span></h3>
9
- <div class="inside">
10
- <table id="wsd_permissions_table" width="100%" border="0" cellspacing="0" cellpadding="3"
11
- style="text-align:center; border: solid 1px #333;">
12
- <thead style="background: #333;">
13
- <th style="border:0px; padding: 4px 4px;"><strong style="color: #f5f5f5">Name</strong></th>
14
- <th style="border:0px; padding: 4px 4px;"><strong style="color: #f5f5f5">File/Dir</strong></th>
15
- <th style="border:0px; padding: 4px 4px;"><strong style="color: #f5f5f5">Needed Chmod</strong></th>
16
- <th style="border:0px; padding: 4px 4px;"><strong style="color: #f5f5f5">Current Chmod</strong></th>
17
- </thead>
18
- <tbody>
19
- <?php
20
- // DIR_NAME | DIR_PATH | EXPECTED_PERMISSION
21
- check_perms("root directory","../","0755");
22
- check_perms("wp-includes/","../wp-includes","0755");
23
- check_perms(".htaccess","../.htaccess","0644");
24
- check_perms("wp-admin/index.php","index.php","0644");
25
- check_perms("wp-admin/js/","js/","0755");
26
- check_perms("wp-content/themes/","../wp-content/themes","0755");
27
- check_perms("wp-content/plugins/","../wp-content/plugins","0755");
28
- check_perms("wp-admin/","../wp-admin","0755");
29
- check_perms("wp-content/","../wp-content","0755");
30
- ?>
31
- </tbody>
32
- </table>
33
-
34
- </div></div></div>
35
- <?php
36
- mrt_wpss_menu_footer();
37
- } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/admin/security.php DELETED
@@ -1,30 +0,0 @@
1
- <?php
2
-
3
- function mrt_opt_mng_pg() {
4
- mrt_wpss_menu_head('WP-Security Admin tools by WebsiteDefender');
5
-
6
- add_meta_box("wpss_mrt_1", 'Initial Scan', "wpss_mrt_meta_box", "wpss");
7
- add_meta_box("wpss_mrt_2", 'System Information Scan', "wpss_mrt_meta_box2", "wpss2");
8
- add_meta_box("wpss_mrt_3", 'About Website Defender', "wsd_render_main", "wpss_wsd");
9
-
10
- echo '
11
- <div class="metabox-holder">
12
- <div style="float:left; width:48%;" class="inner-sidebar1">';
13
-
14
- do_meta_boxes('wpss','advanced','');
15
- do_meta_boxes('wpss2','advanced','');
16
-
17
- echo '
18
- </div>
19
- <div style="float:right;width:48%;" class="inner-sidebar1">';
20
- do_meta_boxes('wpss_wsd','advanced','');
21
- echo '
22
- </div>
23
-
24
- <div style="clear:both"></div>
25
- </div>';
26
-
27
- mrt_wpss_menu_footer();
28
-
29
- }
30
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/admin/support.php DELETED
@@ -1,74 +0,0 @@
1
- <?php
2
- function mrt_sub2()
3
- {
4
- mrt_wpss_menu_head('WP - Security Support');
5
- ?><?php /*
6
- <div>
7
- <br/>
8
- <p>Under Construction...</p>
9
- <br /><br />
10
- <ul>
11
- <li><a href='http://www.websitedefender.com/category/faq/' target="_blank">Documentation</a></li>
12
- </ul>
13
- <br /><br />
14
- <strong>Backup early, backup often!</strong>
15
- <br /><br /><br /><br /><br />
16
- </div>
17
- */?>
18
-
19
- <div class="metabox-holder">
20
- <div class="postbox">
21
- <h3 class="hndle"><span><?php echo __('About WebsiteDefender');?></span></h3>
22
- <div class="inside">
23
- <p><?php echo __('A secure website, free from malware, where your customers can feel safe is vital to your online success.
24
- Unfortunately, the number of web hacking attacks has risen dramatically. Website security is an absolute must.
25
- If you do not protect your website, hackers can gain access to your website, modify your web content, install malware
26
- and have your site banned from Google. They could modify scripts and gain access to your customer data and their credit card details…');?></p>
27
-
28
- <p><?php echo __('WebsiteDefender is an online service that monitors your website for hacker activity, audits the security
29
- of your web site and gives you easy to understand solutions to keep your website safe. With WebsiteDefender you can:');?></p>
30
-
31
- <ul class="wsd_info_list">
32
- <li><?php echo __('Detect Malware present on your website');?></li>
33
- <li><?php echo __('Audit your web site for security issues');?></li>
34
- <li><?php echo __('Avoid getting blacklisted by Google');?></li>
35
- <li><?php echo __('Keep your web site content &amp; data safe');?></li>
36
- <li><?php echo __('Get alerted to suspicious hacker activity');?></li>
37
- </ul>
38
-
39
- <p><?php echo __('All via an easy-to-understand web based dashboard which gives step by step solutions!
40
- Sign up for your FREE account <a href="admin.php?page=wp-security-scan/securityscan.php">here</a>.');?></p>
41
- </div>
42
- </div>
43
- </div>
44
-
45
-
46
- <div class="metabox-holder">
47
- <div class="postbox">
48
- <h3 class="hndle"><span><?php echo __('Get Involved!');?></span></h3>
49
- <div class="inside">
50
- <p></p>
51
- <ul class="wsd_info_list">
52
- <li>
53
- <span><a href="http://www.websitedefender.com/forums/" target="_blank"><?php echo __('WebsiteDefender forums');?></a></span>
54
- </li>
55
- <li>
56
- <span><a href="http://www.websitedefender.com/blog/" target="_blank"><?php echo __('WebsiteDefender blog');?></a></span>
57
- </li>
58
- <li>
59
- <span><a href="http://twitter.com/#!/websitedefender" target="_blank"><?php echo __('WebsiteDefender on Twitter');?></a></span>
60
- </li>
61
- <li>
62
- <span><a href="http://www.facebook.com/WebsiteDefender" target="_blank"><?php echo __('WebsiteDefender on Facebook');?></a></span>
63
- </li>
64
- </ul>
65
- <p></p>
66
- </div>
67
- </div>
68
- </div>
69
-
70
-
71
- <?php
72
- mrt_wpss_menu_footer();
73
- }
74
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/admin/templates/db-backup.php DELETED
@@ -1,91 +0,0 @@
1
- <?php
2
- /*
3
- * Backup Database
4
- */
5
- ?>
6
- <?php
7
- /*
8
- * BACKUP DATABASE SECTION
9
- */
10
- ?>
11
- <br/><br/>
12
- <h2 class="wpss_icon">Backup your database</h2>
13
-
14
- <?php
15
- /*
16
- * Check if the backups directory is writable
17
- */
18
- $wsd_bckDirPath = ABSPATH.PLUGINDIR.'/wp-security-scan/backups/';
19
- if (is_dir($wsd_bckDirPath) && is_writable($wsd_bckDirPath)) :
20
- ?>
21
-
22
- <div style="padding: 7px 7px; margin: 10px 10px;">
23
- <form action="#bck" method="post">
24
- <input type="hidden" name="wsd_db_backup"/>
25
- <input type="submit" name="backupDatabaseButton" value="Backup now!"/>
26
- </form>
27
- </div>
28
-
29
- <?php
30
- if ($_SERVER['REQUEST_METHOD'] == 'POST')
31
- {
32
- if (isset($_POST['wsd_db_backup']))
33
- {
34
- $tables = '*';
35
- if (isset($_POST['tables'])) {
36
- $tables = implode(',',$_POST['tables']);
37
- }
38
-
39
- if (($fname = wsd_backupDatabase($tables)) <> '') {
40
- echo '<p id="bck" class="wsd_user_success">';
41
- echo '<span style="color:#fff;">Database successfully backed up!</span>';
42
- echo '<br/><span style="color:#fff;">Download backup file: </span>';
43
- echo '<a href="',get_option('siteurl'),'/wp-content/plugins/wp-security-scan/backups/',$fname,'" style="color:#0f0">',$fname,'</a>';
44
- echo '</p>';
45
- }
46
- else {
47
- echo '<p id="bck" class="wsd_user_notify">';
48
- echo 'The database could not be backed up!';
49
- echo '<br/>A posible error might be that you didn\'t set up writing permissions for the backups directory!';
50
- echo '</p>';
51
- }
52
- }
53
- }
54
- ?>
55
- <?php else :
56
- // The directory is not writable. Display info message
57
- echo wsd_eInfo('<strong>Important</strong>: The <strong title="'.$wsd_bckDirPath.'" class="wsd_cursor_help">backups</strong> directory must be writable in order to use this functionality!');
58
- endif; ?>
59
-
60
-
61
-
62
- <?php
63
- /*
64
- * DISPLAY AVAILABLE DOWNLOADS
65
- */
66
- ?>
67
- <?php
68
- function wsd_db_download_list()
69
- {
70
- echo '<div>';
71
- $files = wsd_getAvailableBackupFiles();
72
- if (empty($files)) {
73
- echo '<p style="margin:5px 5px;">There are no backup files available for download yet!</p>';
74
- }
75
- else {
76
- echo '<ul id="wsd-information-scan-list">';
77
- foreach($files as $fileName) {
78
- echo '<li>';
79
- echo '<a href="',get_option('siteurl'),'/wp-content/plugins/wp-security-scan/backups/',$fileName,'">',$fileName,'</a>';
80
- echo '</li>';
81
- }
82
- echo '</ul>';
83
- }
84
- echo '</div>';
85
- }
86
- add_meta_box("wpss_mrt_1", 'Available database backups', "wsd_db_download_list", "wsd_db_bck_dwl");
87
- echo '<div style="float:left; width:50%;" class="inner-sidebar1">';
88
- echo '<div class="metabox-holder">';
89
- do_meta_boxes('wsd_db_bck_dwl','advanced','');
90
- echo '</div></div>';
91
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/admin/templates/db-change-prefix.php DELETED
@@ -1,143 +0,0 @@
1
- <?php
2
- /*
3
- * Change Database table Prefix
4
- */
5
- ?>
6
- <br/><br/>
7
- <h2 class="wpss_icon">Change database table prefix</h2>
8
-
9
- <?php
10
- // Holds the error/info messages generated on form postback
11
- $infoMessage = '';
12
-
13
- // Check if user has enough rights to alter the Table structure
14
- $wsd_userDbRights = wsd_getDbUserRights();
15
- $showPage = false; // assume we don't have ALTER rights
16
- if ($wsd_userDbRights['rightsEnough']) {
17
- $showPage = true;
18
- $canAlter = '<span style="color: #060; font-weight: 900;">(Yes)</span>';
19
- }
20
- else { $canAlter = '<span style="color: #f00; font-weight: 900;">(No)</span>'; }
21
- ?>
22
- <p>Change your database table prefix to mitigate zero-day SQL Injection attacks.</p>
23
- <p><strong>Before running this script:</strong>
24
- <ul class="wsd_info_list">
25
- <li>The <strong title="<?php echo ABSPATH.'wp-config.php'; ?>" class="wsd_cursor_help">wp-config.php</strong> file must be set to writable before running this script. <span style="color: #060; font-weight: 900;">(Yes)</span></li>
26
- <li>The database user you're using with WordPress must have <strong>ALTER</strong> rights. <?php echo $canAlter;?></li>
27
- </ul>
28
- <?php
29
- /*
30
- * If the user doesn't have ALTER rights
31
- */
32
- if ( ! $showPage )
33
- {
34
- echo wsd_eInfo('The User: <strong>'.DB_USER.'</strong> used to access the database server must have <strong>ALTER</strong> rights in order to perform this action!');
35
-
36
- // Stop here, no need to load the rest of the page
37
- return;
38
- }
39
- ?>
40
-
41
- <?php
42
- /*
43
- * Issue the file permissions warning
44
- */
45
- $infoMessage = 'It\'s a security risk to have your files writable (0777)!
46
- Please make sure that after running this script, the <strong title="'.ABSPATH.'wp-config.php" class="wsd_cursor_help">wp-config.php</strong> file\'s permissions are set to 0644!
47
- <br/> See: <a href="http://codex.wordpress.org/Changing_File_Permissions" target="_blank">http://codex.wordpress.org/Changing_File_Permissions</a> for more information.';
48
- echo wsd_eInfo($infoMessage,'information');
49
- ?>
50
-
51
-
52
- <?php
53
- /*
54
- * VALIDATE FORM
55
- */
56
- if (!empty($_POST['newPrefixInput']) && isset($_POST['changePrefixButton']))
57
- {
58
- $wsd_isPostBack = true;
59
-
60
- check_admin_referer('prefix-changer-change_prefix');
61
-
62
- $wpdb =& $GLOBALS['wpdb'];
63
- $new_prefix = preg_replace("[^0-9a-zA-Z_]", "", $_POST['newPrefixInput']);
64
- if (empty($wsd_userDbRights['rightsEnough'])) {
65
- $wsd_Message .= wsd_eInfo('The User which is used to access your Wordpress Database, hasn\'t enough rights (is missing the ALTER right) to alter the Table structure.
66
- <br/>Please visit the <a href="http://www.websitedefender.com/category/faq/" target=_blank">WebsiteDefender WP Security Scan WordPress plugin documentation</a> website for more information.
67
- <br/>If the user <code>has ALTER rights</code> and the tool is still not working, please <a href="http://www.websitedefender.com/support/" target="_blank">contact us</a> for assistance!');
68
- }
69
- if (!empty($wsd_userDbRights['rightsTooMuch'])) {
70
- $wsd_Message .= wsd_eInfo('Your currently used User to access the Wordpress Database, holds too many rights.'.
71
- '<br/>We suggest that you limit his rights or to use another User with more limited rights instead, to increase your Security.','information');
72
- }
73
- if (strlen($new_prefix) < strlen($_POST['newPrefixInput'])){
74
- $wsd_Message .= wsd_eInfo('You used some characters disallowed in Table names. The sanitized prefix will be used instead: '. $new_prefix,'information');
75
- }
76
- if ($new_prefix == $old_prefix) {
77
- $wsd_Message .= wsd_eInfo('No change! Please select a new table prefix value.');
78
- }
79
- else
80
- {
81
- // Get the list of tables to modify
82
- $tables = wsd_getTablesToAlter();
83
- if (empty($tables))
84
- {
85
- $wsd_Message .= wsd_eInfo('There are no tables to rename!');
86
- }
87
- else
88
- {
89
- $result = wsd_renameTables($tables, $old_prefix, $new_prefix);
90
-
91
- // check for errors
92
- if (!empty($result))
93
- {
94
- $wsd_Message .= wsd_eInfo('All tables have been successfully updated!','success');
95
-
96
- // try to rename the fields
97
- $wsd_Message .= wsd_renameDbFields($old_prefix, $new_prefix);
98
-
99
- if (wsd_updateWpConfigTablePrefix($wsd_wpConfigFile, $old_prefix, $new_prefix))
100
- {
101
- $wsd_Message .= wsd_eInfo('The wp-config file has been successfully updated!','success');
102
- }
103
- else {
104
- $wsd_Message .= wsd_eInfo('The wp-config file could not be updated! You have to manually update the table_prefix variable
105
- to the one you have specified: '.$new_prefix);
106
- }
107
- }// End if tables successfully renamed
108
- else {
109
- $wsd_Message .= wsd_eInfo('An error has occurred and the tables could not be updated!');
110
- }
111
- }// End if there are tables to rename
112
- }
113
- }// End if (!empty($_POST['newPrefixInput']))
114
- else {
115
- $new_prefix = $old_prefix;
116
- }
117
- ?>
118
-
119
-
120
-
121
- <br/>
122
- <form action="#cdtp" method="post" name="prefixchanging">
123
- <?php
124
- if (function_exists('wp_nonce_field')) {
125
- wp_nonce_field('prefix-changer-change_prefix');
126
- }
127
- ?>
128
- <p>Change the current:
129
- <input type="text" name="newPrefixInput" value="<?php echo $new_prefix;?>" size="20" maxlength="15"/>
130
- table prefix to something different.</p>
131
- <p>Allowed characters: all latin alphanumeric as well as the <strong>_</strong> (underscore).</p>
132
- <input type="submit" name="changePrefixButton" value="Start Renaming" />
133
- </form>
134
-
135
- <div id="cdtp">
136
- <?php
137
- // Display status information
138
- if ($isPostBack)
139
- {
140
- echo $wsd_Message;
141
- }
142
- ?>
143
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/admin/templates/footer.php DELETED
@@ -1,17 +0,0 @@
1
- <?php
2
-
3
- function mrt_wpss_menu_footer(){
4
- echo '
5
- <div style="clear:both;"></div>
6
- <br />
7
- <em>For comments, suggestions, queries and bug reports please visit
8
- the <a href="http://www.websitedefender.com/forums/" target="_blank"
9
- title="WebsiteDefender Forums">WebsiteDefender Forums</a></em>.
10
-
11
- Plugin by <a href="http://websitedefender.com/" target="_blank"
12
- title="WebsiteDefender">WebsiteDefender</a>
13
- </div>
14
- ';
15
- }
16
-
17
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/admin/templates/header.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
-
3
- function mrt_wpss_menu_head($title){
4
-
5
- echo '
6
- <div class="wrap">
7
- <h2 class="wpss_icon">' . $title . '</h2>';
8
-
9
- }
10
-
11
- ?>
 
 
 
 
 
 
 
 
 
 
 
index.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ Plugin Name: Acunetix WP Security
4
+ Plugin URI: http://www.acunetix.com/websitesecurity/wordpress-security-plugin/
5
+ Description: The Acunetix WP Security plugin is the ultimate must-have tool when it comes to WordPress security. The plugin is free and monitors your website for security weaknesses that hackers might exploit and tells you how to easily fix them.
6
+ Version: 4.0.0
7
+ Author: Acunetix
8
+ Author URI: http://www.acunetix.com/
9
+ License: GPLv2 or later
10
+ Text Domain: WSDWP_SECURITY
11
+ Domain Path: /languages
12
+ */
13
+ define('WSS_PLUGIN_PREFIX', 'wss_');
14
+ define('WSS_PLUGIN_NAME', 'Acunetix WP Security');
15
+ define('WSS_PLUGIN_URL', trailingslashit(plugins_url('', __FILE__)));
16
+ define('WSS_PLUGIN_DIR', trailingslashit(plugin_dir_path(__FILE__)));
17
+ define('WSS_PLUGIN_BASE_NAME', basename(__DIR__));
18
+
19
+
20
+ require('wss-settings.php');
21
+ require('res/inc/alerts.php');
22
+ require('res/inc/WsdUtil.php');
23
+ require('res/inc/WsdPlugin.php');
24
+ require('res/inc/WsdInfo.php');
25
+ require('res/inc/WsdSecurity.php');
26
+ require('res/inc/WsdCheck.php');
27
+ require('res/inc/WsdScheduler.php');
28
+ require('res/inc/WsdWatch.php');
29
+ require('res/inc/WsdLiveTraffic.php');
30
+ require('res/inc/wss-functions.php');
31
+
32
+
33
+ //#!--
34
+ add_action('admin_init', array('WsdUtil','loadPluggable'));
35
+ register_activation_hook( __FILE__, array('WsdPlugin', 'activate') );
36
+ register_deactivation_hook( __FILE__, array('WsdPlugin', 'deactivate') );
37
+ register_uninstall_hook( __FILE__, array('WsdPlugin', 'uninstall') );
38
+ //#++
39
+
40
+
41
+ //#! register tasks
42
+ if(false !== get_option('WSD-PLUGIN-CAN-RUN-TASKS',false))
43
+ {
44
+ WsdScheduler::registerTask(array('WsdPlugin','loadResources'), 'init');
45
+ WsdScheduler::registerTask(array('WsdPlugin','createWpMenu'), 'admin_menu');
46
+ WsdScheduler::registerTask(array('WsdLiveTraffic','registerHit'), 'init');
47
+ WsdScheduler::registerTask(array('WsdLiveTraffic','ajaxGetTrafficData'), 'wp_ajax_ajaxGetTrafficData');
48
+ WsdScheduler::registerTask(array('WsdLiveTraffic','ajaxGetTrafficData'), 'wp_ajax_nopriv_ajaxGetTrafficData');
49
+ WsdScheduler::registerTask(array('WsdUtil','addDashboardWidget'), 'wp_dashboard_setup');
50
+
51
+ // override - scheduled task
52
+ WsdScheduler::registerCronTask('wsd_check_user_admin', array('WsdCheck','adminUsername'), '8h');
53
+
54
+ // scheduled task - hourly cleanup of events in live traffic
55
+ WsdScheduler::registerCronTask('wsd_cleanup_live_traffic', array('WsdLiveTraffic','clearEvents'), 'hourly');
56
+
57
+ // stacked
58
+ WsdScheduler::registerTask(array('WsdWatch','userPasswordUpdate'));
59
+
60
+ // #! run fixes. Only those checked by the user will run (@see: settings page)
61
+ WsdScheduler::registerClassTasks('WsdSecurity','fix_');
62
+
63
+ //#! run checks.
64
+ WsdScheduler::registerClassTasks('WsdCheck','check_');
65
+ }
js/json.js DELETED
@@ -1,482 +0,0 @@
1
- /*
2
- http://www.JSON.org/json2.js
3
- 2010-03-20
4
-
5
- Public Domain.
6
-
7
- NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
8
-
9
- See http://www.JSON.org/js.html
10
-
11
-
12
- This code should be minified before deployment.
13
- See http://javascript.crockford.com/jsmin.html
14
-
15
- USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
16
- NOT CONTROL.
17
-
18
-
19
- This file creates a global JSON object containing two methods: stringify
20
- and parse.
21
-
22
- JSON.stringify(value, replacer, space)
23
- value any JavaScript value, usually an object or array.
24
-
25
- replacer an optional parameter that determines how object
26
- values are stringified for objects. It can be a
27
- function or an array of strings.
28
-
29
- space an optional parameter that specifies the indentation
30
- of nested structures. If it is omitted, the text will
31
- be packed without extra whitespace. If it is a number,
32
- it will specify the number of spaces to indent at each
33
- level. If it is a string (such as '\t' or '&nbsp;'),
34
- it contains the characters used to indent at each level.
35
-
36
- This method produces a JSON text from a JavaScript value.
37
-
38
- When an object value is found, if the object contains a toJSON
39
- method, its toJSON method will be called and the result will be
40
- stringified. A toJSON method does not serialize: it returns the
41
- value represented by the name/value pair that should be serialized,
42
- or undefined if nothing should be serialized. The toJSON method
43
- will be passed the key associated with the value, and this will be
44
- bound to the value
45
-
46
- For example, this would serialize Dates as ISO strings.
47
-
48
- Date.prototype.toJSON = function (key) {
49
- function f(n) {
50
- // Format integers to have at least two digits.
51
- return n < 10 ? '0' + n : n;
52
- }
53
-
54
- return this.getUTCFullYear() + '-' +
55
- f(this.getUTCMonth() + 1) + '-' +
56
- f(this.getUTCDate()) + 'T' +
57
- f(this.getUTCHours()) + ':' +
58
- f(this.getUTCMinutes()) + ':' +
59
- f(this.getUTCSeconds()) + 'Z';
60
- };
61
-
62
- You can provide an optional replacer method. It will be passed the
63
- key and value of each member, with this bound to the containing
64
- object. The value that is returned from your method will be
65
- serialized. If your method returns undefined, then the member will
66
- be excluded from the serialization.
67
-
68
- If the replacer parameter is an array of strings, then it will be
69
- used to select the members to be serialized. It filters the results
70
- such that only members with keys listed in the replacer array are
71
- stringified.
72
-
73
- Values that do not have JSON representations, such as undefined or
74
- functions, will not be serialized. Such values in objects will be
75
- dropped; in arrays they will be replaced with null. You can use
76
- a replacer function to replace those with JSON values.
77
- JSON.stringify(undefined) returns undefined.
78
-
79
- The optional space parameter produces a stringification of the
80
- value that is filled with line breaks and indentation to make it
81
- easier to read.
82
-
83
- If the space parameter is a non-empty string, then that string will
84
- be used for indentation. If the space parameter is a number, then
85
- the indentation will be that many spaces.
86
-
87
- Example:
88
-
89
- text = JSON.stringify(['e', {pluribus: 'unum'}]);
90
- // text is '["e",{"pluribus":"unum"}]'
91
-
92
-
93
- text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
94
- // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
95
-
96
- text = JSON.stringify([new Date()], function (key, value) {
97
- return this[key] instanceof Date ?
98
- 'Date(' + this[key] + ')' : value;
99
- });
100
- // text is '["Date(---current time---)"]'
101
-
102
-
103
- JSON.parse(text, reviver)
104
- This method parses a JSON text to produce an object or array.
105
- It can throw a SyntaxError exception.
106
-
107
- The optional reviver parameter is a function that can filter and
108
- transform the results. It receives each of the keys and values,
109
- and its return value is used instead of the original value.
110
- If it returns what it received, then the structure is not modified.
111
- If it returns undefined then the member is deleted.
112
-
113
- Example:
114
-
115
- // Parse the text. Values that look like ISO date strings will
116
- // be converted to Date objects.
117
-
118
- myData = JSON.parse(text, function (key, value) {
119
- var a;
120
- if (typeof value === 'string') {
121
- a =
122
- /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
123
- if (a) {
124
- return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
125
- +a[5], +a[6]));
126
- }
127
- }
128
- return value;
129
- });
130
-
131
- myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
132
- var d;
133
- if (typeof value === 'string' &&
134
- value.slice(0, 5) === 'Date(' &&
135
- value.slice(-1) === ')') {
136
- d = new Date(value.slice(5, -1));
137
- if (d) {
138
- return d;
139
- }
140
- }
141
- return value;
142
- });
143
-
144
-
145
- This is a reference implementation. You are free to copy, modify, or
146
- redistribute.
147
- */
148
-
149
- /*jslint evil: true, strict: false */
150
-
151
- /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
152
- call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
153
- getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
154
- lastIndex, length, parse, prototype, push, replace, slice, stringify,
155
- test, toJSON, toString, valueOf
156
- */
157
-
158
-
159
- // Create a JSON object only if one does not already exist. We create the
160
- // methods in a closure to avoid creating global variables.
161
-
162
- if (!this.JSON) {
163
- this.JSON = {};
164
- }
165
-
166
- (function () {
167
-
168
- function f(n) {
169
- // Format integers to have at least two digits.
170
- return n < 10 ? '0' + n : n;
171
- }
172
-
173
- if (typeof Date.prototype.toJSON !== 'function') {
174
-
175
- Date.prototype.toJSON = function (key) {
176
-
177
- return isFinite(this.valueOf()) ?
178
- this.getUTCFullYear() + '-' +
179
- f(this.getUTCMonth() + 1) + '-' +
180
- f(this.getUTCDate()) + 'T' +
181
- f(this.getUTCHours()) + ':' +
182
- f(this.getUTCMinutes()) + ':' +
183
- f(this.getUTCSeconds()) + 'Z' : null;
184
- };
185
-
186
- String.prototype.toJSON =
187
- Number.prototype.toJSON =
188
- Boolean.prototype.toJSON = function (key) {
189
- return this.valueOf();
190
- };
191
- }
192
-
193
- var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
194
- escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
195
- gap,
196
- indent,
197
- meta = { // table of character substitutions
198
- '\b': '\\b',
199
- '\t': '\\t',
200
- '\n': '\\n',
201
- '\f': '\\f',
202
- '\r': '\\r',
203
- '"' : '\\"',
204
- '\\': '\\\\'
205
- },
206
- rep;
207
-
208
-
209
- function quote(string) {
210
-
211
- // If the string contains no control characters, no quote characters, and no
212
- // backslash characters, then we can safely slap some quotes around it.
213
- // Otherwise we must also replace the offending characters with safe escape
214
- // sequences.
215
-
216
- escapable.lastIndex = 0;
217
- return escapable.test(string) ?
218
- '"' + string.replace(escapable, function (a) {
219
- var c = meta[a];
220
- return typeof c === 'string' ? c :
221
- '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
222
- }) + '"' :
223
- '"' + string + '"';
224
- }
225
-
226
-
227
- function str(key, holder) {
228
-
229
- // Produce a string from holder[key].
230
-
231
- var i, // The loop counter.
232
- k, // The member key.
233
- v, // The member value.
234
- length,
235
- mind = gap,
236
- partial,
237
- value = holder[key];
238
-
239
- // If the value has a toJSON method, call it to obtain a replacement value.
240
-
241
- if (value && typeof value === 'object' &&
242
- typeof value.toJSON === 'function') {
243
- value = value.toJSON(key);
244
- }
245
-
246
- // If we were called with a replacer function, then call the replacer to
247
- // obtain a replacement value.
248
-
249
- if (typeof rep === 'function') {
250
- value = rep.call(holder, key, value);
251
- }
252
-
253
- // What happens next depends on the value's type.
254
-
255
- switch (typeof value) {
256
- case 'string':
257
- return quote(value);
258
-
259
- case 'number':
260
-
261
- // JSON numbers must be finite. Encode non-finite numbers as null.
262
-
263
- return isFinite(value) ? String(value) : 'null';
264
-
265
- case 'boolean':
266
- case 'null':
267
-
268
- // If the value is a boolean or null, convert it to a string. Note:
269
- // typeof null does not produce 'null'. The case is included here in
270
- // the remote chance that this gets fixed someday.
271
-
272
- return String(value);
273
-
274
- // If the type is 'object', we might be dealing with an object or an array or
275
- // null.
276
-
277
- case 'object':
278
-
279
- // Due to a specification blunder in ECMAScript, typeof null is 'object',
280
- // so watch out for that case.
281
-
282
- if (!value) {
283
- return 'null';
284
- }
285
-
286
- // Make an array to hold the partial results of stringifying this object value.
287
-
288
- gap += indent;
289
- partial = [];
290
-
291
- // Is the value an array?
292
-
293
- if (Object.prototype.toString.apply(value) === '[object Array]') {
294
-
295
- // The value is an array. Stringify every element. Use null as a placeholder
296
- // for non-JSON values.
297
-
298
- length = value.length;
299
- for (i = 0; i < length; i += 1) {
300
- partial[i] = str(i, value) || 'null';
301
- }
302
-
303
- // Join all of the elements together, separated with commas, and wrap them in
304
- // brackets.
305
-
306
- v = partial.length === 0 ? '[]' :
307
- gap ? '[\n' + gap +
308
- partial.join(',\n' + gap) + '\n' +
309
- mind + ']' :
310
- '[' + partial.join(',') + ']';
311
- gap = mind;
312
- return v;
313
- }
314
-
315
- // If the replacer is an array, use it to select the members to be stringified.
316
-
317
- if (rep && typeof rep === 'object') {
318
- length = rep.length;
319
- for (i = 0; i < length; i += 1) {
320
- k = rep[i];
321
- if (typeof k === 'string') {
322
- v = str(k, value);
323
- if (v) {
324
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
325
- }
326
- }
327
- }
328
- } else {
329
-
330
- // Otherwise, iterate through all of the keys in the object.
331
-
332
- for (k in value) {
333
- if (Object.hasOwnProperty.call(value, k)) {
334
- v = str(k, value);
335
- if (v) {
336
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
337
- }
338
- }
339
- }
340
- }
341
-
342
- // Join all of the member texts together, separated with commas,
343
- // and wrap them in braces.
344
-
345
- v = partial.length === 0 ? '{}' :
346
- gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
347
- mind + '}' : '{' + partial.join(',') + '}';
348
- gap = mind;
349
- return v;
350
- }
351
- }
352
-
353
- // If the JSON object does not yet have a stringify method, give it one.
354
-
355
- if (typeof JSON.stringify !== 'function') {
356
- JSON.stringify = function (value, replacer, space) {
357
-
358
- // The stringify method takes a value and an optional replacer, and an optional
359
- // space parameter, and returns a JSON text. The replacer can be a function
360
- // that can replace values, or an array of strings that will select the keys.
361
- // A default replacer method can be provided. Use of the space parameter can
362
- // produce text that is more easily readable.
363
-
364
- var i;
365
- gap = '';
366
- indent = '';
367
-
368
- // If the space parameter is a number, make an indent string containing that
369
- // many spaces.
370
-
371
- if (typeof space === 'number') {
372
- for (i = 0; i < space; i += 1) {
373
- indent += ' ';
374
- }
375
-
376
- // If the space parameter is a string, it will be used as the indent string.
377
-
378
- } else if (typeof space === 'string') {
379
- indent = space;
380
- }
381
-
382
- // If there is a replacer, it must be a function or an array.
383
- // Otherwise, throw an error.
384
-
385
- rep = replacer;
386
- if (replacer && typeof replacer !== 'function' &&
387
- (typeof replacer !== 'object' ||
388
- typeof replacer.length !== 'number')) {
389
- throw new Error('JSON.stringify');
390
- }
391
-
392
- // Make a fake root object containing our value under the key of ''.
393
- // Return the result of stringifying the value.
394
-
395
- return str('', {'': value});
396
- };
397
- }
398
-
399
-
400
- // If the JSON object does not yet have a parse method, give it one.
401
-
402
- if (typeof JSON.parse !== 'function') {
403
- JSON.parse = function (text, reviver) {
404
-
405
- // The parse method takes a text and an optional reviver function, and returns
406
- // a JavaScript value if the text is a valid JSON text.
407
-
408
- var j;
409
-
410
- function walk(holder, key) {
411
-
412
- // The walk method is used to recursively walk the resulting structure so
413
- // that modifications can be made.
414
-
415
- var k, v, value = holder[key];
416
- if (value && typeof value === 'object') {
417
- for (k in value) {
418
- if (Object.hasOwnProperty.call(value, k)) {
419
- v = walk(value, k);
420
- if (v !== undefined) {
421
- value[k] = v;
422
- } else {
423
- delete value[k];
424
- }
425
- }
426
- }
427
- }
428
- return reviver.call(holder, key, value);
429
- }
430
-
431
-
432
- // Parsing happens in four stages. In the first stage, we replace certain
433
- // Unicode characters with escape sequences. JavaScript handles many characters
434
- // incorrectly, either silently deleting them, or treating them as line endings.
435
-
436
- text = String(text);
437
- cx.lastIndex = 0;
438
- if (cx.test(text)) {
439
- text = text.replace(cx, function (a) {
440
- return '\\u' +
441
- ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
442
- });
443
- }
444
-
445
- // In the second stage, we run the text against regular expressions that look
446
- // for non-JSON patterns. We are especially concerned with '()' and 'new'
447
- // because they can cause invocation, and '=' because it can cause mutation.
448
- // But just to be safe, we want to reject all unexpected forms.
449
-
450
- // We split the second stage into 4 regexp operations in order to work around
451
- // crippling inefficiencies in IE's and Safari's regexp engines. First we
452
- // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
453
- // replace all simple value tokens with ']' characters. Third, we delete all
454
- // open brackets that follow a colon or comma or that begin the text. Finally,
455
- // we look to see that the remaining characters are only whitespace or ']' or
456
- // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
457
-
458
- if (/^[\],:{}\s]*$/.
459
- test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
460
- replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
461
- replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
462
-
463
- // In the third stage we use the eval function to compile the text into a
464
- // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
465
- // in JavaScript: it can begin a block or an object literal. We wrap the text
466
- // in parens to eliminate the ambiguity.
467
-
468
- j = eval('(' + text + ')');
469
-
470
- // In the optional fourth stage, we recursively walk the new structure, passing
471
- // each name/value pair to a reviver function for possible transformation.
472
-
473
- return typeof reviver === 'function' ?
474
- walk({'': j}, '') : j;
475
- }
476
-
477
- // If the text is not JSON parseable, then a SyntaxError is thrown.
478
-
479
- throw new SyntaxError('JSON.parse');
480
- };
481
- }
482
- }());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/md5.js DELETED
@@ -1,201 +0,0 @@
1
- var wsdMD5 = function (string)
2
- {
3
-
4
- function RotateLeft(lValue, iShiftBits) {
5
- return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
6
- }
7
-
8
- function AddUnsigned(lX,lY) {
9
- var lX4,lY4,lX8,lY8,lResult;
10
- lX8 = (lX & 0x80000000);
11
- lY8 = (lY & 0x80000000);
12
- lX4 = (lX & 0x40000000);
13
- lY4 = (lY & 0x40000000);
14
- lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
15
- if (lX4 & lY4) {
16
- return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
17
- }
18
- if (lX4 | lY4) {
19
- if (lResult & 0x40000000) {
20
- return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
21
- } else {
22
- return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
23
- }
24
- } else {
25
- return (lResult ^ lX8 ^ lY8);
26
- }
27
- }
28
-
29
- function F(x,y,z) { return (x & y) | ((~x) & z); }
30
- function G(x,y,z) { return (x & z) | (y & (~z)); }
31
- function H(x,y,z) { return (x ^ y ^ z); }
32
- function I(x,y,z) { return (y ^ (x | (~z))); }
33
-
34
- function FF(a,b,c,d,x,s,ac) {
35
- a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
36
- return AddUnsigned(RotateLeft(a, s), b);
37
- };
38
-
39
- function GG(a,b,c,d,x,s,ac) {
40
- a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
41
- return AddUnsigned(RotateLeft(a, s), b);
42
- };
43
-
44
- function HH(a,b,c,d,x,s,ac) {
45
- a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
46
- return AddUnsigned(RotateLeft(a, s), b);
47
- };
48
-
49
- function II(a,b,c,d,x,s,ac) {
50
- a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
51
- return AddUnsigned(RotateLeft(a, s), b);
52
- };
53
-
54
- function ConvertToWordArray(string) {
55
- var lWordCount;
56
- var lMessageLength = string.length;
57
- var lNumberOfWords_temp1=lMessageLength + 8;
58
- var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
59
- var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
60
- var lWordArray=Array(lNumberOfWords-1);
61
- var lBytePosition = 0;
62
- var lByteCount = 0;
63
- while ( lByteCount < lMessageLength ) {
64
- lWordCount = (lByteCount-(lByteCount % 4))/4;
65
- lBytePosition = (lByteCount % 4)*8;
66
- lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
67
- lByteCount++;
68
- }
69
- lWordCount = (lByteCount-(lByteCount % 4))/4;
70
- lBytePosition = (lByteCount % 4)*8;
71
- lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
72
- lWordArray[lNumberOfWords-2] = lMessageLength<<3;
73
- lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
74
- return lWordArray;
75
- };
76
-
77
- function WordToHex(lValue) {
78
- var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
79
- for (lCount = 0;lCount<=3;lCount++) {
80
- lByte = (lValue>>>(lCount*8)) & 255;
81
- WordToHexValue_temp = "0" + lByte.toString(16);
82
- WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
83
- }
84
- return WordToHexValue;
85
- };
86
-
87
- function Utf8Encode(string) {
88
- string = string.replace(/\r\n/g,"\n");
89
- var utftext = "";
90
-
91
- for (var n = 0; n < string.length; n++) {
92
-
93
- var c = string.charCodeAt(n);
94
-
95
- if (c < 128) {
96
- utftext += String.fromCharCode(c);
97
- }
98
- else if((c > 127) && (c < 2048)) {
99
- utftext += String.fromCharCode((c >> 6) | 192);
100
- utftext += String.fromCharCode((c & 63) | 128);
101
- }
102
- else {
103
- utftext += String.fromCharCode((c >> 12) | 224);
104
- utftext += String.fromCharCode(((c >> 6) & 63) | 128);
105
- utftext += String.fromCharCode((c & 63) | 128);
106
- }
107
-
108
- }
109
-
110
- return utftext;
111
- };
112
-
113
- var x=Array();
114
- var k,AA,BB,CC,DD,a,b,c,d;
115
- var S11=7, S12=12, S13=17, S14=22;
116
- var S21=5, S22=9 , S23=14, S24=20;
117
- var S31=4, S32=11, S33=16, S34=23;
118
- var S41=6, S42=10, S43=15, S44=21;
119
-
120
- string = Utf8Encode(string);
121
-
122
- x = ConvertToWordArray(string);
123
-
124
- a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
125
-
126
- for (k=0;k<x.length;k+=16) {
127
- AA=a; BB=b; CC=c; DD=d;
128
- a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
129
- d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
130
- c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
131
- b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
132
- a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
133
- d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
134
- c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
135
- b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
136
- a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
137
- d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
138
- c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
139
- b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
140
- a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
141
- d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
142
- c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
143
- b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
144
- a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
145
- d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
146
- c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
147
- b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
148
- a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
149
- d=GG(d,a,b,c,x[k+10],S22,0x2441453);
150
- c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
151
- b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
152
- a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
153
- d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
154
- c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
155
- b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
156
- a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
157
- d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
158
- c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
159
- b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
160
- a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
161
- d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
162
- c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
163
- b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
164
- a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
165
- d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
166
- c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
167
- b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
168
- a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
169
- d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
170
- c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
171
- b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
172
- a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
173
- d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
174
- c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
175
- b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
176
- a=II(a,b,c,d,x[k+0], S41,0xF4292244);
177
- d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
178
- c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
179
- b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
180
- a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
181
- d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
182
- c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
183
- b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
184
- a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
185
- d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
186
- c=II(c,d,a,b,x[k+6], S43,0xA3014314);
187
- b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
188
- a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
189
- d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
190
- c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
191
- b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
192
- a=AddUnsigned(a,AA);
193
- b=AddUnsigned(b,BB);
194
- c=AddUnsigned(c,CC);
195
- d=AddUnsigned(d,DD);
196
- }
197
-
198
- var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
199
-
200
- return temp.toLowerCase();
201
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/remove_wp_version.js DELETED
@@ -1,3 +0,0 @@
1
- jQuery(document).ready(function($) {
2
- $("#wp-version-message, #footer-upgrade").remove();
3
- });
 
 
 
js/scripts.js DELETED
@@ -1,27 +0,0 @@
1
- function testPassword(passwd){
2
- var description = new Array();
3
- description[0] = '<p class="indicator indicator-1"></p> <p><strong>Weakest</strong></p>';
4
- description[1] = '<p class="indicator indicator-2"></p> <p><strong>Weak</strong></p>';
5
- description[2] = '<p class="indicator indicator-3"></p> <p><strong>Improving</strong></p>';
6
- description[3] = '<p class="indicator indicator-4"></p> <p><strong>Strong</strong></p>';
7
- description[4] = '<p class="indicator indicator-5"></p> <p><strong>Strongest</strong></p>';
8
- description[5] = '<p class="indicator indicator-6"></p> <p><strong>Begin Typing</strong></p>';
9
-
10
- var base = 0
11
- var combos = 0
12
- if (passwd.match(/[a-z]/))base = (base+26);
13
- if (passwd.match(/[A-Z]/))base = (base+26);
14
- if (passwd.match(/\d+/))base = (base+10);
15
- if (passwd.match(/[>!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/))base = (base+33);
16
-
17
- combos=Math.pow(base,passwd.length);
18
-
19
- if(combos == 1)strVerdict = description[5];
20
- else if(combos > 1 && combos < 1000000)strVerdict = description[0];
21
- else if (combos >= 1000000 && combos < 1000000000000)strVerdict = description[1];
22
- else if (combos >= 1000000000000 && combos < 1000000000000000000)strVerdict = description[2];
23
- else if (combos >= 1000000000000000000 && combos < 1000000000000000000000000)strVerdict = description[3];
24
- else strVerdict = description[4];
25
-
26
- document.getElementById("Words").innerHTML= (strVerdict);
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/wsd.js DELETED
@@ -1,188 +0,0 @@
1
- if(console===undefined){var console={log:function(){return;}};}
2
-
3
-
4
- function wsdPassStrengthProvider($) {
5
- this.badPass=['abc123','password','computer','123456','tigger','a1b2c3','qwerty','password1','carmen','mickey','secret','summer','internet','service','canada','ranger','shadow','baseball','donald','harley','hockey','letmein','maggie','mustang','snoopy','buster','dragon','jordan','michael','michelle','patrick','123abc','andrew','calvin','changeme','diamond','fuckme','fuckyou','matthew','miller','trustno1','12345678','123456789','avalon','brandy','chelsea','coffee','falcon','freedom','gandalf','helpme','merlin','molson','newyork','soccer','thomas','wizard','Monday','asdfgh','bandit','batman','butthead','dorothy','eeyore','fishing',
6
- 'football','george','iloveyou','jennifer','jonathan','marina','master','monday','monkey','natasha','ncc1701','newpass','pamela','pepper','piglet','poohbear','pookie','rabbit','rachel','rocket','sparky','spring','steven','success','sunshine','thx1138','victoria','whatever','zapata','8675309','Internet','amanda','august','barney','biteme','boomer','cowboy','doctor','fisher','foobar','island','joshua','marley','orange','please','rascal','richard','scooter','shalom','silver','skippy','stanley','taylor','welcome','zephyr','111111','aaaaaa','access','albert','alexander','andrea','anthony','asdfjkl;','ashley','basketball',
7
- 'beavis','booboo','bradley','brandon','caitlin','camaro','charlie','chicken','cricket','dakota','dallas','daniel','debbie','dolphin','elephant','friend','fucker','ginger','goodluck','hammer','heather','iceman','jessica','joseph','jupiter','justin','knight','lacrosse','lakers','lizard','madison','mother','muffin','murphy','ncc1701d','newuser','nirvana','pentium','phoenix','picture','rainbow','saturn','shannon','shithead','skeeter','sophie','special','stephanie','stephen','sweetie','teacher','tennis','test123','topgun','tristan','william','wilson','1q2w3e','654321','666666','a12345','a1b2c3d4','angela','archie','blazer',
8
- 'bond007','booger','charles','christin','claire','control','david1','dennis','digital','disney','edward','flipper','franklin','horses','hunter','indigo','jasper','jeremy','julian','kelsey','killer','kingfish','lauren','maryjane','matrix','maverick','mayday','mercury','mitchell','morgan','mountain','niners','nothing','oliver','peanut','pearljam','phantom','popcorn','princess','psycho','pumpkin','purple','rebecca','reddog','robert','salmon','samson','sharon','sierra','smokey','startrek','steelers','stimpy','sunflower','superman','support','sydney','techno','telecom','walter','willie','willow','winner','zxcvbnm','absolut',
9
- 'alaska','alexis','animal','apples','babylon5','backup','barbara','benjamin','bird33','bluebird','bonnie','camera','chocolate','claudia','cocacola','compton','connect','cookie','cruise','deliver','douglas','dreamer','dreams','duckie','eagles','einstein','explorer','family','ferrari','flamingo','flower','foxtrot','francis','freddy','friday','froggy','galileo','giants','global','gopher','hansolo','happy1','hendrix','herman','houston','iguana','indiana','insane','inside','ironman','jasmin','jeanne','justice','katherine','kermit','leslie','martin','minnie','nascar','nelson','netware','pantera','parker','passwd','penguin',
10
- 'porsche911','prince','punkin','pyramid','raymond','rosebud','route66','running','security','sergei','sheena','sheila','skiing','snapple','snowball','sparrow','spencer','stealth','student','sylvia','tamara','taurus','teresa','theresa','thunderbird','tigers','toyota','training','travel','tuesday','victory','viper1','wesley','whisky','winnie','winter','wolves','xyz123','123123','1234567','696969','888888','Anthony','Bond007','Friday','Hendrix','Joshua','Matthew','October','Taurus','Tigger','abcdef','adidas','adrian','alexandr','alfred','arthur','athena','austin','awesome','badger','bamboo','beagle','beatles','beautiful',
11
- 'beaver','bigmac','blonde','boogie','boston','brenda','bright','bubba1','bubbles','button','buttons','cactus','captain','carlos','caroline','carrie','casper','catalog','catch22','challenge','chance','charity','charlotte','cheese','cheryl','chris1','clancy','clipper','coltrane','compaq','conrad','cooper','cooter','copper','cosmos','cougar','cracker','crawford','crystal','curtis','cyclone','cyrano','deutsch','diablo','dilbert','dollars','dookie','dumbass','dundee','e-mail','elizabeth','europe','export','farmer','firebird','fletcher','fluffy','fountain','france','freak1','friends','fuckoff','gabriel','gabriell','galaxy',
12
- 'gambit','garden','garfield','garlic','garnet','genesis','genius','godzilla','goforit','golfer','goober','grateful','greenday','groovy','grover','guitar','hacker','hector','herbert','horizon','hornet','howard','icecream','imagine','impala','informix','janice','jasmine','jason1','jeanette','jeffrey','jenifer','jesus1','jewels','julie1','junior','justin1','kathleen','kelly1','kennedy','kevin1','knicks','larry1','ledzep','leonard','lestat','library','lincoln','lionking','london','louise','lucky1','maddog','mailman','majordomo','mantra','margaret','mariposa','market','marlboro','martin1','master1','mazda1','mensuck','mercedes',
13
- 'metallic','midori','millie','mirage','money1','monica','monopoly','mookie','moroni','nathan','ncc1701e','nesbitt','nguyen','nicholas','nicole','nimrod','october','olivia','online','oxford','pacific','painter','peaches','penelope','petunia','philip','phoenix1','pickle','player','poiuyt','porsche','porter','python','quality','raquel','remember','republic','research','robbie','robert1','runner','russell','sailing','sailor','samantha','savage','scarlett','school','shadow1','shelby','simple','skipper','smiley','snickers','sniper','snoopdog','snowman','spitfire','sprite','spunky','starwars','station','stella','stingray',
14
- 'stormy','stupid','sumuinen','sunny1','sunrise','surfer','teddy1','testing','theboss','theking','thumper','tintin','tomcat','trebor','trevor','tweety','unicorn','valentine','valerie','vanilla','veronica','victor','vincent','warrior','warriors','weasel','wheels','wilbur','winston','wisdom','wombat','xanadu','xavier','yellow','zaphod','zeppelin','!@#$%^','!@#$%^&*','10sne1','1p2o3i','3bears','Andrew','Broadway','Champs','Family','Fisher','Friends','Jeanne','Killer','Knight','Master','Michael','Michelle','Pentium','Pepper','Raistlin','Sierra','Snoopy','Tennis','Tuesday','abacab','abcd1234','abcdefg','abigail','account',
15
- 'acropolis','alice1','allison','alpine','anders','andre1','andrea1','angel1','annette','antares','apache','apollo','aragorn','arizona','arnold','arsenal','asdfasdf','asdfghjk','avenger','avenir','babydoll','bailey','banana','basket','batman1','beaner','beatrice','bertha','bigben','bigdog','biggles','bigman','biology','bishop','blondie','blowfish','bluefish','bobcat','braves','brazil','bridges','brutus','buffalo','bulldog','bullet','bullshit','business','butler','butter','california','cannondale','carebear','carol1','carole','cassie','castle','catalina','catherine','catnip','cccccc','celine','center','champion','chanel',
16
- 'chelsea1','chester1','chicago','christian','christy','church','cinder','colleen','colorado','columbia','commander','connie','content','cookies','cooking','cordelia','corona','cowboys','coyote','crack1','creative','cuddles','cuervo','daisie','daniel1','danielle','database','davids','deadhead','denali','depeche','design','destiny','dickens','dickhead','digger','dodger','dougie','dragonfly','eclipse','electric','emerald','emmitt','entropy','etoile','excalibur','express','farout','farside','feedback','fender','fireman','firenze','fletch','florida','flowers','foster','fozzie','francesco','francine','francois','french','fuckface',
17
- 'gargoyle','gasman','gemini','general','gerald','germany','gilbert','goaway','golden','goldfish','gordon','graham','graphic','gregory','gretchen','gunner','hal9000','hannah','harold','harrison','harvey','hawkeye','heaven','helena','herzog','hithere','hobbit','ibanez','idontknow','integra','intern','intrepid','ireland','isabel','jackie','jackson','jaguar','jamaica','jenny1','jessie','jethrotull','jkl123','johanna1','johnny','joker1','jordan23','judith','jumanji','kangaroo','karen1','keepout','keith1','kenneth','kidder','kimberly','kingdom','kitkat','kramer','kristen','lambda','laurie','lawrence','lawyer','legend','liberty',
18
- 'lindsay','lindsey','liverpool','logical','lonely','lorrie','lovely','loveme','madonna','malcolm','malibu','marathon','marcel','maria1','mariah','mariah1','marilyn','mariner','marvin','maurice','maxine','maxwell','meggie','melanie','melissa','melody','merlot','mexico','michael1','michele','midnight','midway','miracle','mishka','mmouse','molly1','monique','montreal','moocow','morris','mortimer','mouse1','mulder','nautica','nellie','nermal','newton','nicarao','nirvana1','nissan','norman','notebook','olivier','oranges','oregon','overkill','pacers','packer','pandora','panther','passion','patricia','peewee','pencil','people',
19
- 'person','peter1','picard','picasso','pierre','pinkfloyd','polaris','police','pookie1','predator','preston','primus','prometheus','public','q1w2e3','queenie','quentin','random','rangers','raptor','rastafarian','reality','redrum','remote','reptile','reynolds','rhonda','ricardo','ricardo1','roadrunner','robinhood','robotech','rocknroll','rocky1','ronald','ruthie','sabrina','sakura','salasana','sampson','samuel','sandra','sapphire','scarecrow','scarlet','scorpio','scott1','scottie','scruffy','scuba1','seattle','serena','sergey','shanti','shogun','singer','skibum','skywalker','slacker','smashing','smiles','snowflake','snowski',
20
- 'snuffy','soccer1','soleil','spanky','speedy','spider','spooky','stacey','star69','starter','steven1','sting1','stinky','strawberry','stuart','sunbird','sundance','superfly','suzanne','suzuki','swimmer','swimming','system','tarzan','teddybear','teflon','temporal','terminal','theatre','thejudge','thunder','thursday','tinker','tootsie','tornado','tricia','trident','trojan','truman','trumpet','tucker','turtle','utopia','valhalla','voyager','warcraft','warlock','warren','williams','windsurf','winona','woofwoof','wrangler','wright','xcountry','xfiles','xxxxxx','yankees','yvonne','zenith','zigzag','zombie','zxc123','000000',
21
- '007007','11111111','123321','171717','181818','1a2b3c','1chris','1kitty','1qw23e','4runner','57chevy','7777777','789456','7dwarfs','88888888','Abcdefg','Alexis','Animals','Bailey','Bastard','Beavis','Bismillah','Booboo','Boston','Canucks','Cardinal','Celtics','ChangeMe','Charlie','Computer','Cougar','Creative','Curtis','Daniel','Darkman','Denise','Dragon','Eagles','Elizabeth','Esther','Figaro','Fishing','Fortune','Freddy','Front242','Gandalf','Geronimo','Gingers','Golden','Goober','Gretel','HARLEY','Hacker','Hammer','Harley','Heather','Hershey','Jackson','Jennifer','Jersey','Jessica','Joanna','Johnson','Jordan','KILLER',
22
- 'Kitten','Liberty','Lindsay','Lizard','Madeline','Margaret','Maxwell','Mellon','Merlot','Metallic','Michel1','Monster','Montreal','Newton','Nicholas','Noriko','Paladin','Pamela','Password','Peaches','Peanuts','Phoenix','Piglet','Pookie','Princess','Purple','Rabbit','Raiders','Random','Rebecca','Robert','Russell','Saturn','Service','Shadow','Sidekick','Skeeter','Smokey','Sparky','Speedy','Sterling','Steven','Summer','Sunshine','Superman','Sverige','Swoosh','Taylor','Theresa','Thomas','Thunder','Vernon','Victoria','Vincent','Waterloo','Webster','Willow','Winnie','Wolverine','Woodrow','aardvark','abbott','abcd123','accord',
23
- 'active','admin1','adrock','aerobics','africa','airborne','airwolf','aki123','alfaro','alicia','aliens','alison','allegro','allstate','alpha1','altamira','althea','altima','altima1','amanda1','amazing','america','anderson','andrew!','andrew1','andromed','angels','angie1','anneli','anything','apple1','apple2','applepie','aptiva','aquarius','ariane','arlene','artemis','asdf1234','asdf;lkj','asdfjkl','ashley1','ashraf','ashton','assmunch','asterix','attila','autumn','avatar','ayelet','aylmer','baraka','barbie','barney1','barnyard','barrett','bartman','beaches','beanie','beasty','beauty','beavis1','belgium','belize','belmont',
24
- 'benson','beowulf','bernardo','betacam','bharat','bichon','bigboss','bigred','billy1','bimmer','bioboy','biochem','birdie','birthday','biscuit','bitter','blackjack','blanche','blinds','blowjob','blowme','blueeyes','bluejean','bogart','bombay','boobie','bootsie','boulder','bourbon','boxers','branch','brandi','brewster','bridge','britain','broker','bronco','bronte','brooke','brother','bubble','buddha','budgie','buffett','burton','butterfly','c00per','calendar','calgary','calvin1','camille','campbell','camping','cancer','canela','cannon','carbon','carnage','carolyn','carrot','cascade','catfish','catwoman','cecile','celica',
25
- 'cement','cessna','chainsaw','chameleon','change','chantal','charger','cherry','chiara','chiefs','chinacat','chinook','chouette','chris123','christ1','christmas','christopher','chronos','cicero','cindy1','cinema','circuit','cirque','cirrus','clapton','clarkson','claude','claudel','clueless','cobain','colette','college','colors','colt45','concept','concorde','confused','coolbean','cornflake','corvette','corwin','country','courier','crescent','crowley','crusader','cthulhu','cunningham','cupcake','current','cutlass','cynthia','daedalus','dagger','dagger1','dammit','damogran','dancer','daphne','darkstar','darren','darryl',
26
- 'darwin','datatrain','daytek','deborah','december','decker','deedee','deeznuts','delano','delete','denise','desert','deskjet','detroit','devine','dexter','dharma','dianne','diesel','dillweed','dipper','director','dodgers','dogbert','doitnow','dollar','dominique','domino','dontknow','doogie','doudou','downtown','dragon1','driver','dudley','dutchess','dwight','eagle1','easter','eastern','edmund','element','elina1','elissa','elliot','empire','engage','enigma','enterprise','ernie1','escort','escort1','estelle','eugene','evelyn','explore','faculty','fairview','family1','fatboy','felipe','fenris','ferguson','ferret','ferris',
27
- 'finance','fireball','fishes','fishhead','fishie','flanders','fleurs','flight','florida1','flowerpot','flyboy','forward','franka','freddie','frederic','freebird','freeman','frisco','froggie','froggies','front242','frontier','fugazi','funguy','funtime','future','gaelic','gambler','gammaphi','garcia','garfunkel','gaston','gateway','gateway2','gator1','george1','georgia','german','germany1','getout','ggeorge','gibbons','gibson','gilgamesh','giselle','glider1','gmoney','goblin','goblue','godiva','goethe','gofish','gollum','gramps','grandma','gravis','gremlin','gretzky','grizzly','grumpy','guitar1','gustavo','h2opolo','haggis',
28
- 'hailey','halloween','hallowell','hamilton','hamlet','hanson','happy123','happyday','hardcore','harley1','harriet','harris','harvard','hawkeye1','health','health1','heather1','heather2','hedgehog','heikki','helene','hello1','hello123','hello8','hellohello','help123','helper','hermes','heythere','highland','hillary','histoire','history','hitler','hobbes','holiday','homerj','honda1','hongkong','hoosier','hootie','hosehead','hotrod','hudson','hummer','huskies','hydrogen','ib6ub9','if6was9','iforget','ilmari','iloveu','impact','indonesia','ingvar','insight','instruct','integral','iomega','irmeli','isabelle','israel','italia',
29
- 'j1l2t3','jackie1','james1','jamesbond','jamjam','jeepster','jeffrey1','jennie','jensen','jesse1','jester','jethro','jetta1','jimbob','joanie','joanna','joelle','john316','jordie','journey','jubilee','juhani','julia2','julien','juliet','junebug','juniper','justdoit','justice4','kalamazo','karine','katerina','katie1','keeper','keller','kendall','kerala','kerrya','ketchup','kissa2','kissme','kitten','kittycat','kkkkkk','kleenex','kombat','kristi','kristine','labtec','laddie','ladybug','laserjet','lassie1','laurel','lawson','leader','leblanc','leland','lester','letter','letters','lexus1','lights','lionel','lissabon','little',
30
- 'logger','loislane','lolita','lonestar','longer','longhorn','looney','lovers','loveyou','lucifer','lucky14','macross','macse30','maddie','madmax','madoka','magic1','magnum','maiden','makeitso','mallard','manageme','manson','manuel','marcus','marielle','marine','marino','marshall','martha','matti1','mattingly','maxmax','meatloaf','mechanic','medical','meister','melina','memphis','mercer','mermaid','merrill','michal','michel','michigan','michou','mickel','mickey1','microsoft','midvale','mikael','milano','millenium','million','miranda','miriam','mission','mmmmmm','mobile','mobydick','monkey1','monroe','montana','montana3',
31
- 'montrose','moomoo','moonbeam','morecats','morpheus','motorola','movies','mowgli','mozart','mulder1','munchkin','murray','muscle','mustang1','nadine','napoleon','nation','national','nesbit','nestle','neutrino','newaccount','newlife','newyork1','nexus6','nichole','nicklaus','nightshadow','nightwind','nikita','nintendo','nomore','nopass','normal','norton','notta1','nouveau','novell','nugget','number9','numbers','nutmeg','oaxaca','obiwan','obsession','ohshit','oicu812','openup','orchid','orlando','orville','paagal','packard','packers','packrat','paloma','pancake','paradigm','parola','parrot','partner','pascal','patches',
32
- 'patriots','pauline','payton','peanuts','pedro1','perfect','performa','peterk','peterpan','phialpha','philips','phillips','phishy','piano1','pianoman','pianos','pierce','pigeon','pioneer','pipeline','piper1','pirate','pisces','playboy','poetic','poetry','pontiac','pookey','popeye','prayer','precious','prelude','premier','printing','provider','puddin','pulsar','pussy1','qqq111','quebec','qwerty12','qwertyui','rabbit1','racerx','rachelle','racoon','rafiki','raleigh','randy1','rasta1','ravens','redcloud','redfish','redman','redskins','redwing','redwood','reggae','reggie','reliant','renegade','rescue','revolution','reznor',
33
- 'rhjrjlbk','richard1','richards','richmond','ripper','ripple','roberts','robocop','robotics','rocket1','rockie','rockon','roger1','rogers','roland','rommel','rookie','rootbeer','rossigno','rugger','ruthless','sabbath','sabina','safety','safety1','saigon','samIam','samiam','sammie','samsam','sanjose','saphire','sarah1','saskia','satori','saturday','saturn5','schnapps','science','scooby','scoobydoo','scooter1','scorpion','scotch','scotty','scouts','search','secret3','seeker','september','server','services','seven7','shaggy','shanghai','shanny','shaolin','shasta','shayne','shazam','shelly','shelter','sherry','shirley',
34
- 'shorty','shotgun','sidney','sigmachi','signal','signature','simba1','simsim','sinatra','sirius','skipper1','skydive','skyler','slayer','sleepy','slider','smegma','smile1','smiths','smitty','smurfy','snakes','snapper','sober1','solomon','sonics','sophia','sparks','spartan','sphynx','spike1','sponge','sprocket','squash','starbuck','stargate','starlight','steph1','stephi','steve1','stevens','stewart','stivers','stocks','storage','stranger','strato','stretch','strong','student2','studio','stumpy','sucker','suckme','sultan','summit','sunfire','sunset','superstar','surfing','susan1','susanna','sutton','swanson','sweden',
35
- 'sweetpea','sweety','switzer','swordfish','system5','t-bone','tabatha','tacobell','taiwan','tamtam','tanner','tapani','targas','target','tarheel','tattoo','tazdevil','tequila','terry1','tester','testtest','thankyou','theend','thelorax','thisisit','thompson','thorne','thrasher','tiger2','tightend','timber','timothy','tinkerbell','topcat','topher','toshiba','tototo','toucan','transfer','transit','transport','trapper','travis','treasure','tricky','triton','trombone','trophy','trouble','trucker','tucson','turbo2','tyler1','ultimate','unique','united','upsilon','ursula','vacation','valley','vampire','vanessa','vedder',
36
- 'venice','vermont','victor1','vikram','vincent1','violet','violin','virago','virgil','virginia','vision','visual','volcano','volley','voodoo','vortex','waiting','walden','walleye','wanker','warner','water1','wayne1','webmaster','webster','weezer','wendy1','western','whale1','whitney','whocares','whoville','wibble','wildcat','william1','window','winniethepooh','wolfgang','wolverine','wombat1','wonder','x-files','xxx123','xxxxxxxx','yamaha','yankee','yogibear','yolanda','yomama','yvette','zachary','zebras','zepplin','zoltan','zoomer','zxcvbn','!@#$%^&','00000000','121212','1234qwer','131313','21122112','99999999',
37
- '@#$%^&','ABC123','Abcdef','Asdfgh','Changeme','FuckYou','Fuckyou','JSBach','Michel','NCC1701','Qwerty','Windows','Zxcvbnm','action','amelie','anaconda','apollo13','artist','asshole','benoit','bernard','bernie','bigbird','blizzard','bluesky','bonjour','booster','byteme','caesar','cardinal','carolina','chandler','changeit','chapman','charlie1','chiquita','chocolat','christia','christoph','classroom','cloclo','corrado','cougars','courtney','dolphins','dominic','donkey','eminem','energy','fearless','fiction','forest','forever','french1','gilles','gocougs','good-luck','graymail','guinness','hilbert','homebrew','hotdog',
38
- 'indian','johnson','kristin','lorraine','m1911a1','macintosh','mailer','maxime','memory','mirror','ne1410s','ne1469','ne14a69','nebraska','nemesis','network','newcourt','notused','oatmeal','patton','planet','players','politics','portland','praise','property','protel','psalms','qwaszx','raiders','rambo1','rancid','scrooge','shelley','skidoo','softball','speedo','sports','ssssss','steele','stephani','sunday','sylvie','symbol','tiffany','toronto','trixie','undead','valentin','velvet','viking','walker','watson','zhongguo','babygirl','1234567890','pretty','hottie','987654321','naruto','spongebob','daniela','princesa',
39
- 'christ','blessed','single','qazwsx','pokemon','iloveyou1','iloveyou2','fuckyou1','hahaha','blessing','blahblah','blink182','123qwe','trinity','passw0rd','google','looking','spirit','iloveyou!','qwerty1','rotimi','onelove','mylove','222222','ilovegod','football1','loving','emmanuel','1q2w3e4r','red123','blabla','112233'];
40
-
41
- this.showPassStrength = function(score)
42
- {
43
- var ind = $('.password-meter');
44
- if(score == undefined)
45
- {
46
- ind.hide();
47
- ind.css('background-color','#ffffff');
48
- return;
49
- }
50
- ind.show();
51
- if(score == -1)
52
- {
53
- ind.html('Too Short');
54
- ind.css('background-color','#ee0000');
55
- }
56
- else if(score == 0)
57
- {
58
- ind.html('Obvious');
59
- ind.css('background-color','#ee0000');
60
- }
61
- else if(score < 34)
62
- {
63
- ind.html('Bad');
64
- ind.css('background-color','#eeaaaa');
65
- }
66
- else if(score < 68)
67
- {
68
- ind.html('Good');
69
- ind.css('background-color','#ffff00');
70
- }
71
- else
72
- {
73
- ind.html('Strong');
74
- ind.css('background-color','#00ff00');
75
- }
76
- };
77
-
78
- this.getPassStrength = function(pass)
79
- {
80
- if(typeof pass != 'string'){ this.showPassStrength();return -1;}
81
- var len = pass.length;
82
- if(len == 0){this.showPassStrength();return -1;}
83
- if(len < 6)
84
- {
85
- this.showPassStrength(-1);
86
- return -1;
87
- }
88
- for(var i=0;i<this.badPass.length;i++)
89
- if(this.badPass[i] == pass)
90
- {
91
- this.showPassStrength(0);
92
- return 0;
93
- }
94
- var score=len*4;
95
- var a=0;
96
- var C=0;
97
- var n=0;
98
- var s=0;
99
- var l='';
100
- for(var i=0;i<len;i++)
101
- {
102
- if(l==pass.charAt(i)) score -= 1; else l=pass.charAt(i);
103
- if((pass.charAt(i)>='a')&&(pass.charAt(i)<='z')){a++;continue;}
104
- if((pass.charAt(i)>='A')&&(pass.charAt(i)<='Z')){C++;continue;}
105
- if((pass.charAt(i)>='0')&&(pass.charAt(i)<='9')){n++;continue;}
106
- s++;
107
- }
108
- if(len == a) score -= 10;
109
- if(len == n) score -= 10;
110
- if(len == C) score -= 10;
111
- if(n > 0) score += 5;
112
- if(C > 0) score += 5;
113
- if(s > 0) score += 5;
114
- if((n>0)&&(a>0)) score += 15;
115
- if((C>0)&&(a>0)) score += 15;
116
- if((s>0)&&(a>0)) score += 15;
117
- if(score > 100) score = 100;
118
-
119
- this.showPassStrength(score);
120
- return score;
121
- };
122
-
123
-
124
- // called on document.ready
125
- this.init = function() {
126
-
127
- var $wsd_new_user_form = $('#wsd_new_user_form');
128
-
129
- // Hook for keyup events to display password strength
130
- $wsd_new_user_form.delegate('#wsd_new_user_password', 'keyup',
131
- function() {
132
- _wsdPassStrengthProvider.getPassStrength($('#wsd_new_user_password').val());
133
- });
134
-
135
- // Hook for submit event to prevent form sumittion if password strength is <= BAD
136
- $wsd_new_user_form.delegate('#wsd-new-user', 'click',
137
- function() {
138
- var $wsd_new_user_password = $('#wsd_new_user_password');
139
- var $wsd_new_user_password_re = $('#wsd_new_user_password_re');
140
-
141
- if ($wsd_new_user_password.val() != $wsd_new_user_password_re.val()) {
142
- alert('Passwords do not match.');
143
- return false;
144
- }
145
-
146
- var score = _wsdPassStrengthProvider.getPassStrength($wsd_new_user_password.val());
147
-
148
- if (score <= 1) {
149
- alert('The selected password is weak! Please select passwords with a minimum length of 6 characters, also including numbers and/or special characters is recomended.');
150
- $wsd_new_user_password.val('');
151
- $wsd_new_user_password_re.val('');
152
- _wsdPassStrengthProvider.showPassStrength(score);
153
- return false;
154
- }
155
- else {
156
- var password = $wsd_new_user_password.val();
157
- var passwordHash = wsdMD5(password);
158
-
159
- $wsd_new_user_password.val(passwordHash);
160
- $wsd_new_user_password_re.val(passwordHash);
161
- }
162
- return true;
163
- });
164
-
165
- var $wsd_login_form = $('#wsd_login_form');
166
- $wsd_login_form.delegate('#wsd-login', 'click',
167
- function() {
168
- var $wsd_login_form_password = $('#wsd_login_form_password');
169
- var password = $wsd_login_form_password.val();
170
- if (password != '') {
171
- var passwordHash = wsdMD5(password);
172
- $wsd_login_form_password.val(passwordHash);
173
- }
174
- else {
175
- alert('Password is required!');
176
- $wsd_login_form_password.focus();
177
- return false;
178
- }
179
- return true;
180
- });
181
-
182
-
183
-
184
- };
185
-
186
- }// end of wsdPassStrengthProvider
187
-
188
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/functions.php DELETED
@@ -1,584 +0,0 @@
1
- <?php
2
-
3
- if (!function_exists('make_seed')) :
4
- /**
5
- * @public
6
- * Create a number
7
- * @return double
8
- */
9
- function make_seed()
10
- {
11
- list($usec, $sec) = explode(' ', microtime());
12
- return (float)$sec + ((float)$usec * 100000);
13
- }
14
- endif;
15
-
16
-
17
- if (!function_exists('make_password')) :
18
- /**
19
- * @public
20
- * @uses make_seed()
21
- * Generate a strong password
22
- * @return string
23
- */
24
- function make_password($password_length)
25
- {
26
- srand(make_seed());
27
- $alfa = "!@123!@4567!@890qwer!@tyuiopa@!sdfghjkl@!zxcvbn@!mQWERTYUIO@!PASDFGH@!JKLZXCVBNM!@";
28
- $token = "";
29
- for($i = 0; $i < $password_length; $i ++) {
30
- $token .= $alfa[rand(0, strlen($alfa))];
31
- }
32
- return $token;
33
- }
34
- endif;
35
-
36
- function check_perms($name,$path,$perm)
37
- {
38
- clearstatcache();
39
- $configmod = substr(sprintf("%o", fileperms($path)), -4);
40
- $trcss = (($configmod != $perm) ? "background-color:#F5E679;" : "");
41
- echo "<tr style=".$trcss.">";
42
- echo '<td style="border:0px;">' . $name . "</td>";
43
- echo '<td style="border:0px;">'. $path ."</td>";
44
- echo '<td style="border:0px;">' . $perm . '</td>';
45
- echo '<td style="border:0px;">' . $configmod . '</td>';
46
- echo "</tr>";
47
- }
48
-
49
- //since 3.0.3
50
- function wsd_getFilePermissions($filePath)
51
- {
52
- clearstatcache();
53
- $res = @substr(sprintf("%o", fileperms($filePath)), -4);
54
-
55
- return (empty($res) ? '0' : $res);
56
- }
57
-
58
- function mrt_get_serverinfo() {
59
- global $wpdb;
60
- $sqlversion = $wpdb->get_var("SELECT VERSION() AS version");
61
- $mysqlinfo = $wpdb->get_results("SHOW VARIABLES LIKE 'sql_mode'");
62
- if (is_array($mysqlinfo)) $sql_mode = $mysqlinfo[0]->Value;
63
- if (empty($sql_mode)) $sql_mode = __('Not set');
64
- if(ini_get('safe_mode')) $safe_mode = __('On');
65
- else $safe_mode = __('Off');
66
- if(ini_get('allow_url_fopen')) $allow_url_fopen = __('On');
67
- else $allow_url_fopen = __('Off');
68
- if(ini_get('upload_max_filesize')) $upload_max = ini_get('upload_max_filesize');
69
- else $upload_max = __('N/A');
70
- if(ini_get('post_max_size')) $post_max = ini_get('post_max_size');
71
- else $post_max = __('N/A');
72
- if(ini_get('max_execution_time')) $max_execute = ini_get('max_execution_time');
73
- else $max_execute = __('N/A');
74
- if(ini_get('memory_limit')) $memory_limit = ini_get('memory_limit');
75
- else $memory_limit = __('N/A');
76
- if (function_exists('memory_get_usage')) $memory_usage = round(memory_get_usage() / 1024 / 1024, 2) . __(' MByte');
77
- else $memory_usage = __('N/A');
78
- if (is_callable('exif_read_data')) $exif = __('Yes'). " ( V" . substr(phpversion('exif'),0,4) . ")" ;
79
- else $exif = __('No');
80
- if (is_callable('iptcparse')) $iptc = __('Yes');
81
- else $iptc = __('No');
82
- if (is_callable('xml_parser_create')) $xml = __('Yes');
83
- else $xml = __('No');
84
-
85
- ?>
86
- <li><?php _e('Operating System'); ?> : <strong><?php echo PHP_OS; ?></strong></li>
87
- <li><?php _e('Server'); ?> : <strong><?php echo $_SERVER["SERVER_SOFTWARE"]; ?></strong></li>
88
- <li><?php _e('Memory usage'); ?> : <strong><?php echo $memory_usage; ?></strong></li>
89
- <li><?php _e('MYSQL Version'); ?> : <strong><?php echo $sqlversion; ?></strong></li>
90
- <li><?php _e('SQL Mode'); ?> : <strong><?php echo $sql_mode; ?></strong></li>
91
- <li><?php _e('PHP Version'); ?> : <strong><?php echo PHP_VERSION; ?></strong></li>
92
- <li><?php _e('PHP Safe Mode'); ?> : <strong><?php echo $safe_mode; ?></strong></li>
93
- <li><?php _e('PHP Allow URL fopen'); ?> : <strong><?php echo $allow_url_fopen; ?></strong></li>
94
- <li><?php _e('PHP Memory Limit'); ?> : <strong><?php echo $memory_limit; ?></strong></li>
95
- <li><?php _e('PHP Max Upload Size'); ?> : <strong><?php echo $upload_max; ?></strong></li>
96
- <li><?php _e('PHP Max Post Size'); ?> : <strong><?php echo $post_max; ?></strong></li>
97
- <li><?php _e('PHP Max Script Execute Time'); ?> : <strong><?php echo $max_execute; ?>s</strong></li>
98
- <li><?php _e('PHP Exif support'); ?> : <strong><?php echo $exif; ?></strong></li>
99
- <li><?php _e('PHP IPTC support'); ?> : <strong><?php echo $iptc; ?></strong></li>
100
- <li><?php _e('PHP XML support'); ?> : <strong><?php echo $xml; ?></strong></li>
101
- <?php
102
- }
103
-
104
- function mrt_check_table_prefix(){
105
- if($GLOBALS['table_prefix']=='wp_'){
106
- echo '<span style="color:#f00">
107
- Your table prefix should not be <em>wp_</em>. Click <a href="admin.php?page=database">here</a> to change it.
108
- Read more on why should change the prefix
109
- <a href="http://www.websitedefender.com/wordpress-security/wordpress-blog-security-tables-prefix/"
110
- title="Why should you change the default wp table prefix"
111
- target="_blank">here</a>.</span><br />';
112
- }
113
- else { echo '<span class="scanpass">Your table prefix is not <i>wp_</i>.</span><br />'; }
114
- }
115
-
116
- function mrt_errorsoff(){
117
- echo '<span class="scanpass">WordPress DB Errors turned off.</span><br />';
118
- }
119
-
120
- function mrt_wpdberrors()
121
- {
122
- global $wpdb;
123
- $wpdb->show_errors = false;
124
- }
125
-
126
- function mrt_version_removal(){
127
- global $wp_version;
128
- echo '<span class="scanpass">Your WordPress version is successfully hidden.</span><br />';
129
- }
130
-
131
- function mrt_remove_wp_version()
132
- {
133
- function filter_generator( $gen, $type ) {
134
- switch ( $type ) {
135
- case 'html':
136
- $gen = '<meta name="generator" content="WordPress">';
137
- break;
138
- case 'xhtml':
139
- $gen = '<meta name="generator" content="WordPress" />';
140
- break;
141
- case 'atom':
142
- $gen = '<generator uri="http://wordpress.org/">WordPress</generator>';
143
- break;
144
- case 'rss2':
145
- $gen = '<generator>http://wordpress.org/?v=</generator>';
146
- break;
147
- case 'rdf':
148
- $gen = '<admin:generatorAgent rdf:resource="http://wordpress.org/?v=" />';
149
- break;
150
- case 'comment':
151
- $gen = '<!-- generator="WordPress" -->';
152
- break;
153
- }
154
- return $gen;
155
- }
156
- foreach ( array( 'html', 'xhtml', 'atom', 'rss2', 'rdf', 'comment' ) as $type ) {
157
- add_filter( "get_the_generator_$type", 'filter_generator', 10, 2 );
158
- }
159
- }
160
- //@ update 10/03/2011
161
- function mrt_check_version()
162
- {
163
- $c = get_site_transient( 'update_core' );
164
- if ( is_object($c))
165
- {
166
- if (empty($c->updates))
167
- {
168
- echo '<span class="acx-icon-alert-success">'.__('You have the latest version of Wordpress.').'</span>';
169
- return;
170
- }
171
-
172
- if (!empty($c->updates[0]))
173
- {
174
- $c = $c->updates[0];
175
-
176
- if ( !isset($c->response) || 'latest' == $c->response ) {
177
- echo '<span class="acx-icon-alert-success">'.__('You have the latest version of Wordpress.').'</span>';
178
- return;
179
- }
180
-
181
- if ('upgrade' == $c->response)
182
- {
183
- $lv = $c->current;
184
- $m = '<span class="acx-icon-alert-critical">'.sprintf('A new version of Wordpress <strong>(%s)</strong> is available. You should upgrade to the latest version.', $lv).'</span>';
185
- echo __($m);
186
- return;
187
- }
188
- }
189
- }
190
-
191
- echo '<span class="acx-icon-alert-critical">'.__('An error has occurred while trying to retrieve the status of your Wordpress version.').'</span>';
192
- }
193
-
194
-
195
- function mrt_javascript(){
196
- $siteurl = get_option('siteurl');
197
- ?><script language="JavaScript" type="text/javascript" src="<?php echo WP_PLUGIN_DIR;?>/wp-security-scan/js/scripts.js"></script><?php
198
- }
199
-
200
-
201
-
202
- /**
203
- * @public
204
- * @since v3.0.2
205
- * Check permissions (&& if we can automatically change it) for the wp-config.php file
206
- * @param string $wpConfigFilePath The path to the wp-config file
207
- * @return boolean
208
- */
209
- function wsd_wpConfigCheckPermissions($wpConfigFilePath)
210
- {
211
- if (!is_writable($wpConfigFilePath)) { return false; }
212
-
213
- // We use these functions later to access the wp-config file
214
- // so if they're not available we stop here
215
- if (!function_exists('file') || !function_exists('file_get_contents') || !function_exists('file_put_contents'))
216
- {
217
- return false;
218
- }
219
-
220
- return true;
221
- }
222
-
223
- /**
224
- * @public
225
- * @since v3.0.2
226
- * @return array
227
- */
228
- function wsd_getDbUserRights()
229
- {
230
- global $wpdb;
231
-
232
- $rightsenough = $rightstoomuch = false;
233
- $data = array(
234
- 'rightsEnough' => false,
235
- 'rightsTooMuch' => false
236
- );
237
-
238
- //@ $r1 09/12/2011 {c} $
239
-
240
- $rights = $wpdb->get_results("SHOW PRIVILEGES", ARRAY_N);
241
-
242
- if (empty($rights)) { return $data; }
243
-
244
- $_tooManyRights = array('CREATE','DELETE','DROP','EVENT','EXECUTE','FILE','GRANT','PROCESS','RELOAD','SHUTDOWN','SUPER');
245
- $numRights = 0;
246
- foreach ($rights as $right)
247
- {
248
- if (! empty($right[0]))
249
- {
250
- $_right = strtoupper($right[0]);
251
- if ('ALTER' == $_right) {
252
- $rightsenough = true;
253
- }
254
- if (in_array($_right, $_tooManyRights)) {
255
- $numRights += 1;
256
- }
257
- }
258
- }
259
- if ($numRights >= 5) {
260
- $rightstoomuch = true;
261
- }
262
-
263
- return array(
264
- 'rightsEnough' => $rightsenough,
265
- 'rightsTooMuch' => $rightstoomuch,
266
- );
267
- }
268
-
269
-
270
- /**
271
- * @public
272
- * @since v3.0.2
273
- * @revision $1 07/13/2011 $k
274
- *
275
- * Update the wp-config file to reflect the table prefix change.
276
- * The wp file must be writable for this operation to work!
277
- *
278
- * @param string $wsd_wpConfigFile The path to the wp-config file
279
- * @param string $newPrefix The new prefix to use instead of the old one
280
- * @return boolean
281
- */
282
- function wsd_updateWpConfigTablePrefix($wsd_wpConfigFile, $oldPrefix, $newPrefix)
283
- {
284
- // Check file' status's permissions
285
- if (!is_writable($wsd_wpConfigFile))
286
- {
287
- return -1;
288
- }
289
-
290
- if (!function_exists('file')) {
291
- return -1;
292
- }
293
-
294
- // Try to update the wp-config file
295
- $lines = file($wsd_wpConfigFile);
296
- $fcontent = '';
297
- $result = -1;
298
- foreach($lines as $line)
299
- {
300
- $line = ltrim($line);
301
- if (!empty($line)){
302
- if (strpos($line, '$table_prefix') !== false){
303
- $line = preg_replace("/=(.*)\;/", "= '".$newPrefix."';", $line);
304
- }
305
- }
306
- $fcontent .= $line;
307
- }
308
- if (!empty($fcontent)){
309
- // Save wp-config file
310
- $result = file_put_contents($wsd_wpConfigFile, $fcontent);
311
- }
312
-
313
- return $result;
314
- }
315
-
316
- /**
317
- * @public
318
- * @since v3.0.2
319
- * Get the list of tables to modify
320
- * @global object $wpdb
321
- * @return array
322
- */
323
- function wsd_getTablesToAlter()
324
- {
325
- global $wpdb;
326
-
327
- return $wpdb->get_results("SHOW TABLES LIKE '".$GLOBALS['table_prefix']."%'", ARRAY_N);
328
- }
329
-
330
- /**
331
- * @public
332
- * @since v3.0.2
333
- * Rename tables from database
334
- * @global object $wpdb
335
- * @param array the list of tables to rename
336
- * @param string $currentPrefix the current prefix in use
337
- * @param string $newPrefix the new prefix to use
338
- * @return array
339
- */
340
- function wsd_renameTables($tables, $currentPrefix, $newPrefix)
341
- {
342
- global $wpdb;
343
-
344
- $changedTables = array();
345
-
346
- foreach ($tables as $k=>$table)
347
- {
348
- $tableOldName = $table[0];
349
-
350
- // Hide errors
351
- $wpdb->hide_errors();
352
-
353
- // Try to rename the table
354
- $tableNewName = substr_replace($tableOldName, $newPrefix, 0, strlen($currentPrefix));
355
- //$tableNewName = str_ireplace($currentPrefix, $newPrefix, $tableOldName);
356
-
357
- // Try to rename the table
358
- $wpdb->query("RENAME TABLE `{$tableOldName}` TO `{$tableNewName}`");
359
- array_push($changedTables, $tableNewName);
360
- }
361
- return $changedTables;
362
- }
363
-
364
- /**
365
- * @public
366
- * @since v3.0.2
367
- * @revision $1 07/13/2011 $k
368
- *
369
- * Rename some fields from options & usermeta tables in order to reflect the prefix change
370
- *
371
- * @global object $wpdb
372
- * @param string $newPrefix the new prefix to use
373
- */
374
- function wsd_renameDbFields($oldPrefix,$newPrefix)
375
- {
376
- global $wpdb;
377
-
378
- /*
379
- * usermeta table
380
- * ===========================
381
- wp_*
382
-
383
- * options table
384
- * ===========================
385
- wp_user_roles
386
-
387
- */
388
- $str = '';
389
-
390
- if (false === $wpdb->query("UPDATE {$newPrefix}options SET option_name='{$newPrefix}user_roles' WHERE option_name='{$oldPrefix}user_roles';")) {
391
- $str .= '<br/>Changing value: '.$newPrefix.'user_roles in table <strong>'.$newPrefix.'options</strong>: <font color="#ff0000">Failed</font>';
392
- }
393
-
394
- $query = 'update '.$newPrefix.'usermeta
395
- set meta_key = CONCAT(replace(left(meta_key, ' . strlen($oldPrefix) . "), '{$oldPrefix}', '{$newPrefix}'), SUBSTR(meta_key, " . (strlen($oldPrefix) + 1) . "))
396
- where
397
- meta_key in ('{$oldPrefix}autosave_draft_ids', '{$oldPrefix}capabilities', '{$oldPrefix}metaboxorder_post', '{$oldPrefix}user_level', '{$oldPrefix}usersettings',
398
- '{$oldPrefix}usersettingstime', '{$oldPrefix}user-settings', '{$oldPrefix}user-settings-time', '{$oldPrefix}dashboard_quick_press_last_post_id')";
399
-
400
- if (false === $wpdb->query($query)) {
401
- $str .= '<br/>Changing values in table <strong>'.$newPrefix.'usermeta</strong>: <font color="#ff0000">Failed</font>';
402
- }
403
-
404
- if (!empty($str)) {
405
- $str = '<div class="wsd_user_information"><p>Changing database prefix:</p><p>'.$str.'</p></div>';
406
- }
407
-
408
- return $str;
409
- }
410
-
411
-
412
- /**
413
- * @public
414
- * @since v3.0.2
415
- * Backup the database and save the script to backups directory
416
- * @param string $tables the table or the list of tables to backup.
417
- * Defaults to all tables
418
- * @return int The function returns the number of bytes that were written to the file, or
419
- * false on failure.
420
- */
421
- function wsd_backupDatabase($tables = '*')
422
- {
423
- // cache
424
- $_tables = $tables;
425
-
426
- $link = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
427
- if (!$link) {
428
- exit('Error: Cannot connect to db');
429
- }
430
- if (!mysql_select_db(DB_NAME,$link)) {
431
- exit('Error: Could not select db');
432
- }
433
-
434
- //get all of the tables
435
- if($tables == '*')
436
- {
437
- $tables = array();
438
- $result = mysql_query('SHOW TABLES');
439
- while($row = mysql_fetch_row($result))
440
- {
441
- $tables[] = $row[0];
442
- }
443
- }
444
- else
445
- {
446
- $tables = is_array($tables) ? $tables : explode(',',$tables);
447
- }
448
-
449
- $return = 'CREATE DATABASE IF NOT EXISTS '.DB_NAME.";\n\n";
450
- $return .= 'USE '.DB_NAME.";\n\n";
451
-
452
- //cycle through
453
- foreach($tables as $table)
454
- {
455
- $result = mysql_query('SELECT * FROM '.$table);
456
- $num_fields = mysql_num_fields($result);
457
-
458
- $return.= 'DROP TABLE IF EXISTS '.$table.';';
459
- $row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));
460
- $return.= "\n\n".$row2[1].";\n\n";
461
-
462
- for ($i = 0; $i < $num_fields; $i++)
463
- {
464
- while($row = mysql_fetch_row($result))
465
- {
466
- $return.= 'INSERT INTO '.$table.' VALUES(';
467
- for($j=0; $j<$num_fields; $j++)
468
- {
469
- $row[$j] = addslashes($row[$j]);
470
- $row[$j] = ereg_replace("\n","\\n",$row[$j]);
471
- if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
472
- if ($j<($num_fields-1)) { $return.= ','; }
473
- }
474
- $return.= ");\n";
475
- }
476
- }
477
- $return.="\n\n\n";
478
- }
479
-
480
- //save file
481
- $fname = 'bck-'.date("m-d-Y",time()).'-'.md5(uniqid(rand())).'.sql';
482
- $filePath = ABSPATH.PLUGINDIR .'/wp-security-scan/backups/'.$fname;
483
- $ret = file_put_contents($filePath, $return);
484
- if ($ret > 0) {
485
- return $fname;
486
- }
487
- return '';
488
- }
489
-
490
- /*
491
- * @public
492
- * @since v3.0.2
493
- * Retrieve the list of tables from database
494
- * @return array
495
- */
496
- function wsd_getTablesList()
497
- {
498
- global $wpdb;
499
- $data = $wpdb->get_results("SHOW TABLES",ARRAY_N);
500
- if (empty($data))
501
- {
502
- return array();
503
- }
504
- $tmp = array();
505
- foreach($data as $k=>$v)
506
- {
507
- array_push($tmp, $v[0]);
508
- }
509
- return $tmp;
510
- }
511
-
512
- /**
513
- * @public
514
- * @since v3.0.2
515
- * Retrieve the list of all available backup files from the backups directory
516
- * @return array
517
- */
518
- function wsd_getAvailableBackupFiles()
519
- {
520
- $files = glob(ABSPATH. '/wp-content/plugins/wp-security-scan/backups/*.sql');
521
- if (empty($files)) { return array();}
522
- return array_map('basename', $files/*, array('.sql')*/);
523
-
524
- }
525
-
526
-
527
- /**
528
- * @public
529
- * @since v3.0.2
530
- * Retrieve the content of the specified template file
531
- * from the inc/admin/templates directory
532
- *
533
- * @param string $fileName The name of the file to retrieve. Without the .php extension!
534
- * @param array $vars The list of variables to send to the template
535
- * @return string The file's content
536
- */
537
- function wsd_getTemplate($fileName, array $vars = array())
538
- {
539
- $file = ABSPATH.PLUGINDIR.'/wp-security-scan/inc/admin/templates/'.$fileName.'.php';
540
- if (!is_file($file)) { return ''; }
541
-
542
- $str = '';
543
- ob_start();
544
- if (!empty($vars)) {
545
- extract($vars);
546
- }
547
- include $file;
548
- $str = ob_get_contents();
549
- ob_end_clean();
550
-
551
- return $str;
552
- }
553
-
554
-
555
- /**
556
- * @public
557
- * @since v3.0.2
558
- * Display a specific message
559
- * @param string $infoMessage The info message to display
560
- * @param string $alertType The type of the message to display. This string
561
- * should be part of the wsd_user_* css class that will be used to style the output.
562
- * Defaults to 'notify' (wsd_user_notify).
563
- * @return string
564
- */
565
- function wsd_eInfo($infoMessage, $alertType = 'notify')
566
- {
567
- return ('<p class="wsd_user_'.$alertType.'">'.$infoMessage.'</p>');
568
- }
569
-
570
- /**
571
- * @public
572
- * @since v3.0.8
573
- * Add the 'Settings' link to the plugin page
574
- * @param array $links
575
- * @return array
576
- */
577
- function wpss_admin_plugin_actions($links) {
578
- $links[] = '<a href="admin.php?page=wp-security-scan/securityscan.php">'.__('Settings').'</a>';
579
- return $links;
580
- }
581
-
582
-
583
-
584
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/json.php DELETED
@@ -1,806 +0,0 @@
1
- <?php
2
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
-
4
- /**
5
- * Converts to and from JSON format.
6
- *
7
- * JSON (JavaScript Object Notation) is a lightweight data-interchange
8
- * format. It is easy for humans to read and write. It is easy for machines
9
- * to parse and generate. It is based on a subset of the JavaScript
10
- * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
11
- * This feature can also be found in Python. JSON is a text format that is
12
- * completely language independent but uses conventions that are familiar
13
- * to programmers of the C-family of languages, including C, C++, C#, Java,
14
- * JavaScript, Perl, TCL, and many others. These properties make JSON an
15
- * ideal data-interchange language.
16
- *
17
- * This package provides a simple encoder and decoder for JSON notation. It
18
- * is intended for use with client-side Javascript applications that make
19
- * use of HTTPRequest to perform server communication functions - data can
20
- * be encoded into JSON notation for use in a client-side javascript, or
21
- * decoded from incoming Javascript requests. JSON format is native to
22
- * Javascript, and can be directly eval()'ed with no further parsing
23
- * overhead
24
- *
25
- * All strings should be in ASCII or UTF-8 format!
26
- *
27
- * LICENSE: Redistribution and use in source and binary forms, with or
28
- * without modification, are permitted provided that the following
29
- * conditions are met: Redistributions of source code must retain the
30
- * above copyright notice, this list of conditions and the following
31
- * disclaimer. Redistributions in binary form must reproduce the above
32
- * copyright notice, this list of conditions and the following disclaimer
33
- * in the documentation and/or other materials provided with the
34
- * distribution.
35
- *
36
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
37
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
39
- * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
40
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
41
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
42
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
45
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46
- * DAMAGE.
47
- *
48
- * @category
49
- * @package Services_JSON
50
- * @author Michal Migurski <mike-json@teczno.com>
51
- * @author Matt Knapp <mdknapp[at]gmail[dot]com>
52
- * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
53
- * @copyright 2005 Michal Migurski
54
- * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
55
- * @license http://www.opensource.org/licenses/bsd-license.php
56
- * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
57
- */
58
-
59
- /**
60
- * Marker constant for Services_JSON::decode(), used to flag stack state
61
- */
62
- define('SERVICES_JSON_SLICE', 1);
63
-
64
- /**
65
- * Marker constant for Services_JSON::decode(), used to flag stack state
66
- */
67
- define('SERVICES_JSON_IN_STR', 2);
68
-
69
- /**
70
- * Marker constant for Services_JSON::decode(), used to flag stack state
71
- */
72
- define('SERVICES_JSON_IN_ARR', 3);
73
-
74
- /**
75
- * Marker constant for Services_JSON::decode(), used to flag stack state
76
- */
77
- define('SERVICES_JSON_IN_OBJ', 4);
78
-
79
- /**
80
- * Marker constant for Services_JSON::decode(), used to flag stack state
81
- */
82
- define('SERVICES_JSON_IN_CMT', 5);
83
-
84
- /**
85
- * Behavior switch for Services_JSON::decode()
86
- */
87
- define('SERVICES_JSON_LOOSE_TYPE', 16);
88
-
89
- /**
90
- * Behavior switch for Services_JSON::decode()
91
- */
92
- define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
93
-
94
- /**
95
- * Converts to and from JSON format.
96
- *
97
- * Brief example of use:
98
- *
99
- * <code>
100
- * // create a new instance of Services_JSON
101
- * $json = new Services_JSON();
102
- *
103
- * // convert a complexe value to JSON notation, and send it to the browser
104
- * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
105
- * $output = $json->encode($value);
106
- *
107
- * print($output);
108
- * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
109
- *
110
- * // accept incoming POST data, assumed to be in JSON notation
111
- * $input = file_get_contents('php://input', 1000000);
112
- * $value = $json->decode($input);
113
- * </code>
114
- */
115
- class Services_JSON
116
- {
117
- /**
118
- * constructs a new JSON instance
119
- *
120
- * @param int $use object behavior flags; combine with boolean-OR
121
- *
122
- * possible values:
123
- * - SERVICES_JSON_LOOSE_TYPE: loose typing.
124
- * "{...}" syntax creates associative arrays
125
- * instead of objects in decode().
126
- * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
127
- * Values which can't be encoded (e.g. resources)
128
- * appear as NULL instead of throwing errors.
129
- * By default, a deeply-nested resource will
130
- * bubble up with an error, so all return values
131
- * from encode() should be checked with isError()
132
- */
133
- function Services_JSON($use = 0)
134
- {
135
- $this->use = $use;
136
- }
137
-
138
- /**
139
- * convert a string from one UTF-16 char to one UTF-8 char
140
- *
141
- * Normally should be handled by mb_convert_encoding, but
142
- * provides a slower PHP-only method for installations
143
- * that lack the multibye string extension.
144
- *
145
- * @param string $utf16 UTF-16 character
146
- * @return string UTF-8 character
147
- * @access private
148
- */
149
- function utf162utf8($utf16)
150
- {
151
- // oh please oh please oh please oh please oh please
152
- if(function_exists('mb_convert_encoding')) {
153
- return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
154
- }
155
-
156
- $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
157
-
158
- switch(true) {
159
- case ((0x7F & $bytes) == $bytes):
160
- // this case should never be reached, because we are in ASCII range
161
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
162
- return chr(0x7F & $bytes);
163
-
164
- case (0x07FF & $bytes) == $bytes:
165
- // return a 2-byte UTF-8 character
166
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
167
- return chr(0xC0 | (($bytes >> 6) & 0x1F))
168
- . chr(0x80 | ($bytes & 0x3F));
169
-
170
- case (0xFFFF & $bytes) == $bytes:
171
- // return a 3-byte UTF-8 character
172
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
173
- return chr(0xE0 | (($bytes >> 12) & 0x0F))
174
- . chr(0x80 | (($bytes >> 6) & 0x3F))
175
- . chr(0x80 | ($bytes & 0x3F));
176
- }
177
-
178
- // ignoring UTF-32 for now, sorry
179
- return '';
180
- }
181
-
182
- /**
183
- * convert a string from one UTF-8 char to one UTF-16 char
184
- *
185
- * Normally should be handled by mb_convert_encoding, but
186
- * provides a slower PHP-only method for installations
187
- * that lack the multibye string extension.
188
- *
189
- * @param string $utf8 UTF-8 character
190
- * @return string UTF-16 character
191
- * @access private
192
- */
193
- function utf82utf16($utf8)
194
- {
195
- // oh please oh please oh please oh please oh please
196
- if(function_exists('mb_convert_encoding')) {
197
- return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
198
- }
199
-
200
- switch(strlen($utf8)) {
201
- case 1:
202
- // this case should never be reached, because we are in ASCII range
203
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
204
- return $utf8;
205
-
206
- case 2:
207
- // return a UTF-16 character from a 2-byte UTF-8 char
208
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
209
- return chr(0x07 & (ord($utf8{0}) >> 2))
210
- . chr((0xC0 & (ord($utf8{0}) << 6))
211
- | (0x3F & ord($utf8{1})));
212
-
213
- case 3:
214
- // return a UTF-16 character from a 3-byte UTF-8 char
215
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
216
- return chr((0xF0 & (ord($utf8{0}) << 4))
217
- | (0x0F & (ord($utf8{1}) >> 2)))
218
- . chr((0xC0 & (ord($utf8{1}) << 6))
219
- | (0x7F & ord($utf8{2})));
220
- }
221
-
222
- // ignoring UTF-32 for now, sorry
223
- return '';
224
- }
225
-
226
- /**
227
- * encodes an arbitrary variable into JSON format
228
- *
229
- * @param mixed $var any number, boolean, string, array, or object to be encoded.
230
- * see argument 1 to Services_JSON() above for array-parsing behavior.
231
- * if var is a strng, note that encode() always expects it
232
- * to be in ASCII or UTF-8 format!
233
- *
234
- * @return mixed JSON string representation of input var or an error if a problem occurs
235
- * @access public
236
- */
237
- function encode($var)
238
- {
239
- switch (gettype($var)) {
240
- case 'boolean':
241
- return $var ? 'true' : 'false';
242
-
243
- case 'NULL':
244
- return 'null';
245
-
246
- case 'integer':
247
- return (int) $var;
248
-
249
- case 'double':
250
- case 'float':
251
- return (float) $var;
252
-
253
- case 'string':
254
- // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
255
- $ascii = '';
256
- $strlen_var = strlen($var);
257
-
258
- /*
259
- * Iterate over every character in the string,
260
- * escaping with a slash or encoding to UTF-8 where necessary
261
- */
262
- for ($c = 0; $c < $strlen_var; ++$c) {
263
-
264
- $ord_var_c = ord($var{$c});
265
-
266
- switch (true) {
267
- case $ord_var_c == 0x08:
268
- $ascii .= '\b';
269
- break;
270
- case $ord_var_c == 0x09:
271
- $ascii .= '\t';
272
- break;
273
- case $ord_var_c == 0x0A:
274
- $ascii .= '\n';
275
- break;
276
- case $ord_var_c == 0x0C:
277
- $ascii .= '\f';
278
- break;
279
- case $ord_var_c == 0x0D:
280
- $ascii .= '\r';
281
- break;
282
-
283
- case $ord_var_c == 0x22:
284
- case $ord_var_c == 0x2F:
285
- case $ord_var_c == 0x5C:
286
- // double quote, slash, slosh
287
- $ascii .= '\\'.$var{$c};
288
- break;
289
-
290
- case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
291
- // characters U-00000000 - U-0000007F (same as ASCII)
292
- $ascii .= $var{$c};
293
- break;
294
-
295
- case (($ord_var_c & 0xE0) == 0xC0):
296
- // characters U-00000080 - U-000007FF, mask 110XXXXX
297
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
298
- $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
299
- $c += 1;
300
- $utf16 = $this->utf82utf16($char);
301
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
302
- break;
303
-
304
- case (($ord_var_c & 0xF0) == 0xE0):
305
- // characters U-00000800 - U-0000FFFF, mask 1110XXXX
306
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
307
- $char = pack('C*', $ord_var_c,
308
- ord($var{$c + 1}),
309
- ord($var{$c + 2}));
310
- $c += 2;
311
- $utf16 = $this->utf82utf16($char);
312
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
313
- break;
314
-
315
- case (($ord_var_c & 0xF8) == 0xF0):
316
- // characters U-00010000 - U-001FFFFF, mask 11110XXX
317
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
318
- $char = pack('C*', $ord_var_c,
319
- ord($var{$c + 1}),
320
- ord($var{$c + 2}),
321
- ord($var{$c + 3}));
322
- $c += 3;
323
- $utf16 = $this->utf82utf16($char);
324
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
325
- break;
326
-
327
- case (($ord_var_c & 0xFC) == 0xF8):
328
- // characters U-00200000 - U-03FFFFFF, mask 111110XX
329
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
330
- $char = pack('C*', $ord_var_c,
331
- ord($var{$c + 1}),
332
- ord($var{$c + 2}),
333
- ord($var{$c + 3}),
334
- ord($var{$c + 4}));
335
- $c += 4;
336
- $utf16 = $this->utf82utf16($char);
337
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
338
- break;
339
-
340
- case (($ord_var_c & 0xFE) == 0xFC):
341
- // characters U-04000000 - U-7FFFFFFF, mask 1111110X
342
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
343
- $char = pack('C*', $ord_var_c,
344
- ord($var{$c + 1}),
345
- ord($var{$c + 2}),
346
- ord($var{$c + 3}),
347
- ord($var{$c + 4}),
348
- ord($var{$c + 5}));
349
- $c += 5;
350
- $utf16 = $this->utf82utf16($char);
351
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
352
- break;
353
- }
354
- }
355
-
356
- return '"'.$ascii.'"';
357
-
358
- case 'array':
359
- /*
360
- * As per JSON spec if any array key is not an integer
361
- * we must treat the the whole array as an object. We
362
- * also try to catch a sparsely populated associative
363
- * array with numeric keys here because some JS engines
364
- * will create an array with empty indexes up to
365
- * max_index which can cause memory issues and because
366
- * the keys, which may be relevant, will be remapped
367
- * otherwise.
368
- *
369
- * As per the ECMA and JSON specification an object may
370
- * have any string as a property. Unfortunately due to
371
- * a hole in the ECMA specification if the key is a
372
- * ECMA reserved word or starts with a digit the
373
- * parameter is only accessible using ECMAScript's
374
- * bracket notation.
375
- */
376
-
377
- // treat as a JSON object
378
- if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
379
- $properties = array_map(array($this, 'name_value'),
380
- array_keys($var),
381
- array_values($var));
382
-
383
- foreach($properties as $property) {
384
- if(Services_JSON::isError($property)) {
385
- return $property;
386
- }
387
- }
388
-
389
- return '{' . join(',', $properties) . '}';
390
- }
391
-
392
- // treat it like a regular array
393
- $elements = array_map(array($this, 'encode'), $var);
394
-
395
- foreach($elements as $element) {
396
- if(Services_JSON::isError($element)) {
397
- return $element;
398
- }
399
- }
400
-
401
- return '[' . join(',', $elements) . ']';
402
-
403
- case 'object':
404
- $vars = get_object_vars($var);
405
-
406
- $properties = array_map(array($this, 'name_value'),
407
- array_keys($vars),
408
- array_values($vars));
409
-
410
- foreach($properties as $property) {
411
- if(Services_JSON::isError($property)) {
412
- return $property;
413
- }
414
- }
415
-
416
- return '{' . join(',', $properties) . '}';
417
-
418
- default:
419
- return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
420
- ? 'null'
421
- : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
422
- }
423
- }
424
-
425
- /**
426
- * array-walking function for use in generating JSON-formatted name-value pairs
427
- *
428
- * @param string $name name of key to use
429
- * @param mixed $value reference to an array element to be encoded
430
- *
431
- * @return string JSON-formatted name-value pair, like '"name":value'
432
- * @access private
433
- */
434
- function name_value($name, $value)
435
- {
436
- $encoded_value = $this->encode($value);
437
-
438
- if(Services_JSON::isError($encoded_value)) {
439
- return $encoded_value;
440
- }
441
-
442
- return $this->encode(strval($name)) . ':' . $encoded_value;
443
- }
444
-
445
- /**
446
- * reduce a string by removing leading and trailing comments and whitespace
447
- *
448
- * @param $str string string value to strip of comments and whitespace
449
- *
450
- * @return string string value stripped of comments and whitespace
451
- * @access private
452
- */
453
- function reduce_string($str)
454
- {
455
- $str = preg_replace(array(
456
-
457
- // eliminate single line comments in '// ...' form
458
- '#^\s*//(.+)$#m',
459
-
460
- // eliminate multi-line comments in '/* ... */' form, at start of string
461
- '#^\s*/\*(.+)\*/#Us',
462
-
463
- // eliminate multi-line comments in '/* ... */' form, at end of string
464
- '#/\*(.+)\*/\s*$#Us'
465
-
466
- ), '', $str);
467
-
468
- // eliminate extraneous space
469
- return trim($str);
470
- }
471
-
472
- /**
473
- * decodes a JSON string into appropriate variable
474
- *
475
- * @param string $str JSON-formatted string
476
- *
477
- * @return mixed number, boolean, string, array, or object
478
- * corresponding to given JSON input string.
479
- * See argument 1 to Services_JSON() above for object-output behavior.
480
- * Note that decode() always returns strings
481
- * in ASCII or UTF-8 format!
482
- * @access public
483
- */
484
- function decode($str)
485
- {
486
- $str = $this->reduce_string($str);
487
-
488
- switch (strtolower($str)) {
489
- case 'true':
490
- return true;
491
-
492
- case 'false':
493
- return false;
494
-
495
- case 'null':
496
- return null;
497
-
498
- default:
499
- $m = array();
500
-
501
- if (is_numeric($str)) {
502
- // Lookie-loo, it's a number
503
-
504
- // This would work on its own, but I'm trying to be
505
- // good about returning integers where appropriate:
506
- // return (float)$str;
507
-
508
- // Return float or int, as appropriate
509
- return ((float)$str == (integer)$str)
510
- ? (integer)$str
511
- : (float)$str;
512
-
513
- } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
514
- // STRINGS RETURNED IN UTF-8 FORMAT
515
- $delim = substr($str, 0, 1);
516
- $chrs = substr($str, 1, -1);
517
- $utf8 = '';
518
- $strlen_chrs = strlen($chrs);
519
-
520
- for ($c = 0; $c < $strlen_chrs; ++$c) {
521
-
522
- $substr_chrs_c_2 = substr($chrs, $c, 2);
523
- $ord_chrs_c = ord($chrs{$c});
524
-
525
- switch (true) {
526
- case $substr_chrs_c_2 == '\b':
527
- $utf8 .= chr(0x08);
528
- ++$c;
529
- break;
530
- case $substr_chrs_c_2 == '\t':
531
- $utf8 .= chr(0x09);
532
- ++$c;
533
- break;
534
- case $substr_chrs_c_2 == '\n':
535
- $utf8 .= chr(0x0A);
536
- ++$c;
537
- break;
538
- case $substr_chrs_c_2 == '\f':
539
- $utf8 .= chr(0x0C);
540
- ++$c;
541
- break;
542
- case $substr_chrs_c_2 == '\r':
543
- $utf8 .= chr(0x0D);
544
- ++$c;
545
- break;
546
-
547
- case $substr_chrs_c_2 == '\\"':
548
- case $substr_chrs_c_2 == '\\\'':
549
- case $substr_chrs_c_2 == '\\\\':
550
- case $substr_chrs_c_2 == '\\/':
551
- if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
552
- ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
553
- $utf8 .= $chrs{++$c};
554
- }
555
- break;
556
-
557
- case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
558
- // single, escaped unicode character
559
- $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
560
- . chr(hexdec(substr($chrs, ($c + 4), 2)));
561
- $utf8 .= $this->utf162utf8($utf16);
562
- $c += 5;
563
- break;
564
-
565
- case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
566
- $utf8 .= $chrs{$c};
567
- break;
568
-
569
- case ($ord_chrs_c & 0xE0) == 0xC0:
570
- // characters U-00000080 - U-000007FF, mask 110XXXXX
571
- //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
572
- $utf8 .= substr($chrs, $c, 2);
573
- ++$c;
574
- break;
575
-
576
- case ($ord_chrs_c & 0xF0) == 0xE0:
577
- // characters U-00000800 - U-0000FFFF, mask 1110XXXX
578
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
579
- $utf8 .= substr($chrs, $c, 3);
580
- $c += 2;
581
- break;
582
-
583
- case ($ord_chrs_c & 0xF8) == 0xF0:
584
- // characters U-00010000 - U-001FFFFF, mask 11110XXX
585
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
586
- $utf8 .= substr($chrs, $c, 4);
587
- $c += 3;
588
- break;
589
-
590
- case ($ord_chrs_c & 0xFC) == 0xF8:
591
- // characters U-00200000 - U-03FFFFFF, mask 111110XX
592
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
593
- $utf8 .= substr($chrs, $c, 5);
594
- $c += 4;
595
- break;
596
-
597
- case ($ord_chrs_c & 0xFE) == 0xFC:
598
- // characters U-04000000 - U-7FFFFFFF, mask 1111110X
599
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
600
- $utf8 .= substr($chrs, $c, 6);
601
- $c += 5;
602
- break;
603
-
604
- }
605
-
606
- }
607
-
608
- return $utf8;
609
-
610
- } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
611
- // array, or object notation
612
-
613
- if ($str{0} == '[') {
614
- $stk = array(SERVICES_JSON_IN_ARR);
615
- $arr = array();
616
- } else {
617
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
618
- $stk = array(SERVICES_JSON_IN_OBJ);
619
- $obj = array();
620
- } else {
621
- $stk = array(SERVICES_JSON_IN_OBJ);
622
- $obj = new stdClass();
623
- }
624
- }
625
-
626
- array_push($stk, array('what' => SERVICES_JSON_SLICE,
627
- 'where' => 0,
628
- 'delim' => false));
629
-
630
- $chrs = substr($str, 1, -1);
631
- $chrs = $this->reduce_string($chrs);
632
-
633
- if ($chrs == '') {
634
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
635
- return $arr;
636
-
637
- } else {
638
- return $obj;
639
-
640
- }
641
- }
642
-
643
- //print("\nparsing {$chrs}\n");
644
-
645
- $strlen_chrs = strlen($chrs);
646
-
647
- for ($c = 0; $c <= $strlen_chrs; ++$c) {
648
-
649
- $top = end($stk);
650
- $substr_chrs_c_2 = substr($chrs, $c, 2);
651
-
652
- if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
653
- // found a comma that is not inside a string, array, etc.,
654
- // OR we've reached the end of the character list
655
- $slice = substr($chrs, $top['where'], ($c - $top['where']));
656
- array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
657
- //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
658
-
659
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
660
- // we are in an array, so just push an element onto the stack
661
- array_push($arr, $this->decode($slice));
662
-
663
- } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
664
- // we are in an object, so figure
665
- // out the property name and set an
666
- // element in an associative array,
667
- // for now
668
- $parts = array();
669
-
670
- if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
671
- // "name":value pair
672
- $key = $this->decode($parts[1]);
673
- $val = $this->decode($parts[2]);
674
-
675
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
676
- $obj[$key] = $val;
677
- } else {
678
- $obj->$key = $val;
679
- }
680
- } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
681
- // name:value pair, where name is unquoted
682
- $key = $parts[1];
683
- $val = $this->decode($parts[2]);
684
-
685
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
686
- $obj[$key] = $val;
687
- } else {
688
- $obj->$key = $val;
689
- }
690
- }
691
-
692
- }
693
-
694
- } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
695
- // found a quote, and we are not inside a string
696
- array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
697
- //print("Found start of string at {$c}\n");
698
-
699
- } elseif (($chrs{$c} == $top['delim']) &&
700
- ($top['what'] == SERVICES_JSON_IN_STR) &&
701
- ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
702
- // found a quote, we're in a string, and it's not escaped
703
- // we know that it's not escaped becase there is _not_ an
704
- // odd number of backslashes at the end of the string so far
705
- array_pop($stk);
706
- //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
707
-
708
- } elseif (($chrs{$c} == '[') &&
709
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
710
- // found a left-bracket, and we are in an array, object, or slice
711
- array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
712
- //print("Found start of array at {$c}\n");
713
-
714
- } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
715
- // found a right-bracket, and we're in an array
716
- array_pop($stk);
717
- //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
718
-
719
- } elseif (($chrs{$c} == '{') &&
720
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
721
- // found a left-brace, and we are in an array, object, or slice
722
- array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
723
- //print("Found start of object at {$c}\n");
724
-
725
- } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
726
- // found a right-brace, and we're in an object
727
- array_pop($stk);
728
- //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
729
-
730
- } elseif (($substr_chrs_c_2 == '/*') &&
731
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
732
- // found a comment start, and we are in an array, object, or slice
733
- array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
734
- $c++;
735
- //print("Found start of comment at {$c}\n");
736
-
737
- } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
738
- // found a comment end, and we're in one now
739
- array_pop($stk);
740
- $c++;
741
-
742
- for ($i = $top['where']; $i <= $c; ++$i)
743
- $chrs = substr_replace($chrs, ' ', $i, 1);
744
-
745
- //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
746
-
747
- }
748
-
749
- }
750
-
751
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
752
- return $arr;
753
-
754
- } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
755
- return $obj;
756
-
757
- }
758
-
759
- }
760
- }
761
- }
762
-
763
- /**
764
- * @todo Ultimately, this should just call PEAR::isError()
765
- */
766
- function isError($data, $code = null)
767
- {
768
- if (class_exists('pear')) {
769
- return PEAR::isError($data, $code);
770
- } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
771
- is_subclass_of($data, 'services_json_error'))) {
772
- return true;
773
- }
774
-
775
- return false;
776
- }
777
- }
778
-
779
- if (class_exists('PEAR_Error')) {
780
-
781
- class Services_JSON_Error extends PEAR_Error
782
- {
783
- function Services_JSON_Error($message = 'unknown error', $code = null,
784
- $mode = null, $options = null, $userinfo = null)
785
- {
786
- parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
787
- }
788
- }
789
-
790
- } else {
791
-
792
- /**
793
- * @todo Ultimately, this class shall be descended from PEAR_Error
794
- */
795
- class Services_JSON_Error
796
- {
797
- function Services_JSON_Error($message = 'unknown error', $code = null,
798
- $mode = null, $options = null, $userinfo = null)
799
- {
800
-
801
- }
802
- }
803
-
804
- }
805
-
806
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/recaptchalib.php DELETED
@@ -1,277 +0,0 @@
1
- <?php
2
- /*
3
- * This is a PHP library that handles calling reCAPTCHA.
4
- * - Documentation and latest version
5
- * http://recaptcha.net/plugins/php/
6
- * - Get a reCAPTCHA API Key
7
- * https://www.google.com/recaptcha/admin/create
8
- * - Discussion group
9
- * http://groups.google.com/group/recaptcha
10
- *
11
- * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
12
- * AUTHORS:
13
- * Mike Crawford
14
- * Ben Maurer
15
- *
16
- * Permission is hereby granted, free of charge, to any person obtaining a copy
17
- * of this software and associated documentation files (the "Software"), to deal
18
- * in the Software without restriction, including without limitation the rights
19
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20
- * copies of the Software, and to permit persons to whom the Software is
21
- * furnished to do so, subject to the following conditions:
22
- *
23
- * The above copyright notice and this permission notice shall be included in
24
- * all copies or substantial portions of the Software.
25
- *
26
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
- * THE SOFTWARE.
33
- */
34
-
35
- /**
36
- * The reCAPTCHA server URL's
37
- */
38
- define("WSD_RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
39
- define("WSD_RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
40
- define("WSD_RECAPTCHA_VERIFY_SERVER", "www.google.com");
41
-
42
- /**
43
- * Encodes the given data into a query string format
44
- * @param $data - array of string elements to be encoded
45
- * @return string - encoded request
46
- */
47
- function wsd__recaptcha_qsencode ($data) {
48
- $req = "";
49
- foreach ( $data as $key => $value )
50
- $req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
51
-
52
- // Cut the last '&'
53
- $req=substr($req,0,strlen($req)-1);
54
- return $req;
55
- }
56
-
57
-
58
-
59
- /**
60
- * Submits an HTTP POST to a reCAPTCHA server
61
- * @param string $host
62
- * @param string $path
63
- * @param array $data
64
- * @param int port
65
- * @return array response
66
- */
67
- function wsd__recaptcha_http_post($host, $path, $data, $port = 80) {
68
-
69
- $req = wsd__recaptcha_qsencode ($data);
70
-
71
- $http_request = "POST $path HTTP/1.0\r\n";
72
- $http_request .= "Host: $host\r\n";
73
- $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
74
- $http_request .= "Content-Length: " . strlen($req) . "\r\n";
75
- $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
76
- $http_request .= "\r\n";
77
- $http_request .= $req;
78
-
79
- $response = '';
80
- if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
81
- die ('Could not open socket');
82
- }
83
-
84
- fwrite($fs, $http_request);
85
-
86
- while ( !feof($fs) )
87
- $response .= fgets($fs, 1160); // One TCP-IP packet
88
- fclose($fs);
89
- $response = explode("\r\n\r\n", $response, 2);
90
-
91
- return $response;
92
- }
93
-
94
-
95
-
96
- /**
97
- * Gets the challenge HTML (javascript and non-javascript version).
98
- * This is called from the browser, and the resulting reCAPTCHA HTML widget
99
- * is embedded within the HTML form it was called from.
100
- * @param string $pubkey A public key for reCAPTCHA
101
- * @param string $error The error given by reCAPTCHA (optional, default is null)
102
- * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
103
-
104
- * @return string - The HTML to be embedded in the user's form.
105
- */
106
- function wsd_recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
107
- {
108
- if ($pubkey == null || $pubkey == '') {
109
- die ('To use reCAPTCHA you must get an API key from <a href="https://www.google.com/recaptcha/admin/create" target="_blank">https://www.google.com/recaptcha/admin/create</a>');
110
- }
111
-
112
- if ($use_ssl) {
113
- $server = WSD_RECAPTCHA_API_SECURE_SERVER;
114
- } else {
115
- $server = WSD_RECAPTCHA_API_SERVER;
116
- }
117
-
118
- $errorpart = "";
119
- if ($error) {
120
- $errorpart = "&amp;error=" . $error;
121
- }
122
- return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
123
-
124
- <noscript>
125
- <iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
126
- <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
127
- <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
128
- </noscript>';
129
- }
130
-
131
-
132
-
133
-
134
- /**
135
- * A wsd_ReCaptchaResponse is returned from wsd_recaptcha_check_answer()
136
- */
137
- class wsd_ReCaptchaResponse {
138
- var $is_valid;
139
- var $error;
140
- }
141
-
142
-
143
- /**
144
- * Calls an HTTP POST function to verify if the user's guess was correct
145
- * @param string $privkey
146
- * @param string $remoteip
147
- * @param string $challenge
148
- * @param string $response
149
- * @param array $extra_params an array of extra variables to post to the server
150
- * @return wsd_ReCaptchaResponse
151
- */
152
- function wsd_recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
153
- {
154
- if ($privkey == null || $privkey == '') {
155
- die ('To use reCAPTCHA you must get an API key from <a href="https://www.google.com/recaptcha/admin/create" target="_blank">https://www.google.com/recaptcha/admin/create</a>');
156
- }
157
-
158
- if ($remoteip == null || $remoteip == '') {
159
- die ('For security reasons, you must pass the remote ip to reCAPTCHA');
160
- }
161
-
162
-
163
-
164
- //discard spam submissions
165
- if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
166
- $recaptcha_response = new wsd_ReCaptchaResponse();
167
- $recaptcha_response->is_valid = false;
168
- $recaptcha_response->error = 'incorrect-captcha-sol';
169
- return $recaptcha_response;
170
- }
171
-
172
- $response = wsd__recaptcha_http_post (WSD_RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
173
- array (
174
- 'privatekey' => $privkey,
175
- 'remoteip' => $remoteip,
176
- 'challenge' => $challenge,
177
- 'response' => $response
178
- ) + $extra_params
179
- );
180
-
181
- $answers = explode ("\n", $response [1]);
182
- $recaptcha_response = new wsd_ReCaptchaResponse();
183
-
184
- if (trim ($answers [0]) == 'true') {
185
- $recaptcha_response->is_valid = true;
186
- }
187
- else {
188
- $recaptcha_response->is_valid = false;
189
- $recaptcha_response->error = $answers [1];
190
- }
191
- return $recaptcha_response;
192
-
193
- }
194
-
195
- /**
196
- * gets a URL where the user can sign up for reCAPTCHA. If your application
197
- * has a configuration page where you enter a key, you should provide a link
198
- * using this function.
199
- * @param string $domain The domain where the page is hosted
200
- * @param string $appname The name of your application
201
- */
202
- function wsd_recaptcha_get_signup_url ($domain = null, $appname = null) {
203
- return 'https://www.google.com/recaptcha/admin/create?' . wsd__recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
204
- }
205
-
206
- function wsd__recaptcha_aes_pad($val) {
207
- $block_size = 16;
208
- $numpad = $block_size - (strlen ($val) % $block_size);
209
- return str_pad($val, strlen ($val) + $numpad, chr($numpad));
210
- }
211
-
212
- /* Mailhide related code */
213
-
214
- function wsd__recaptcha_aes_encrypt($val,$ky) {
215
- if (! function_exists ("mcrypt_encrypt")) {
216
- die ('To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.');
217
- }
218
- $mode=MCRYPT_MODE_CBC;
219
- $enc=MCRYPT_RIJNDAEL_128;
220
- $val=wsd__recaptcha_aes_pad($val);
221
- return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
222
- }
223
-
224
-
225
- function wsd__wsd_recaptcha_mailhide_urlbase64 ($x) {
226
- return strtr(base64_encode ($x), '+/', '-_');
227
- }
228
-
229
- /* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
230
- function wsd_recaptcha_mailhide_url($pubkey, $privkey, $email) {
231
- if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
232
- die ('To use reCAPTCHA Mailhide, you have to sign up for a public and private key, ' .
233
- 'you can do so at <a href="http://www.google.com/recaptcha/mailhide/apikey" target="_blank">http://www.google.com/recaptcha/mailhide/apikey</a>');
234
- }
235
-
236
-
237
- $ky = pack('H*', $privkey);
238
- $cryptmail = wsd__recaptcha_aes_encrypt ($email, $ky);
239
-
240
- return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . wsd__wsd_recaptcha_mailhide_urlbase64 ($cryptmail);
241
- }
242
-
243
- /**
244
- * gets the parts of the email to expose to the user.
245
- * eg, given johndoe@example,com return ["john", "example.com"].
246
- * the email is then displayed as john...@example.com
247
- */
248
- function wsd__recaptcha_mailhide_email_parts ($email) {
249
- $arr = preg_split("/@/", $email );
250
-
251
- if (strlen ($arr[0]) <= 4) {
252
- $arr[0] = substr ($arr[0], 0, 1);
253
- } else if (strlen ($arr[0]) <= 6) {
254
- $arr[0] = substr ($arr[0], 0, 3);
255
- } else {
256
- $arr[0] = substr ($arr[0], 0, 4);
257
- }
258
- return $arr;
259
- }
260
-
261
- /**
262
- * Gets html to display an email address given a public an private key.
263
- * to get a key, go to:
264
- *
265
- * http://www.google.com/recaptcha/mailhide/apikey
266
- */
267
- function wsd_recaptcha_mailhide_html($pubkey, $privkey, $email) {
268
- $emailparts = wsd__recaptcha_mailhide_email_parts ($email);
269
- $url = wsd_recaptcha_mailhide_url ($pubkey, $privkey, $email);
270
-
271
- return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
272
- "' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
273
-
274
- }
275
-
276
-
277
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/wpssUtil.php DELETED
@@ -1,167 +0,0 @@
1
- <?php
2
- /**
3
- * utility methods
4
- *
5
- * @author kos
6
- */
7
- class wpssUtil
8
- {
9
- //@since v3.0.8
10
- private static $_pluginID = 'acx_plugin_dashboard_widget';
11
- /**
12
- * @public
13
- * @static
14
- * @global WPSS_WSD_BLOG_FEED
15
- * Retrieve and display a list of links for an existing RSS feed, limiting the selection to the 5 most recent items.
16
- * @return void
17
- */
18
- public static function displayDashboardWidget()
19
- {
20
- //@since v3.0.8
21
- if ($_SERVER['REQUEST_METHOD'] == 'POST')
22
- {
23
- $opt = get_option('WSD-RSS-WGT-DISPLAY');
24
- if (empty($opt)) {
25
- add_option('WSD-RSS-WGT-DISPLAY', 'no');
26
- }
27
- else {
28
- update_option('WSD-RSS-WGT-DISPLAY', 'no');
29
- }
30
- self::_hideDashboardWidget();
31
- return;
32
- }
33
-
34
- //@ flag
35
- $run = false;
36
-
37
- //@ check cache
38
- $optData = get_option('wsd_feed_data');
39
- if (! empty($optData))
40
- {
41
- if (is_object($optData))
42
- {
43
-
44
- $lastUpdateTime = @$optData->expires;
45
- // invalid cache
46
- if (empty($lastUpdateTime)) { $run = true; }
47
- else
48
- {
49
- $nextUpdateTime = $lastUpdateTime+(24*60*60);
50
- if ($nextUpdateTime >= $lastUpdateTime)
51
- {
52
- $data = @$optData->data;
53
- if (empty($data)) { $run = true; }
54
- else {
55
- // still a valid cache
56
- echo $data;
57
- return;
58
- }
59
- }
60
- else { $run = true; }
61
- }
62
- }
63
- else { $run = true; }
64
- }
65
- else { $run = true; }
66
-
67
- if (!$run) { return; }
68
-
69
- $rss = fetch_feed(WPSS_WSD_BLOG_FEED);
70
-
71
- $out = '';
72
- if (is_wp_error( $rss ) )
73
- {
74
- $out = '<li>'.__('An error has occurred while trying to load the rss feed!').'</li>';
75
- echo $out;
76
- return;
77
- }
78
- else
79
- {
80
- // Limit to 5 entries.
81
- $maxitems = $rss->get_item_quantity(5);
82
-
83
- // Build an array of all the items,
84
- $rss_items = $rss->get_items(0, $maxitems);
85
-
86
- $out .= '<ul>';
87
- if ($maxitems == 0)
88
- {
89
- $out.= '<li>'.__('There are no entries for this rss feed!').'</li>';
90
- }
91
- else
92
- {
93
- foreach ( $rss_items as $item ) :
94
- $url = esc_url($item->get_permalink());
95
- $out.= '<li>';
96
- $out.= '<h4><a href="'.$url.'" target="_blank" title="Posted on '.$item->get_date('F j, Y | g:i a').'">';
97
- $out.= esc_html( $item->get_title() );
98
- $out.= '</a></h4>';
99
- $out.= '<p>';
100
- $d = $item->get_description();
101
- $p = substr($d, 0, 115).' <a href="'.$url.'" target="_blank" title="Read all article">[...]</a>';
102
- $out.= $p;
103
- $out.= '</p>';
104
- $out.= '</li>';
105
- endforeach;
106
- }
107
- $out.= '</ul>';
108
-
109
- $path = trailingslashit(get_option('siteurl')).'wp-content/plugins/wp-security-scan/';
110
-
111
- $out .= '<div style="border-top: solid 1px #ccc; margin-top: 4px; padding: 2px 0;">';
112
- $out .= '<p style="margin: 5px 0 0 0; padding: 0 0; line-height: normal; overflow: hidden;">';
113
- $out .= '<a href="http://feeds.feedburner.com/Websitedefendercom"
114
- style="float: left; display: block; width: 50%; text-align: right; margin-top: 0; margin-left: 30px;
115
- padding-right: 22px; background: url('.$path.'images/rss.png) no-repeat right center;"
116
- target="_blank">Follow us on RSS</a>';
117
- $out .= '<a href="#" id="wsd_close_rss_widget"
118
- style="float: right; display: block; width: 16px; height: 16px;
119
- margin: 0 0; background: url('.$path.'images/close-button.png) no-repeat 0 0;"
120
- title="Close widget"></a><form id="wsd_form" method="post"></form>';
121
- $out .= '</p>';
122
- $out .= '<script type="text/javascript">
123
- document.getElementById("wsd_close_rss_widget").onclick = function(){
124
- document.getElementById("wsd_form").submit();
125
- };
126
- </script>';
127
- $out .= '</div>';
128
- }
129
-
130
- // Update cache
131
- $obj = new stdClass();
132
- $obj->expires = time();
133
- $obj->data = $out;
134
- update_option('wsd_feed_data', $obj);
135
-
136
- echo $out;
137
- }
138
-
139
- /**
140
- * @public
141
- * @static
142
- * Add the rss widget to dashboard
143
- * @return void
144
- */
145
- public static function addDashboardWidget()
146
- {
147
- // update 10/04/2011
148
- $opt = get_option('WSD-RSS-WGT-DISPLAY');
149
- if(strtolower($opt) == 'yes'):
150
- wp_add_dashboard_widget(self::$_pluginID,
151
- __('WebsiteDefender news and updates'),
152
- 'wpssUtil::displayDashboardWidget');
153
- endif;
154
- }
155
-
156
- /**
157
- * Hide the dashboard rss widget
158
- * @static
159
- * @public
160
- * @since v3.0.8
161
- */
162
- public static function _hideDashboardWidget()
163
- {
164
- echo '<script>document.getElementById("'.self::$_pluginID.'").style.display = "none";</script>';
165
- }
166
-
167
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
libs/wsd.php DELETED
@@ -1,835 +0,0 @@
1
- <?php
2
- define("WSD_URL", "https://dashboard.websitedefender.com/");
3
- define("WSD_URL_RPC", WSD_URL . "jsrpc.php");
4
- define("WSD_URL_DOWN", WSD_URL . "download.php");
5
- define("WSD_SOURCE", 2);
6
- //error codes
7
- define('WSD_ERROR_LIMITATION' ,0x27);
8
- define('WSD_ERROR_WPP_SERVICE_DOWN' ,0x50);
9
- define('WSD_ERROR_WPP_ERROR_INVALID_URL' ,0x51);
10
- define('WSD_ERROR_WPP_URL_REGISTERED' ,0x52);
11
- define('WSD_WSD_ERROR_WPP_NEWUSR_PARAM' ,0x53);
12
- define('WSD_ERROR_WPP_INVALID_CAPTCHA' ,0x54);
13
- define('WSD_ERROR_WPP_USER_EXIST' ,0x55);
14
- define('WSD_ERROR_WPP_URL_EXIST' ,0x56);
15
- //http status
16
- define("HTTP_STATUS", 0);
17
- define("HTTP_HEADERS", 1);
18
- define("HTTP_BODY", 2);
19
- define("HTTP_CHUNK_HEADER", 3);
20
- define("HTTP_CHUNK_BODY", 4);
21
- //globals
22
- $GLOBALS['wsd_last_err'] = array('code'=>0, 'message'=>'');
23
-
24
- function wsd_site_url(){
25
- $url = get_option( 'siteurl' );
26
- return trailingslashit($url);
27
- }
28
-
29
- function wsd_parseUrl($url)
30
- {
31
- $result = parse_url($url);
32
- if($result === NULL) return array("error"=>"Invalid URL.");
33
- $result["error"] = NULL;
34
- if(!array_key_exists("port", $result)) $result["port"] = 80;
35
- if(!array_key_exists("scheme", $result)) $result["scheme"] = "http";
36
- if(!array_key_exists("query", $result)) $result["query"] = ""; else $result["query"] = "?" . $result["query"];
37
- if(array_key_exists("host", $result))
38
- {
39
- if(!array_key_exists("path", $result)) $result["path"] = "";
40
- }
41
- else
42
- {
43
- if(array_key_exists("path", $result))
44
- {
45
- $dirs = explode("/", $result["path"], 2);
46
- $result["host"] = $dirs[0];
47
- if(count($dirs)>1)
48
- $result["path"] = "/".$dirs[1];
49
- else
50
- $result["path"] = "/";
51
- }
52
- else return array("error"=>"Invalid URL (no host).");
53
- }
54
-
55
- if($result["host"] == "") return array("error"=>"Invalid URL (no host).");
56
-
57
- $scheme = "http";
58
- if(array_key_exists("scheme", $result)) $scheme = $result["scheme"];
59
-
60
- if((strcasecmp($scheme,"http")!=0) && (strcasecmp($scheme,"https")!=0)) return array("error"=>"Invalid URL (unknown scheme).");
61
-
62
- if(strcasecmp($scheme,"https")==0) $result["port"] = 443;
63
-
64
- $userPass = "";
65
- if(array_key_exists("user", $result) && array_key_exists("pass", $result))
66
- $userPass = $result["user"].":".$result["pass"]."@";
67
-
68
- $port = "";
69
- if(array_key_exists("port", $result)) $port = ":".$result["port"];
70
-
71
- $result["all"] = $scheme."://".$userPass.$result["host"].$port;
72
- return $result;
73
- }
74
-
75
- function wsd_httpRequest($verb, $url, $body="", $headers=array(), $timeout = 10)
76
- {
77
- $e = error_reporting(0);
78
-
79
- $result = array();
80
- $result["cookie"] = NULL;
81
- $result["body"] = "";
82
- $result["length"] = NULL;
83
- $result["error"] = NULL;
84
-
85
- $now = time();
86
- $url = wsd_parseUrl($url);
87
-
88
- if($url["error"] !== NULL) return $url;
89
-
90
- $scheme = $url["scheme"]=="https" ? "ssl://" : "";
91
-
92
- $fp = fsockopen($scheme.$url["host"], $url["port"] , $errno, $errstr, $timeout);
93
-
94
- if (!$fp)
95
- {
96
- if($scheme == "ssl://")
97
- {
98
- $fp = fsockopen($url["host"], 80 , $errno, $errstr, $timeout);
99
- if (!$fp)
100
- {
101
- error_reporting($e);
102
- return array("error"=>"Can't connect to server [$errno].");
103
- }
104
- }
105
- else
106
- {
107
- error_reporting($e);
108
- return array("error"=>"Can't connect to server [$errno].");
109
- }
110
- }
111
-
112
- $out = $verb." ".$url["path"].$url["query"]." HTTP/1.1\r\n";
113
- $out .= "Host: ". $url["host"] . "\r\n";
114
- $out .= "Connection: Close\r\n";
115
- $out .= "Accept-Encoding: identity\r\n";
116
- if($verb == "POST") $out .= "Content-Length: " . strlen($body) . "\r\n";
117
- foreach ($headers as $name => $value) $out .= $name .": " . $value . "\r\n";
118
- $out .= "\r\n";
119
- if($verb == "POST") $out .= $body;
120
- fwrite($fp, $out);
121
- fflush($fp);
122
-
123
- //print "<br>".str_replace("\r\n", "<br>", $out)."<br>";
124
-
125
- $status = HTTP_STATUS;
126
- $chunked = False;
127
- $lastChunk = "";
128
- $chunkLength = 0;
129
-
130
- while (!feof($fp))
131
- {
132
- $remaining = $timeout - (time() - $now);
133
- if($remaining < 0) return array("error"=>"Request timed out [1].");
134
-
135
- stream_set_timeout($fp, $remaining + 1);
136
- $data = fgets($fp, 4096);
137
- $info = stream_get_meta_data($fp);
138
-
139
- if ($info["timed_out"])
140
- {
141
- error_reporting($e);
142
- return array("error"=>"Request timed out [2].");
143
- }
144
-
145
- //print($data."<br>");
146
-
147
- if($status == HTTP_STATUS)
148
- {
149
- //TODO: check status for 200, error on rest, eventually work arround 302 303
150
- $resultStatus = trim($data);
151
- $status = HTTP_HEADERS;
152
- continue;
153
- }
154
-
155
- if($status == HTTP_HEADERS)
156
- {
157
- if($data == "\r\n")
158
- {
159
- if($chunked)
160
- $status = HTTP_CHUNK_HEADER;
161
- else
162
- $status = HTTP_BODY;
163
- continue;
164
- }
165
-
166
- $data = trim($data);
167
- $separator = strpos($data, ": ");
168
-
169
- if(($separator === False)||($separator == 0) || ($separator >= (strlen($data) -2)))
170
- return array("error"=>"Invalid HTTP response header.");
171
-
172
- $name = substr($data, 0, $separator);
173
- $value = substr($data, $separator + 2);
174
- if(strcasecmp("Set-Cookie", $name) == 0)
175
- {
176
- $result["cookie"] = $value;
177
- continue;
178
- }
179
- if(strcasecmp("Content-Length", $name) == 0)
180
- {
181
- $result["length"] = $value + 0;
182
- continue;
183
- }
184
- if((strcasecmp("Transfer-Encoding", $name) == 0) && (strpos($value, 'chunked') !== False) )
185
- {
186
- $chunked = True;
187
- continue;
188
- }
189
- continue;
190
- }
191
-
192
- if($status == HTTP_CHUNK_HEADER)
193
- {
194
- $data = trim($data);
195
- $sc = strpos($data, ';');
196
- if($sc !== False) $data = substr($data, 0, $sc);
197
- $chunkLength = hexdec($data);
198
- if($chunkLength == 0)
199
- break;
200
- $lastChunk = "";
201
- $status = HTTP_CHUNK_BODY;
202
- continue;
203
- }
204
-
205
- if($status == HTTP_CHUNK_BODY)
206
- {
207
- $lastChunk .= $data;
208
- if(strlen($lastChunk) >= $chunkLength)
209
- {
210
- $result["body"] .= substr($lastChunk, 0, $chunkLength);
211
- $status = HTTP_CHUNK_HEADER;
212
- }
213
- continue;
214
- }
215
-
216
- if($status == HTTP_BODY)
217
- {
218
- $result["body"] .= $data;
219
- if(($result["length"] !== NULL) && (strlen($result["body"]) >= $result["length"]))
220
- break;
221
- continue;
222
- }
223
- }
224
- fclose($fp);
225
-
226
- if(($result["length"] !== NULL) && (strlen($result["body"]) != $result["length"]))
227
- array("error"=>"Invalid HTTP body length.");
228
-
229
- error_reporting($e);
230
- return $result;
231
- }
232
-
233
- function wsd_jsonHttpRequest($url, $data, $timeout = 10)
234
- {
235
- $body = json_encode($data);
236
- $headers = array("Content-type" => "application/json");
237
-
238
- $cookie = '';
239
- $option_cookie = get_option("WSD-COOKIE");
240
- if($option_cookie !== False) $cookie = $option_cookie;
241
-
242
- $token = get_option("WSD-TOKEN");
243
- if($token !== False)
244
- {
245
- if($cookie != '') $cookie .= '; ';
246
- $cookie .= "token=".$token;
247
- }
248
-
249
- if($cookie != '')
250
- $headers["Cookie"] = $cookie;
251
-
252
- $result = wsd_httpRequest("POST", $url, $body, $headers, $timeout);
253
-
254
- if($result["cookie"] !== NULL)
255
- {
256
- if($option_cookie === False)
257
- add_option("WSD-COOKIE", $result["cookie"]);
258
- else
259
- update_option("WSD-COOKIE", $result["cookie"]);
260
- }
261
-
262
- if($result["error"] === NULL)
263
- {
264
- $decoded = json_decode($result["body"], true);
265
- if($decoded == NULL) $result["error"] = "Invalid JSON response.".$result["body"];
266
- $result["body"] = $decoded;
267
- }
268
- return $result;
269
- }
270
-
271
- function wsd_jsonRPC($url, $method, $params, $timeout = 10)
272
- {
273
- $GLOBALS['wsd_last_err'] = array('code'=>0, 'message'=>'');
274
- $id = rand(1,100);
275
-
276
- $token = get_option("WSD-TOKEN");
277
- if($token === False)
278
- $request = array("jsonrpc"=>"2.0", "id"=>$id, "method"=>$method, "params"=>$params);
279
- else
280
- $request = array("jsonrpc"=>"2.0", "id"=>$id, "method"=>$method, "params"=>$params, "token"=>$token);
281
-
282
- $response = wsd_jsonHttpRequest($url, $request, $timeout);
283
-
284
- //print("request:");print_r($request); print("<hr>"); print("response:");print_r($response); print("<hr>");
285
-
286
- if($response["error"] !== NULL)
287
- {
288
- $GLOBALS['wsd_last_err'] = array("code" => 0, "message" => $response["error"]);
289
- return NULL;
290
- }
291
-
292
- if((! array_key_exists("id", $response["body"])) || ($response["body"]["id"] != $id) )
293
- {
294
- $GLOBALS['wsd_last_err'] = array("code" => 0, "message" => "Invalid JSONRPC response [0]." . var_export($response, true));
295
- return NULL;
296
- }
297
-
298
- if( array_key_exists("token", $response["body"]))
299
- {
300
- if($token === False) add_option("WSD-TOKEN", $response["body"]['token']);
301
- else update_option("WSD-TOKEN", $response["body"]['token']);
302
- }
303
-
304
- if(array_key_exists("error", $response["body"]))
305
- {
306
- $GLOBALS['wsd_last_err'] = $response["body"]["error"];
307
- return NULL;
308
- }
309
-
310
- if(! array_key_exists("result", $response["body"]))
311
- {
312
- $GLOBALS['wsd_last_err'] = array("code" => 0, "message" => "Invalid JSONRPC response [1].");
313
- return NULL;
314
- }
315
-
316
- return $response["body"]["result"];
317
- }
318
-
319
- // ========================= RENDER UI ===========================================================
320
-
321
- function wsd_render_error($custom_message = null)
322
- {
323
- $html = '';
324
- if ($custom_message === NULL)
325
- $html = '<p class="wsd-error-summary">' . $GLOBALS['wsd_last_err']['message'];
326
- else
327
- $html = '<p class="wsd-error-summary">' . $custom_message;
328
- $html .= '<br /><span class="wsd-error-summary-detail">If the problem persists please continue at <a href="https://dashboard.websitedefender.com" target="_blank">Website Defender</a>.</span></p>';
329
- echo $html;
330
- }
331
-
332
- function wsd_render_agent_install_issues($message)
333
- {
334
- //echo "wsd_render_agent_install_issues<br>";
335
- $html = '<p class="wsd-error-summary">' . $message;
336
- $html .= '<br /><span class="wsd-error-summary-detail">It has to be installed manually from the <a href="https://dashboard.websitedefender.com" target="_blank">WebsiteDefender dashboard</a>.</span></p>';
337
- echo $html;
338
- }
339
-
340
- function wsd_render_user_login($error = '')
341
- {
342
- if($error !== '') wsd_render_error($error);
343
- ?>
344
-
345
- <?php if(!empty($error)) { ?>
346
- <div class="wsd-inside">
347
- <?php } ?>
348
-
349
- <p class="wsd-login-notice">Login here if you already have a WSD account.</p>
350
- <form action="" method="post" id="wsd_login_form" name="wsd_login_form">
351
- <div>
352
- <div class="wsd-login-section">
353
- <label for="wsd_login_form_email">Email:</label>
354
- <input type="text" name="wsd_login_form_email" id="wsd_login_form_email" value="<?php echo get_option("admin_email"); ?>" />
355
- </div>
356
- <div class="wsd-login-section">
357
- <label for="wsd_login_form_password">Password:</label>
358
- <input type="password" name="wsd_login_form_password" id="wsd_login_form_password" />
359
- </div>
360
- <input type="submit" name="wsd-login" id="wsd-login" value="Login">
361
- </div>
362
- </form>
363
-
364
- <?php if(!empty($error)) { ?>
365
- </div>
366
- <?php } ?>
367
-
368
- <?php
369
- }
370
-
371
- function wsd_render_new_user($error = '')
372
- {
373
- //print "wsd_render_new_user $error<br>";
374
-
375
- $form = wsd_jsonRPC(WSD_URL_RPC, "cPlugin.getfrm", wsd_site_url());
376
- if ($form === NULL)
377
- {
378
- wsd_render_error();
379
- return;
380
- }
381
- $recaptcha_publickey = $form['captcha'];
382
- if(empty($recaptcha_publickey))
383
- {
384
- wsd_render_error('Invalid server response.');
385
- return;
386
- }
387
-
388
- //intro text
389
- echo '<p class="wsd-inside" style="margin-top: 0px;">';
390
- _e('WebsiteDefender.com is based upon web application scanning technology from <a href="http://www.acunetix.com/" target="_blank">Acunetix</a>; a pioneer in website security. <a href="http://www.websitedefender.com" target="_blank">WebsiteDefender</a> requires no installation, no learning curve and no maintenance. Above all, there is no impact on site performance! WebsiteDefender regularly scans and monitors your WordPress website/blog effortlessly, efficient, easily and is available for Free! Start scanning your WordPress website/blog against malware and hackers, absolutely free!', FB_SWP_TEXTDOMAIN);
391
- echo "</p>";
392
-
393
- ?>
394
- <div class="wsd-inside">
395
- <?php
396
- wsd_render_user_login();
397
- ?>
398
-
399
- <h4><?php _e('Register here to use all the WebsiteDefender.com advanced features', FB_SWP_TEXTDOMAIN)?></h4>
400
- <p><?php _e('WebsiteDefender is an online service that protects your website from any hacker activity by monitoring and auditing the security of your website, giving you easy to understand solutions to keep your website safe, always! WebsiteDefender\'s enhanced WordPress Security Checks allow it to optimise any threats on a blog or site powered by WordPress.', FB_SWP_TEXTDOMAIN)?></p>
401
- <p><?php _e('<strong>With WebsiteDefender you can:</strong>', FB_SWP_TEXTDOMAIN)?></p>
402
- <ul class="wsd_commonList">
403
- <li><span>Detect Malware present on your website</span></li>
404
- <li><span>Audit your website for security issues</span></li>
405
- <li><span>Avoid getting blacklisted by Google</span></li>
406
- <li><span>Keep your website content and data safe</span></li>
407
- <li><span>Get alerted to suspicious hacker activity</span></li>
408
- </ul>
409
-
410
- <p><?php _e('WebsiteDefender.com does all this an more via an easy-to-understand web-based dashboard, which gives step by step solutions on how to make sure your website stays secure!', FB_SWP_TEXTDOMAIN)?></p>
411
-
412
- <h4><?php _e('Sign up for your FREE account here', FB_SWP_TEXTDOMAIN)?></h4>
413
-
414
- <?php
415
- if($error !== '') wsd_render_error($error);
416
- ?>
417
-
418
- <form action="#em" method="post" id="wsd_new_user_form" name="wsd_new_user_form">
419
- <div id="em" class="wsd-new-user-section">
420
- <label for="wsd_new_user_email">Email:</label>
421
- <input type="text" name="wsd_new_user_email" id="wsd_new_user_email" value="<?php echo get_option("admin_email"); ?>" />
422
- </div>
423
- <div class="wsd-new-user-section">
424
- <label for="wsd_new_user_name">Name:</label>
425
- <input type="text" name="wsd_new_user_name" id="wsd_new_user_name" value="<?php echo isset($_POST['wsd_new_user_name']) ? $_POST['wsd_new_user_name'] : '' ?>" />
426
- </div>
427
- <div class="wsd-new-user-section">
428
- <label for="wsd_new_user_surname">Surname:</label>
429
- <input type="text" name="wsd_new_user_surname" id="wsd_new_user_surname" value="<?php echo isset($_POST['wsd_new_user_surname']) ? $_POST['wsd_new_user_surname']: '' ?>" />
430
- </div>
431
- <div class="wsd-new-user-section">
432
- <label for="wsd_new_user_password">Password:</label>
433
- <input type="password" name="wsd_new_user_password" id="wsd_new_user_password"/>
434
- <label class="password-meter" style="background-color: rgb(238, 0, 0);">Too Short</label>
435
- </div>
436
- <div class="wsd-new-user-section">
437
- <label for="wsd_new_user_password_re">Retype Password:</label>
438
- <input type="password" name="wsd_new_user_password_re" id="wsd_new_user_password_re"/>
439
- </div>
440
- <div class="wsd-new-user-section">
441
- <?php
442
- echo wsd_recaptcha_get_html($recaptcha_publickey, NULL, true);
443
- ?>
444
- </div>
445
- <input type="submit" name="wsd-new-user" id="wsd-new-user" value="Register">
446
- </form>
447
- </div>
448
- <?php
449
- }
450
-
451
-
452
- function wsd_process_login()
453
- {
454
- $email = isset($_POST['wsd_login_form_email']) ? $_POST['wsd_login_form_email'] : null;
455
- $password = isset($_POST['wsd_login_form_password']) ? $password = $_POST['wsd_login_form_password'] : null;
456
-
457
- if (empty($email)) {
458
- wsd_render_user_login('Email address is required.');
459
- return;
460
- }
461
-
462
- if (empty($password)) {
463
- wsd_render_user_login('Password is required.');
464
- return;
465
- }
466
-
467
- // $password is received as MD5 hash
468
- $login = wsd_jsonRPC(WSD_URL_RPC, "cUser.login", array($email, $password));
469
-
470
- if ($login == NULL) {
471
- wsd_render_user_login('Invalid login');
472
- return;
473
- }
474
-
475
- $user = get_option("WSD-USER");
476
- if ($user === False)
477
- add_option("WSD-USER", $email);
478
- else
479
- update_option("WSD-USER", $email);
480
-
481
- wsd_add_or_process_target();
482
- }
483
-
484
- function wsd_render_add_target_id()
485
- {
486
- ?>
487
- <div class="wsd-inside">
488
- <?php if(!empty($error)) wsd_render_error($error); ?>
489
- <form action="" method="post" id="wsd_target_id_form" name="wsd_target_id_form">
490
- <?php
491
- $emailAddress = get_option('WSD-USER');
492
- if(empty($emailAddress)){
493
- $emailAddress = get_option('admin_email');
494
- }
495
- ?>
496
- <p>
497
- <label><?php echo __('WebsiteDefender email account');?>:</label>
498
- <br/>
499
- <input type="text" name="wpss_user_email" id="wpss_user_email" style="width: 200px;" value="<?php echo $emailAddress;?>"/>
500
- </p>
501
- <p>
502
- <label for="wsd_target_update_id"><?php echo __('Target ID');?>:</label>
503
- <br/>
504
- <input type="text" name="targetid" id="targetid" value="<?php echo get_option('WSD-TARGETID');?>"/>
505
- <br/><br/>
506
- <input type="submit" name="wsd_update_target_id" value="<?php echo __('Update');?>" />
507
- </p>
508
- </form>
509
- <div class="wsd_user_information">
510
- <p style="margin: 0 0;">
511
- <?php
512
- echo __('To get the WebsiteDefender target ID of your website, login to the
513
- <a href="https://dashboard.websitedefender.com/" target="_blank">WebsiteDefender dashboard</a>
514
- and from the <code>Website Settings</code> navigate to the <code>Status</code> tab. The Target ID
515
- can be found under the <code>Scan Status</code> section.');
516
- ?>
517
- </p>
518
- </div>
519
- </div>
520
- <?php
521
- }
522
-
523
- function wsd_process_add_target_id()
524
- {
525
- //echo "process_add_target_id<br>";
526
- if(! empty($_POST['targetid'])){
527
- add_option('WSD-TARGETID', $_POST['targetid']);
528
- }
529
- if( ! empty($_POST['wpss_user_email'])){
530
- add_option('WSD-USER', $_POST['wpss_user_email']);
531
- }
532
- wsd_render_target_status();
533
- }
534
-
535
- function wsd_add_or_process_target()
536
- {
537
- //check if we already registered
538
- $targetid = get_option('WSD-TARGETID');
539
-
540
- if($targetid !== false)
541
- {
542
- wsd_render_target_status();
543
- return;
544
- }
545
- else
546
- {
547
- //check first is this url is already there
548
- $target = wsd_jsonRPC(WSD_URL_RPC, "cPlugin.urlstatus", wsd_site_url());
549
- if($target === NULL)
550
- {
551
- wsd_render_error();
552
- return;
553
- }
554
- if(array_key_exists('id', $target) && ($target['id'] != NULL))
555
- {
556
- if($targetid === False) add_option('WSD-TARGETID', $target['id']);
557
- else update_option('WSD-TARGETID', $target['id']);
558
- wsd_render_target_status();
559
- return;
560
- }
561
- }
562
-
563
- //the target was not there so we have to register a new one
564
- $newtarget = wsd_jsonRPC(WSD_URL_RPC, "cTargets.add", wsd_site_url());
565
- if($newtarget === NULL)
566
- {
567
- if($GLOBALS['wsd_last_err']['code'] == WSD_ERROR_LIMITATION)
568
- {
569
- wsd_render_error("This account reached the maximum number of targets.");
570
- return;
571
- }
572
- if($GLOBALS['wsd_last_err']['code'] == WSD_ERROR_WPP_URL_EXIST)
573
- {
574
- wsd_render_add_target_id();
575
- return;
576
- }
577
- print_r($GLOBALS['wsd_last_err']);
578
- return;
579
- }
580
-
581
- if(!array_key_exists("id", $newtarget))
582
- {
583
- wsd_render_error("Invalid WSD response received.");
584
- return;
585
- }
586
-
587
- delete_option('WSD-TARGETID');
588
- add_option('WSD-TARGETID', $newtarget['id']);
589
-
590
- //download agent
591
- $targetInstalError = '';
592
-
593
- $headers = array("a"=>"a");
594
- $option_cookie = get_option("WSD-COOKIE");
595
- if($option_cookie !== False) $headers["Cookie"] = $option_cookie;
596
-
597
- //print "<br>Downloading: ". WSD_URL_DOWN.'?id='.$newtarget['id'] ."#". print_r($headers, true). "<br>";
598
-
599
- $agent = wsd_httpRequest("GET", WSD_URL_DOWN.'?id='.$newtarget['id'], "", $headers);
600
-
601
- if($agent["error"] !== NULL)
602
- $targetInstalError = 'The WebsiteDefender Agent failed to install automatically [0x01].'; //can't download
603
- else
604
- {
605
- //try to copy the target
606
- $agentURL = $agent["sensor_url"];
607
- if(preg_match('/[a-f0-9]{40}.php/', $newtarget["sensor_url"], $matches))
608
- {
609
- $path = rtrim(ABSPATH, '/');
610
- $path .= '/'.$matches[0];
611
-
612
- $r = file_put_contents($path, $agent['body']);
613
- if(!$r) $targetInstalError = 'The WebsiteDefender Agent failed to install automatically [0x02].'; //can't save
614
- }
615
- else $targetInstalError = 'The WebsiteDefender Agent failed to install automatically [0x03].'; //other
616
- }
617
-
618
- //test the agent, this will triger agentless if agent not functioning
619
- $testTarget = wsd_jsonRPC(WSD_URL_RPC, "cTargets.agenttest", $newtarget['id']);
620
- $enbableTarget = wsd_jsonRPC(WSD_URL_RPC, "cTargets.enable", array($newtarget['id'], true));
621
-
622
- if($targetInstalError != '')wsd_render_agent_install_issues($targetInstalError);
623
-
624
- wsd_render_target_status();
625
- }
626
-
627
- function wsd_process_new_user_form()
628
- {
629
- //print "wsd_process_new_user_form<br>";
630
-
631
- $email = $_POST['wsd_new_user_email'];
632
- $name = $_POST['wsd_new_user_name'];
633
- $surname = $_POST['wsd_new_user_surname'];
634
- $password = $_POST['wsd_new_user_password'];
635
- $password_re = $_POST['wsd_new_user_password_re'];
636
-
637
- if (empty($email)) {
638
- wsd_render_new_user('Email is required.');
639
- return;
640
- }
641
- if (empty($name)) {
642
- wsd_render_new_user('Name is required.');
643
- return;
644
- }
645
- if (empty($surname)) {
646
- wsd_render_new_user('Surname is required.');
647
- return;
648
- }
649
- if (empty($password)) {
650
- wsd_render_new_user('Password is required.');
651
- return;
652
- }
653
- if ($password != $password_re) {
654
- wsd_render_new_user('Passwords do not match.');
655
- return;
656
- }
657
-
658
- $register = wsd_jsonRPC(WSD_URL_RPC, "cPlugin.register",
659
- array(
660
- array("challenge"=>$_POST['recaptcha_challenge_field'],
661
- "response"=>$_POST['recaptcha_response_field']),
662
- array(
663
- "url" => wsd_site_url(),
664
- "email" => $email,
665
- "name" => $name,
666
- "surname" => $surname,
667
- // the password comes from the client already as a hash
668
- "pass" => $password,
669
- "source" => WSD_SOURCE
670
- )
671
- ));
672
- if($register == NULL)
673
- {
674
- if($GLOBALS['wsd_last_err']['code'] == WSD_ERROR_WPP_INVALID_CAPTCHA)
675
- {
676
- wsd_render_new_user('Invalid captcha. Please try again.');
677
- return;
678
- }
679
- if($GLOBALS['wsd_last_err']['code'] == WSD_ERROR_WPP_USER_EXIST)
680
- {
681
- wsd_render_new_user("This user is already registered. To continue with this user, please use the login form above or register with a new user name.");
682
- return;
683
- }
684
- wsd_render_new_user('Registration failed! Please try again.');
685
- return;
686
- }
687
- $user = get_option("WSD-USER");
688
- if($user === False) add_option("WSD-USER", $email); else update_option("WSD-USER", $email);
689
- wsd_add_or_process_target();
690
- }
691
-
692
- function wsd_render_target_status()
693
- {
694
- #echo "wsd_render_target_status<br>";
695
- $user = get_option('WSD-USER');
696
- if((!is_string($user))||($user == "") ) $user = get_option("admin_email");
697
- $status = wsd_jsonRPC(WSD_URL_RPC, "cPlugin.status", array($user, get_option('WSD-TARGETID'), wsd_site_url()));
698
- if($status === NULL)
699
- {
700
- return;
701
- }
702
- if((!array_key_exists('active', $status)) || ($status['active'] !== 1))
703
- {
704
- //our target is not valid anymore
705
- delete_option('WSD-TARGETID');
706
-
707
- // Display the add target id form
708
- // update: sept 20
709
- wsd_render_add_target_id();
710
- wsd_render_error('Invalid Target ID!');
711
- return false;
712
- }
713
-
714
- echo '<p class="wsd-inside">';
715
- echo 'Thank you for registering with WebsiteDefender. Please navigate to the <a target="_blank" href="https://dashboard.websitedefender.com/">WebsiteDefender dashboard</a> to see the alerts.';
716
- echo "</p>";
717
-
718
- $enabled = array_key_exists('enabled', $status) ? $status['enabled'] : null;
719
- $scanned = array_key_exists('scanned', $status) ? $status['scanned'] : null;
720
- $agentless = array_key_exists('agentless', $status) ? $status['agentless'] : null;
721
-
722
- if (!is_numeric($enabled) || !is_numeric($scanned) || !is_numeric($agentless))
723
- {
724
- wsd_render_error('Invalid server response.');
725
- return;
726
- }
727
- $enabled = intval($enabled);
728
- $scanned = intval($scanned);
729
- $agentless = intval($agentless);
730
- ?>
731
-
732
- <div id="wsd-target-status-holder" class="wsd-inside">
733
- <p class="wsd-target-status-title">
734
- Website status on Website Defender
735
- </p>
736
- <div class="wsd-target-status-section">
737
- <?php
738
- $statusText = 'NO';
739
- if ($enabled == 1) {
740
- $statusText = 'YES';
741
- }
742
- echo '<span class="wsd-target-status-section-label">Enabled: </span>',
743
- '<span class="wsd-target-status-section-', $enabled ? 'enabled' : 'disabled', '">', $statusText, '</span>';
744
- ?>
745
- </div>
746
- <div class="wsd-target-status-section">
747
- <?php
748
- $statusText = 'NO';
749
- if ($scanned == 1) {
750
- $statusText = 'YES';
751
- }
752
- echo '<span class="wsd-target-status-section-label">Scanned: </span>',
753
- '<span class="wsd-target-status-section-', $scanned ? 'enabled' : 'disabled', '">', $statusText, '</span>';
754
- ?>
755
- </div>
756
- <div class="wsd-target-status-section">
757
- <?php
758
- $statusText = 'UP';
759
- if ($agentless == 1) {
760
- $statusText = 'DOWN';
761
- }
762
- echo '<span class="wsd-target-status-section-label">Agent status: </span>',
763
- '<span class="wsd-target-status-section-', $agentless ? 'disabled' : 'enabled', '">', $statusText, '</span>';
764
- ?>
765
- </div>
766
- </div>
767
-
768
- <?php
769
-
770
- return True;
771
- }
772
-
773
- function wsd_render_main()
774
- {
775
- if(1==0)
776
- {
777
- delete_option('WSD-TARGETID');
778
- delete_option("WSD-COOKIE");
779
- delete_option("WSD-USER");
780
- return;
781
- }
782
-
783
- if(isset($_POST['wsd-new-user']))
784
- {
785
- wsd_process_new_user_form();
786
- return;
787
- }
788
-
789
- if(isset($_POST['wsd-login']))
790
- {
791
- wsd_process_login();
792
- return;
793
- }
794
-
795
- if(isset($_POST['wsd_update_target_id']))
796
- {
797
- wsd_process_add_target_id();
798
- return;
799
- }
800
-
801
- $targetid = get_option("WSD-TARGETID");
802
- if($targetid !== False)
803
- {
804
- wsd_render_target_status();
805
- return;
806
- }
807
-
808
- $hello = wsd_jsonRPC(WSD_URL_RPC, "cPlugin.hello", wsd_site_url());
809
-
810
- if($hello == NULL)
811
- {
812
- // update sept 20
813
- wsd_render_new_user();
814
- return;
815
- }
816
-
817
- if($hello == 'registered')
818
- {
819
- wsd_render_add_target_id();
820
- return;
821
- }
822
- elseif($hello == 'new')
823
- {
824
- //$user = get_option("WSD-USER"); if($user === FALSE)
825
- wsd_render_new_user();
826
- //else wsd_render_user_login();
827
- }
828
- else
829
- {
830
- wsd_render_error("Invalid server response.");
831
- return;
832
- }
833
- }
834
-
835
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -1,17 +1,20 @@
1
- === WP Security Scan ===
2
- Contributors: WebsiteDefender
3
- Author: WebsiteDefender
4
- Tags: security, securityscan, chmod, permissions, admin, administration, authentication, database, dashboard, post, notification, password, plugin, posts, wsd, websitedefender,
5
  plugins, private, protection, tracking, wordpress
6
  Requires at least: 3.0
7
- Tested up to: 3.2.1
8
  Stable tag: trunk
9
 
10
  Scans your WordPress installation for security vulnerabilities.
11
 
12
  == Description ==
 
 
 
13
 
14
- WP Security Scan checks your WordPress website/blog for security vulnerabilities and suggests corrective actions such as:
15
 
16
  1. Passwords
17
  2. File permissions
@@ -22,25 +25,148 @@ WP Security Scan checks your WordPress website/blog for security vulnerabilities
22
 
23
  = Requirements =
24
 
25
- * WordPress version 3.0 and higher (tested at <= 3.2.1)
26
  * PHP5 (tested with PHP Interpreter >= 5.2.9)
27
 
28
- For more information on the WP Security Scan and other WordPress security news, visit the <a href="http://www.websitedefender.com/blog" target="_blank">WebsiteDefender Blog</a> and join our <a href="http://www.facebook.com/websitedefender" target="_blank">Facebook</a> page. Post any questions or feedback on the <a href="http://www.websitedefender.com/forums/wp-security-scan-plugin/" target="_blank">WP Security Scan plugin forum</a>.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
 
31
  == Installation ==
32
 
33
- 1. Make a backup of your current installation
34
- 2. Unpack the download package
35
- 3. Upload the extracted files to the /wp-content/plugins/ directory
36
- 4. Activate the plugin through the 'Plugins' menu in WordPress
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- If you do encounter any bugs, or have comments or suggestions, please contact the WebsiteDefender team on support@websitedefender.com.
 
 
 
39
 
40
- For more information on the WP Security Scan and other WordPress security news, visit the <a href="http://www.websitedefender.com/blog" target="_blank">WebsiteDefender Blog</a> and join our <a href="http://www.facebook.com/websitedefender" target="_blank">Facebook</a> page. Post any questions or feedback on the <a href="http://www.websitedefender.com/forums/wp-security-scan-plugin/" target="_blank">WP Security Scan plugin forum</a>.
41
 
42
  == Changelog ==
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  = v3.0.8 =
45
  * New feature: Option to open / close WebsiteDefender dashboard widget
46
  * Update: More help resource links
@@ -87,59 +213,7 @@ For more information on the WP Security Scan and other WordPress security news,
87
  * Feature: Rebranding of the plugin
88
  * Feature: Integrated WebsiteDefender.com registration in Settings
89
 
90
- For more information on the WP Security Scan and other WordPress security news, visit the <a href="http://www.websitedefender.com/blog" target="_blank">WebsiteDefender Blog</a> and join our <a href="http://www.facebook.com/websitedefender" target="_blank">Facebook</a> page. Post any questions or feedback on the <a href="http://www.websitedefender.com/forums/wp-security-scan-plugin/" target="_blank">WP Security Scan plugin forum</a>.
91
-
92
- == Frequently Asked Questions ==
93
-
94
- = Can I deactivate WP Security Scan once I've run it once? =
95
-
96
- No. WP Security Scan needs to be left activated to work. Version hiding,
97
- turning off DB errors, removing WP ID META tag from HTML output, and other
98
- functionality will cease if you deactivate the plugin.
99
-
100
- = How do I change the file permissions on my WordPress installation? =
101
-
102
- From the Linux command line (for advanced users):
103
- chmod xxx filename.ext
104
- (replace xxx with with the permissions settings for the file or folder).
105
-
106
- From your FTP client:
107
- Most FTP clients, such as filezilla, etc, allow for changing file
108
- permissions. Please consult your client's documentation for your specific
109
- directions.
110
-
111
- For more information, please visit http://codex.wordpress.org/Changing_File_Permissions
112
-
113
- = Why do I need to hide my version of WordPress? =
114
-
115
- Many attackers and automated tools will try and determine software versions
116
- before launching exploit code. Removing your WordPress blog version may
117
- discourage some attackers and certainly will mitigate virus and malware programs
118
- that rely on software versions.
119
-
120
- NOTE: Hiding your version of WordPress may break any plugins you have which
121
- are version dependant.
122
-
123
- = How do I make Dagon Design's sitemap generator plugin compatible? =
124
- There is currently a small compatibility issue. This can be temporarily
125
- solved by opening securityscan.php and commenting out the line
126
- `add_action("init",mrt_remove_wp_version,1);`
127
-
128
-
129
- For more information on the WP Security Scan and other WordPress security news, visit the <a href="http://www.websitedefender.com/blog" target="_blank">WebsiteDefender Blog</a> and join our <a href="http://www.facebook.com/websitedefender" target="_blank">Facebook</a> page. Post any questions or feedback on the <a href="http://www.websitedefender.com/forums/wp-security-scan-plugin/" target="_blank">WP Security Scan plugin forum</a>.
130
-
131
- == Screenshots ==
132
-
133
- 1. file/directories permissions check
134
- 2. password tools
135
-
136
- == WordPress Security ==
137
-
138
- Security Scanner:
139
-
140
- 1. Scans Wordpress installation for file/directory permissions vulnerabilites
141
- 2. Recommends corrective actions
142
- 3. Scans for general security vulnerabilities
143
-
144
-
145
- For more information on the WP Security Scan and other WordPress security news, visit the <a href="http://www.websitedefender.com/blog" target="_blank">WebsiteDefender Blog</a> and join our <a href="http://www.facebook.com/websitedefender" target="_blank">Facebook</a> page. Post any questions or feedback on the <a href="http://www.websitedefender.com/forums/wp-security-scan-plugin/" target="_blank">WP Security Scan plugin forum</a>.
1
+ === Acunetix WP Security ===
2
+ Contributors: Acunetix
3
+ Author: Acunetix
4
+ Tags: security, securityscan, chmod, permissions, admin, administration, authentication, database, dashboard, post, notification, password, plugin, posts,
5
  plugins, private, protection, tracking, wordpress
6
  Requires at least: 3.0
7
+ Tested up to: 3.6
8
  Stable tag: trunk
9
 
10
  Scans your WordPress installation for security vulnerabilities.
11
 
12
  == Description ==
13
+ Acunetix WP Security plugin is a free and comprehensive security tool that helps you secure your WordPress
14
+ installation and suggests corrective measures for: securing file permissions, security of the database, version hiding,
15
+ WordPress admin protection and lots more.
16
 
17
+ Acunetix WP Security checks your WordPress website/blog for security vulnerabilities and suggests corrective actions such as:
18
 
19
  1. Passwords
20
  2. File permissions
25
 
26
  = Requirements =
27
 
28
+ * WordPress version 3.0 and higher
29
  * PHP5 (tested with PHP Interpreter >= 5.2.9)
30
 
31
+ For more information on the Acunetix WP Security plug-in and other WordPress security news, visit the
32
+ <a href="http://www.acunetix.com/blog/" target="_blank">Acunetix Blog</a> and join
33
+ our <a href="http://www.facebook.com/Acunetix" target="_blank">Facebook</a> page. Post any questions or feedback
34
+ on the <a href="http://wordpress.org/support/plugin/wp-security-scan" target="_blank">Acunetix WP Security plug-in forum</a>.
35
+
36
+ = Key security features: =
37
+
38
+ * Easy backup of WordPress database for disaster recovery
39
+ * Removal of error-information on login-page
40
+ * Addition of index.php to the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listings
41
+ * Removal of wp-version, except in admin-area
42
+ * Removal of Really Simple Discovery meta tag
43
+ * Removal of Windows Live Writer meta tag
44
+ * Removal of core update information for non-admins
45
+ * Removal of plugin-update information for non-admins
46
+ * Removal of theme-update information for non-admins (only WP 2.8 and higher)
47
+ * Hiding of wp-version in backend-dashboard for non-admins
48
+ * Removal of version in URLs from scripts and stylesheets only on frontend
49
+ * Reporting of security overview after WordPress blog is scanned
50
+ * Reporting of file permissions following security checks
51
+ * Live traffic tool to monitor your website activity in real time
52
+ * Integrated tool to change the database prefix
53
+ * Disabling of database error reporting (if enabled)
54
+ * Disabling of PHP error reporting
55
+
56
+ For more information on the Acunetix WP Security plug-in and other WordPress security news, visit the
57
+ <a href="http://www.acunetix.com/blog/" target="_blank">Acunetix Blog</a> and join
58
+ our <a href="http://www.facebook.com/Acunetix" target="_blank">Facebook</a> page. Post any questions or feedback
59
+ on the <a href="http://wordpress.org/support/plugin/wp-security-scan" target="_blank">Acunetix WP Security plug-in forum</a>.
60
+
61
 
62
 
63
  == Installation ==
64
 
65
+ * Make a backup of your current installation
66
+ * Unpack the downloaded package
67
+ * Upload the extracted files to the /wp-content/plugins/ directory
68
+ * Activate the plugin through the 'Plugins' menu in WordPress
69
+
70
+ If you encounter any bugs, or have comments or suggestions, please post them on the
71
+ <a href="http://wordpress.org/support/plugin/wp-security-scan" target="_blank">Acunetix WP Security plug-in forum</a>.
72
+
73
+ For more information on the Acunetix WP Security plug-in and other WordPress security news, visit the
74
+ <a href="http://www.acunetix.com/blog/" target="_blank">Acunetix Blog</a> and join
75
+ our <a href="http://www.facebook.com/Acunetix" target="_blank">Facebook</a> page. Post any questions or feedback
76
+ on the <a href="http://wordpress.org/support/plugin/wp-security-scan" target="_blank">Acunetix WP Security plug-in forum</a>.
77
+
78
+
79
+ == WordPress Security ==
80
+
81
+ Security Scanner:
82
+
83
+ 1. Scans Wordpress installation for file/directory permissions vulnerabilites
84
+ 2. Recommends corrective actions
85
+ 3. Scans for general security vulnerabilities
86
+
87
+
88
+ For more information on the Acunetix WP Security plug-in and other WordPress security news, visit the
89
+ <a href="http://www.acunetix.com/blog/" target="_blank">Acunetix Blog</a> and join
90
+ our <a href="http://www.facebook.com/Acunetix" target="_blank">Facebook</a> page. Post any questions or feedback
91
+ on the <a href="http://wordpress.org/support/plugin/wp-security-scan" target="_blank">Acunetix WP Security plug-in forum</a>.
92
+
93
+
94
+ == Frequently Asked Questions ==
95
+
96
+ = Can I deactivate Acunetix WP Security once I've run it once? =
97
+
98
+ No. Acunetix WP Security needs to be left activated to work. Version hiding,
99
+ turning off DB errors, removing WP ID META tag from HTML output, and other
100
+ functionality will cease if you deactivate the plugin.
101
+
102
+ = How do I change the file permissions on my WordPress installation? =
103
+
104
+ From the Linux command line (for advanced users):
105
+ chmod xxx filename.ext
106
+ (replace xxx with with the permissions settings for the file or folder).
107
+
108
+ From your FTP client:
109
+ Most FTP clients, such as FileZilla, etc, allow for changing file
110
+ permissions. Please consult your client's documentation for your specific
111
+ directions.
112
+
113
+ For more information, please visit http://codex.wordpress.org/Changing_File_Permissions
114
+
115
+ = Why do I need to hide my version of WordPress? =
116
+
117
+ Many attackers and automated tools will try and determine software versions
118
+ before launching exploit code. Removing your WordPress blog version may
119
+ discourage some attackers and certainly will mitigate virus and malware programs
120
+ that rely on software versions.
121
+
122
+ For more information on the Acunetix WP Security plug-in and other WordPress security news, visit the
123
+ <a href="http://www.acunetix.com/blog/" target="_blank">Acunetix Blog</a> and join
124
+ our <a href="http://www.facebook.com/Acunetix" target="_blank">Facebook</a> page. Post any questions or feedback
125
+ on the <a href="http://wordpress.org/support/plugin/wp-security-scan" target="_blank">Acunetix WP Security plug-in forum</a>.
126
+
127
+
128
+ == Screenshots ==
129
+
130
+ 1. The File Scan Report
131
+ 2. The Settings page, displaying all configurable options
132
+ 3. The Live Traffic page
133
+ 4. The new Dashboard page
134
+
135
+
136
+ == Other Notes ==
137
+ = License =
138
+ Good news, this plugin is free for everyone! Since it's released under the GPL, you can use it free of charge on your personal or commercial blog.
139
 
140
+ For more information on the Acunetix WP Security plug-in and other WordPress security news, visit the
141
+ <a href="http://www.acunetix.com/blog/" target="_blank">Acunetix Blog</a> and join
142
+ our <a href="http://www.facebook.com/Acunetix" target="_blank">Facebook</a> page. Post any questions or feedback
143
+ on the <a href="http://wordpress.org/support/plugin/wp-security-scan" target="_blank">Acunetix WP Security plug-in forum</a>.
144
 
 
145
 
146
  == Changelog ==
147
 
148
+ = 4.0.0 =
149
+ * Complete core update
150
+ * Added live traffic functionality
151
+ * Added check for the wp-config.php file one level above if not found in the install directory
152
+ * Fixed broken functionalities
153
+ * Security settings are now configurable
154
+
155
+
156
+ = 3.1.0 =
157
+ * Removed the registration requirement
158
+
159
+ = v3.0.9 =
160
+ * New feature: Added tooltips to the most important sections of the System Information box
161
+ * Update: Added 'nonce' fields to forms where needed (thanks to julio from boiteaweb.fr)
162
+ * Update: Updated the deprecated function call get_bloginfo('siteurl') to get_bloginfo('url')
163
+ * Update: Updated paths to external resources such as javascript and css files for ssl compatibility
164
+ * Update: Updated validation for plug-in form fields (email address, user name, target id, etc.)
165
+ * Update: Enhanced the input validation for the Change Database Prefix tool
166
+ * Update: Plugin settings are now accessible only by WordPress administrators
167
+ * Update: Improved user-rights retrieval in the WordPress database
168
+
169
+
170
  = v3.0.8 =
171
  * New feature: Option to open / close WebsiteDefender dashboard widget
172
  * Update: More help resource links
213
  * Feature: Rebranding of the plugin
214
  * Feature: Integrated WebsiteDefender.com registration in Settings
215
 
216
+ For more information on the Acunetix WP Security plug-in and other WordPress security news, visit the
217
+ <a href="http://www.acunetix.com/blog/" target="_blank">Acunetix Blog</a> and join
218
+ our <a href="http://www.facebook.com/Acunetix" target="_blank">Facebook</a> page. Post any questions or feedback
219
+ on the <a href="http://wordpress.org/support/plugin/wp-security-scan" target="_blank">Acunetix WP Security plug-in forum</a>.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
res/backups/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
res/css/acx-styles-extra.css ADDED
@@ -0,0 +1 @@
 
1
+ .update-plugins, #login #login_error, #wp-version-message, #footer-upgrade {display: none !important;}
res/css/blog.css ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #pageblog { margin: 10px 0 10px 16px;}
3
+
4
+ #pageblog #header {
5
+ background: transparent;
6
+ padding: 10px 10px;
7
+ overflow: hidden;
8
+ border-bottom: 1px solid #cccccc;
9
+ background: url("../images/blog/featured-slider-bg.jpg") no-repeat center top;
10
+ }
11
+ #pageblog #header #logo {
12
+ float: left;
13
+ width: 301px;
14
+ margin: 0 13px 0 0;
15
+ }
16
+ #pageblog #header #logo a {
17
+ width: 300px;
18
+ height: 70px;
19
+ float: left;
20
+ text-indent: -9999px;
21
+ background: url("../images/blog/logo.png") no-repeat left top;
22
+ }
23
+ #pageblog #header #main-nav {
24
+ float: right;
25
+ zoom: 1;
26
+ display: block;
27
+ margin: 27px 0 0 0;
28
+ }
29
+ #pageblog #header #main-nav:after {
30
+ content: '\\0020';
31
+ display: block;
32
+ height: 0;
33
+ clear: both;
34
+ visibility: hidden;
35
+ font-size: 0;
36
+ }
37
+
38
+ #pageblog #header #main-nav .facebook, #pageblog #header #main-nav .twitter {
39
+ float: left;
40
+ width: 16px;
41
+ height: 16px;
42
+ margin: 4px 0 0 10px;
43
+ text-indent: -9999px;
44
+ }
45
+ #pageblog #header #main-nav .facebook { background: url("../images/blog/ico-facebook.png") no-repeat left top; }
46
+ #pageblog #header #main-nav .twitter { background: url("../images/blog/ico-twitter.png") no-repeat left top; }
47
+
48
+ #pageblog #content {
49
+ background: none repeat scroll 0 0 #F5F5F5;
50
+ border-top: 1px solid #FFFFFF;
51
+ padding: 10px 0 5px;
52
+ width: 100%;
53
+ }
54
+ #pageblog #content #feed-list{ list-style-position: outside; list-style-type: none; margin: 10px 30px;}
55
+ #pageblog #content #feed-list li {
56
+ padding: 2px 0;
57
+ }
58
+ #pageblog #content #feed-list li h4 {
59
+ background: url('../images/logo-small.png') no-repeat left center;
60
+ padding: 2px 0 2px 25px;
61
+ }
62
+
63
+
64
+
65
+
66
+
res/css/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
res/css/styles.alerts.css ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * CSS used for alerts page
3
+ *
4
+ **/
5
+
6
+ /** Indicators **/
7
+ .wsdplugin_content td.wsdplugin_alert_indicator
8
+ {
9
+ text-align: center;
10
+ vertical-align: middle;
11
+ width: 14px;
12
+ height: 17px;
13
+ }
14
+ .wsdplugin_content td.wsdplugin_alert_indicator.wsdplugin_alert_indicator_info { background: transparent url('../images/indicator-green.png') no-repeat scroll center center; }
15
+ .wsdplugin_content td.wsdplugin_alert_indicator.wsdplugin_alert_indicator_low { background: transparent url('../images/indicator-blue.png') no-repeat scroll center center; }
16
+ .wsdplugin_content td.wsdplugin_alert_indicator.wsdplugin_alert_indicator_medium { background: transparent url('../images/indicator-yellow.png') no-repeat scroll center center; }
17
+ .wsdplugin_content td.wsdplugin_alert_indicator.wsdplugin_alert_indicator_critical { background: transparent url('../images/indicator-red.png') no-repeat scroll center center; }
18
+
19
+ /** Actions Bar **/
20
+ .wsdplugin_content .wsdplugin_page_alerts_action_bar .wsdplugin_alerts_select_actions select,
21
+ .wsdplugin_content .wsdplugin_page_alerts_action_bar .wsdplugin_alerts_bulk_actions select,
22
+ .wsdplugin_content .wsdplugin_page_alerts_action_bar .wsdplugin_alerts_filter_severity select { width: 130px; }
23
+ .wsdplugin_content .wsdplugin_page_alerts_action_bar .wsdplugin_alerts_sort .wsdplugin_alerts_sort_field { width: 120px; }
24
+ .wsdplugin_content .wsdplugin_page_alerts_action_bar .wsdplugin_alerts_sort .wsdplugin_alerts_sort_dir { width: 110px; }
25
+ .wsdplugin_content .wsdplugin_alerts_show_view select { width: 90px; }
26
+
27
+ /** Alert Page **/
28
+ .wsdplugin_content .wsdplugin_page_alerts { }
29
+ .wsdplugin_content .wsdplugin_alert_section_title
30
+ {
31
+ clear: both;
32
+ padding: 20px 50px 20px 15px;
33
+ font-size: 18px;
34
+ border-radius: 3px;
35
+ margin-bottom: 20px;
36
+ margin-top: 10px;
37
+ }
38
+ .wsdplugin_content .wsdplugin_alert_section_title.wsdplugin_alert_section_title_category { background-color: #F9F9F9; border: 1px solid #DFDFDF; margin-bottom: 10px; box-shadow: 0px 0px 3px #DFDFDF; }
39
+
40
+ .acx-section-box { padding-top: 0 !important; padding-bottom: 0 !important;}
41
+
42
+ /** Checkbox **/
43
+ .wsdplugin-overflow { overflow: hidden; }
44
+ .wsdplugin-overflow .wsdplugin_checkbox { float: left; display: block; text-align: center; vertical-align: middle; width: 13px; margin-top: 1px; }
45
+ .wsdplugin-overflow span { float: left; display: block; margin-left: 7px; margin-top: 0;}
46
+ .wsdplugin-overflow .wsdplugin_checkbox a
47
+ {
48
+ background: transparent url('../images/checkbox.png') no-repeat scroll 0 0;
49
+ display: block;
50
+ width: 13px;
51
+ height: 13px;
52
+ }
53
+ .wsdplugin-overflow .wsdplugin_checkbox-active a { background-position: -13px 0; }
54
+
res/css/styles.base.css ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ .status-indicator { display: block; width: 16px; height: 16px;}
3
+ /* == 0 */
4
+ .indicator-green { background: url('../images/indicator-green.png') no-repeat 0 0; }
5
+ /* == 1 */
6
+ .indicator-red { background: url('../images/indicator-red.png') no-repeat 0 0; }
7
+ /* == 2 */
8
+ .indicator-yellow { background: url('../images/indicator-yellow.png') no-repeat 0 0; }
9
+ /* == 3 */
10
+ .indicator-blue { background: url('../images/indicator-blue.png') no-repeat 0 0; }
11
+
12
+ .wsd-content-section { float: left; display: block; }
13
+
14
+ #wsd-banner-rotator {
15
+ display: block; clear: both;
16
+ margin-top: 50px;
17
+ }
18
+
19
+ .entry {}
20
+ .entry-description { display: none; }
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
res/css/styles.general.css ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ /** General Styling **/
3
+
4
+ .wsdplugin_content
5
+ {
6
+
7
+ }
8
+
9
+ .wsdplugin_content .wsdplugin_status_page_ico {
10
+ background: url('../images/logo.png') no-repeat scroll center center transparent;
11
+ }
12
+ .wsdplugin_content .wsdplugin_alerts-page-ico {
13
+ background: url('../images/alerts-page-ico.png') no-repeat scroll center center transparent;
14
+ }
15
+
16
+
17
+ /*
18
+ * Error box
19
+ */
20
+ .wsdplugin_content .wsdplugin_error_box { }
21
+ .wsdplugin_content .wsdplugin_error_box p { overflow: hidden; }
22
+ .wsdplugin_content .wsdplugin_error_box p strong { display: block; float: left; }
23
+ .wsdplugin_content .wsdplugin_error_box p a.dismiss { float: right; display: block; }
24
+
25
+
26
+ .wsdplugin_content .wsdplugin_info_box {
27
+ background-color: #E0E9F9;
28
+ border-color: #98BCF9;
29
+ }
30
+ .wsdplugin_content .wsdplugin_info_box p { overflow: hidden; }
31
+ .wsdplugin_content .wsdplugin_info_box p strong { display: block; float: left; }
32
+ .wsdplugin_content .wsdplugin_info_box p a.dismiss { float: right; display: block; }
33
+
34
+
35
+
36
+ /*
37
+ * INFO / ERROR boxes
38
+ */
39
+ .wsdplugin_message
40
+ {
41
+ margin: 5px 0 15px;
42
+ padding: 0 0.6em;
43
+ border-radius: 3px;
44
+ border: 1px solid;
45
+ }
46
+ .wsdplugin_message.wsdplugin_message_warning
47
+ {
48
+ background-color: #FFFFE0;
49
+ border-color: #E6DB55;
50
+ }
51
+ .wsdplugin_message.wsdplugin_message_error
52
+ {
53
+ background-color: #FCC2C2;
54
+ border-color: #CC0000;
55
+ }
56
+ .wsdplugin_message.wsdplugin_message_success
57
+ {
58
+ background-color: #FFFFE0;
59
+ border-color: #E6DB55;
60
+ color: #006600;
61
+ }
62
+ .wsdplugin_message p
63
+ {
64
+ margin: 0.5em 0;
65
+ padding: 2px;
66
+ }
67
+
68
+
69
+
70
+ /*
71
+ * auth menu
72
+ */
73
+ #wsdplugin_advert a, #wsdplugin_advert img { border: none 0; outline: none 0;}
74
+ .wsdplugin_website_detail { overflow: hidden; float: none; clear: both;}
75
+ .wsdplugin_page_title { overflow: hidden; display: block; clear: both; }
76
+
77
+ .wsdplugin_page_title h2 {
78
+ background: url("../images/logo.png") no-repeat scroll 0 50% transparent;
79
+ padding-left: 45px;
80
+ }
81
+ .wsdplugin_page_title #uinfo {
82
+ float: right;
83
+ margin: 10px 10px;
84
+ cursor: pointer;
85
+ padding: 5px 0;
86
+ background-color: transparent;
87
+ border: 1px solid transparent;
88
+ border-radius: 3px;
89
+ /*width: 180px;*/
90
+ overflow: hidden;
91
+ text-align: right;
92
+ }
93
+ .wsdplugin_page_title #uinfo #wsdplugin-current-user-name { display: block; color: #CC0000; padding-right: 7px; padding-left: 7px; }
94
+ .wsdplugin_page_title #uinfo #wsdplugin-current-user-menu{
95
+ width: 180px;
96
+ display: none;
97
+ margin: 5px 0 0 0 !important;
98
+ padding: 5px 0;
99
+ background-color: #F9F9F9;
100
+ border: 1px solid #DFDFDF;
101
+ border-top: none 0;
102
+ border-bottom-right-radius: 3px;
103
+ border-bottom-left-radius: 3px;
104
+ }
105
+ .wsdplugin_page_title #uinfo:hover{
106
+ background-color: #F9F9F9;
107
+ border: 1px solid #DFDFDF;
108
+ border-radius: 3px;
109
+ }
110
+
111
+ .wsdplugin_page_title #uinfo:hover #wsdplugin-current-user-menu{
112
+ position: absolute; z-index: 9888998;
113
+ display: block; clear: both;
114
+ border-top: solid 1px #dadada;
115
+ right: 25px;
116
+ }
117
+ .wsdplugin_page_title #uinfo:hover #wsdplugin-current-user-menu ul,
118
+ .wsdplugin_page_title #uinfo:hover #wsdplugin-current-user-menu ul li { margin: 0 0; padding: 0 0; width: 100%; list-style-type: none; list-style-position: outside;}
119
+ .wsdplugin_page_title #uinfo:hover #wsdplugin-current-user-menu ul li { padding: 7px 5px; text-align: left !important; }
120
+ .wsdplugin_page_title #uinfo:hover #wsdplugin-current-user-menu ul li a { display: block; margin: 3px 5px;}
121
+
122
+
123
+ .wsdplugin_page_title .wsdplugin_error_box { clear: both; }
124
+ .wsdplugin_page_alerts { float: none; clear: both;}
125
+
126
+
127
+ /*
128
+ * Page: database
129
+ */
130
+ .acx-section-box { padding: 0.5em; margin: 0.5em; }
131
+ .acx-common-list {
132
+ list-style-type: none;
133
+ list-style-position: outside;
134
+ list-style-image: none;
135
+ }
136
+ .acx-common-list li {
137
+ background: url('../images/arrow-black-icon.png') no-repeat left center;
138
+ padding-left: 20px;
139
+ }
140
+ .acx-common-list li p span {}
141
+ .acx-common-list li .acx-icon-alert-critical { padding-top: 2px; }
142
+ .acx-common-list li .acx-icon-alert-info { padding-top: 2px; }
143
+
144
+ .acx-info-box {
145
+ margin: 7px 7px; padding: 0.2em 0.2em 0.2em 2.2em;
146
+ font-family: Verdana, Geneva, sans-serif; font-size: 1em; color: #d00000;
147
+ background: #FFC url('../images/icon-info.png') no-repeat 5px 50%; border: solid 1px #FC0;
148
+ }
149
+
150
+ .acx-info-box-noicon { background-image: none; }
151
+
152
+ .acx-notice-info { color: #252525; }
153
+ .acx-notice-success { color: #060; font-weight: 900; }
154
+
155
+ .acx-icon-alert-success { background: url('../images/green-check-icon.png') no-repeat right bottom; padding-right: 25px; line-height: 22px; }
156
+ .acx-icon-alert-critical { background: url('../images/alert-info-critical.png') no-repeat right bottom; padding-right: 25px; line-height: 22px; }
157
+ .acx-icon-alert-info { background: url('../images/alert-info-icon.png') no-repeat right bottom; padding-right: 25px; line-height: 22px; }
158
+
159
+ .acx-table tbody td.td_success { width: 20px; background: url('../images/green-check-icon.png') no-repeat 5px center; }
160
+ .acx-table tbody td.td_error { width: 20px; background: url('../images/alert-info-icon.png') no-repeat 5px center; }
161
+ .acx-table tbody tr:hover { background: #e0e0e0; }
162
+
163
+
164
+
165
+ .wsdplugin-tooltip {
166
+ cursor: pointer;
167
+ /*margin-left: 15px;*/
168
+ color: #21759B;
169
+ background: url('../images/icon-info.png') no-repeat 0 0 ! important;;
170
+ }
171
+
172
+ #tt {
173
+ position:absolute;
174
+ display:block;
175
+ }
176
+ #tttop {
177
+ display:block;
178
+ height:5px;
179
+ margin-left:5px;
180
+ background:url("../images/tooltips/tt_top.gif") top right no-repeat;
181
+ overflow:hidden;
182
+ }
183
+ #ttcont {
184
+ display:block;
185
+ padding:2px 12px 3px 12px;
186
+ margin-left:5px;
187
+ background:#666;
188
+ color:#fff;
189
+ }
190
+ #ttbot {
191
+ display:block;
192
+ height:5px;
193
+ margin-left:5px;
194
+ background:url("../images/tooltips/tt_bottom.gif") top right no-repeat;
195
+ overflow:hidden;
196
+ }
res/css/styles.status.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ .wsdplugin_page_status {
3
+ display: block;
4
+ border-radius: 3px;
5
+ border: 1px solid #DFDFDF;
6
+ box-shadow: 0 0 1px #DFDFDF;
7
+ background-color: #FFFFFF;
8
+ padding: 10px 4px;
9
+ margin-bottom: 15px;
10
+ margin-top: 5px;
11
+ }
12
+ .wsdplugin_status_box {
13
+ display: inline-block;
14
+ margin-left: 5px;
15
+ line-height: 22px;
16
+ }
17
+ .wsdplugin_status_box span:first-child {
18
+ margin-right: 8px;
19
+ font-weight: bold;
20
+ display: inline;
21
+ }
22
+ .wsdplugin_status_box span.wsdplugin_status_ok {
23
+ color: #006400;
24
+ }
25
+ .wsdplugin_status_box span.wsdplugin_status_bad {
26
+ color: #cc0000;
27
+ }
28
+ .wsdplugin_status_box_spacer {
29
+ display: inline-block;
30
+ width: 2px;
31
+ border-left: 1px solid #BCB8B8;
32
+ border-right: 1px solid #fff;
33
+ margin-left: 10px;
34
+ }
35
+ .wsdplugin_page_status_horizontal .wsdplugin_status_box span:first-child {
36
+ display: inline-block;
37
+ width: 180px;
38
+ }
res/images/ajax-loader.gif ADDED
Binary file
res/images/alert-info-critical.png ADDED
Binary file
res/images/alert-info-icon.png ADDED
Binary file
res/images/alerts-page-ico.png ADDED
Binary file
images/wpss_icon_small_combined.png → res/images/arrow-black-icon.png RENAMED
Binary file
res/images/blog/featured-slider-bg.jpg ADDED
Binary file
res/images/blog/ico-facebook.png ADDED
Binary file
res/images/blog/ico-twitter.png ADDED
Binary file
res/images/blog/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
res/images/blog/logo.png ADDED
Binary file
images/wpss_icon_large.png → res/images/checkbox.png RENAMED
Binary file
{images → res/images}/close-button.png RENAMED
File without changes
res/images/green-check-icon.png ADDED
Binary file
res/images/icon-info.png ADDED
Binary file
res/images/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
res/images/indicator-blue.png ADDED
Binary file
res/images/indicator-green.png ADDED
Binary file
res/images/indicator-red.png ADDED
Binary file
res/images/indicator-yellow.png ADDED
Binary file
images/wsd-logo-small-list.png → res/images/logo-small.png RENAMED
File without changes
res/images/logo.png ADDED
Binary file
{images → res/images}/rss.png RENAMED
File without changes
res/images/tooltips/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
res/images/tooltips/tt_bottom.gif ADDED
Binary file
res/images/tooltips/tt_top.gif ADDED
Binary file
res/inc/WsdCheck.php ADDED
@@ -0,0 +1,286 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! defined('WSS_PLUGIN_PREFIX')) return;
2
+ /**
3
+ * Class WsdCheck
4
+ * Static class. Provides security checks for Wordpress
5
+ */
6
+ class WsdCheck extends WsdPlugin
7
+ {
8
+ // type: stack - cron
9
+ public static function adminUsername()
10
+ {
11
+ global $wpdb, $wsdPluginAlertsArray;
12
+ $actionName = $wsdPluginAlertsArray['check_username_admin']['name'];
13
+ $alertType = $wsdPluginAlertsArray['check_username_admin']['type'];
14
+
15
+ $u = $wpdb->get_var("SELECT `ID` FROM $wpdb->users WHERE user_login='admin';");
16
+ if(empty($u)){
17
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
18
+ sprintf(__('User <strong>"%s"</strong> (with administrative rights) was not found'), 'admin'),
19
+ sprintf(__('<p>One well known and dangerous WordPress security vulnerability is User Enumeration, in which a
20
+ malicious user is able to enumerate a valid WordPress user account to launch a brute force attack against it.
21
+ In order to help deter this type of attack, it is important not to have the default <a href="%s" target="%s">WordPress administrator</a>
22
+ username enabled on your blog.</p>'), 'http://www.acunetix.com/blog/web-security-zone/articles/default-wordpress-administrator-account/', '_blank')
23
+ );
24
+ }
25
+ else {
26
+ // check to see if this user is an administrator
27
+ $userRole = $wpdb->get_var("SELECT meta_value FROM ".$wpdb->usermeta. " WHERE user_id = $u AND meta_key = '".$wpdb->prefix."user_level'");
28
+ if(! empty($userRole)){
29
+ $userRole = intval($userRole);
30
+ if(in_array($userRole, array(8,9,10))){
31
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_CRITICAL,
32
+ sprintf(__('The default user <strong>"%s"</strong> was found'), 'admin'),
33
+ sprintf(__('<p>One well known and dangerous WordPress security vulnerability is User Enumeration, in which a malicious user is able to enumerate
34
+ a valid WordPress user account to launch a brute force attack against it.</p>
35
+ <p>In order to help deter this type of attack, you should change your default <a href="%s" target="%s">WordPress administrator</a>
36
+ username to something more difficult to guess.</p>'), 'http://www.acunetix.com/blog/web-security-zone/articles/default-wordpress-administrator-account/', '_blank'),
37
+ // solution
38
+ __('<p>Do not make the following change unless you are comfortable working with PHPMyAdmin and MySQL. If not, ask someone who is familiar with WordPress and MySQL to assist you. </p>
39
+ <p>Also, it is of utmost importance to backup your whole blog - including the database - before making any of the changes described below.</p>
40
+ <p>To change your WordPress default admin username, navigate to your web host\'s MySQL administration tool (probably PHPMyAdmin) and browse to your WordPress database.
41
+ Locate the users table, in which you will find a user_login column. One of the rows will contain admin in the field.
42
+ Change this to a complex and hard-to-guess name, which ideally consists of alpha-numeric characters.</p>
43
+ <p><strong>IMPORTANT:</strong> Even if the username is hard to guess, you will still need a very strong password.</p>'));
44
+ return;
45
+ }
46
+ }
47
+ }
48
+ }
49
+
50
+ // type: overwrite
51
+ public static function check_tablePrefix()
52
+ {
53
+ global $wpdb, $wsdPluginAlertsArray;
54
+ $actionName = $wsdPluginAlertsArray['check_table_prefix']['name'];
55
+ $alertType = $wsdPluginAlertsArray['check_table_prefix']['type'];
56
+
57
+ if(strcasecmp('wp_', $wpdb->prefix)==0){
58
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_CRITICAL,
59
+ sprintf(__('The default WordPress database prefix (<strong>%s</strong>) is used'), $wpdb->prefix),
60
+ __('<p>The majority of reported WordPress database security attacks were performed by exploiting SQL Injection vulnerabilities.
61
+ By renaming the WordPress database table prefixes you are securing your WordPress blog and website from zero day SQL injections attacks.</p>
62
+ <p>Therefore by renaming the WordPress database table prefixes, you are automatically enforcing your WordPress database security against such dangerous attacks
63
+ because the attacker would not be able to guess the table names.</p>
64
+ <p>We recommend to use difficult to guess prefixes, like long random strings which include both letters and numbers.</p>'),
65
+ sprintf(__('<p>This plugin can automatically <a href="%s">do this</a> for you, but if you want to do it manually then please read this <a href="%s" target="%s">article</a> first.</p>'),
66
+ 'admin.php?page=wsd_database',
67
+ 'http://www.websitedefender.com/wordpress-security/change-wordpress-database-prefix/', '_blank')
68
+ );
69
+ }
70
+ else {
71
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
72
+ __('The default WordPress database prefix is not used'),
73
+ __('<p>The majority of reported WordPress database security attacks were performed by exploiting SQL Injection vulnerabilities.
74
+ By renaming the WordPress database table prefixes you are securing your WordPress blog and website from zero day SQL injections attacks.</p>
75
+ <p>Therefore by renaming the WordPress database table prefixes, you are automatically enforcing your WordPress database security against such dangerous attacks because the attacker would not be able to guess the table names.</p>')
76
+ );
77
+ }
78
+ }
79
+
80
+ // type: overwrite
81
+ public static function check_currentVersion()
82
+ {
83
+ global $wsdPluginAlertsArray;
84
+ $actionName = $wsdPluginAlertsArray['check_wp_current_version']['name'];
85
+ $alertType = $wsdPluginAlertsArray['check_wp_current_version']['type'];
86
+
87
+ $c = get_site_transient('update_core');
88
+ if(is_object($c))
89
+ {
90
+ if(empty($c->updates)) {
91
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
92
+ __('You have the latest version of WordPress installed'),
93
+ __('<p>The latest WordPress version is usually more stable and secure, and is only released to include new features or fix technical and WordPress security bugs;
94
+ making it an important part of your website administration to keep up to date since some fixes might resolve security issues.<p>
95
+ <p>Running an older WordPress version could put your blog security at risk, allowing a hacker to exploit known vulnerabilities for your specific version and take full control over your web server.</p>')
96
+ );
97
+ }
98
+ else {
99
+ if (!empty($c->updates[0]))
100
+ {
101
+ $c = $c->updates[0];
102
+ if (!isset($c->response) || 'latest' == $c->response ) {
103
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
104
+ __('You have the latest version of WordPress installed'),
105
+ __('<p>The latest WordPress version is usually more stable and secure, and is only released to include new features or fix technical and WordPress security bugs;
106
+ making it an important part of your website administration to keep up to date since some fixes might resolve security issues.<p>
107
+ <p>Running an older WordPress version could put your blog security at risk, allowing a hacker to exploit known vulnerabilities for your specific version and take full control over your web server.</p>')
108
+ );
109
+ }
110
+ elseif ('upgrade' == $c->response) {
111
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_CRITICAL,
112
+ sprintf(__('An updated version of WordPress is available: <strong>%s</strong>'), $c->current),
113
+ __('<p>The latest WordPress version is usually more stable and secure, and is only released to include new features or fix technical and WordPress security bugs;
114
+ making it an important part of your website administration to keep up to date since some fixes might resolve security issues.<p>
115
+ <p>Running an older WordPress version could put your blog security at risk, allowing a hacker to exploit known vulnerabilities for your specific version and take full control over your web server.</p>'),
116
+ sprintf(__('<p>It is recommended to update your WordPress installation as soon as possible. More information on updating WordPress manually and automatically
117
+ can be found on the official <a href="%s" target="%s">WordPress site</a>.</p>'), 'http://codex.wordpress.org/Updating_WordPress', '_blank')
118
+ );
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }
124
+
125
+ // type: overwrite
126
+ public static function check_files()
127
+ {
128
+ global $wsdPluginAlertsArray;
129
+
130
+ $actionName = $wsdPluginAlertsArray['check_index_wp_content']['name'];
131
+ $alertType = $wsdPluginAlertsArray['check_index_wp_content']['type'];
132
+ $path = WP_CONTENT_DIR.'/index.php';
133
+ if(!is_file($path)) {
134
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
135
+ sprintf(__('The <strong>"%s"</strong> file was not found in the <strong>"%s"</strong> directory'), 'index.php', '/wp-content'),
136
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory. The specific risks and consequences vary depending on which files are listed and accessible.</p>
137
+ <p>Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>'),
138
+ sprintf(__('<p>This plugin can automatically create an empty <strong>"%s"</strong> file in the following directories: wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads if
139
+ the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
140
+ 'index.php', 'Try to create the index.php file in the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listing')
141
+ );
142
+ }
143
+ else {
144
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
145
+ sprintf(__('The <strong>"%s"</strong> file was found in the <strong>"%s"</strong> directory'), 'index.php', '/wp-content'),
146
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory. The specific risks and consequences vary depending on which files are listed and accessible.</p>
147
+ <p>Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
148
+ );
149
+ }
150
+
151
+ $actionName = $wsdPluginAlertsArray['check_index_wp_plugins']['name'];
152
+ $alertType = $wsdPluginAlertsArray['check_index_wp_plugins']['type'];
153
+ $path = WP_CONTENT_DIR.'/plugins/index.php';
154
+ if(!is_file($path)) {
155
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
156
+ sprintf(__('The <strong>"%s"</strong> file was not found in the <strong>"%s"</strong> directory'), 'index.php', '/wp-content/plugins'),
157
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory. The specific risks and consequences vary depending on which files are listed and accessible.</p>
158
+ <p>Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>'),
159
+ sprintf(__('<p>This plugin can automatically create an empty <strong>"%s"</strong> file in the following directories: wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads if
160
+ the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
161
+ 'index.php', 'Try to create the index.php file in the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listing')
162
+ );
163
+ }
164
+ else {
165
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
166
+ sprintf(__('The <strong>"%s"</strong> file was found in the <strong>"%s"</strong> directory'), 'index.php', '/wp-content/plugins'),
167
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory. The specific risks and consequences vary depending on which files are listed and accessible.</p>
168
+ <p>Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
169
+ );
170
+ }
171
+
172
+ $actionName = $wsdPluginAlertsArray['check_index_wp_themes']['name'];
173
+ $alertType = $wsdPluginAlertsArray['check_index_wp_themes']['type'];
174
+ $path = WP_CONTENT_DIR.'/themes/index.php';
175
+ if(!is_file($path)) {
176
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
177
+ sprintf(__('The <strong>"%s"</strong> file was not found in the <strong>"%s"</strong> directory'), 'index.php', '/wp-content/themes'),
178
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory. The specific risks and consequences vary depending on which files are listed and accessible.</p>
179
+ <p>Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>'),
180
+ sprintf(__('<p>This plugin can automatically create an empty <strong>"%s"</strong> file in the following directories: wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads if
181
+ the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
182
+ 'index.php', 'Try to create the index.php file in the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listing')
183
+ );
184
+ }
185
+ else {
186
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
187
+ sprintf(__('The <strong>"%s"</strong> file was found in the <strong>"%s"</strong> directory'), 'index.php', '/wp-content/themes'),
188
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory. The specific risks and consequences vary depending on which files are listed and accessible.</p>
189
+ <p>Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
190
+ );
191
+ }
192
+
193
+ $actionName = $wsdPluginAlertsArray['check_index_wp_uploads']['name'];
194
+ $alertType = $wsdPluginAlertsArray['check_index_wp_uploads']['type'];
195
+ $path = WP_CONTENT_DIR.'/uploads';
196
+ if(is_dir($path))
197
+ {
198
+ if(!is_file(WP_CONTENT_DIR.'/uploads/index.php')) {
199
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
200
+ sprintf(__('The <strong>"%s"</strong> file was not found in the <strong>"%s"</strong> directory'), 'index.php', '/wp-content/uploads'),
201
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory. The specific risks and consequences vary depending on which files are listed and accessible.</p>
202
+ <p>Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>'),
203
+ sprintf(__('<p>This plugin can automatically create an empty <strong>"%s"</strong> file in the following directories: wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads if the
204
+ option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
205
+ 'index.php', 'Try to create the index.php file in the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listing')
206
+ );
207
+ }
208
+ else {
209
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
210
+ sprintf(__('The <strong>"%s"</strong> file was found in the <strong>"%s"</strong> directory'), 'index.php', '/wp-content/uploads'),
211
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory. The specific risks and consequences vary depending on which files are listed and accessible.</p>
212
+ <p>Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
213
+ );
214
+ }
215
+ }
216
+
217
+ $actionName = $wsdPluginAlertsArray['check_htaccess_wp_admin']['name'];
218
+ $alertType = $wsdPluginAlertsArray['check_htaccess_wp_admin']['type'];
219
+ $path = ABSPATH.'wp-admin/.htaccess';
220
+ if(!is_file($path)){
221
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
222
+ sprintf(__('The <strong>"%s"</strong> file was not found in the <strong>"%s"</strong> directory'), '.htaccess', 'wp-admin'),
223
+ __('<p>An .htaccess file is a configuration file which provides the ability to specify configuration settings for a specific directory in a website.
224
+ The .htaccess file can include one or more configuration settings which apply only for the directory in which the .htaccess file has been placed.
225
+ So while web servers have their own main configuration settings file, the .htaccess file can be used to override their main configuration settings.</p>'),
226
+ sprintf(__('<p>Please refer to this <a href="%s" target="%s">article</a> for more information on how to create an .htaccess file.</p>'),
227
+ 'http://www.acunetix.com/blog/web-security-zone/articles/what-is-an-htaccess-file/', '_blank')
228
+ );
229
+ }
230
+ else {
231
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
232
+ sprintf(__('The <strong>"%s"</strong> file was found in the <strong>"%s"</strong> directory'), '.htaccess', 'wp-admin'),
233
+ __('<p>An .htaccess file is a configuration file which provides the ability to specify configuration settings for a specific directory in a website.
234
+ The .htaccess file can include one or more configuration settings which apply only for the directory in which the .htaccess file has been placed.
235
+ So while web servers have their own main configuration settings file, the .htaccess file can be used to override their main configuration settings.</p>')
236
+ );
237
+ }
238
+
239
+ $actionName = $wsdPluginAlertsArray['check_readme_wp_root']['name'];
240
+ $alertType = $wsdPluginAlertsArray['check_readme_wp_root']['type'];
241
+ $path = ABSPATH.'readme.html';
242
+ if(is_file($path))
243
+ {
244
+ if(is_readable($path)){
245
+ $fsize = @filesize($path);
246
+ // couldn't retrieve the file's size
247
+ if($fsize > 0){
248
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
249
+ __('The <strong>readme.html</strong> file was found in the root directory'),
250
+ __('<p>A default WordPress installation contains a readme.html file.
251
+ This file is a simple html file that does not contain executable content that can be exploited by hackers or malicious users.
252
+ Still, this file can provide hackers the version of your WordPress installation, therefore it is important to either delete this file or make it inaccessible for your visitors.</p>'),
253
+ sprintf(__('<p>This plugin can automatically delete its content if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.
254
+ You can also delete this file manually by connecting to your website through an FTP connection.</p>'),'Empty the content of the readme.html file from the root directory.')
255
+ );
256
+ }
257
+ else {
258
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
259
+ __('The <strong>readme.html</strong> file is either empty or not accessible.'),
260
+ __('<p>A default WordPress installation contains a readme.html file.
261
+ This file is a simple html file that does not contain executable content that can be exploited by hackers or malicious users.
262
+ Still, this file can provide hackers the version of your WordPress installation, therefore it is important to either delete this file or make it inaccessible for your visitors.</p>')
263
+ );
264
+ }
265
+ }
266
+ else {
267
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
268
+ __('The <strong>readme.html</strong> file is not accessible.'),
269
+ __('<p>A default WordPress installation contains a readme.html file.
270
+ This file is a simple html file that does not contain executable content that can be exploited by hackers or malicious users.
271
+ Still, this file can provide hackers the version of your WordPress installation, therefore it is important to either delete this file or make it inaccessible for your visitors.</p>')
272
+ );
273
+ }
274
+ }
275
+ else{
276
+ // file not found or file is not accessible
277
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
278
+ __('The <strong>readme.html</strong> file was not found in the root directory'),
279
+ __('<p>A default WordPress installation contains a readme.html file.
280
+ This file is a simple html file that does not contain executable content that can be exploited by hackers or malicious users.
281
+ Still, this file can provide hackers the version of your WordPress installation, therefore it is important to either delete this file or make it inaccessible for your visitors.</p>')
282
+ );
283
+ }
284
+ }
285
+
286
+ }
res/inc/WsdInfo.php ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class WsdInfo
4
+ * Static class. Provides common methods to inspect a WordPress installation settings
5
+ */
6
+ class WsdInfo
7
+ {
8
+ public static function getCurrentVersionInfo()
9
+ {
10
+ $c = get_site_transient( 'update_core' );
11
+ if ( is_object($c))
12
+ {
13
+ if (empty($c->updates))
14
+ {
15
+ return '<span class="acx-icon-alert-success">'.__('You have the latest version of Wordpress.').'</span>';
16
+ }
17
+
18
+ if (!empty($c->updates[0]))
19
+ {
20
+ $c = $c->updates[0];
21
+
22
+ if ( !isset($c->response) || 'latest' == $c->response ) {
23
+ return '<span class="acx-icon-alert-success">'.__('You have the latest version of Wordpress.').'</span>';
24
+ }
25
+
26
+ if ('upgrade' == $c->response)
27
+ {
28
+ $lv = $c->current;
29
+ $m = '<span class="acx-icon-alert-critical">'.sprintf('A new version of Wordpress <strong>(%s)</strong> is available. You should upgrade to the latest version.', $lv).'</span>';
30
+ return __($m);
31
+ }
32
+ }
33
+ }
34
+
35
+ return '<span class="acx-icon-alert-critical">'.__('An error has occurred while trying to retrieve the status of your Wordpress version.').'</span>';
36
+ }
37
+
38
+ public static function getDatabasePrefixInfo()
39
+ {
40
+ global $table_prefix;
41
+
42
+ if (strcasecmp('wp_', $table_prefix)==0) {
43
+ return '<span class="acx-icon-alert-critical">'
44
+ .__('Your database prefix should not be <code>wp_</code>.')
45
+ .'(<a href="http://www.websitedefender.com/wordpress-security/wordpress-database-tables-prefix/" target="_blank">'.__('read more').'</a>)</span>';
46
+ }
47
+
48
+ return '<span class="acx-icon-alert-success">'.__('Your database prefix is not <code>wp_</code>.').'</span>';
49
+ }
50
+
51
+ public static function getWpVersionStatusInfo()
52
+ {
53
+ if (WsdSecurity::$isVersionHidden) {
54
+ return '<span class="acx-icon-alert-success">'.__('The Wordpress version <code>is</code> hidden for all users but administrators.').'</span>';
55
+ }
56
+ }
57
+
58
+ public static function getPhpStartupErrorStatusInfo()
59
+ {
60
+ $dse = strtolower(ini_get('display_startup_errors'));
61
+ if ($dse == 0) {
62
+ return '<span class="acx-icon-alert-success">'.__('Startup errors <code>are not</code> displayed.').'</span><br/>';
63
+ }
64
+
65
+ return '<span class="acx-icon-alert-critical">'.__('Startup errors <code>are displayed</code>.').'</span>'.'<br/>';
66
+ }
67
+
68
+ public static function getAdminUsernameInfo()
69
+ {
70
+ global $wpdb;
71
+
72
+ $u = $wpdb->get_var("SELECT `ID` FROM $wpdb->users WHERE user_login='admin';");
73
+
74
+ if (empty($u)) {
75
+ return '<span class="acx-icon-alert-success">'.__('User <code>admin</code> was not found.').'</span>';
76
+ }
77
+
78
+ return '<span class="acx-icon-alert-critical">'.__('User <code>admin</code> was found! You should change it in order to avoid user enumeration attacks.').'</span>';
79
+ }
80
+
81
+ public static function getWpAdminHtaccessInfo()
82
+ {
83
+ $file = trailingslashit(ABSPATH).'wp-admin/.htaccess';
84
+ if (is_file($file)) {
85
+ return '<span class="acx-icon-alert-success">'.__('The <code>.htaccess</code> file was found in the <code>wp-admin</code> directory.').'</span>';
86
+ }
87
+
88
+ return '<span class="acx-icon-alert-info">'
89
+ .__('The <code>.htaccess</code> file was not found in the <code>wp-admin</code> directory.')
90
+ .'(<a href="http://www.websitedefender.com/wordpress-security/htaccess-files-wordpress-security/" target="_blank">'.__('read more').'</a>)</span>';
91
+ }
92
+
93
+ public static function getDatabaseUserAccessRightsInfo()
94
+ {
95
+ $rights = WsdInfoServer::getDatabaseUserAccessRights();
96
+ $rightsNeeded = $rights['rightsNeeded'];
97
+ $rightsHaving = $rights['rightsHaving'];
98
+ $rightsMissing = array_diff($rightsNeeded, $rightsHaving);
99
+
100
+ if ($rights['rightsTooMuch']) {
101
+ $e = '<code>'.implode('</code>, <code>', $rightsNeeded).'</code>';
102
+ $m = sprintf(__("Your currently used User to access the WordPress Database <code>holds too many rights</code>.
103
+ We suggest that you limit his rights (to only %s) or to use another User with more limited rights instead, to increase your website's Security."),$e);
104
+ return '<span class="acx-icon-alert-info">'.$m.'</span>';
105
+ }
106
+ else
107
+ {
108
+ if($rights['rightsEnough']){
109
+ $m = __("Your currently used User to access the WordPress Database holds the appropriate rights to interact with the database.");
110
+ return '<span class="acx-icon-alert-success">'.$m.'</span>';
111
+ }
112
+ else {
113
+ $missing = '<code>'.implode('</code>, <code>', $rightsMissing).'</code>';
114
+ $m = sprintf(__("Your currently used User to access the WordPress Database is missing the following rights to interact with the database: %s"),$missing);
115
+ return '<span class="acx-icon-alert-info">'.$m.'</span>';
116
+ }
117
+ }
118
+ }
119
+
120
+ public static function getWpContentIndexInfo()
121
+ {
122
+ if (is_file(trailingslashit(WP_CONTENT_DIR).'index.php')) {
123
+ return '<span class="acx-icon-alert-success">'.__('The <code>index.php</code> file <code>was found</code> in the wp-content directory.').'</span>'.'<br/>';
124
+ }
125
+
126
+ return '<span class="acx-icon-alert-info">'.__('The <code>index.php</code> file <code>was not found</code> in the wp-content directory! You should create one in order to prevent directory listings.').'</span>'.'<br/>';
127
+ }
128
+
129
+ public static function getWpContentPluginsIndexInfo()
130
+ {
131
+ $dirPath = trailingslashit(WP_CONTENT_DIR).'plugins/';
132
+ if(!is_dir($dirPath)) { return ''; }
133
+ if (is_file($dirPath.'index.php')) {
134
+ return '<span class="acx-icon-alert-success">'.__('The <code>index.php</code> file <code>was found</code> in the plugins directory.').'</span>'.'<br/>';
135
+ }
136
+
137
+ return '<span class="acx-icon-alert-info">'.acxt_t('The <code>index.php</code> file <code>was not found</code> in the plugins directory! You should create one in order to prevent directory listings.').'</span>'.'<br/>';
138
+ }
139
+
140
+ public static function getWpContentThemesIndexInfo()
141
+ {
142
+ $dirPath = trailingslashit(WP_CONTENT_DIR).'themes/';
143
+ if(!is_dir($dirPath)) { return ''; }
144
+ if (is_file($dirPath.'index.php')) {
145
+ return '<span class="acx-icon-alert-success">'.__('The <code>index.php</code> file <code>was found</code> in the themes directory.').'</span>'.'<br/>';
146
+ }
147
+
148
+ return '<span class="acx-icon-alert-info">'.__('The <code>index.php</code> file <code>was not found</code> in the themes directory! You should create one in order to prevent directory listings.').'</span>'.'<br/>';
149
+ }
150
+
151
+ public static function getWpContentUploadsIndexInfo()
152
+ {
153
+ $dirPath = trailingslashit(WP_CONTENT_DIR).'uploads/';
154
+ if(!is_dir($dirPath)) { return ''; }
155
+ if (is_file($dirPath.'index.php')) {
156
+ return '<span class="acx-icon-alert-success">'.__('The <code>index.php</code> file <code>was found</code> in the uploads directory.').'</span>'.'<br/>';
157
+ }
158
+ return '<span class="acx-icon-alert-info">'.__('The <code>index.php</code> file <code>was not found</code> in the uploads directory! You should create one in order to prevent directory listings.').'</span>'.'<br/>';
159
+ }
160
+
161
+ }
162
+
163
+ class WsdInfoServer extends WsdInfo
164
+ {
165
+ public static function getServerInfo()
166
+ {
167
+ global $wpdb;
168
+ $sqlversion = $wpdb->get_var("SELECT VERSION() AS version");
169
+ $mysqlinfo = $wpdb->get_results("SHOW VARIABLES LIKE 'sql_mode'");
170
+ if (is_array($mysqlinfo)) $sql_mode = $mysqlinfo[0]->Value;
171
+ if (empty($sql_mode)) $sql_mode = __('Not set');
172
+ $sm = ini_get('safe_mode');
173
+ if (strcasecmp('On', $sm) == 0) { $safe_mode = __('On'); }
174
+ else { $safe_mode = __('Off'); }
175
+ if(ini_get('allow_url_fopen')) $allow_url_fopen = __('On');
176
+ else $allow_url_fopen = __('Off');
177
+ if(ini_get('upload_max_filesize')) $upload_max = ini_get('upload_max_filesize');
178
+ else $upload_max = __('N/A');
179
+ if(ini_get('post_max_size')) $post_max = ini_get('post_max_size');
180
+ else $post_max = __('N/A');
181
+ if(ini_get('max_execution_time')) $max_execute = ini_get('max_execution_time');
182
+ else $max_execute = __('N/A');
183
+ if(ini_get('memory_limit')) $memory_limit = ini_get('memory_limit');
184
+ else $memory_limit = __('N/A');
185
+ if (function_exists('memory_get_usage')) $memory_usage = round(memory_get_usage() / 1024 / 1024, 2) . __(' MByte');
186
+ else $memory_usage = __('N/A');
187
+ if (is_callable('exif_read_data')) $exif = __('Yes'). " ( V" . substr(phpversion('exif'),0,4) . ")" ;
188
+ else $exif = __('No');
189
+ if (is_callable('iptcparse')) $iptc = __('Yes');
190
+ else $iptc = __('No');
191
+ if (is_callable('xml_parser_create')) $xml = __('Yes');
192
+ else $xml = __('No');
193
+
194
+ $sqlModeText = __('SQL Mode (sql_mode) is a MySQL system variable. By means of this variable the MySQL Server SQL Mode is controlled.
195
+ Many operational characteristics of MySQL Server can be configured by setting the SQL Mode.
196
+ By setting the SQL Mode appropriately, a client program can instruct the server how strict or forgiving to be about accepting input data, enable or disable behaviors relating to standard SQL conformance,
197
+ or provide better compatibility with other database systems. By default, the server uses a sql_mode value of \'\' (the empty string), which enables no restrictions.
198
+ Thus, the server operates in forgiving mode (non-strict mode) by default. In non-strict mode, the MySQL server converts erroneous input values to the closest legal
199
+ values (as determined from column definitions) and continues on its way.');
200
+ $phpSafeModeText = __('The PHP Safe Mode (safe_mode) is an attempt to solve the shared-server security problem.
201
+ It is architecturally incorrect to try to solve this problem at the PHP level, but since the alternatives at the web server and OS levels aren\'t
202
+ very realistic, many people, especially ISP\'s, use safe mode for now.');
203
+ $phpAllowFopenText = __('PHP allow_url_fopen option, if enabled (allows PHP\'s file functions - such as \'file_get_contents()\' and the \'include\' and \'require\' statements),
204
+ can retrieve data from remote locations, like an FTP or web site, which may pose a security risk.');
205
+ $phpMemoryLimitText = __('PHP memory_limit option sets the maximum amount of memory in bytes that a script is allowed to allocate.
206
+ By enabling a realistic memory_limit you can protect your applications from certain types of Denial of Service attacks, and also from bugs in
207
+ applications (such as infinite loops, poor use of image based functions, or other memory intensive mistakes).');
208
+ $phpMaxUploadSizeText = __('PHP upload_max_filesize option limits the maximum size of files that PHP will accept through uploads. Attackers may attempt to send grossly oversized files to exhaust your system resources;
209
+ by setting a realistic value here you can mitigate some of the damage by those attacks.');
210
+ $phpMaxPostSizeText = __('PHP post_max_size option limits the maximum size of the POST request that PHP will process. Attackers may attempt to send grossly oversized POST requests to exhaust your system resources;
211
+ by setting a realistic value here you can mitigate some of the damage by those attacks.');
212
+ $phpScriptExecTimeText = __('PHP max_execution_time option sets the maximum time in seconds a script is allowed to run before it is terminated by the parser.
213
+ This helps prevent poorly written scripts from tying up the server.');
214
+ $exifText = __('PHP exif extension enables you to work with image meta data. For example, you may use exif functions to read meta data of pictures taken from digital cameras by working with
215
+ information stored in the headers of the JPEG and TIFF images.');
216
+ $iptcText = __('IPTC data is a method of storing textual information in images defined by the International Press Telecommunications Council.
217
+ It was developed for press photographers who need to attach information to images when they are submitting them electronically but it is useful for all photographers.
218
+ It provides a standard way of storing information such as captions, keywords, location. Because the information is stored in the image in a standard way this information
219
+ can be accessed by other IPTC aware applications.');
220
+ $xmlText = __('XML (eXtensible Markup Language) is a data format for structured document interchange on the Web. It is a standard defined by the World Wide Web Consortium (W3C).');
221
+
222
+ $str = '<script type="text/javascript" src="'. WsdUtil::jsUrl('wsdplugin_glossary_tooltip.js').'"></script>';
223
+ $str .= '<ul class="acx-common-list">';
224
+ $str .= '<li>'. __('Operating System').' : <strong> '.PHP_OS.'</strong></li>';
225
+ $str .= '<li>'. __('Server').' : <strong>'.$_SERVER["SERVER_SOFTWARE"].'</strong></li>';
226
+ $str .= '<li>'. __('Memory usage').' : <strong>'.$memory_usage.'</strong></li>';
227
+ $str .= '<li>'. __('PHP Version').' : <strong>'. PHP_VERSION.'</strong></li>';
228
+ $str .= '<li>'. __('MYSQL Version').' : <strong>'.$sqlversion.'</strong></li>';
229
+ $str .= '</ul>';
230
+
231
+ $str .= '<p class="clear" style="margin-top: 7px;"></p>';
232
+
233
+ $str .= '<ul class="acx-common-list">';
234
+ $str .= '<li class="wsdplugin-tooltip" onmouseover="wsdplugin_glossary_tooltip.show(this);" data-bind-title="'.$sqlModeText.'" onmouseout="wsdplugin_glossary_tooltip.hide();">'. __('SQL Mode').' : <strong>'.$sql_mode.'</strong></li>';
235
+ $str .= '<li class="wsdplugin-tooltip" onmouseover="wsdplugin_glossary_tooltip.show(this);" data-bind-title="'.$phpSafeModeText.'" onmouseout="wsdplugin_glossary_tooltip.hide();">'. __('PHP Safe Mode').' : <strong>'. $safe_mode.'</strong></li>';
236
+ $str .= '<li class="wsdplugin-tooltip" onmouseover="wsdplugin_glossary_tooltip.show(this);" data-bind-title="'.$phpAllowFopenText.'" onmouseout="wsdplugin_glossary_tooltip.hide();">'. __('PHP Allow URL fopen').' : <strong>'. $allow_url_fopen.'</strong></li>';
237
+ $str .= '<li class="wsdplugin-tooltip" onmouseover="wsdplugin_glossary_tooltip.show(this);" data-bind-title="'.$phpMemoryLimitText.'" onmouseout="wsdplugin_glossary_tooltip.hide();">'. __('PHP Memory Limit').' : <strong>'. $memory_limit.'</strong></li>';
238
+ $str .= '<li class="wsdplugin-tooltip"onmouseover="wsdplugin_glossary_tooltip.show(this);" data-bind-title="'.$phpMaxUploadSizeText.'" onmouseout="wsdplugin_glossary_tooltip.hide();">'. __('PHP Max Upload Size').' : <strong>'. $upload_max.'</strong></li>';
239
+ $str .= '<li class="wsdplugin-tooltip" onmouseover="wsdplugin_glossary_tooltip.show(this);" data-bind-title="'.$phpMaxPostSizeText.'" onmouseout="wsdplugin_glossary_tooltip.hide();">'. __('PHP Max Post Size').' : <strong>'. $post_max.'</strong></li>';
240
+ $str .= '<li class="wsdplugin-tooltip" onmouseover="wsdplugin_glossary_tooltip.show(this);" data-bind-title="'.$phpScriptExecTimeText.'" onmouseout="wsdplugin_glossary_tooltip.hide();">'. __('PHP Max Script Execute Time').' : <strong>'. $max_execute.'s</strong></li>';
241
+ $str .= '<li class="wsdplugin-tooltip" onmouseover="wsdplugin_glossary_tooltip.show(this);" data-bind-title="'.$exifText.'" onmouseout="wsdplugin_glossary_tooltip.hide();">'. __('PHP Exif support').' : <strong>'. $exif.'</strong></li>';
242
+ $str .= '<li class="wsdplugin-tooltip" onmouseover="wsdplugin_glossary_tooltip.show(this);" data-bind-title="'.$iptcText.'" onmouseout="wsdplugin_glossary_tooltip.hide();">'. __('PHP IPTC support').' : <strong>'. $iptc.'</strong></li>';
243
+ $str .= '<li class="wsdplugin-tooltip" onmouseover="wsdplugin_glossary_tooltip.show(this);" data-bind-title="'.$xmlText.'" onmouseout="wsdplugin_glossary_tooltip.hide();">'. __('PHP XML support').' : <strong>'. $xml.'</strong></li>';
244
+ $str .= '</ul>';
245
+ return $str;
246
+ }
247
+
248
+ /**
249
+ * @public
250
+ * @static
251
+ * @global $wpdb, DB_USER, DB_HOST
252
+ *
253
+ * Retrieve the rights the current used user to connect to the database server has.
254
+ *
255
+ * @return array array('rightsEnough' => true|false, 'rightsTooMuch' => true|false, 'rightsMissing' => array, 'rightsNeeded' => array);
256
+ */
257
+ public static function getDatabaseUserAccessRights()
258
+ {
259
+ global $wpdb;
260
+
261
+ $rightsNeeded = array('SELECT','INSERT','UPDATE','DELETE','ALTER');
262
+ $data = array(
263
+ 'rightsEnough' => false,
264
+ 'rightsTooMuch' => false,
265
+ 'rightsHaving' => array(),
266
+ 'rightsNeeded' => $rightsNeeded
267
+ );
268
+
269
+ $rights = $wpdb->get_results("SHOW GRANTS FOR '".DB_USER."'@'".DB_HOST."'", ARRAY_N);
270
+
271
+ if (empty($rights)) {
272
+ //return $data;
273
+ $rights = $wpdb->get_results("SHOW GRANTS FOR current_user()", ARRAY_N);
274
+ if(empty($rights)){
275
+ return $data;
276
+ }
277
+ }
278
+
279
+ foreach($rights as $_right)
280
+ {
281
+ $right = $_right[0];
282
+ //#! no rights
283
+ if(preg_match("/GRANT USAGE ON/", $right)){
284
+ continue;
285
+ }
286
+ //#! way too many. db scope || global scope
287
+ $right = str_replace('\\','',$right);
288
+ $pattern = "/ALL PRIVILEGES ON `?".preg_quote(DB_NAME)."`?/";
289
+ if(preg_match($pattern, $right) || preg_match("/ALL PRIVILEGES ON \*\./", $right)){
290
+ array_push($rightsNeeded, 'CREATE');
291
+ $data = array(
292
+ 'rightsEnough' => true,
293
+ 'rightsTooMuch' => true,
294
+ 'rightsHaving' => $rightsNeeded,
295
+ 'rightsNeeded' => $rightsNeeded
296
+ );
297
+ break;
298
+ }
299
+ //#! more secure. db scope || global scope
300
+ elseif(preg_match_all("/GRANT (.*) ON `?".preg_quote(DB_NAME)."`?/",$right,$matches) || preg_match_all("/GRANT (.*) ON \*\./",$right,$matches)){
301
+ if(! empty($matches[1][0])){
302
+ $foundRights = explode(',', $matches[1][0]);
303
+ $foundRights = array_map("trim", $foundRights);
304
+ $missingRights = array_diff($rightsNeeded, $foundRights);
305
+ $data = array(
306
+ 'rightsEnough' => (empty($missingRights) ? true : false),
307
+ 'rightsTooMuch' => false,
308
+ 'rightsHaving' => $foundRights,
309
+ 'rightsNeeded' => $rightsNeeded
310
+ );
311
+ break;
312
+ }
313
+ }
314
+ }
315
+ return $data;
316
+ }
317
+ }
res/inc/WsdLiveTraffic.php ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! defined('WSS_PLUGIN_PREFIX')) return;
2
+ /**
3
+ * Class WsdLiveTraffic
4
+ */
5
+ class WsdLiveTraffic
6
+ {
7
+ private function __construct(){}
8
+ private function __clone(){}
9
+
10
+ final public static function clearEvents()
11
+ {
12
+ global $wpdb;
13
+ $settings = WsdPlugin::getSettings();
14
+ $keepMaxEntries = (int)$settings['keepNumEntriesLiveTraffic'];
15
+
16
+ if($keepMaxEntries < 1){
17
+ $query = "TRUNCATE ".WsdPlugin::getTableName(WSS_PLUGIN_LIVE_TRAFFIC_TABLE_NAME);
18
+ $wpdb->query($query);
19
+ return;
20
+ }
21
+
22
+ $optData = get_option('WSS_PLUGIN_ENTRIES_LIVE_TRAFFIC');
23
+ if(empty($optData)){
24
+ return;
25
+ }
26
+
27
+ $numEntries = $wpdb->get_var("SELECT COUNT(entryId) FROM ".WsdPlugin::getTableName(WSS_PLUGIN_LIVE_TRAFFIC_TABLE_NAME));
28
+
29
+ if($numEntries <> $keepMaxEntries){
30
+ update_option('WSS_PLUGIN_ENTRIES_LIVE_TRAFFIC', $numEntries);
31
+ }
32
+
33
+ if(intval($optData) <= $keepMaxEntries){
34
+ return;
35
+ }
36
+
37
+ $tableName = WsdPlugin::getTableName(WSS_PLUGIN_LIVE_TRAFFIC_TABLE_NAME);
38
+
39
+ $querySelect = "SELECT min(t.entryTime)
40
+ FROM
41
+ (
42
+ SELECT
43
+ entryTime
44
+ FROM
45
+ ".$tableName."
46
+ ORDER BY
47
+ entryTime DESC
48
+ LIMIT ".$keepMaxEntries."
49
+ ) AS t";
50
+
51
+
52
+ $deleteFromTime = $wpdb->get_var($querySelect);
53
+
54
+ $queryDelete = "DELETE FROM ".$tableName." WHERE entryTime < %s";
55
+ $result = $wpdb->query($wpdb->prepare($queryDelete,$deleteFromTime));
56
+
57
+ if(false === $result){
58
+ return;
59
+ }
60
+ // update option
61
+ $numEntries = $wpdb->get_var("SELECT COUNT(entryId) FROM ".WsdPlugin::getTableName(WSS_PLUGIN_LIVE_TRAFFIC_TABLE_NAME));
62
+ update_option('WSS_PLUGIN_ENTRIES_LIVE_TRAFFIC', $numEntries);
63
+ }
64
+
65
+ final public static function registerHit()
66
+ {
67
+ if(is_admin()){ return; }
68
+
69
+ global $wpdb;
70
+
71
+ $url = self::getRequestedUrl();
72
+
73
+ if(self::isUrlExcluded($url)){ return; }
74
+
75
+ $ip = self::getIP();
76
+ $referrer = self::getReferrer();
77
+ $ua = self::getUserAgent();
78
+
79
+ $query = $wpdb->prepare("INSERT INTO ".WsdPlugin::getTableName(WSS_PLUGIN_LIVE_TRAFFIC_TABLE_NAME)." (entryTime, entryIp, entryReferrer, entryUA, entryRequestedUrl)
80
+ VALUES(CURRENT_TIMESTAMP, %s, %s, %s, %s)", $ip, $referrer, $ua, $url);
81
+ if(false === @$wpdb->query($query)){
82
+ return;
83
+ }
84
+
85
+ $numEvents = 0;
86
+ $optData = get_option('WSS_PLUGIN_ENTRIES_LIVE_TRAFFIC');
87
+ if(empty($optData)){
88
+ add_option('WSS_PLUGIN_ENTRIES_LIVE_TRAFFIC', $numEvents);
89
+ }
90
+ else { $numEvents = intval($optData); }
91
+
92
+ update_option('WSS_PLUGIN_ENTRIES_LIVE_TRAFFIC', $numEvents + 1);
93
+ }
94
+
95
+ final public static function getIP()
96
+ {
97
+ $ip = null;
98
+ if ( isset($_SERVER["REMOTE_ADDR"]) ) { $ip = $_SERVER["REMOTE_ADDR"]; }
99
+ else if ( isset($_SERVER["HTTP_X_FORWARDED_FOR"]) ) { $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; }
100
+ else if ( isset($_SERVER["HTTP_CLIENT_IP"]) ) { $ip = $_SERVER["HTTP_CLIENT_IP"]; }
101
+ if(! is_null($ip) && self::isValidIp($ip)){ return $ip; }
102
+ return 'unknown';
103
+ }
104
+
105
+ final public static function getReferrer() { return (empty($_SERVER['HTTP_REFERER']) ? '' : htmlentities($_SERVER['HTTP_REFERER'],ENT_QUOTES)); }
106
+
107
+ final public static function getUserAgent() { return (empty($_SERVER['HTTP_USER_AGENT']) ? '' : htmlentities($_SERVER['HTTP_USER_AGENT'],ENT_QUOTES)); }
108
+
109
+ final public static function isValidIp($ip){
110
+ if(preg_match('/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/', $ip, $m)){
111
+ if(
112
+ $m[0] >= 0 && $m[0] <= 255 &&
113
+ $m[1] >= 0 && $m[1] <= 255 &&
114
+ $m[2] >= 0 && $m[2] <= 255 &&
115
+ $m[3] >= 0 && $m[3] <= 255
116
+ ){
117
+ return true;
118
+ }
119
+ }
120
+ return false;
121
+ }
122
+ final public static function getRequestedUrl(){
123
+ if(isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST']){
124
+ $host = $_SERVER['HTTP_HOST']; }
125
+ else {
126
+ $host = $_SERVER['SERVER_NAME'];
127
+ }
128
+ $url = (@$_SERVER['HTTPS'] ? 'https' : 'http') . '://' . $host . $_SERVER['REQUEST_URI'];
129
+ return htmlentities($url,ENT_QUOTES);
130
+ }
131
+
132
+ /**
133
+ * @param int $maxEntries If $maxEntries is 0 it means to load all entries, otherwise it will limit the select to that number
134
+ * @return mixed
135
+ */
136
+ final public static function getTrafficData($maxEntries = 0)
137
+ {
138
+ global $wpdb;
139
+ if(empty($maxEntries)){
140
+ return $wpdb->get_results("SELECT entryId,entryTime,entryIp,entryReferrer,entryUA,entryRequestedUrl FROM ".SwpaPlugin::getTableName(SWPA_PLUGIN_LIVE_TRAFFIC_TABLE_NAME)." ORDER BY entryId DESC");
141
+ }
142
+ else { return $wpdb->get_results("SELECT entryId,entryTime,entryIp,entryReferrer,entryUA,entryRequestedUrl FROM ".SwpaPlugin::getTableName(SWPA_PLUGIN_LIVE_TRAFFIC_TABLE_NAME)." ORDER BY entryId DESC LIMIT 0, ".$maxEntries);}
143
+ }
144
+
145
+ final public static function getLastID()
146
+ {
147
+ global $wpdb;
148
+ return $wpdb->get_var("SELECT entryId FROM ".SwpaPlugin::getTableName(SWPA_PLUGIN_LIVE_TRAFFIC_TABLE_NAME)." ORDER BY entryId DESC");
149
+ }
150
+
151
+ final public static function ajaxGetTrafficData($maxEntries = 0)
152
+ {
153
+ if ( !wp_verify_nonce( $_REQUEST['nonce'], "wsdTrafficScan_nonce")) { exit(__('Invalid request - nonce')); }
154
+
155
+ if ( !isset( $_REQUEST['lastID'])) { exit(__('Invalid request - lastID')); }
156
+
157
+ if ( !isset( $_REQUEST['forceLoad'])) { exit(__('Invalid request - forceload')); }
158
+
159
+ if ( isset( $_REQUEST['maxEntries'])) { $maxEntries = intval($_REQUEST['maxEntries']); }
160
+
161
+ $result = array();
162
+ $forceLoad = (bool)$_REQUEST['forceLoad'];
163
+
164
+ // no changes yet
165
+ if(! $forceLoad)
166
+ {
167
+ if($_REQUEST['lastID'] == self::getLastID())
168
+ {
169
+ $result['type'] = 'success';
170
+ $result['data'] = '';
171
+ $result = json_encode($result);
172
+ exit($result);
173
+ }
174
+ }
175
+
176
+ if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
177
+ $result['type'] = 'success';
178
+ $result['data'] = '';
179
+ $data = self::getTrafficData($maxEntries);
180
+ if(empty($data)){ $result['data'] = '<tr><td><p style="margin: 5px 5px; font-weight: bold; color: #cc0000">No data yet.</p></td></tr>'; }
181
+ else {
182
+ $title= sprintf('title="%s"',__('Opens in a new tab'));
183
+ foreach($data as $entry)
184
+ {
185
+ $result['data'] .= '<tr><td class="wsd-scan-entry">';
186
+ $result['data'] .= '<div>';
187
+ if(empty($entry->entryReferrer)){
188
+ $ref = '';
189
+ }
190
+ else {
191
+ $url = htmlentities(urldecode($entry->entryReferrer),ENT_QUOTES);
192
+ $ref = __('coming from').' <span class="w-entry"><a href="'.$url.'" target="_blank" '.$title.'>'. $url . '</a></span>';
193
+ }
194
+
195
+ //@todo: add geo-location + flag
196
+
197
+ $result['data'] .= '<p><span class="w-ip">'.$entry->entryIp . '</span> ';
198
+ $rurl = urldecode($entry->entryRequestedUrl);
199
+ $result['data'] .= $ref.' '.__('requested').' <span class="w-entry"><a href="'.$rurl.'" target="_blank" '.$title.'>'.htmlentities($rurl,ENT_QUOTES).'</a></span></p>';
200
+ $result['data'] .= '<p><strong>'.__('Date').'</strong>: <span class="w-date">'.$entry->entryTime.'</span></p>';
201
+ $result['data'] .= '<p><strong>'.__('Agent').'</strong>: <span class="w-ua">'.htmlentities($entry->entryUA,ENT_QUOTES).'</span></p>';
202
+ $result['data'] .= '</div>';
203
+ $result['data'] .= '</td></tr>';
204
+ }
205
+ }
206
+ $result = json_encode($result);
207
+ exit($result);
208
+ }
209
+ exit('Invalid request!');
210
+ }
211
+
212
+
213
+ /**
214
+ * @param $url
215
+ * @return bool
216
+ * Exclude urls
217
+ */
218
+ private static function isUrlExcluded($url)
219
+ {
220
+ if(false !==(strpos($url, 'wp-cron.php?doing_wp_cron'))) { return true; }
221
+ return false;
222
+ }
223
+ }
res/inc/WsdPlugin.php ADDED
@@ -0,0 +1,380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! defined('WSS_PLUGIN_PREFIX')) return;
2
+ /**
3
+ * Class WsdPlugin
4
+ * Static class
5
+ */
6
+ class WsdPlugin
7
+ {
8
+ public static function createWpMenu()
9
+ {
10
+ if (current_user_can('administrator') && function_exists('add_menu_page'))
11
+ {
12
+ $reqCap = 'activate_plugins';
13
+ add_menu_page('WP Security', 'WP Security', $reqCap, WSS_PLUGIN_PREFIX, array(get_class(),'pageMain'), WsdUtil::imageUrl('logo-small.png'));
14
+ add_submenu_page(WSS_PLUGIN_PREFIX, 'Dashboard', __('Dashboard'), $reqCap, WSS_PLUGIN_PREFIX, array(get_class(),'pageMain'));
15
+ add_submenu_page(WSS_PLUGIN_PREFIX, 'Database', __('Database'), $reqCap, WSS_PLUGIN_PREFIX.'database', array(get_class(),'pageDatabase'));
16
+ add_submenu_page(WSS_PLUGIN_PREFIX, 'Scanner', __('Scanner'), $reqCap, WSS_PLUGIN_PREFIX.'scanner', array(get_class(),'pageScanner'));
17
+ add_submenu_page(WSS_PLUGIN_PREFIX, 'Live traffic', __('Live traffic'), $reqCap, WSS_PLUGIN_PREFIX.'live_traffic', array(get_class(),'pageLiveTraffic'));
18
+ add_submenu_page(WSS_PLUGIN_PREFIX, 'Blog', __('Blog'), $reqCap, WSS_PLUGIN_PREFIX.'blog', array(get_class(),'pageBlog'));
19
+ add_submenu_page(WSS_PLUGIN_PREFIX, 'Settings', __('Settings'), $reqCap, WSS_PLUGIN_PREFIX.'settings', array(get_class(),'pageSettings'));
20
+ add_submenu_page(WSS_PLUGIN_PREFIX, 'About', __('About'), $reqCap, WSS_PLUGIN_PREFIX.'about', array(get_class(),'pageAbout'));
21
+ }
22
+ }
23
+
24
+ public static function pageMain() { WsdUtil::includePage('dashboard.php'); }
25
+ public static function pageDatabase() { WsdUtil::includePage('database.php'); }
26
+ public static function pageScanner() { WsdUtil::includePage('scanner.php'); }
27
+ public static function pageLiveTraffic() { WsdUtil::includePage('live_traffic.php'); }
28
+ public static function pageBlog() { WsdUtil::includePage('blog.php'); }
29
+ public static function pageSettings() { WsdUtil::includePage('settings.php'); }
30
+ public static function pageAbout() { WsdUtil::includePage('about.php'); }
31
+
32
+ public static function loadResources()
33
+ {
34
+ if(WsdUtil::canLoad()){
35
+ wp_enqueue_style('wsd-styles-base', WsdUtil::cssUrl('styles.base.css'));
36
+ wp_enqueue_style('wsd-styles-alerts', WsdUtil::cssUrl('styles.alerts.css'));
37
+ wp_enqueue_style('wsd-styles-general', WsdUtil::cssUrl('styles.general.css'));
38
+ wp_enqueue_style('wsd-styles-status', WsdUtil::cssUrl('styles.status.css'));
39
+ wp_enqueue_script('wsdplugin-js-util', WsdUtil::jsUrl('wsd-util.js'), array('jquery'));
40
+ }
41
+ }
42
+
43
+
44
+ /**
45
+ * Common method to add an alert to database.
46
+ * @static
47
+ * @param string $actionName The name of the action of the alert
48
+ * @param int $type Can only be one of the following: WSS_PLUGIN_ALERT_TYPE_OVERWRITE | WSS_PLUGIN_ALERT_TYPE_STACK. Defaults to WSS_PLUGIN_ALERT_TYPE_OVERWRITE
49
+ * @param int $severity Can only have one of the following values: 0 1 2 3. Defaults to 0.
50
+ * @param string $title
51
+ * @param string $description
52
+ * @param string $solution
53
+ * @return bool
54
+ */
55
+ public static function alert($actionName, $type = 0, $severity = 0, $title = '', $description = '', $solution = '') {
56
+ global $wpdb;
57
+
58
+ $table = self::getTableName();
59
+
60
+ if($type == WSS_PLUGIN_ALERT_TYPE_STACK)
61
+ {
62
+ //#! Check the max number of stacked alerts to keep and remove the exceeding ones
63
+ $afsDate = $wpdb->get_var("SELECT alertFirstSeen FROM $table WHERE alertActionName = '$actionName' ORDER BY `alertDate`;");
64
+ if(empty($afsDate)){ $afsDate = "CURRENT_TIMESTAMP()";}
65
+ else { $afsDate = "'".$afsDate."'"; }
66
+ $result = $wpdb->get_var("SELECT COUNT(alertId) FROM $table WHERE alertActionName = '$actionName';");
67
+ if($result >= WSS_PLUGIN_ALERT_STACK_MAX_KEEP){
68
+ // remove older entries to make room for the new ones
69
+ $query = "DELETE FROM $table ORDER BY alertDate ASC LIMIT ".($result - (WSS_PLUGIN_ALERT_STACK_MAX_KEEP - 1));
70
+ $wpdb->query($query);
71
+ }
72
+
73
+ //Add the new entry
74
+ $query = $wpdb->prepare(
75
+ "INSERT INTO $table
76
+ (`alertType`,
77
+ `alertSeverity`,
78
+ `alertActionName`,
79
+ `alertTitle`,
80
+ `alertDescription`,
81
+ `alertSolution`,
82
+ `alertDate`,
83
+ `alertFirstSeen`)
84
+ VALUES
85
+ (%d,
86
+ %d,
87
+ '%s',
88
+ '%s',
89
+ '%s',
90
+ '%s',
91
+ CURRENT_TIMESTAMP(),
92
+ $afsDate
93
+ );",
94
+ $type, $severity, $actionName, $title, $description, $solution);
95
+ }
96
+ elseif($type == WSS_PLUGIN_ALERT_TYPE_OVERWRITE)
97
+ {
98
+ //#! Find the record by actionName and update fields
99
+ $result = $wpdb->get_var("SELECT alertId FROM $table WHERE alertActionName = '".$actionName."'; ");
100
+ //#! found. do update
101
+ if($result > 0){
102
+ $query = $wpdb->prepare("UPDATE $table
103
+ SET
104
+ `alertType` = %d,
105
+ `alertSeverity` = %d,
106
+ `alertActionName` = '%s',
107
+ `alertTitle` = '%s',
108
+ `alertDescription` = '%s',
109
+ `alertSolution` = '%s',
110
+ `alertDate` = CURRENT_TIMESTAMP()
111
+ WHERE alertId = %d;",
112
+ $type, $severity, $actionName, $title, $description, $solution,$result);
113
+ }
114
+ //#! record not found. insert query
115
+ else {
116
+ $query = $wpdb->prepare("INSERT INTO $table
117
+ (`alertType`,
118
+ `alertSeverity`,
119
+ `alertActionName`,
120
+ `alertTitle`,
121
+ `alertDescription`,
122
+ `alertSolution`,
123
+ `alertDate`,
124
+ `alertFirstSeen`)
125
+ VALUES
126
+ (%d,
127
+ %d,
128
+ '%s',
129
+ '%s',
130
+ '%s',
131
+ '%s',
132
+ CURRENT_TIMESTAMP(),
133
+ CURRENT_TIMESTAMP()
134
+ );",
135
+ $type, $severity, $actionName, $title, $description, $solution);
136
+ }
137
+ }
138
+ $result = $wpdb->query($query);
139
+ if($result === false){
140
+ //#! MySQL error
141
+ return false;
142
+ }
143
+ return true;
144
+ }
145
+
146
+ public static function getTableName($tableName = WSS_PLUGIN_ALERT_TABLE_NAME){
147
+ global $wpdb;
148
+ return $wpdb->prefix.$tableName;
149
+ }
150
+
151
+ /**
152
+ * Get all alerts grouped by alertActionName
153
+ * @return array
154
+ */
155
+ public static function getAlerts()
156
+ {
157
+ global $wpdb;
158
+ $columns = "`alertId`,`alertType`,`alertSeverity`,`alertActionName`,`alertTitle`,`alertDescription`,`alertSolution`,`alertDate`,`alertFirstSeen`";
159
+ return $wpdb->get_results("SELECT $columns FROM ".self::getTableName(WSS_PLUGIN_ALERT_TABLE_NAME)." GROUP BY `alertActionName`;");
160
+ }
161
+
162
+ // filter alerts by input
163
+ public static function getAlertsBy($alertSeverity)
164
+ {
165
+ global $wpdb;
166
+ $columns = "`alertId`,`alertType`,`alertSeverity`,`alertActionName`,`alertTitle`,`alertDescription`,`alertSolution`,`alertDate`,`alertFirstSeen`";
167
+ return $wpdb->get_results("SELECT $columns FROM ".self::getTableName(WSS_PLUGIN_ALERT_TABLE_NAME)." WHERE `alertSeverity` = '$alertSeverity' GROUP BY `alertActionName`;");
168
+ }
169
+
170
+ public static function getChildAlerts($alertId, $alertType)
171
+ {
172
+ global $wpdb;
173
+ $columns = "`alertId`,`alertType`,`alertSeverity`,`alertActionName`,`alertTitle`,`alertDescription`,`alertSolution`,`alertDate`,`alertFirstSeen`";
174
+ return $wpdb->get_results("SELECT $columns FROM ".self::getTableName()." WHERE (alertId <> $alertId AND alertType = '$alertType') ORDER BY `alertDate` DESC");
175
+ }
176
+
177
+ /**
178
+ * Retrieve the settings from database. This method will extract all methods found in the WsdSecurity class and provide them as
179
+ * settings in the settings page. It will also auto update itself in case new methods are added to the class or if
180
+ * some of them were removed.
181
+ * @return array
182
+ */
183
+ public static function getSettings()
184
+ {
185
+ $className = 'WsdSecurity';
186
+ if(! class_exists($className)){
187
+ return array();
188
+ }
189
+ $settings = get_option(WSS_PLUGIN_SETTINGS_OPTION_NAME);
190
+ $class = new ReflectionClass($className);
191
+ $methods = $class->getMethods();
192
+
193
+ if(empty($settings))
194
+ {
195
+ $settings = array();
196
+ foreach($methods as $method)
197
+ {
198
+ $mn = $method->name;
199
+ if($className != $method->class){
200
+ continue;
201
+ }
202
+ $comment = $method->getDocComment();
203
+ if(false !== ($pos = strpos($mn,WsdSecurity::$methodPrefix))){
204
+ $settings[$mn] = array(
205
+ 'name' => $mn,
206
+ 'value' => 0, // 0 or 1 ; whether or not the option will show as selected by default in the plugin's settings page
207
+ 'desc' => trim(str_replace(array('/**','*/'),'', $comment))
208
+ );
209
+ }
210
+ }
211
+ add_option(WSS_PLUGIN_SETTINGS_OPTION_NAME, $settings);
212
+ }
213
+ else
214
+ {
215
+ $n1 = (isset($settings['keepNumEntriesLiveTraffic']) ? $settings['keepNumEntriesLiveTraffic'] : 500);
216
+ $n2 = (isset($settings['liveTrafficRefreshRateAjax']) ? $settings['liveTrafficRefreshRateAjax'] : 10);
217
+ // Check to see whether or not new methods were added or subtracted
218
+ $numSettings = count($settings);
219
+ $numMethods = count($methods);
220
+ if($numMethods <> $numSettings)
221
+ {
222
+ // add new methods
223
+ $_temp = array();
224
+ foreach($methods as $method){
225
+ if($className != $method->class){
226
+ continue;
227
+ }
228
+ $comment = $method->getDocComment();
229
+ if(false === ($pos = strpos($method->name,WsdSecurity::$methodPrefix))){ continue; }
230
+ if(! isset($settings[$method->name])){
231
+ $settings[$method->name] = array(
232
+ 'name' => $method->name,
233
+ 'value' => 0,
234
+ 'desc' => trim(str_replace(array('/**','*/'),'', $comment))
235
+ );
236
+ }
237
+ array_push($_temp, $method->name);
238
+ }
239
+ // remove missing methods
240
+ foreach($settings as $k => &$entry){
241
+ if(! in_array($entry['name'], $_temp)){
242
+ unset($settings[$k]);
243
+ }
244
+ }
245
+
246
+ $settings['keepNumEntriesLiveTraffic'] = $n1;
247
+ $settings['liveTrafficRefreshRateAjax'] = $n2;
248
+ update_option(WSS_PLUGIN_SETTINGS_OPTION_NAME, $settings);
249
+ }
250
+ }
251
+ return $settings;
252
+ }
253
+
254
+ /**
255
+ * Check to see whether or not the provided setting is enabled (as the settings are configurable the user might chose to turn some of them off)
256
+ * @param string $name The name of the setting to look for in the settings array
257
+ * @return bool
258
+ */
259
+ public static function isSettingEnabled($name)
260
+ {
261
+ $settings = self::getSettings();
262
+ return (isset($settings[$name]) ? $settings[$name]['value'] : false);
263
+ }
264
+
265
+ public static function activate(){
266
+ global $wpdb;
267
+ $charset_collate = '';
268
+
269
+ if ( ! empty($wpdb->charset) ){$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";}
270
+ if ( ! empty($wpdb->collate) ){$charset_collate .= " COLLATE $wpdb->collate";}
271
+
272
+ // MUST HAVE "CREATE" RIGHTS if a table is not found and needs to be created
273
+ $rights = WsdInfoServer::getDatabaseUserAccessRights();
274
+ $hasCreateRight = in_array('CREATE', $rights['rightsHaving']);
275
+ $table1 = self::getTableName(WSS_PLUGIN_ALERT_TABLE_NAME);
276
+ $table2 = self::getTableName(WSS_PLUGIN_LIVE_TRAFFIC_TABLE_NAME);
277
+
278
+ if(! WsdUtil::tableExists($table1)){
279
+ $query1 = "CREATE TABLE IF NOT EXISTS ".$table1." (
280
+ `alertId` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
281
+ `alertType` TINYINT NOT NULL DEFAULT 0 ,
282
+ `alertSeverity` INT NOT NULL DEFAULT 0 ,
283
+ `alertActionName` VARCHAR (255) NOT NULL,
284
+ `alertTitle` VARCHAR(255) NOT NULL ,
285
+ `alertDescription` TEXT NOT NULL ,
286
+ `alertSolution` TEXT NOT NULL ,
287
+ `alertDate` DATETIME NOT NULL default '0000-00-00 00:00:00',
288
+ `alertFirstSeen` DATETIME NOT NULL default '0000-00-00 00:00:00',
289
+ PRIMARY KEY (`alertId`) ,
290
+ UNIQUE INDEX `alertId_UNIQUE` (`alertId` ASC) ) $charset_collate;";
291
+ if(! $hasCreateRight){
292
+ $notices= get_option('wsd_plugin_install_error', array());
293
+ $notices[]= '<strong>'.WSS_PLUGIN_NAME."</strong>: The database user needs the '<strong>CREATE</strong>' right in order to install this plugin.";
294
+ update_option('wsd_plugin_install_error', $notices);
295
+ return;
296
+ }
297
+ $result = @$wpdb->query($query1);
298
+ if($result === false){
299
+ //#! MySQL error
300
+ $GLOBALS['WSS_PLUGIN_INSTALL_ERROR'] = 'Error running query: '.$query1;
301
+ $notices= get_option('wsd_plugin_install_error', array());
302
+ $notices[]= '<strong>'.WSS_PLUGIN_NAME."</strong>. Error running query: <strong><pre>$query1</pre></strong>.";
303
+ update_option('wsd_plugin_install_error', $notices);
304
+ return;
305
+ }
306
+ }
307
+
308
+ if(! WsdUtil::tableExists($table2)){
309
+ $query2 = "CREATE TABLE IF NOT EXISTS ".$table2." (
310
+ `entryId` bigint(20) unsigned NOT NULL auto_increment,
311
+ `entryTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
312
+ `entryIp` text,
313
+ `entryReferrer` text,
314
+ `entryUA` text,
315
+ `entryRequestedUrl` text,
316
+ PRIMARY KEY (entryId)) $charset_collate;";
317
+ if(! $hasCreateRight){
318
+ $notices= get_option('wsd_plugin_install_error', array());
319
+ $notices[]= '<strong>'.WSS_PLUGIN_NAME."</strong>: The database user needs the '<strong>CREATE</strong>' right in order to install this plugin.";
320
+ update_option('wsd_plugin_install_error', $notices);
321
+ return;
322
+ }
323
+ $result = @$wpdb->query($query2);
324
+ if($result === false){
325
+ //#! MySQL error
326
+ $GLOBALS['WSS_PLUGIN_INSTALL_ERROR'] = 'Error running query: '.$query2;
327
+ $notices= get_option('wsd_plugin_install_error', array());
328
+ $notices[]= '<strong>'.WSS_PLUGIN_NAME."</strong>. Error running query: <strong><pre>$query2</pre></strong>.";
329
+ update_option('wsd_plugin_install_error', $notices);
330
+ return;
331
+ }
332
+ }
333
+
334
+ add_option('WSD-PLUGIN-CAN-RUN-TASKS', 1);
335
+ }
336
+ public static function deactivate() {
337
+ if(self::swpPluginInstalled()){
338
+ return;
339
+ }
340
+ WsdScheduler::unregisterCronTasks();
341
+ delete_option(WSS_PLUGIN_SETTINGS_OPTION_NAME);
342
+ delete_option('wsd_plugin_install_error');
343
+ delete_option('WSD-PLUGIN-CAN-RUN-TASKS');
344
+ }
345
+ public static function uninstall(){
346
+ if(self::swpPluginInstalled()){
347
+ return;
348
+ }
349
+ delete_option('WSS_PLUGIN_ENTRIES_LIVE_TRAFFIC');
350
+ global $wpdb;
351
+ $wpdb->query("DROP TABLE IF EXISTS ".WsdPlugin::getTableName(WSS_PLUGIN_ALERT_TABLE_NAME));
352
+ $wpdb->query("DROP TABLE IF EXISTS ".WsdPlugin::getTableName(WSS_PLUGIN_LIVE_TRAFFIC_TABLE_NAME));
353
+ }
354
+
355
+ /**
356
+ * Check to see whether or not the Secure WordPress plugin is installed
357
+ * @return bool
358
+ */
359
+ public static function swpPluginInstalled()
360
+ {
361
+ $pluginPath = 'secure-wordpress/index.php';
362
+ $pluginFilePath = trailingslashit(ABSPATH).'wp-content/plugins/'.$pluginPath;
363
+ if(function_exists('is_plugin_active')){
364
+ if(is_plugin_active($pluginPath)){
365
+ return true;
366
+ }
367
+ else {
368
+ // check plugins dir
369
+ if(is_file($pluginFilePath)){
370
+ return true;
371
+ }
372
+ }
373
+ }
374
+ // check plugins dir
375
+ if(is_file($pluginFilePath)){
376
+ return true;
377
+ }
378
+ return false;
379
+ }
380
+ }
res/inc/WsdScheduler.php ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! defined('WSS_PLUGIN_PREFIX')) return;
2
+ /**
3
+ * Class WsdScheduler
4
+ * Provides common methods to register action with wp-cron
5
+ */
6
+ class WsdScheduler
7
+ {
8
+ /**
9
+ * @var array
10
+ * Holds all the registered cron tasks so to provide an easy way to
11
+ * unregister them all upon deactivation of the plugin
12
+ */
13
+ private static $_cronTasks = array();
14
+
15
+ /**
16
+ * Register a cron task
17
+ * @param string $cronActionName The name of the action that will be registered with wp-cron
18
+ * @param string $callback The function to register with wp-cron
19
+ * @param string $interval can only be one of the following: hourly, daily and twicedaily if no other custom intervals are registered. Defaults to daily
20
+ * @return void
21
+ */
22
+ public static function registerCronTask($cronActionName, $callback, $interval = 'daily')
23
+ {
24
+ if(! is_callable($callback)) { return; }
25
+
26
+ // if cron disabled -> run callback
27
+ if(! self::canRegisterCronTask()){
28
+ self::registerTask($callback);
29
+ return;
30
+ }
31
+ $interval = strtolower($interval);
32
+ if(empty($interval)){ $interval = 'daily'; }
33
+ else{
34
+ // check to see if the time interval is valid
35
+ $timeIntervals = wp_get_schedules();
36
+ if(! array_key_exists($interval, $timeIntervals)){
37
+ $interval = 'daily';
38
+ }
39
+ }
40
+ // avoid duplicate crons
41
+ add_action($cronActionName, $callback);
42
+ if ( ! wp_next_scheduled($cronActionName) ) {
43
+ wp_schedule_event( time(), $interval, $cronActionName );
44
+ array_push(self::$_cronTasks, $cronActionName);
45
+ }
46
+ }
47
+
48
+ public static function unregisterCronTask($cronActionName){
49
+ wp_clear_scheduled_hook($cronActionName);
50
+ if(! empty(self::$_cronTasks)){
51
+ if(isset(self::$_cronTasks[$cronActionName])){
52
+ unset(self::$_cronTasks[$cronActionName]);
53
+ }
54
+ }
55
+ }
56
+
57
+ public static function unregisterCronTasks(){
58
+ if(! empty(self::$_cronTasks)){
59
+ foreach (self::$_cronTasks as $task) {
60
+ wp_clear_scheduled_hook($task);
61
+ }
62
+ self::$_cronTasks = array();
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Check to see whether or not cron is enabled in WordPress
68
+ * @return bool
69
+ */
70
+ public static function canRegisterCronTask(){ return ((defined('DISABLE_WP_CRON') && 'DISABLE_WP_CRON') ? false : true); }
71
+
72
+ /**
73
+ * Register a task
74
+ * @param string $callback The callback to register
75
+ * @param string $wpActionName Optional. If provided it must be a valid action name to hook the $callback to. If omitted, then the $callback will just be executed.
76
+ * @return void
77
+ */
78
+ public static function registerTask($callback, $wpActionName = '') {
79
+ if(! empty($wpActionName)){
80
+ add_action($wpActionName, $callback);
81
+ }
82
+ else {
83
+ if(is_callable($callback)){
84
+ call_user_func($callback);
85
+ }
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Execute all methods of a class that are prefixed with $onlyWithPrefix (if provided)
91
+ * @param $className The name of the class
92
+ * @param string $onlyWithPrefix Optional. The prefix to look up in the methods' name
93
+ * @return void
94
+ */
95
+ public static function registerClassTasks($className, $onlyWithPrefix = '')
96
+ {
97
+ $_class = new ReflectionClass($className);
98
+ $methods = $_class->getMethods();
99
+ if(! empty($methods)){
100
+ $pLength = strlen($onlyWithPrefix);
101
+ foreach($methods as $_method){
102
+ $method = $_method->name;
103
+ // only certain methods
104
+ if($pLength > 0){
105
+ $search = substr($method, 0, $pLength);
106
+ if(strcasecmp($search,$onlyWithPrefix) == 0){
107
+ call_user_func(array($className, $method));
108
+ }
109
+ }
110
+ else { call_user_func(array($className, $method)); }
111
+ }
112
+ }
113
+ }
114
+
115
+ }
res/inc/WsdSecurity.php ADDED
@@ -0,0 +1,726 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! defined('WSS_PLUGIN_PREFIX')) return;
2
+ /**
3
+ * Class WsdSecurity
4
+ * Static class. Provides security fixes for WordPress
5
+ */
6
+
7
+ class WsdSecurity extends WsdPlugin
8
+ {
9
+ /**
10
+ * The prefix each method should have in order to be executed automatically.
11
+ * @var string Defaults to 'fix_'
12
+ */
13
+ public static $methodPrefix = 'fix_';
14
+ public static $isVersionHidden = false;
15
+
16
+ /** Hide WordPress version for all users but administrators */
17
+ public static function fix_hideWpVersion()
18
+ {
19
+ global $wsdPluginAlertsArray;
20
+ $actionName = $wsdPluginAlertsArray['fix_wp_version_hidden']['name'];
21
+ $alertType = $wsdPluginAlertsArray['fix_wp_version_hidden']['type'];
22
+
23
+ /* This check is important so this function will run only if the user enables it. */
24
+ if(! self::isSettingEnabled(__FUNCTION__)){
25
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_CRITICAL,
26
+ __('WordPress version is displayed for all users'),
27
+ __('<p>Displaying your WordPress version on frontend and in the backend\'s footer to all visitors
28
+ and users of your website is a security risk because if a hacker knows which version of WordPress a website is running, it can make it easier for him to target a known WordPress security issue.</p>'),
29
+ sprintf(__('<p>This plugin can automatically hide your WordPress version from frontend, backend and rss feeds if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
30
+ 'Hide WordPress version for all users but administrators')
31
+ );
32
+ return;
33
+ }
34
+
35
+ $isAdmin = WsdUtil::isAdministrator();
36
+
37
+ //@@ back-end
38
+ if(is_admin())
39
+ {
40
+ if(! $isAdmin){
41
+ function __hideFooterVersion(){ return ' ';}
42
+ add_filter( 'update_footer', '__hideFooterVersion',800);
43
+ self::$isVersionHidden = true;
44
+ }
45
+ // version hidden
46
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
47
+ __('WordPress version is only displayed to administrator users'),
48
+ __('<p>Displaying your WordPress version on frontend and in the backend\'s footer to all visitors
49
+ and users of your website is a security risk because if a hacker knows which version of WordPress a website is running, it can make it easier for him to target a known WordPress security issue.</p>')
50
+ );
51
+ }
52
+ //@@ front-end
53
+ else {
54
+ if (!$isAdmin)
55
+ {
56
+ global $wp_version, $wp_db_version, $manifest_version, $tinymce_version;
57
+
58
+ // random values
59
+ $v = intval( rand(0, 9999) );
60
+ $d = intval( rand(9999, 99999) );
61
+ $m = intval( rand(99999, 999999) );
62
+ $t = intval( rand(999999, 9999999) );
63
+
64
+ if ( function_exists('the_generator') )
65
+ {
66
+ // eliminate version for wordpress >= 2.4
67
+ remove_filter( 'wp_head', 'wp_generator' );
68
+ $actions = array( 'rss2_head', 'commentsrss2_head', 'rss_head', 'rdf_header', 'atom_head', 'comments_atom_head', 'opml_head', 'app_head' );
69
+ foreach ( $actions as $action ) {
70
+ remove_action( $action, 'the_generator' );
71
+ }
72
+ // for vars
73
+ $wp_version = $v;
74
+ $wp_db_version = $d;
75
+ $manifest_version = $m;
76
+ $tinymce_version = $t;
77
+ }
78
+ else {
79
+ // for wordpress < 2.4
80
+ add_filter( "bloginfo_rss('version')", create_function('$a', "return $v;") );
81
+ // for rdf and rss v0.92
82
+ $wp_version = $v;
83
+ $wp_db_version = $d;
84
+ $manifest_version = $m;
85
+ $tinymce_version = $t;
86
+ }
87
+ self::$isVersionHidden = true;
88
+ }
89
+ // version hidden
90
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
91
+ __('WordPress version is only displayed to administrator users'),
92
+ __('<p>Displaying your WordPress version on frontend and in the backend\'s footer to all visitors
93
+ and users of your website is a security risk because if a hacker knows which version of WordPress a website is running, it can make it easier for him to target a known WordPress security issue.</p>')
94
+ );
95
+ }
96
+ }
97
+
98
+ /** Remove various meta tags generators from the blog's head tag for non-administrators. */
99
+ public static function fix_removeWpMetaGeneratorsFrontend()
100
+ {
101
+ global $wsdPluginAlertsArray;
102
+ $actionName = $wsdPluginAlertsArray['fix_wp_generators_frontend']['name'];
103
+ $alertType = $wsdPluginAlertsArray['fix_wp_generators_frontend']['type'];
104
+
105
+ /* This check is important so this function will run only if the user enables it. */
106
+ if(! self::isSettingEnabled(__FUNCTION__)){
107
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_CRITICAL,
108
+ __('WordPress meta tags are displayed on frontend to all users'),
109
+ __('<p>By default, WordPress creates a few meta tags, among which is the currently installed version, that give a hacker the knowledge about your WordPress installation. At the moment, these meta tags are available for anyone to see, which is a potentially security risk.</p>'),
110
+ sprintf(__('<p>This plugin can automatically hide your WordPress\'s default meta tags if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'), 'Remove various meta tags generators from the blog\'s head tag for non-administrators')
111
+ );
112
+ return;
113
+ }
114
+
115
+ if (!is_admin())
116
+ {
117
+ if(!WsdUtil::isAdministrator()){
118
+ //@@ remove various meta tags generators from blog's head tag
119
+ function acx_filter_generator($gen, $type)
120
+ {
121
+ switch ( $type ) {
122
+ case 'html':
123
+ $gen = '<meta name="generator" content="WordPress">';
124
+ break;
125
+ case 'xhtml':
126
+ $gen = '<meta name="generator" content="WordPress" />';
127
+ break;
128
+ case 'atom':
129
+ $gen = '<generator uri="http://wordpress.org/">WordPress</generator>';
130
+ break;
131
+ case 'rss2':
132
+ $gen = '<generator>http://wordpress.org/?v=</generator>';
133
+ break;
134
+ case 'rdf':
135
+ $gen = '<admin:generatorAgent rdf:resource="http://wordpress.org/?v=" />';
136
+ break;
137
+ case 'comment':
138
+ $gen = '<!-- generator="WordPress" -->';
139
+ break;
140
+ }
141
+ return $gen;
142
+ }
143
+ foreach ( array( 'html', 'xhtml', 'atom', 'rss2', 'rdf', 'comment' ) as $type ) {
144
+ add_filter( "get_the_generator_".$type, 'acx_filter_generator', 10, 2 );
145
+ }
146
+ }
147
+ }
148
+ // version hidden
149
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
150
+ __('WordPress meta tags are only displayed on frontend to administrator users'),
151
+ __('<p>By default, WordPress creates a few meta tags, among which is the currently installed version, that give a hacker the knowledge about your WordPress installation.
152
+ At the moment, all WordPress\'s defaults meta tags are hidden for all users but administrators.</p>')
153
+ );
154
+ }
155
+
156
+ /** Remove Really Simple Discovery meta tags from front-end */
157
+ public static function fix_removeReallySimpleDiscovery()
158
+ {
159
+ global $wsdPluginAlertsArray;
160
+ $actionName = $wsdPluginAlertsArray['fix_wp_rsd_frontend']['name'];
161
+ $alertType = $wsdPluginAlertsArray['fix_wp_rsd_frontend']['type'];
162
+
163
+ /* This check is important so this function will run only if the user enables it. */
164
+ if(! self::isSettingEnabled(__FUNCTION__)){
165
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
166
+ __('WordPress Really Simple Discovery tag is displayed on frontend to all users'),
167
+ sprintf(__('<p>By default, WordPress creates the <strong>rsd meta tag</strong> to allow bloggers to consume services like Flickr using the <a href="%s" target="%s">XML-RPC</a> protocol.
168
+ If you don\'t use such services it is recommended to hide this meta tag.</p>'),
169
+ 'http://en.wikipedia.org/wiki/XML-RPC', '_blank'),
170
+ sprintf(__('<p>This plugin can automatically hide the rsd meta tag if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'), 'Remove Really Simple Discovery meta tags from front-end')
171
+ );
172
+ return;
173
+ }
174
+
175
+ if (!is_admin()) {
176
+ if(!WsdUtil::isAdministrator() && function_exists('rsd_link')) {
177
+ remove_action('wp_head', 'rsd_link');
178
+ }
179
+ }
180
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
181
+ __('WordPress Really Simple Discovery tag is only displayed on frontend to administrator users.'),
182
+ sprintf(__('<p>By default, WordPress creates the <strong>rsd meta tag</strong> to allow bloggers to consume services like Flickr using the <a href="%s" target="%s">XML-RPC</a> protocol.
183
+ If you don\'t use such services it is recommended to hide this meta tag.</p>'),
184
+ 'http://en.wikipedia.org/wiki/XML-RPC', '_blank')
185
+ );
186
+ }
187
+
188
+ /** Remove Windows Live Writer meta tags from front-end */
189
+ public static function fix_removeWindowsLiveWriter()
190
+ {
191
+ global $wsdPluginAlertsArray;
192
+ $actionName = $wsdPluginAlertsArray['fix_wp_wlw_frontend']['name'];
193
+ $alertType = $wsdPluginAlertsArray['fix_wp_wlw_frontend']['type'];
194
+
195
+ /* This check is important so this function will run only if the user enables it. */
196
+ if(! self::isSettingEnabled(__FUNCTION__)){
197
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
198
+ __('WordPress Windows Live Writer tag is displayed on frontend for all users'),
199
+ sprintf(__('<p>By default, WordPress creates the wlw meta tag to allow bloggers to publish their articles using the <strong>"%s"</strong> application.
200
+ It is recommended to hide this meta tag from all visitors. If the option <strong>"%s"</strong> is checked on the plugin\'s settings page, this meta tag
201
+ will still be available for administrator users to use the <strong>"%s"</strong> application to publish their blog posts.</p>'),
202
+ 'Windows Live Writer', 'Remove Windows Live Writer meta tags from front-end', 'Windows Live Writer'),
203
+ sprintf(__('<p>This plugin can automatically hide the wlw meta tag if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'), 'Remove Windows Live Writer meta tags from front-end"')
204
+ );
205
+ return;
206
+ }
207
+
208
+ if (!is_admin() && function_exists('wlwmanifest_link')) {
209
+ if(!WsdUtil::isAdministrator()) {
210
+ remove_action('wp_head', 'wlwmanifest_link');
211
+ }
212
+ }
213
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
214
+ __('WordPress Windows Live Writer tag is only displayed on frontend for administrator users'),
215
+ sprintf(__('<p>By default, WordPress creates the wlw meta tag to allow bloggers to publish their articles using the <strong>"%s"</strong> application.
216
+ It is recommended to hide this meta tag from all visitors. If the option <strong>"%s"</strong> is checked on the plugin\'s settings page, this meta tag
217
+ will still be available for administrator users to use the <strong>"%s"</strong> application to publish their blog posts.</p>'),
218
+ 'Windows Live Writer', 'Remove Windows Live Writer meta tags from front-end', 'Windows Live Writer')
219
+ );
220
+ }
221
+
222
+ /** Disable error reporting (php + db) for all but administrators */
223
+ public static function fix_disableErrorReporting()
224
+ {
225
+ global $wsdPluginAlertsArray;
226
+ $actionName = $wsdPluginAlertsArray['fix_wp_error_reporting']['name'];
227
+ $alertType = $wsdPluginAlertsArray['fix_wp_error_reporting']['type'];
228
+
229
+ /* This check is important so this function will run only if the user enables it. */
230
+ if(! self::isSettingEnabled(__FUNCTION__)){
231
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_CRITICAL,
232
+ __('The check for PHP and database error reporting is disabled'),
233
+ sprintf(__('<p>By default, WordPress hides database errors, but there are times when a plugin might enable them thus it is very important to have this type of errors turned off
234
+ so if there is an error during a connection to the database the user will not get access to the error message generated during that request.</p>
235
+ <p>As regarding the PHP errors, with the <strong>display_error</strong> PHP configuration directive enabled, untrusted sources can see detailed web application environment
236
+ error messages which include sensitive information that can be used to craft further attacks.</p>
237
+ <p>Attackers will do anything to collect information in order to design their attack in a more sophisticated way to eventually hack your website or web application, and causing
238
+ errors to display is a common starting point. Website errors can always occur, but they should be suppressed from being displayed back to the public.</p>
239
+ <p>Therefore we highly recommend you to have the <strong>"%s"</strong> option checked on the plugin\'s settings page to ensure PHP and
240
+ database errors will be hidden from all users. For more information, please check the following <a href="%s" target="%s">article</a>.</p>'),
241
+ 'Disable error reporting (php + db) for all but administrators', 'http://www.acunetix.com/blog/web-security-zone/articles/php-security-directive-your-website-is-showing-php-errors/', '_blank'),
242
+ sprintf(__('<p>This plugin can do this automatically if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
243
+ 'Disable error reporting (php + db) for all but administrators')
244
+ );
245
+ return;
246
+ }
247
+ if(! WsdUtil::isAdministrator())
248
+ {
249
+ @error_reporting(0);
250
+ @ini_set('display_errors','Off');
251
+ @ini_set('display_startup_errors', 0);
252
+ global $wpdb;
253
+ $wpdb->hide_errors();
254
+ $wpdb->suppress_errors();
255
+ }
256
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
257
+ __('Error reporting, PHP and database, is enabled only for administrator users'),
258
+ sprintf(__('<p>By default, WordPress hides database errors, but there are times when a plugin might enable them thus it is very important to have this type of errors turned off
259
+ so if there is an error during a connection to the database the user will not get access to the error message generated during that request.</p>
260
+ <p>As regarding the PHP errors, with the <strong>display_error</strong> PHP configuration directive enabled, untrusted sources can see detailed web application environment
261
+ error messages which include sensitive information that can be used to craft further attacks.</p>
262
+ <p>Attackers will do anything to collect information in order to design their attack in a more sophisticated way to eventually hack your website or web application, and causing
263
+ errors to display is a common starting point. Website errors can always occur, but they should be suppressed from being displayed back to the public.</p>
264
+ <p>Therefore we highly recommend you to have the <strong>"%s"</strong> option checked on the plugin\'s settings page to ensure PHP and
265
+ database errors will be hidden from all users. For more information, please check the following <a href="%s" target="%s">article</a>.</p>'),
266
+ 'Disable error reporting (php + db) for all but administrators', 'http://www.acunetix.com/blog/web-security-zone/articles/php-security-directive-your-website-is-showing-php-errors/', '_blank')
267
+ );
268
+ }
269
+
270
+ /** Remove core update notifications from back-end for all but administrators */
271
+ public static function fix_removeCoreUpdateNotification()
272
+ {
273
+ global $wsdPluginAlertsArray;
274
+ $actionName = $wsdPluginAlertsArray['fix_wp_core_update_notif']['name'];
275
+ $alertType = $wsdPluginAlertsArray['fix_wp_core_update_notif']['type'];
276
+
277
+ /* This check is important so this function will run only if the user enables it. */
278
+ if(! self::isSettingEnabled(__FUNCTION__)){
279
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_CRITICAL,
280
+ __('Core update notifications are displayed to all users'),
281
+ __('<p>These notifications are displayed at the top of the screen by the WordPress platform whenever the website was updated or needs an update.</p>
282
+ <p>These notifications should only be viewed by the website\'s administrators and not visible to any other users registered with that website.</p>'),
283
+ sprintf(__('<p>This plugin can automatically hide these notifications if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'), 'Remove core update notifications from back-end for all but administrators')
284
+ );
285
+ return;
286
+ }
287
+
288
+ if (!WsdUtil::isAdministrator())
289
+ {
290
+ add_action( 'admin_init', create_function( '$a', "remove_action( 'admin_notices', 'maintenance_nag' );" ) );
291
+ add_action( 'admin_init', create_function( '$a', "remove_action( 'admin_notices', 'update_nag', 3 );" ) );
292
+ add_action( 'admin_init', create_function( '$a', "remove_action( 'admin_init', '_maybe_update_core' );" ) );
293
+ add_action( 'init', create_function( '$a', "remove_action( 'init', 'wp_version_check' );" ) );
294
+ add_filter( 'pre_option_update_core', create_function( '$a', "return null;" ) );
295
+ remove_action( 'wp_version_check', 'wp_version_check' );
296
+ remove_action( 'admin_init', '_maybe_update_core' );
297
+ add_filter( 'pre_transient_update_core', create_function( '$a', "return null;" ) );
298
+ add_filter( 'pre_site_transient_update_core', create_function( '$a', "return null;" ) );
299
+ }
300
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
301
+ __('Core update notifications are only displayed to administrator users.'),
302
+ __('<p>These notifications are displayed at the top of the screen by the WordPress platform whenever the website was updated or needs an update.</p>
303
+ <p>Currently, these notifications are only displayed to administrator users.</p>')
304
+ );
305
+ }
306
+
307
+ /** Remove plug-ins update notifications from back-end */
308
+ public static function fix_removePluginUpdateNotifications()
309
+ {
310
+ global $wsdPluginAlertsArray;
311
+ $actionName = $wsdPluginAlertsArray['fix_wp_plugins_update_notif']['name'];
312
+ $alertType = $wsdPluginAlertsArray['fix_wp_plugins_update_notif']['type'];
313
+
314
+ /* This check is important so this function will run only if the user enables it. */
315
+ if(! self::isSettingEnabled(__FUNCTION__)){
316
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
317
+ __('Plugins update notifications are displayed to all users'),
318
+ __('<p>These notifications are displayed at the top of the screen by the WordPress platform whenever the blog administrator
319
+ needs to be informed about an available update for a plugin.</p>
320
+ <p>These notifications should only be viewed by the website\'s administrators and not visible to any other users registered with that website.</p>'),
321
+ sprintf(__('<p>This plugin can automatically hide these notifications if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'), 'Remove plug-ins update notifications from back-end')
322
+ );
323
+ return;
324
+ }
325
+
326
+ if (!WsdUtil::isAdministrator())
327
+ {
328
+ add_action( 'admin_init', create_function( '$a', "remove_action( 'admin_init', 'wp_plugin_update_rows' );" ), 2 );
329
+ add_action( 'admin_init', create_function( '$a', "remove_action( 'admin_init', '_maybe_update_plugins' );" ), 2 );
330
+ add_action( 'admin_menu', create_function( '$a', "remove_action( 'load-plugins.php', 'wp_update_plugins' );" ) );
331
+ add_action( 'admin_init', create_function( '$a', "remove_action( 'admin_init', 'wp_update_plugins' );" ), 2 );
332
+ add_action( 'init', create_function( '$a', "remove_action( 'init', 'wp_update_plugins' );" ), 2 );
333
+ add_filter( 'pre_option_update_plugins', create_function( '$a', "return null;" ) );
334
+ remove_action( 'load-plugins.php', 'wp_update_plugins' );
335
+ remove_action( 'load-update.php', 'wp_update_plugins' );
336
+ remove_action( 'admin_init', '_maybe_update_plugins' );
337
+ remove_action( 'wp_update_plugins', 'wp_update_plugins' );
338
+ remove_action( 'load-update-core.php', 'wp_update_plugins' );
339
+ add_filter( 'pre_transient_update_plugins', create_function( '$a', "return null;" ) );
340
+ }
341
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
342
+ __('Plugins update notifications are only displayed to administrator users'),
343
+ __('<p>Currently, these notifications are only displayed to administrator users.</p>')
344
+ );
345
+ }
346
+
347
+ /** Remove themes update notifications from back-end */
348
+ public static function fix_removeThemeUpdateNotifications()
349
+ {
350
+ global $wsdPluginAlertsArray;
351
+ $actionName = $wsdPluginAlertsArray['fix_wp_themes_update_notif']['name'];
352
+ $alertType = $wsdPluginAlertsArray['fix_wp_themes_update_notif']['type'];
353
+
354
+ /* This check is important so this function will run only if the user enables it. */
355
+ if(! self::isSettingEnabled(__FUNCTION__)){
356
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
357
+ __('Themes update notifications are displayed to all users.'),
358
+ __('<p>These notifications are displayed at the top of the screen by the WordPress platform whenever the blog administrator
359
+ needs to be informed about an available update for a theme.</p>
360
+ <p>These notifications should only be viewed by the website\'s administrators and not visible to any other users registered with that website.</p>'),
361
+ sprintf(__('<p>This plugin can automatically hide these notifications if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'), 'Remove themes update notifications from back-end')
362
+ );
363
+ return;
364
+ }
365
+
366
+ if (!WsdUtil::isAdministrator())
367
+ {
368
+ remove_action( 'load-themes.php', 'wp_update_themes' );
369
+ remove_action( 'load-update.php', 'wp_update_themes' );
370
+ remove_action( 'admin_init', '_maybe_update_themes' );
371
+ remove_action( 'wp_update_themes', 'wp_update_themes' );
372
+ remove_action( 'load-update-core.php', 'wp_update_themes' );
373
+ add_filter( 'pre_transient_update_themes', create_function( '$a', "return null;" ) );
374
+ }
375
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
376
+ __('Themes update notifications are only displayed to administrator users'),
377
+ __('<p>Currently, these notifications are only displayed to administrator users.</p>')
378
+ );
379
+ }
380
+
381
+ /** Remove login error notifications from front-end */
382
+ public static function fix_removeLoginErrorNotificationsFrontEnd()
383
+ {
384
+ global $wsdPluginAlertsArray;
385
+ $actionName = $wsdPluginAlertsArray['fix_wp_login_errors']['name'];
386
+ $alertType = $wsdPluginAlertsArray['fix_wp_login_errors']['type'];
387
+
388
+ /* This check is important so this function will run only if the user enables it. */
389
+ if(! self::isSettingEnabled(__FUNCTION__)){
390
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
391
+ __('WordPress login errors are displayed.'),
392
+ __('<p>Every time a failed login is encountered, the WordPress platform generates an error message that is displayed to the user.
393
+ This is a potential security risk because it let\'s the user know of his mistake (be it a wrong user name or password) thus making your
394
+ WordPress website more vulnerable to attacks.</p>
395
+ <p>We strongly recommend you to hide these login error messages from all users to ensure a better security of your blog.</p>'),
396
+ sprintf(__('<p>This plugin can automatically hide these notifications if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'), 'Remove login error notifications from front-end')
397
+ );
398
+ return;
399
+ }
400
+ $str = '<link rel="stylesheet" type="text/css" href="'.WsdUtil::cssUrl('acx-styles-extra.css').'"/>';
401
+ add_action('login_head', create_function('$a', "echo '{$str}';"));
402
+ add_filter('login_errors', create_function('$a', "return null;"));
403
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
404
+ __('WordPress login errors are not displayed.'),
405
+ __('<p>Currently, these errors are hidden to all users.</p>')
406
+ );
407
+ }
408
+
409
+ /** Hide admin notifications for non admins. */
410
+ public static function fix_hideAdminNotifications()
411
+ {
412
+ global $wsdPluginAlertsArray;
413
+ $actionName = $wsdPluginAlertsArray['fix_wp_admin_notices']['name'];
414
+ $alertType = $wsdPluginAlertsArray['fix_wp_admin_notices']['type'];
415
+
416
+ /* This check is important so this function will run only if the user enables it. */
417
+ if(! self::isSettingEnabled(__FUNCTION__)){
418
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
419
+ __('WordPress admin notifications are displayed to all users.'),
420
+ __('<p>These notifications are displayed at the top of the screen by the WordPress platform whenever the blog administrator
421
+ needs to be informed about an event that has occurred inside WordPress, it could be about an available update for the
422
+ WordPress platform, a plugin or a theme that was updated or needs an update or to be configured, etc.</p>
423
+ <p>These notifications should only be viewed by the website\'s administrators and not visible to any other users registered with that website.</p>'),
424
+ sprintf(__('<p>This plugin can automatically hide these notifications if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'), 'Hide admin notifications for non admins')
425
+ );
426
+ return;
427
+ }
428
+
429
+ if (!WsdUtil::isAdministrator())
430
+ {
431
+ add_action('init', create_function('$a', "remove_action('init', 'wp_version_check');"), 2);
432
+ add_filter('pre_option_update_core', create_function('$a', "return null;"));
433
+ }
434
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
435
+ __('WordPress admin notifications are only displayed to administrator users.'),
436
+ __('<p>These notifications are displayed at the top of the screen by the WordPress platform whenever the blog administrator
437
+ needs to be informed about an event that has occurred inside WordPress, it could be about an available update for the
438
+ WordPress platform, a plugin or a theme that was updated or needs an update or to be configured, etc.</p>
439
+ <p>Currently, these notifications are displayed only to administrator users.</p>'));
440
+ }
441
+
442
+ /** Try to create the index.php file in the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listing */
443
+ public static function fix_preventDirectoryListing()
444
+ {
445
+ global $wsdPluginAlertsArray;
446
+
447
+ $actionName = $wsdPluginAlertsArray['fix_wp_dir_listing']['name'];
448
+ $alertType = $wsdPluginAlertsArray['fix_wp_dir_listing']['type'];
449
+ /* This check is important so this function will run only if the user enables it. */
450
+ if(! self::isSettingEnabled(__FUNCTION__)){
451
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
452
+ __('Directory listing check is disabled. This option should be enabled.'),
453
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
454
+ The specific risks and consequences vary depending on which files are listed and accessible.
455
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>'),
456
+ sprintf(__('<p>This plugin can automatically create an empty <strong>index.php</strong> file in the following directories: wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads if
457
+ the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
458
+ 'Try to create the index.php file in the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listing')
459
+ );
460
+ return;
461
+ }
462
+ else {
463
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
464
+ __('Directory listing check is enabled.'),
465
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
466
+ The specific risks and consequences vary depending on which files are listed and accessible.
467
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
468
+ );
469
+ }
470
+
471
+ $data = '<?php exit;?>';
472
+ $contentDir = trailingslashit(WP_CONTENT_DIR);
473
+ $pluginsDir = $contentDir.'plugins';
474
+ $themesDir = $contentDir.'themes';
475
+ $uploadsDir = $contentDir.'uploads';
476
+
477
+ $actionName = $wsdPluginAlertsArray['fix_wp_index_content']['name'];
478
+ $alertType = $wsdPluginAlertsArray['fix_wp_index_content']['type'];
479
+ $file = $contentDir.'/index.php';
480
+ if(is_dir($contentDir)){
481
+ if(is_file($file)){
482
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
483
+ sprintf(__('<strong>"%s"</strong> directory is secure from directory listing.'),'/wp-content'),
484
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
485
+ The specific risks and consequences vary depending on which files are listed and accessible.
486
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
487
+ );
488
+ }
489
+ else {
490
+ if (is_writable($contentDir))
491
+ {
492
+ WsdUtil::writeFile($file,$data);
493
+ @chmod($file,'0644');
494
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
495
+ sprintf(__('<strong>"%s"</strong> directory is secure from directory listing.'),'/wp-content'),
496
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
497
+ The specific risks and consequences vary depending on which files are listed and accessible.
498
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
499
+ );
500
+ }
501
+ else {
502
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
503
+ sprintf(__('<strong>"%s"</strong> directory is not secure from directory listing.'),'/wp-content'),
504
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
505
+ The specific risks and consequences vary depending on which files are listed and accessible.
506
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>'),
507
+ sprintf(__('<p>This plugin can automatically create an empty <strong>index.php</strong> file in the following directories: wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads if
508
+ the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
509
+ 'Try to create the index.php file in the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listing')
510
+ );
511
+ }
512
+ }
513
+ }
514
+
515
+ $actionName = $wsdPluginAlertsArray['fix_wp_index_plugins']['name'];
516
+ $alertType = $wsdPluginAlertsArray['fix_wp_index_plugins']['type'];
517
+ $file = $pluginsDir.'/index.php';
518
+ if(is_dir($pluginsDir)){
519
+ if(is_file($file)){
520
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
521
+ sprintf(__('<strong>"%s"</strong> directory is not secure from directory listing.'),'/wp-content/plugins'),
522
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
523
+ The specific risks and consequences vary depending on which files are listed and accessible.
524
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
525
+ );
526
+ }
527
+ else {
528
+ if (is_writable($pluginsDir))
529
+ {
530
+ WsdUtil::writeFile($file,$data);
531
+ @chmod($file,'0644');
532
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
533
+ sprintf(__('<strong>"%s"</strong> directory is not secure from directory listing.'),'/wp-content/plugins'),
534
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
535
+ The specific risks and consequences vary depending on which files are listed and accessible.
536
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
537
+ );
538
+ }
539
+ else {
540
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
541
+ sprintf(__('<strong>"%s"</strong> directory is not secure from directory listing.'),'/wp-content/plugins'),
542
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
543
+ The specific risks and consequences vary depending on which files are listed and accessible.
544
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>'),
545
+ sprintf(__('<p>This plugin can automatically create an empty <strong>index.php</strong> file in the following directories: wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads if
546
+ the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
547
+ 'Try to create the index.php file in the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listing')
548
+ );
549
+ }
550
+ }
551
+ }
552
+
553
+ $actionName = $wsdPluginAlertsArray['fix_wp_index_themes']['name'];
554
+ $alertType = $wsdPluginAlertsArray['fix_wp_index_themes']['type'];
555
+ $file = $themesDir.'/index.php';
556
+ if(is_dir($themesDir)){
557
+ if(is_file($file)){
558
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
559
+ sprintf(__('<strong>"%s"</strong> directory is not secure from directory listing.'),'/wp-content/themes'),
560
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
561
+ The specific risks and consequences vary depending on which files are listed and accessible.
562
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
563
+ );
564
+ }
565
+ else {
566
+ if (is_writable($themesDir))
567
+ {
568
+ WsdUtil::writeFile($file,$data);
569
+ @chmod($file,'0644');
570
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
571
+ sprintf(__('<strong>"%s"</strong> directory is not secure from directory listing.'),'/wp-content/themes'),
572
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
573
+ The specific risks and consequences vary depending on which files are listed and accessible.
574
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
575
+ );
576
+ }
577
+ else {
578
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
579
+ sprintf(__('<strong>"%s"</strong> directory is not secure from directory listing.'),'/wp-content/themes'),
580
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
581
+ The specific risks and consequences vary depending on which files are listed and accessible.
582
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>'),
583
+ sprintf(__('<p>This plugin can automatically create an empty <strong>index.php</strong> file in the following directories: wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads if
584
+ the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
585
+ 'Try to create the index.php file in the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listing')
586
+ );
587
+ }
588
+ }
589
+ }
590
+
591
+ $actionName = $wsdPluginAlertsArray['fix_wp_index_uploads']['name'];
592
+ $alertType = $wsdPluginAlertsArray['fix_wp_index_uploads']['type'];
593
+ $file = $uploadsDir.'/index.php';
594
+ if(is_dir($uploadsDir)){
595
+ if(is_file($file)){
596
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
597
+ sprintf(__('<strong>"%s"</strong> directory is not secure from directory listing.'),'/wp-content/uploads'),
598
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
599
+ The specific risks and consequences vary depending on which files are listed and accessible.
600
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
601
+ );
602
+ }
603
+ else {
604
+ if (is_writable($uploadsDir))
605
+ {
606
+ WsdUtil::writeFile($file,$data);
607
+ @chmod($file,'0644');
608
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
609
+ sprintf(__('<strong>"%s"</strong> directory is not secure from directory listing.'),'/wp-content/uploads'),
610
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
611
+ The specific risks and consequences vary depending on which files are listed and accessible.
612
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>')
613
+ );
614
+ }
615
+ else {
616
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
617
+ sprintf(__('<strong>"%s"</strong> directory is not secure from directory listing.'),'/wp-content/uploads'),
618
+ __('<p>A directory listing provides an attacker with the complete index of all the resources located inside of the directory.
619
+ The specific risks and consequences vary depending on which files are listed and accessible.
620
+ Therefore, it is important to protect your directories by having an empty index.php or index.htm file inside them.</p>'),
621
+ sprintf(__('<p>This plugin can automatically create an empty <strong>index.php</strong> file in the following directories: wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads if
622
+ the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'),
623
+ 'Try to create the index.php file in the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listing')
624
+ );
625
+ }
626
+ }
627
+ }
628
+ }
629
+
630
+ /** Remove the version parameter from urls */
631
+ public static function fix_removeWpVersionFromLinks($src = '')
632
+ {
633
+ global $wsdPluginAlertsArray;
634
+ $actionName = $wsdPluginAlertsArray['fix_remove_wp_version_links']['name'];
635
+ $alertType = $wsdPluginAlertsArray['fix_remove_wp_version_links']['type'];
636
+
637
+ /* This check is important so this function will run only if the user enables it. */
638
+ if(! self::isSettingEnabled(__FUNCTION__)){
639
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_CRITICAL,
640
+ __('WordPress version is displayed in links for all users'),
641
+ __('<p>By default, WordPress will display the current version in links to javascript scripts or stylesheets.
642
+ Therefore, if anyone has access to this information it might be a security risk because if a hacker knows which version of WordPress a website is running,
643
+ it can make it easier for him to target a known WordPress security issue.</p>'),
644
+ sprintf(__('<p>This plugin can automatically hide the WordPress version from links if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.</p>'), 'Remove the version parameter from urls')
645
+ );
646
+ return;
647
+ }
648
+
649
+ if (!WsdUtil::isAdministrator())
650
+ {
651
+ add_filter('script_loader_src', array('WsdSecurityHelper', '__removeWpVersionFromLinks'));
652
+ add_filter('style_loader_src', array('WsdSecurityHelper', '__removeWpVersionFromLinks'));
653
+ }
654
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
655
+ __('WordPress version displayed in links only for administrator users.'),
656
+ __('<p>By default, WordPress will display the current version in links to javascript scripts or stylesheets.
657
+ Therefore, if anyone has access to this information it might be a security risk because if a hacker knows which version of WordPress a website is running,
658
+ it can make it easier for him to target a known WordPress security issue.</p>')
659
+ );
660
+ }
661
+
662
+ /** Empty the content of the readme.html file from the root directory. */
663
+ public static function fix_emptyReadmeFileFromRoot()
664
+ {
665
+ global $wsdPluginAlertsArray;
666
+
667
+ // if the file is 404 or not readable or empty, there is no need to display the alert
668
+ $filePath = trailingslashit(ABSPATH).'readme.html';
669
+ if(! is_file($filePath)){ return; }
670
+ if(! is_readable($filePath)) { return; }
671
+ $fsize = @filesize($filePath);
672
+ if(false !== $fsize && $fsize == 0) { return; }
673
+
674
+ $actionName = $wsdPluginAlertsArray['fix_empty_root_readme_file']['name'];
675
+ $alertType = $wsdPluginAlertsArray['fix_empty_root_readme_file']['type'];
676
+ /* This check is important so this function will run only if the user enables it. */
677
+ if(! self::isSettingEnabled(__FUNCTION__)){
678
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
679
+ sprintf(__('Clearing the content of the <strong>"%s"</strong> file from the <strong>"%s"</strong> directory is disabled.'), 'readme.html', 'root'),
680
+ __('<p>A default WordPress installation contains a readme.html file. This file is a simple html file that does not contain executable content that can be exploited by hackers or malicious users.
681
+ Still, this file can provide hackers the version of your WordPress installation, therefore it is important to either delete this file or make it inaccessible for your visitors.</p>'),
682
+ sprintf(__('<p>This plugin can automatically delete its content (assuming the file exists) if the option <strong>"%s"</strong> is checked on the plugin\'s settings page.
683
+ You can also delete this file manually by connecting to your website through an FTP connection.</p>'), 'Empty the content of the readme.html file from the root directory')
684
+ );
685
+ return;
686
+ }
687
+ else {
688
+ // clear the content of the file
689
+ $result = file_put_contents($filePath,'');
690
+ // failure
691
+ if(false === $result){
692
+ // todo
693
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
694
+ sprintf(__('The content of the <strong>"%s"</strong> file from the <strong>"%s"</strong> directory could not be deleted.'), 'readme.html', 'root'),
695
+ __('<p>A default WordPress installation contains a readme.html file. This file is a simple html file that does not contain executable content that can be exploited by hackers or malicious users.
696
+ Still, this file can provide hackers the version of your WordPress installation, therefore it is important to either delete this file or make it inaccessible for your visitors.</p>'),
697
+ __('<p>We have encountered an error while trying to delete the content of this file, thus you will have to manually delete it or make it inaccessible from your visitors by setting the file permissions to <strong>0440</strong> or lower.</p>')
698
+ );
699
+ return;
700
+ }
701
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_INFO,
702
+ __('The content of the readme.html file from the root directory has been deleted.'),
703
+ __('<p>A default WordPress installation contains a readme.html file. This file is a simple html file that does not contain executable content that can be exploited by hackers or malicious users.
704
+ Still, this file can provide hackers the version of your WordPress installation, therefore it is important to either delete this file or make it inaccessible for your visitors.</p>')
705
+ );
706
+ }
707
+
708
+ }
709
+
710
+ }
711
+
712
+ class WsdSecurityHelper
713
+ {
714
+ /**
715
+ * @private
716
+ * @param $src
717
+ * @return mixed
718
+ */
719
+ public static function __removeWpVersionFromLinks($src)
720
+ {
721
+ // Just the URI without the query string.
722
+ $src = preg_replace("/\?ver=(.*)/mi", '', $src);
723
+ return $src;
724
+ }
725
+
726
+ }
res/inc/WsdUtil.php ADDED
@@ -0,0 +1,601 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! defined('WSS_PLUGIN_PREFIX')) return;
2
+
3
+ /**
4
+ * Class WsdUtil
5
+ * Static class. Provides utility methods for various tasks
6
+ */
7
+ class WsdUtil
8
+ {
9
+ /**
10
+ * @return bool
11
+ * Convenient method to check whether or not the plugin's resources can be loaded
12
+ */
13
+ public static function canLoad() { return ((false === ($pos = stripos($_SERVER['REQUEST_URI'], WSS_PLUGIN_PREFIX))) ? false : true); }
14
+ public static function cssUrl($fileName){ return WSS_PLUGIN_URL.'res/css/'.$fileName; }
15
+ public static function imageUrl($fileName){ return WSS_PLUGIN_URL.'res/images/'.$fileName; }
16
+ public static function jsUrl($fileName) { return WSS_PLUGIN_URL.'res/js/'.$fileName; }
17
+ public static function resUrl() { return WSS_PLUGIN_URL.'res/'; }
18
+ public static function includePage($fileName)
19
+ {
20
+ if(! self::canLoad()) { return; }
21
+ $dirPath = WSS_PLUGIN_DIR.'res/pages/';
22
+ if(! is_dir($dirPath)) { return; }
23
+ if(! is_readable($dirPath)) { return; }
24
+ $fname = $dirPath.$fileName;
25
+ if(false !== ($pos = strpos($fname, '../')) || false !== ($pos = strpos($fname, './'))){ return; }
26
+ if(! is_file($fname) || ! is_readable($fname)) { return; }
27
+ include($fname);
28
+ }
29
+
30
+ /**
31
+ * @public
32
+ * @static
33
+ * Load the text domain
34
+ * @return void
35
+ */
36
+ public static function loadTextDomain(){ if ( function_exists('load_plugin_textdomain') ) { load_plugin_textdomain(WSS_PLUGIN_TEXT_DOMAIN, false, WSS_PLUGIN_DIR.'res/languages/'); } }
37
+
38
+ /**
39
+ * @public
40
+ * @static
41
+ * @uses self::checkFileName()
42
+ *
43
+ * Retrieve the content of the specified template file.
44
+ *
45
+ * @param type $fileName the name of the template file to load.
46
+ * Without the ".php" file extension.
47
+ * @param array $data The data to send to the template file
48
+ * @return string The parsed content of the template file
49
+ */
50
+ public static function loadTemplate($fileName, array $data = array())
51
+ {
52
+ self::checkFileName($fileName);
53
+ $str = '';
54
+ $file = WSS_PLUGIN_DIR.'res/pages/tpl/'.$fileName.'.php';
55
+ if (is_file($file))
56
+ {
57
+ ob_start();
58
+ if (!empty($data)) {
59
+ extract($data);
60
+ }
61
+ include($file);
62
+ $str = ob_get_contents();
63
+ ob_end_clean();
64
+ }
65
+ return $str;
66
+ }
67
+
68
+ /**
69
+ * @public
70
+ * @static
71
+ * @uses wp_die()
72
+ *
73
+ * Check the specified file name for directory traversal attacks.
74
+ * Exits the script if the "..[/]" is found in the $fileName.
75
+ *
76
+ * @param string $fileName The name of the file to check
77
+ * @return void
78
+ */
79
+ public static function checkFileName($fileName)
80
+ {
81
+ $fileName = trim($fileName);
82
+ //@@ Check for directory traversal attacks
83
+ if (preg_match("/\.\.\//",$fileName)) {
84
+ wp_die('Invalid Request!');
85
+ }
86
+ }
87
+
88
+ /**
89
+ * @public
90
+ * @static
91
+ *
92
+ * Attempts to write the provided $data into the specified $file
93
+ * using either file_put_contents or fopen/fwrite functions (whichever is available).
94
+ *
95
+ * @param string $file The path to the file
96
+ * @param string $data The content to write into the file
97
+ * @param resource $fh The file handle to use if fopen function is available. Optional, defaults to null
98
+ *
99
+ * @return int The number of bytes written to the file, otherwise -1.
100
+ */
101
+ public static function writeFile($file, $data, $fh = null)
102
+ {
103
+ if(! is_null($fh) && is_resource($fh)){
104
+ fwrite($fh,$data);
105
+ return strlen($data);
106
+ }
107
+ else {
108
+ if (function_exists('file_put_contents')) {
109
+ return file_put_contents($file,$data);
110
+ }
111
+ }
112
+ return -1;
113
+ }
114
+
115
+ /**
116
+ * @public
117
+ * @param array $acxFileList
118
+ * Apply the suggested permissions for the list of files
119
+ * provided in the global $acxFileList array.
120
+ * @return array array('success' => integer, 'failed' => integer)
121
+ */
122
+ public static function changeFilePermissions($acxFileList)
123
+ {
124
+ if (empty($acxFileList)) {
125
+ return array();
126
+ }
127
+ // chmod doesn't work on windows... :/
128
+ if (self::isWinOs()) {
129
+ return array();
130
+ }
131
+
132
+ $s = $f = 0;
133
+ foreach($acxFileList as $k => $v)
134
+ {
135
+ $filePath = $v['filePath'];
136
+ $sp = $v['suggestedPermissions'];
137
+ $sp = (is_string($sp) ? octdec($sp) : $sp);
138
+
139
+ //@ include directories too
140
+ if (file_exists($filePath))
141
+ {
142
+ if (false !== @chmod($filePath, $sp)) {
143
+ $s++;
144
+ }
145
+ else { $f++; }
146
+ }
147
+ else {
148
+ // if no path provided
149
+ if(empty($filePath)){
150
+ $f++;
151
+ continue;
152
+ }
153
+ // try to create the missing files
154
+ if(false !== file_put_contents($filePath, '')){
155
+ if (false !== @chmod($filePath, $sp)) {
156
+ $s++;
157
+ }
158
+ else { $f++; }
159
+ }
160
+ else { $f++; }
161
+ }
162
+ }
163
+ return array('success' => $s, 'failed' => $f);
164
+ }
165
+
166
+ public static function getFilePermissions($filePath)
167
+ {
168
+ if (!function_exists('fileperms')) {
169
+ return '-1';
170
+ }
171
+ if (!file_exists($filePath)) {
172
+ return '-1';
173
+ }
174
+ clearstatcache();
175
+ return substr(sprintf("%o", fileperms($filePath)), -4);
176
+ }
177
+
178
+ public static function normalizePath($path) {
179
+ return str_replace('\\', '/', $path);
180
+ }
181
+
182
+ public static function isWinOs(){
183
+ return ((strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? true : false);
184
+ }
185
+
186
+ /**
187
+ * Check to see whether or not the current user is an administrator
188
+ * @return bool
189
+ */
190
+ public static function isAdministrator(){
191
+ self::loadPluggable();
192
+ return user_can(wp_get_current_user(),'update_core');
193
+ }
194
+
195
+ /**
196
+ * Check to see whether or not the specified table exists in the database
197
+ * @param $tableName The table to check for existence. It requires the full qualified name of the table
198
+ * - which means the prefix must be there as well.
199
+ * @return bool
200
+ */
201
+ public static function tableExists($tableName)
202
+ {
203
+ global $wpdb;
204
+ $result = $wpdb->get_var("SHOW TABLES LIKE '$tableName'");
205
+ return (is_null($result) ? false : true);
206
+ }
207
+
208
+ /**
209
+ * @public
210
+ * @uses wp_die()
211
+ *
212
+ * Backup the database and save the script to the plug-in's backups directory.
213
+ * This directory must be writable!
214
+ *
215
+ * @return string The name of the generated backup file or empty string on failure.
216
+ */
217
+ public static function backupDatabase()
218
+ {
219
+ if (!is_writable(WSS_PLUGIN_BACKUPS_DIR))
220
+ {
221
+ $s = sprintf(__('The %s directory <strong>MUST</strong> be writable for this feature to work!'), WSS_PLUGIN_BACKUPS_DIR);
222
+ wp_die($s);
223
+ }
224
+
225
+ $link = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
226
+ if (!$link) {
227
+ wp_die(__('Error: Cannot connect to database!'));
228
+ }
229
+ if (!mysql_select_db(DB_NAME,$link)) {
230
+ wp_die(__('Error: Could not select the database!'));
231
+ }
232
+
233
+ //get all of the tables
234
+ $tables = array();
235
+ $result = mysql_query('SHOW TABLES');
236
+ while($row = mysql_fetch_row($result))
237
+ {
238
+ if(! empty($row[0])){
239
+ $tables[] = $row[0];
240
+ }
241
+ }
242
+
243
+ if (empty($tables))
244
+ {
245
+ wp_die(__('Could not retrieve the list of tables from the database!'));
246
+ }
247
+
248
+ $h = null;
249
+ $time = gmdate("m-j-Y-h-i-s", time());
250
+ $rand = self::makeSeed()+rand(12131, 9999999);
251
+ $fname = 'bck_'.$time.'_'.$rand.'.sql';
252
+ $filePath = WSS_PLUGIN_BACKUPS_DIR.$fname;
253
+
254
+ if(function_exists('fopen') && function_exists('fwrite') && function_exists('fclose'))
255
+ {
256
+ $h = fopen($filePath,'a+');
257
+ self::__doBackup($filePath, $tables, $h);
258
+ fclose($h);
259
+ }
260
+ else {
261
+ if(function_exists('file_put_contents')){
262
+ self::__doBackup($filePath, $tables, $h);
263
+ }
264
+ }
265
+ if(! is_file($filePath)){
266
+ return '';
267
+ }
268
+ $fs = @filesize($filePath);
269
+ return (($fs > 0) ? $fname : '');
270
+ }
271
+
272
+ /**
273
+ * @private
274
+ */
275
+ private static function __doBackup($filePath, array $tables = array(), $h = null)
276
+ {
277
+ $data = 'CREATE DATABASE IF NOT EXISTS '.DB_NAME.';'.PHP_EOL;
278
+ $data .= 'USE '.DB_NAME.';'.PHP_EOL;
279
+ self::writeFile($filePath, $data, $h);
280
+
281
+ //cycle through
282
+ foreach($tables as $table)
283
+ {
284
+ $result = mysql_query('SELECT * FROM '.$table);
285
+ $num_fields = mysql_num_fields($result);
286
+
287
+ $data = 'DROP TABLE IF EXISTS '.$table.';';
288
+ $row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));
289
+ $data .= $row2[1].';'.PHP_EOL;
290
+ self::writeFile($filePath, $data, $h);
291
+
292
+ for ($i = 0; $i < $num_fields; $i++)
293
+ {
294
+ while($row = mysql_fetch_row($result))
295
+ {
296
+ $data = 'INSERT INTO '.$table.' VALUES(';
297
+ for($j=0; $j<$num_fields; $j++)
298
+ {
299
+ $row[$j] = addslashes($row[$j]);
300
+ $row[$j] = @preg_replace("/\n(\s*\n)+/",PHP_EOL,$row[$j]);
301
+ if (isset($row[$j])) { $data .= '"'.$row[$j].'"' ; } else { $data .= '""'; }
302
+ if ($j<($num_fields-1)) { $data .= ','; }
303
+ }
304
+ $data .= ");".PHP_EOL;
305
+ self::writeFile($filePath, $data, $h);
306
+ }
307
+ } //#! end for
308
+ } //#! end foreach
309
+ }
310
+
311
+
312
+ /**
313
+ * @public
314
+ * Retrieve the list of all available backup files from the backups directory
315
+ * @return array
316
+ */
317
+ public static function getAvailableBackupFiles()
318
+ {
319
+ $files = glob(WSS_PLUGIN_BACKUPS_DIR.'*.sql');
320
+ if (empty($files)) { return array();}
321
+ return array_map('basename', $files/*, array('.sql')*/);
322
+ }
323
+
324
+
325
+ /**
326
+ * @public
327
+ * Create a number
328
+ * @return double
329
+ */
330
+ public static function makeSeed()
331
+ {
332
+ list($usec, $sec) = explode(' ', microtime());
333
+ return (float)$sec + ((float)$usec * 100000);
334
+ }
335
+
336
+
337
+ /**
338
+ * @public
339
+ * @global object $wpdb
340
+ * Get the list of tables to modify
341
+ * @return array
342
+ */
343
+ public static function getTablesToAlter()
344
+ {
345
+ global $wpdb;
346
+ return $wpdb->get_results("SHOW TABLES LIKE '".$GLOBALS['table_prefix']."%'", ARRAY_N);
347
+ }
348
+
349
+
350
+
351
+ /**
352
+ * @public
353
+ * @global object $wpdb
354
+ * Rename tables from database
355
+ * @param array the list of tables to rename
356
+ * @param string $currentPrefix the current prefix in use
357
+ * @param string $newPrefix the new prefix to use
358
+ * @return array
359
+ */
360
+ public static function renameTables($tables, $currentPrefix, $newPrefix)
361
+ {
362
+ global $wpdb;
363
+ $changedTables = array();
364
+ foreach ($tables as $k=>$table){
365
+ $tableOldName = $table[0];
366
+ // Try to rename the table
367
+ $tableNewName = substr_replace($tableOldName, $newPrefix, 0, strlen($currentPrefix));
368
+ // Try to rename the table
369
+ $wpdb->query("RENAME TABLE `{$tableOldName}` TO `{$tableNewName}`");
370
+ array_push($changedTables, $tableNewName);
371
+ }
372
+ return $changedTables;
373
+ }
374
+
375
+
376
+
377
+ /**
378
+ * @public
379
+ * @global object $wpdb
380
+ * Rename some fields from options & usermeta tables in order to reflect the prefix change
381
+ * @param string $oldPrefix the existent db prefix
382
+ * @param string $newPrefix the new prefix to use
383
+ * @return string
384
+ */
385
+ public static function renameDbFields($oldPrefix,$newPrefix)
386
+ {
387
+ global $wpdb;
388
+ $str = '';
389
+ if (false === $wpdb->query("UPDATE {$newPrefix}options SET option_name='{$newPrefix}user_roles' WHERE option_name='{$oldPrefix}user_roles';")) {
390
+ $str .= '<br/>'.sprintf(__('Changing value: %suser_roles in table <strong>%soptions</strong>: <span style="color:#ff0000;">Failed</span>'),$newPrefix, $newPrefix);
391
+ }
392
+ $query = 'UPDATE '.$newPrefix.'usermeta
393
+ SET meta_key = CONCAT(replace(left(meta_key, ' . strlen($oldPrefix) . "), '{$oldPrefix}', '{$newPrefix}'), SUBSTR(meta_key, " . (strlen($oldPrefix) + 1) . "))
394
+ WHERE
395
+ meta_key IN ('{$oldPrefix}autosave_draft_ids', '{$oldPrefix}capabilities', '{$oldPrefix}metaboxorder_post', '{$oldPrefix}user_level', '{$oldPrefix}usersettings',
396
+ '{$oldPrefix}usersettingstime', '{$oldPrefix}user-settings', '{$oldPrefix}user-settings-time', '{$oldPrefix}dashboard_quick_press_last_post_id')";
397
+
398
+ if (false === $wpdb->query($query)) {
399
+ $str .= '<br/>'.sprintf(__('Changing values in table <strong>%susermeta</strong>: <span style="color:#ff0000;">Failed</span>'), $newPrefix);
400
+ }
401
+ if (!empty($str)) {
402
+ $str = __('Changing database prefix').': '.$str;
403
+ }
404
+ return $str;
405
+ }
406
+
407
+
408
+
409
+ /**
410
+ * @public
411
+ * Update the wp-config file to reflect the table prefix change.
412
+ * The wp file must be writable for this operation to work!
413
+ *
414
+ * @param string $wsd_wpConfigFile The path to the wp-config file
415
+ * @param string $newPrefix The new prefix to use instead of the old one
416
+ * @return int the number of bytes written to te file or -1 on error
417
+ */
418
+ public static function updateWpConfigTablePrefix($wsd_wpConfigFile, $newPrefix)
419
+ {
420
+ // If file is not writable...
421
+ if (!is_writable($wsd_wpConfigFile)){
422
+ return -1;
423
+ }
424
+
425
+ // We need the 'file' function...
426
+ if (!function_exists('file')) {
427
+ return -1;
428
+ }
429
+
430
+ // Try to update the wp-config file
431
+ $lines = file($wsd_wpConfigFile);
432
+ $fcontent = '';
433
+ $result = -1;
434
+ foreach($lines as $line)
435
+ {
436
+ $line = ltrim($line);
437
+ if (!empty($line)){
438
+ if (strpos($line, '$table_prefix') !== false){
439
+ $line = preg_replace("/=(.*)\;/", "= '".$newPrefix."';", $line);
440
+ }
441
+ }
442
+ $fcontent .= $line;
443
+ }
444
+ if (!empty($fcontent))
445
+ {
446
+ // Save wp-config file
447
+ $result = self::writeFile($wsd_wpConfigFile, $fcontent);
448
+ }
449
+ return $result;
450
+ }
451
+
452
+
453
+
454
+ private static $_pluginID = 'acx_plugin_dashboard_widget';
455
+
456
+ /**
457
+ * @public
458
+ * @static
459
+ * @const WSS_PLUGIN_BLOG_FEED
460
+ * Retrieve and display a list of links for an existing RSS feed, limiting the selection to the 5 most recent items.
461
+ * @return void
462
+ */
463
+ public static function displayDashboardWidget()
464
+ {
465
+ if ($_SERVER['REQUEST_METHOD'] == 'POST')
466
+ {
467
+ $opt = get_option('WSD-RSS-WGT-DISPLAY');
468
+ if (empty($opt) || ($opt == 'no')) {
469
+ update_option('WSD-RSS-WGT-DISPLAY', 'no');
470
+ self::_hideDashboardWidget();
471
+ return;
472
+ }
473
+ }
474
+
475
+ //@ flag
476
+ $run = false;
477
+
478
+ //@ check cache
479
+ $optData = get_option('wsd_feed_data');
480
+ if (! empty($optData))
481
+ {
482
+ if (is_object($optData))
483
+ {
484
+ $lastUpdateTime = @$optData->expires;
485
+ // invalid cache
486
+ if (empty($lastUpdateTime)) { $run = true; }
487
+ else
488
+ {
489
+ $nextUpdateTime = $lastUpdateTime+(24*60*60);
490
+ if ($nextUpdateTime >= $lastUpdateTime)
491
+ {
492
+ $data = @$optData->data;
493
+ if (empty($data)) { $run = true; }
494
+ else {
495
+ // still a valid cache
496
+ echo $data;
497
+ return;
498
+ }
499
+ }
500
+ else { $run = true; }
501
+ }
502
+ }
503
+ else { $run = true; }
504
+ }
505
+ else { $run = true; }
506
+
507
+ if (!$run) { return; }
508
+
509
+ $rss = fetch_feed(WSS_PLUGIN_BLOG_FEED);
510
+
511
+ $out = '';
512
+ if (is_wp_error( $rss ) )
513
+ {
514
+ $out = '<li>'.__('An error has occurred while trying to load the rss feed!').'</li>';
515
+ echo $out;
516
+ return;
517
+ }
518
+ else
519
+ {
520
+ // Limit to 5 entries.
521
+ $maxitems = $rss->get_item_quantity(5);
522
+
523
+ // Build an array of all the items,
524
+ $rss_items = $rss->get_items(0, $maxitems);
525
+
526
+ $out .= '<ul>';
527
+ if ($maxitems == 0)
528
+ {
529
+ $out.= '<li>'.__('There are no entries for this rss feed!').'</li>';
530
+ }
531
+ else
532
+ {
533
+ foreach ( $rss_items as $item ) :
534
+ $url = esc_url($item->get_permalink());
535
+ $out.= '<li>';
536
+ $out.= '<h4><a href="'.$url.'" target="_blank" title="Posted on '.$item->get_date('F j, Y | g:i a').'">';
537
+ $out.= esc_html( $item->get_title() );
538
+ $out.= '</a></h4>';
539
+ $out.= '<p>';
540
+ $d = utf8_decode( $item->get_description());
541
+ $p = substr($d, 0, 120).' <a href="'.$url.'" target="_blank" title="Read all article">[...]</a>';
542
+ $out.= $p;
543
+ $out.= '</p>';
544
+ $out.= '</li>';
545
+ endforeach;
546
+ }
547
+ $out.= '</ul>';
548
+ $out .= '<div style="border-top: solid 1px #ccc; margin-top: 4px; padding: 2px 0;">';
549
+ $out .= '<p style="margin: 5px 0 0 0; padding: 0 0; line-height: normal; overflow: hidden;">';
550
+ $out .= '<a href="http://feeds.acunetix.com/acunetixwebapplicationsecurityblog"
551
+ style="float: left; display: block; width: 50%; text-align: right; margin-left: 30px;
552
+ padding-right: 22px; background: url('.self::imageUrl('rss.png').') no-repeat right center;"
553
+ target="_blank">'.__('Follow us on RSS').'</a>';
554
+ $out .= '</p>';
555
+ $out .= '</div>';
556
+ }
557
+
558
+ // Update cache
559
+ $obj = new stdClass();
560
+ $obj->expires = time();
561
+ $obj->data = $out;
562
+ update_option('wsd_feed_data', $obj);
563
+
564
+ echo $out;
565
+ }
566
+
567
+ /**
568
+ * @public
569
+ * @static
570
+ * Add the rss widget to dashboard
571
+ * @return void
572
+ */
573
+ public static function addDashboardWidget()
574
+ {
575
+ $rssWidgetData = get_option('WSD-RSS-WGT-DISPLAY');
576
+ if(($rssWidgetData == 'yes')){
577
+ wp_add_dashboard_widget('acx_plugin_dashboard_widget', __('WebsiteDefender news and updates'), array(get_class(),'displayDashboardWidget'));
578
+ }
579
+ }
580
+ /**
581
+ * Hide the dashboard rss widget
582
+ * @static
583
+ * @public
584
+ */
585
+ public static function _hideDashboardWidget() { echo '<script>document.getElementById("'.self::$_pluginID.'").style.display = "none";</script>'; }
586
+
587
+
588
+ public static function loadPluggable(){ @require_once(ABSPATH.'wp-includes/pluggable.php'); }
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+
597
+
598
+
599
+
600
+
601
+ }
res/inc/WsdWatch.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! defined('WSS_PLUGIN_PREFIX')) return;
2
+ /**
3
+ * Class WsdWatch
4
+ * Static class. Provides common methods to be used to monitor website activity.
5
+ */
6
+ class WsdWatch extends WsdPlugin
7
+ {
8
+ /*
9
+ * PUBLIC METHODS
10
+ * ==============================================
11
+ */
12
+
13
+ public static function userPasswordUpdate(){
14
+ add_action('edit_user_profile_update', array(get_class(), '_watchUserInfoUpdated'));
15
+ add_action('personal_options_update', array(get_class(), '_watchUserInfoUpdated'));
16
+ }
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+ /*
25
+ * PRIVATE METHODS
26
+ * ==============================================
27
+ */
28
+
29
+ // returns array(userName, userRole)
30
+ public static function _getUserInfo($userID)
31
+ {
32
+ global $wpdb;
33
+
34
+ $t = $wpdb->prefix.'users';
35
+ $username = $wpdb->get_var("SELECT user_login FROM $t WHERE ID=$userID");
36
+ $user = new WP_User( $userID );
37
+ $userRole = (empty($user->roles[0]) ? '' : $user->roles[0]);
38
+ return array(
39
+ 'userName' => $username,
40
+ 'userRole' => $userRole
41
+ );
42
+ }
43
+ /**
44
+ * @internal
45
+ * @param $userID
46
+ */
47
+ public static function _watchUserInfoUpdated($userID)
48
+ {
49
+ // If an admin user's password has been updated
50
+ if(! empty($_POST['pass1'])){
51
+ $userInfo = self::_getUserInfo($userID);
52
+ $userName = $userInfo['userName'];
53
+ $userRole = $userInfo['userRole'];
54
+ if($userRole == 'administrator')
55
+ {
56
+ global $wsdPluginAlertsArray;
57
+ $actionName = $wsdPluginAlertsArray['watch_admin_password_update']['name'];
58
+ $alertType = $wsdPluginAlertsArray['watch_admin_password_update']['type'];
59
+
60
+ self::alert($actionName, $alertType, WSS_PLUGIN_ALERT_MEDIUM,
61
+ sprintf(__('Administrator (%s) password updated'), $userName),
62
+ __('<p>This alert is generated every time an administrator\'s password is updated.</p>'));
63
+ }
64
+ }
65
+ }
66
+
67
+ }
res/inc/alerts.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php /** Alerts & descriptions */
2
+ $wsdPluginAlertsArray = array
3
+ (
4
+ // WsdCheck::adminUsername
5
+ 'check_username_admin' => array('name' => 'check_username_admin ', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
6
+ // WsdCheck::tablePrefix
7
+ 'check_table_prefix' => array('name' => 'check_table_prefix', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
8
+ // WsdCheck::currentVersion
9
+ 'check_wp_current_version' => array('name' => 'check_wp_current_version', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
10
+ // WsdCheck::files
11
+ 'check_index_wp_content' => array('name' => 'check_index_wp_content', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
12
+ // WsdCheck::files
13
+ 'check_index_wp_content' => array('name' => 'check_index_wp_content', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
14
+ // WsdCheck::files
15
+ 'check_index_wp_plugins' => array('name' => 'check_index_wp_plugins', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
16
+ // WsdCheck::files
17
+ 'check_index_wp_themes' => array('name' => 'check_index_wp_themes', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
18
+ // WsdCheck::files - alert issued only if the wp-content/uploads directory exists
19
+ 'check_index_wp_uploads' => array('name' => 'check_index_wp_uploads', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
20
+ // WsdCheck::files
21
+ 'check_htaccess_wp_admin' => array('name' => 'check_htaccess_wp_admin', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
22
+ // WsdCheck::files
23
+ 'check_readme_wp_root' => array('name' => 'check_readme_wp_root', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
24
+
25
+
26
+ // WsdSecurity::fix_hideWpVersion
27
+ 'fix_wp_version_hidden' => array('name' => 'fix_wp_version_hidden', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
28
+ // WsdSecurity::fix_removeWpMetaGeneratorsFrontend
29
+ 'fix_wp_generators_frontend' => array('name' => 'fix_wp_generators_frontend', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
30
+ // WsdSecurity::fix_removeReallySimpleDiscovery
31
+ 'fix_wp_rsd_frontend' => array('name' => 'fix_wp_rsd_frontend', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
32
+ // WsdSecurity::fix_removeWindowsLiveWriter
33
+ 'fix_wp_wlw_frontend' => array('name' => 'fix_wp_wlw_frontend', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
34
+ // WsdSecurity::fix_disableErrorReporting
35
+ 'fix_wp_error_reporting' => array('name' => 'fix_wp_error_reporting', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
36
+ // WsdSecurity::fix_removeCoreUpdateNotification
37
+ 'fix_wp_core_update_notif' => array('name' => 'fix_wp_core_update_notif', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
38
+ // WsdSecurity::fix_removePluginUpdateNotifications
39
+ 'fix_wp_plugins_update_notif' => array('name' => 'fix_wp_plugins_update_notif', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
40
+ // WsdSecurity::fix_removeThemeUpdateNotifications
41
+ 'fix_wp_themes_update_notif' => array('name' => 'fix_wp_themes_update_notif', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
42
+ // WsdSecurity::fix_removeLoginErrorNotificationsFrontEnd
43
+ 'fix_wp_login_errors' => array('name' => 'fix_wp_login_errors', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
44
+ // WsdSecurity::fix_hideAdminNotifications
45
+ 'fix_wp_admin_notices' => array('name' => 'fix_wp_admin_notices', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
46
+ // WsdSecurity::fix_preventDirectoryListing
47
+ 'fix_wp_dir_listing' => array('name' => 'fix_wp_dir_listing', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
48
+ // WsdSecurity::fix_preventDirectoryListing
49
+ 'fix_wp_index_content' => array('name' => 'fix_wp_index_content', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
50
+ // WsdSecurity::fix_preventDirectoryListing
51
+ 'fix_wp_index_plugins' => array('name' => 'fix_wp_index_plugins', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
52
+ // WsdSecurity::fix_preventDirectoryListing
53
+ 'fix_wp_index_themes' => array('name' => 'fix_wp_index_themes', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
54
+ // WsdSecurity::fix_preventDirectoryListing - alert issued only if the wp-content/uploads directory exists
55
+ 'fix_wp_index_uploads' => array('name' => 'fix_wp_index_uploads', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
56
+ // WsdSecurity::fix_removeWpVersionFromLinks
57
+ 'fix_remove_wp_version_links' => array('name' => 'fix_remove_wp_version_links', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
58
+ // WsdSecurity::fix_emptyReadmeFileFromRoot
59
+ 'fix_empty_root_readme_file' => array('name' => 'fix_empty_root_readme_file', 'type' => WSS_PLUGIN_ALERT_TYPE_OVERWRITE ),
60
+
61
+
62
+ // WsdWatch::userPasswordUpdate
63
+ 'watch_admin_password_update' => array('name' => 'watch_admin_password_update', 'type' => WSS_PLUGIN_ALERT_TYPE_STACK ),
64
+ );
res/inc/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
res/inc/wss-functions.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! defined('WSS_PLUGIN_PREFIX')) return;
2
+
3
+ /**
4
+ * Common function to add custom time intervals to wp cron.
5
+ * This function should not be called directly.
6
+ *
7
+ * Usage: add_filter( 'cron_schedules', 'wsdplugin_addCronIntervals' );
8
+ *
9
+ * @param $schedules
10
+ * @return mixed
11
+ */
12
+ function wsdplugin_addCronIntervals( $schedules )
13
+ {
14
+ $schedules['8h'] = array( // The name to be used in code
15
+ 'interval' => 28800, // Intervals: in seconds
16
+ 'display' => __('Every 8 hours') // display name
17
+ );
18
+ return $schedules;
19
+ }
20
+ add_filter( 'cron_schedules', 'wsdplugin_addCronIntervals' );
21
+
22
+ if(WsdUtil::canLoad() && WsdUtil::isAdministrator())
23
+ {
24
+ //#!++
25
+ add_action('admin_notices', 'wsdPluginInstallErrorNotice');
26
+ function wsdPluginInstallErrorNotice() {
27
+ if ($notices = get_option('wsd_plugin_install_error')) {
28
+ if(! empty($notices)){
29
+ foreach ($notices as $notice) {
30
+ echo "<div class='updated'><p>$notice</p></div>";
31
+ }
32
+ }
33
+ }
34
+ }
35
+ //#--
36
+ }
res/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
res/js/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
res/js/wsd-util.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This function will bind the click event for entry items in the dashboard
3
+ * that will toggle the entry description row
4
+ */
5
+ function wsdplugin_bindEntryClick($)
6
+ {
7
+ $('.entry-event').each(function(){
8
+ var self = $(this);
9
+ self.click(function(){
10
+ var e = self.next('tr.entry-description');
11
+ e.fadeToggle('fast','linear');
12
+ });
13
+ });
14
+ }
15
+ /**
16
+ * Update the querystring param if found otherwise add it
17
+ * @param uri
18
+ * @param key
19
+ * @param value
20
+ * @returns string The updated uri
21
+ */
22
+ function updateQueryStringParam(uri, key, value) {
23
+ var re = new RegExp("([?|&])" + key + "=.*?(&|$)", "i"),separator = uri.indexOf('?') !== -1 ? "&" : "?";
24
+ if (uri.match(re)) { return uri.replace(re, '$1' + key + "=" + value + '$2'); }else { return uri + separator + key + "=" + value; }
25
+ }
res/js/wsdplugin_glossary_tooltip.js ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * @ glossary tooltips
3
+ */
4
+
5
+ var wsdplugin_glossary_tooltip=function(){
6
+ var id = 'tt';
7
+ var top = 3;
8
+ var left = 3;
9
+ var maxw = 400;
10
+ var speed = 10;
11
+ var timer = 20;
12
+ var endalpha = 95;
13
+ var alpha = 0;
14
+ var tt,t,c,b,h;
15
+ var ie = document.all ? true : false;
16
+ return{
17
+ show:function(self,w){
18
+ if(tt == null){
19
+ tt = document.createElement('div');
20
+ tt.setAttribute('id',id);
21
+ t = document.createElement('div');
22
+ t.setAttribute('id',id + 'top');
23
+ c = document.createElement('div');
24
+ c.setAttribute('id',id + 'cont');
25
+ b = document.createElement('div');
26
+ b.setAttribute('id',id + 'bot');
27
+ tt.appendChild(t);
28
+ tt.appendChild(c);
29
+ tt.appendChild(b);
30
+ document.body.appendChild(tt);
31
+ tt.style.opacity = 0;
32
+ tt.style.filter = 'alpha(opacity=0)';
33
+ document.onmousemove = this.pos;
34
+ }
35
+ tt.style.display = 'block';
36
+ c.innerHTML = self.getAttribute('data-bind-title');
37
+ tt.style.width = w ? w + 'px' : 'auto';
38
+ if(!w && ie){
39
+ t.style.display = 'none';
40
+ b.style.display = 'none';
41
+ tt.style.width = tt.offsetWidth;
42
+ t.style.display = 'block';
43
+ b.style.display = 'block';
44
+ }
45
+ if(tt.offsetWidth > maxw){tt.style.width = maxw + 'px'}
46
+ h = parseInt(tt.offsetHeight) + top;
47
+ clearInterval(tt.timer);
48
+ tt.timer = setInterval(function(){wsdplugin_glossary_tooltip.fade(1)},timer);
49
+ },
50
+ pos:function(e){
51
+ var u = ie ? event.clientY + document.documentElement.scrollTop : e.pageY;
52
+ var l = ie ? event.clientX + document.documentElement.scrollLeft : e.pageX;
53
+ tt.style.top = (u - h) + 'px';
54
+ tt.style.left = (l + left) + 'px';
55
+ },
56
+ fade:function(d){
57
+ var a = alpha;
58
+ if((a != endalpha && d == 1) || (a != 0 && d == -1)){
59
+ var i = speed;
60
+ if(endalpha - a < speed && d == 1){
61
+ i = endalpha - a;
62
+ }else if(alpha < speed && d == -1){
63
+ i = a;
64
+ }
65
+ alpha = a + (i * d);
66
+ tt.style.opacity = alpha * .01;
67
+ tt.style.filter = 'alpha(opacity=' + alpha + ')';
68
+ }else{
69
+ clearInterval(tt.timer);
70
+ if(d == -1){tt.style.display = 'none'}
71
+ }
72
+ },
73
+ hide:function(){
74
+ clearInterval(tt.timer);
75
+ tt.timer = setInterval(function(){wsdplugin_glossary_tooltip.fade(-1)},timer);
76
+ }
77
+ };
78
+ }();
res/languages/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
res/pages/about.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <div class="wrap wsdplugin_content">
3
+ <h2><?php echo WSS_PLUGIN_NAME.' - '.__('About');?></h2>
4
+
5
+ <div class="metabox-holder">
6
+
7
+ <div style="width:60%; float: left;" class="postbox">
8
+ <h3 class="hndle" style="cursor: default;"><span><?php echo __('About'). ' '.WSS_PLUGIN_NAME .' plugin';?></span></h3>
9
+ <div class="inside acx-section-box">
10
+ <p>
11
+ <?php echo WSS_PLUGIN_NAME.' plug-in beefs up the security of your WordPress installation by removing error information on login pages, adds index.php to plugin directories, hides the WordPress version and much more.'; ?>
12
+ </p>
13
+ <div class="acx-section-box">
14
+ <ul class="acx-common-list">
15
+ <li><span class="acx-icon-alert-success"><?php echo __('Removes error-information on login-page.');?></span></li>
16
+ <li><span class="acx-icon-alert-success"><?php echo __('Adds index.php to the wp-content, wp-content/plugins, wp-content/themes and wp-content/uploads directories to prevent directory listings.');?></span></li>
17
+ <li><span class="acx-icon-alert-success"><?php echo __('Removes the wp-version from everyone but administrators.');?></span></li>
18
+ <li><span class="acx-icon-alert-success"><?php echo __('Removes Really Simple Discovery meta tag.');?></span></li>
19
+ <li><span class="acx-icon-alert-success"><?php echo __('Removes Windows Live Writer meta tag.');?></span></li>
20
+ <li><span class="acx-icon-alert-success"><?php echo __('Removes core update information for non-admins.');?></span></li>
21
+ <li><span class="acx-icon-alert-success"><?php echo __('Removes plugin-update information for non-admins.');?></span></li>
22
+ <li><span class="acx-icon-alert-success"><?php echo __('Removes theme-update information for non-admins (only WP 2.8 and higher).');?></span></li>
23
+ <li><span class="acx-icon-alert-success"><?php echo __('Removes version on URLs from scripts and stylesheets.');?></span></li>
24
+ <li><span class="acx-icon-alert-success"><?php echo __('Provides various information after scanning your WordPress blog.');?></span></li>
25
+ <li><span class="acx-icon-alert-success"><?php echo __('Provides file permissions security checks.');?></span></li>
26
+ <li><span class="acx-icon-alert-success"><?php echo __('Provides a Live Traffic tool to monitor your website activity in real time.');?></span></li>
27
+ <li><span class="acx-icon-alert-success"><?php echo __('Provides a tool for changing the database prefix.');?></span></li>
28
+ <li><span class="acx-icon-alert-success"><?php echo __('Provides a tool to easily backup your WordPress database.');?></span></li>
29
+ <li><span class="acx-icon-alert-success"><?php echo __('Turns off database error reporting (if enabled).');?></span></li>
30
+ <li><span class="acx-icon-alert-success"><?php echo __('Turns off PHP error reporting.');?></span></li>
31
+ </ul>
32
+ </div>
33
+ </div>
34
+ </div>
35
+
36
+ <div style="width:38%; float: right;" class="postbox">
37
+ <h3 class="hndle" style="cursor: default;"><span><?php echo __('Get involved');?></span></h3>
38
+ <div class="inside acx-section-box">
39
+ <ul class="acx-common-list">
40
+ <li>
41
+ <span><a href="//www.acunetix.com/blog/" target="_blank"><?php echo __('Acunetix blog');?></a></span>
42
+ </li>
43
+ <li>
44
+ <span><a href="//twitter.com/acunetix" target="_blank"><?php echo __('Acunetix on Twitter');?></a></span>
45
+ </li>
46
+ <li>
47
+ <span><a href="//www.facebook.com/Acunetix" target="_blank"><?php echo __('Acunetix on Facebook');?></a></span>
48
+ </li>
49
+ <li>
50
+ <span><a href="//wordpress.org/support/plugin/wp-security-scan" target="_blank"><?php echo __('Support');?></a></span>
51
+ </li>
52
+ </ul>
53
+ </div>
54
+ </div>
55
+ </div>
56
+
57
+ </div>
res/pages/blog.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <?php wp_enqueue_style('wsdplugin_css_blog', WsdUtil::cssUrl('blog.css'), array(), '1.0'); ?>
3
+
4
+ <div class="wrap wsdplugin_content">
5
+ <div id="pageblog" class="wrap wsdplugin_content">
6
+
7
+ <div id="header">
8
+ <div class="wrapper">
9
+ <div id="logo"><a href="http://www.acunetix.com" target="_blank">Acunetix</a></div>
10
+ <div id="main-nav">
11
+ <a class="twitter" target="_blank" href="http://twitter.com/acunetix" title="<?php echo __('Follow us on Twitter');?>">Twitter</a>
12
+ <a class="facebook" target="_blank" href="http://www.facebook.com/Acunetix" title="<?php echo __('Follow us on Facebook');?>">Facebook</a>
13
+ </div>
14
+ </div>
15
+ </div>
16
+ <div id="content">
17
+ <ul id="feed-list">
18
+ <?php
19
+ /**
20
+ * @internal
21
+ * @param int $maxItems
22
+ * @return string
23
+ */
24
+ function wsdplugin_GetFeedData($maxItems = 10)
25
+ {
26
+ $rss = fetch_feed(WSS_PLUGIN_BLOG_FEED);
27
+ $out = '';
28
+ if (is_wp_error( $rss ) ) { return '<li>'.__('An error has occurred while trying to load the rss feed!').'</li>'; }
29
+ else{
30
+ // Limit to $maxItems entries.
31
+ $maxitems = $rss->get_item_quantity($maxItems);
32
+
33
+ // Build an array of all the items,
34
+ $rss_items = $rss->get_items(0, $maxitems);
35
+
36
+ if ($maxitems == 0){ $out.= '<li>'.__('There are no entries for this feed!').'</li>'; }
37
+ else {
38
+ foreach ( $rss_items as $item ) :
39
+ $url = esc_url($item->get_permalink());
40
+ $out.= '<li>';
41
+ $out.= '<h4><a href="'.$url.'" target="_blank" title="'.__('Posted on ').$item->get_date('F j, Y | g:i a').'">';
42
+ $out.= esc_html( $item->get_title() );
43
+ $out.= '</a></h4>';
44
+ $out.= '<div>' . $item->get_description() . '</div>';
45
+ $out.= '</li>';
46
+ endforeach;
47
+ }
48
+ $out .= '<div style="border-top: solid 1px #ccc; margin-top: 4px; padding: 2px 0;">';
49
+ $out .= '<p style="margin: 5px 0 0 0; padding: 0 0; line-height: normal; overflow: hidden;">';
50
+ $out .= '<a href="http://feeds.acunetix.com/acunetixwebapplicationsecurityblog"
51
+ style="float: left; display: block; width: 50%; text-align: right; margin-left: 30px;
52
+ padding-right: 22px; background: url(\'rss.png\') no-repeat right center;"
53
+ target="_blank">'.__('Follow us on RSS').'</a>';
54
+ $out .= '</p>';
55
+ $out .= '</div>';
56
+ }
57
+ return $out;
58
+ }
59
+ /**
60
+ * @internal
61
+ * @param $optName
62
+ * @param $optData
63
+ */
64
+ function wsdplugin_updateRssFeedOption($optName, $optData)
65
+ {
66
+ $obj = new stdClass();
67
+ $obj->expires = time() + (24*60*60);
68
+ $obj->data = $optData;
69
+ update_option($optName, $obj);
70
+ }
71
+ /**
72
+ * @public
73
+ * @param $optName
74
+ * @param $getMaxRssEntries
75
+ */
76
+ function wsdplugin_handleDisplayRssData($optName, $getMaxRssEntries)
77
+ {
78
+ $data = wsdplugin_GetFeedData($getMaxRssEntries);
79
+ wsdplugin_updateRssFeedOption($optName, $data);
80
+ echo str_ireplace("url('rss.png')", "url('".WsdUtil::imageUrl('rss.png')."')", $data);
81
+ }
82
+
83
+ $optName = 'WSD-FEED-DATA';
84
+ $getMaxRssEntries = 10;
85
+
86
+ //@ check cache
87
+ $optData = get_option($optName);
88
+
89
+ if(empty($optData)) { wsdplugin_handleDisplayRssData($optName, $getMaxRssEntries); }
90
+ else{
91
+ // check cache expiry date
92
+ if (is_object($optData)) {
93
+ $lastUpdateTime = @$optData->expires;
94
+ // invalid cache: UPDATE
95
+ if (empty($lastUpdateTime)) { wsdplugin_handleDisplayRssData($optName, $getMaxRssEntries); }
96
+ else {
97
+ $nextUpdateTime = $lastUpdateTime+(24*60*60);
98
+ if ($nextUpdateTime >= $lastUpdateTime){
99
+ $data = @$optData->data;
100
+ if (empty($data)) { wsdplugin_handleDisplayRssData($optName, $getMaxRssEntries); }
101
+ // still a valid cache: DISPLAY
102
+ else { echo str_ireplace("url('rss.png')", "url('".WsdUtil::imageUrl('rss.png')."')", $data); }
103
+ }
104
+ else { wsdplugin_handleDisplayRssData($optName, $getMaxRssEntries); }
105
+ }
106
+ }
107
+ else { wsdplugin_handleDisplayRssData($optName, $getMaxRssEntries); }
108
+ }
109
+ ?>
110
+ </ul>
111
+ </div>
112
+ </div>
113
+ </div>
res/pages/dashboard.php ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <?php if(! WsdUtil::isAdministrator()) { return; } ?>
3
+ <?php
4
+ if(!isset($_GET['filter']))
5
+ {
6
+ $alertsFilterBy = 'all';
7
+ $alertsSortBy = 's';
8
+ $alerts = WsdPlugin::getAlerts();
9
+ }
10
+ else {
11
+ $alertsFilterBy = trim($_GET['filter']);
12
+ if($alertsFilterBy == 'all'){ $alerts = WsdPlugin::getAlerts(); }
13
+ else {
14
+ $alertsFilterBy = intval($alertsFilterBy);
15
+ if(! in_array($alertsFilterBy, array(0,1,2,3))){
16
+ $alertsFilterBy = 'all';
17
+ $alerts = WsdPlugin::getAlerts();
18
+ }
19
+ else { $alerts = WsdPlugin::getAlertsBy($alertsFilterBy); }
20
+ }
21
+ }
22
+ ?>
23
+ <div class="wrap wsdplugin_content">
24
+ <h2><?php echo WSS_PLUGIN_NAME.' - '. __('Dashboard');?></h2>
25
+
26
+ <p class="clear"></p>
27
+ <div style="clear: both; display: block;">
28
+ <!-- Current Alerts -->
29
+ <div class="wsdplugin_page_alert_types_current">
30
+
31
+ <!-- Action Bar -->
32
+ <div class="wsdplugin_page_alerts_action_bar" style="float: left;">
33
+ <div class="tablenav">
34
+ <div class="alignleft actions wsdplugin_alerts_filter_severity">
35
+ <select id="FilterAlertTypeSelect">
36
+ <option value="all"><?php echo __('All Severity Levels');?></option>
37
+ <option value="3"><?php echo __('Critical');?></option>
38
+ <option value="2"><?php echo __('Medium');?></option>
39
+ <option value="1"><?php echo __('Low');?></option>
40
+ <option value="0"><?php echo __('Informational');?></option>
41
+ </select>
42
+ <input type="button" value="Filter" class="button-secondary action" id="FilterAlertTypeButton">
43
+ </div>
44
+ </div>
45
+ </div>
46
+
47
+ <!-- Title -->
48
+ <div class="wsdplugin_alert_section_title wsdplugin_alert_section_title_category"><?php echo __('Current Alerts');?></div>
49
+
50
+ <!-- Body -->
51
+ <div class="wsdplugin_alert_section_body">
52
+ <table class="widefat" cellspacing="0" cellpadding="0">
53
+ <thead>
54
+ <th style="width:60px"><?php echo __('Severity');?></th>
55
+ <th style="width: 150px;"><?php echo __('Date');?></th>
56
+ <th><?php echo __('Title');?></th>
57
+ </thead>
58
+ <tbody>
59
+ <?php
60
+ if(! empty($alerts)){
61
+ foreach($alerts as $entry){
62
+ $alertId = $entry->alertId;
63
+ $alertType = $entry->alertType;
64
+ $severity = $entry->alertSeverity;
65
+ $afsDate = $entry->alertFirstSeen;
66
+ if($severity == WSS_PLUGIN_ALERT_INFO){ $severity = 'info'; }
67
+ elseif($severity == WSS_PLUGIN_ALERT_LOW){ $severity = 'low'; }
68
+ elseif($severity == WSS_PLUGIN_ALERT_MEDIUM){ $severity = 'medium'; }
69
+ elseif($severity == WSS_PLUGIN_ALERT_CRITICAL){ $severity = 'critical'; }
70
+ else { $severity = 'info'; }
71
+ echo '<tr class="entry-event alt" title="'.__('Click to expand/collapse').'">';
72
+ echo '<td class="wsdplugin_alert_indicator wsdplugin_alert_indicator_'.$severity.'" title="'.ucfirst($severity).'"></td>';
73
+ echo '<td>'.$entry->alertDate.'</td>';
74
+ echo '<td>'.$entry->alertTitle.'</td>';
75
+ echo '</tr>';
76
+ echo '<tr class="entry-description">';
77
+ echo '<td colspan="3">';
78
+ if($alertType == WSS_PLUGIN_ALERT_TYPE_STACK)
79
+ {
80
+ // get child alerts
81
+ $childAlerts = WsdPlugin::getChildAlerts($alertId, $alertType);
82
+ if(! empty($childAlerts)){
83
+ echo '<h3>'.__('Previous alerts').'</h3>';
84
+ echo '<table cellspacing="0" cellpadding="0" style="margin: 7px 11px;"><tbody>';
85
+ foreach($childAlerts as $childAlert){
86
+ $afsDate = $childAlert->alertFirstSeen;
87
+ echo '<tr class="alt">';
88
+ echo '<td class="wsdplugin_alert_indicator wsdplugin_alert_indicator_'.$severity.'" title="'.ucfirst($severity).'"></td>';
89
+ echo '<td>'.$childAlert->alertDate.'</td>';
90
+ echo '<td>'.$childAlert->alertTitle.'</td>';
91
+ echo '</tr>';
92
+ }
93
+ echo '</tbody></table>';
94
+ }
95
+ echo '<p>Alert first seen on: <strong>'.$afsDate.'</strong></p>';
96
+ echo '<h3>'.__('Description').'</h3>';
97
+ echo '<div><p>'.$entry->alertDescription.'</p></div>';
98
+ if(! empty($entry->alertSolution)){
99
+ echo '<h3>'.__('Solution').'</h3>';
100
+ echo '<div><p>'.$entry->alertSolution.'</p></div>';
101
+ }
102
+
103
+ }
104
+ else {
105
+ echo '<p>Alert first seen on: <strong>'.$afsDate.'</strong></p>';
106
+ echo '<h3>'.__('Description').'</h3>';
107
+ echo '<div><p>'.$entry->alertDescription.'</p></div>';
108
+ if(! empty($entry->alertSolution)){
109
+ echo '<h3>'.__('Solution').'</h3>';
110
+ echo '<div><p>'.$entry->alertSolution.'</p></div>';
111
+ }
112
+ }
113
+ echo '</td>';
114
+ echo '</tr>';
115
+ }
116
+ }
117
+ else { echo '<tr class="entry-event alt"><td colspan="3"><p style="font-weight:800;padding-top:6px;">'.__('No alerts found.').'</p></td></tr>'; }
118
+ ?>
119
+ </tbody>
120
+ </table>
121
+ </div>
122
+ </div>
123
+ <!-- Current Alerts -->
124
+ </div>
125
+ <script type="text/javascript">
126
+ jQuery(document).ready(function($){
127
+ wsdplugin_bindEntryClick($);
128
+ $("#FilterAlertTypeSelect").val("<?php echo $alertsFilterBy;?>").attr("selected", "selected");
129
+ $('#FilterAlertTypeButton').click(function(){window.location = updateQueryStringParam(document.URL,'filter',$('#FilterAlertTypeSelect').val());});
130
+ });
131
+ </script>
132
+
133
+ <?php echo WsdUtil::loadTemplate('box-banners');?>
134
+ </div>
res/pages/database.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <?php if(! WsdUtil::isAdministrator()) { return; } ?>
3
+ <div class="wrap wsdplugin_content">
4
+ <h2><?php echo WSS_PLUGIN_NAME.' - '. __('Database Tools');?></h2>
5
+
6
+ <p class="clear"></p>
7
+ <div style="clear: both; display: block;">
8
+ <?php /*[ DATABASE BACKUP ]*/ ?>
9
+ <div class="metabox-holder" style="overflow: hidden;">
10
+
11
+ <?php
12
+ /*
13
+ * DATABASE BACKUP TOOL
14
+ * ================================================================
15
+ */
16
+ ?>
17
+ <div id="bckdb" style="float:left; width:49%;" class="inner-sidebar1 postbox">
18
+ <h3 class="hndle" style="cursor: default;"><span><?php echo __('Backup Database');?></span></h3>
19
+ <div class="inside">
20
+ <?php
21
+ echo WsdUtil::loadTemplate('box-database-backup');
22
+ ?>
23
+ </div>
24
+ </div>
25
+
26
+ <?php
27
+ /*
28
+ * DATABASE BACKUPS
29
+ * ================================================================
30
+ */
31
+ ?>
32
+ <div style="float:right;width:49%;" class="inner-sidebar1 postbox">
33
+ <h3 class="hndle" style="cursor: default;"><span><?php echo __('Database Backup Files');?></span></h3>
34
+ <div class="inside">
35
+ <?php
36
+ echo WsdUtil::loadTemplate('box-available-backups');
37
+ ?>
38
+ </div>
39
+ </div>
40
+ </div>
41
+
42
+ <p class="clear"></p>
43
+ <div class="metabox-holder" style="width:99.8%; padding-top: 0;">
44
+ <?php
45
+ /*
46
+ * CHANGE DATABASE PREFIX TOOL
47
+ * ================================================================
48
+ */
49
+ ?>
50
+ <div id="cdtp" class="postbox">
51
+ <h3 class="hndle" style="cursor: default;"><span><?php echo __('Change Database Prefix');?></span></h3>
52
+ <div class="inside">
53
+ <?php
54
+ echo WsdUtil::loadTemplate('box-database-change-prefix');
55
+ ?>
56
+ </div>
57
+ </div>
58
+ </div>
59
+
60
+ </div>
61
+ </div>
res/pages/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
res/pages/live_traffic.php ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <?php if(! WsdUtil::isAdministrator()) { return; } ?>
3
+ <?php
4
+ // flag for getting data
5
+ $forceLoad = 1;
6
+ $refreshRates = array(0, 5, 10, 15, 20, 25, 30);
7
+ $settings = WsdPlugin::getSettings();
8
+ ?>
9
+ <?php
10
+ $rm = strtoupper($_SERVER['REQUEST_METHOD']);
11
+ if('POST' == $rm)
12
+ {
13
+ // check nonce
14
+ if(isset($_POST['wsdplugin_update_settings_field'])){
15
+ if(!wp_verify_nonce($_POST['wsdplugin_update_settings_field'],'wsdplugin_update_settings')){
16
+ exit('Invalid request.');
17
+ }
18
+ }
19
+ else {exit('Invalid request.');}
20
+
21
+ function wsdPluginValidateSettingsForm($settings, $refreshRates)
22
+ {
23
+ if(isset($_POST['max_number_live_traffic']) && isset($_POST['refreshRateOption']))
24
+ {
25
+ // validate input $_POST['max_number_live_traffic']
26
+ $keepNumEntriesLiveTraffic = intval($_POST['max_number_live_traffic']);
27
+ if($keepNumEntriesLiveTraffic == 0){
28
+ $keepNumEntriesLiveTraffic = 0;
29
+ }
30
+ elseif(! preg_match("/[0-9]{1,5}/", $keepNumEntriesLiveTraffic)){
31
+ $keepNumEntriesLiveTraffic = 500;
32
+ }
33
+
34
+ // validate input $_POST['refreshRateOption']
35
+ $liveTrafficRefreshRateAjax = intval($_POST['refreshRateOption']);
36
+ if(! in_array($liveTrafficRefreshRateAjax, $refreshRates)){
37
+ $liveTrafficRefreshRateAjax = 10;
38
+ }
39
+ elseif($_POST['refreshRateOption'] == 0){
40
+ $liveTrafficRefreshRateAjax = 0;
41
+ }
42
+ elseif(! preg_match("/[0-9]{1,2}/", $liveTrafficRefreshRateAjax)){
43
+ $liveTrafficRefreshRateAjax = 10;
44
+ }
45
+
46
+ $settings['keepNumEntriesLiveTraffic'] = $keepNumEntriesLiveTraffic;
47
+ $settings['liveTrafficRefreshRateAjax'] = $liveTrafficRefreshRateAjax;
48
+
49
+ // update settings
50
+ update_option(WSS_PLUGIN_SETTINGS_OPTION_NAME, $settings);
51
+
52
+ return $settings;
53
+ }
54
+ else { exit('Invalid request.'); }
55
+ }
56
+
57
+
58
+ // check form
59
+ if(isset($_POST['updateSettingsButton']))
60
+ {
61
+ if(isset($_POST['max_number_live_traffic']) && isset($_POST['refreshRateOption']))
62
+ {
63
+ $settings = wsdPluginValidateSettingsForm($settings, $refreshRates);
64
+ }
65
+ else { exit('Invalid request.'); }
66
+ }
67
+ elseif(isset($_POST['deleteEntriesButton'])){
68
+ global $wpdb;
69
+ $query = "TRUNCATE ".WsdPlugin::getTableName(WSS_PLUGIN_LIVE_TRAFFIC_TABLE_NAME);
70
+ $wpdb->query($query);
71
+ $settings = wsdPluginValidateSettingsForm($settings, $refreshRates);
72
+ }
73
+ else { exit('Invalid request.'); }
74
+ }
75
+
76
+
77
+ $keepNumEntriesLiveTraffic = (isset($settings['keepNumEntriesLiveTraffic']) ? $settings['keepNumEntriesLiveTraffic'] : 500);
78
+ $liveTrafficRefreshRateAjax = (isset($settings['liveTrafficRefreshRateAjax']) ? $settings['liveTrafficRefreshRateAjax'] : 10);
79
+ ?>
80
+ <style type="text/css">
81
+ .wsd-clear { float: none; clear: both; height: 0; width: 100%; margin: 0 0; padding: 0 0;}
82
+ .wsdTrafficScan { }
83
+ .wsd-scan-entry { border-bottom: solid 1px #000; }
84
+ .wsd-scan-entry p { margin: 0 0; padding: 0 0; font-size: 100%; }
85
+ .wsd-scan-entry p .w-entry { color: #21759B; }
86
+ .wsd-scan-entry p .w-ip { color: #d00000; }
87
+ .wsd-scan-entry p .w-ua { color: #808080; }
88
+ .wsd-scan-entry p .w-date { color: #006600; }
89
+ #loaderWrapper {
90
+ float: right;
91
+ margin: 0 5px 0 0;
92
+ padding: 0 0;
93
+ overflow: hidden; min-height: 1px;
94
+ height: 20px;
95
+ }
96
+ #loaderWrapper span img { float: left;display:block; margin-top:4px; }
97
+ #loaderWrapper span span { float: left;display:block;padding-top: 0;margin-left:10px;color:#000000; }
98
+ .wsdPluginFieldsetSettingsExpanded { background: #F9F9F9; border: solid 1px #DFDFDF; padding: 0 0; }
99
+ .wsdPluginFieldsetSettingsCollapsed { background: transparent; border: none; border-top: solid 1px #DFDFDF; padding: 0 0; }
100
+ #settingsLegend {
101
+ background: linear-gradient(to top, #ECECEC, #F9F9F9) repeat scroll 0 0 #F1F1F1;
102
+ border: solid 1px #DFDFDF; padding: 2px 5px; margin-left: 5px; cursor: pointer;
103
+ }
104
+ #settingsContent { padding: 0 0; margin: 2px 0 5px 10px; line-height: normal; }
105
+ #max_number_live_traffic { margin-top: -5px; padding-top: 0; padding-bottom: 0; width: 50px; }
106
+ .btn {
107
+ -moz-box-sizing: border-box;
108
+ border-radius: 3px 3px 3px 3px;
109
+ border-style: solid;
110
+ border-width: 1px;
111
+ cursor: pointer;
112
+ display: inline-block;
113
+ font-size: 12px;
114
+ height: 24px;
115
+ line-height: 23px;
116
+ margin: 0;
117
+ padding: 0 10px 1px;
118
+ text-decoration: none;
119
+ white-space: nowrap;
120
+ }
121
+ .btn-danger {
122
+ color: #ffffff;
123
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
124
+ background-color: #da4f49;
125
+ background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
126
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
127
+ background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
128
+ background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
129
+ background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
130
+ background-repeat: repeat-x;
131
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
132
+ border-color: #bd362f #bd362f #802420;
133
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
134
+ *background-color: #bd362f;
135
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
136
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
137
+ }
138
+ .btn-inverse {
139
+ color: #ffffff;
140
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
141
+ background-color: #363636;
142
+ background-image: -moz-linear-gradient(top, #444444, #222222);
143
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
144
+ background-image: -webkit-linear-gradient(top, #444444, #222222);
145
+ background-image: -o-linear-gradient(top, #444444, #222222);
146
+ background-image: linear-gradient(to bottom, #444444, #222222);
147
+ background-repeat: repeat-x;
148
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
149
+ border-color: #222222 #222222 #000000;
150
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
151
+ *background-color: #222222;
152
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
153
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
154
+ }
155
+ </style>
156
+ <div class="wrap wsdplugin_content">
157
+ <h2><?php echo WSS_PLUGIN_NAME.' - '. __('Live Traffic');?></h2>
158
+
159
+ <p class="clear"></p>
160
+
161
+ <div style="padding: 0 0;">
162
+ <form method="post">
163
+ <?php wp_nonce_field('wsdplugin_update_settings','wsdplugin_update_settings_field'); ?>
164
+ <fieldset class="wsdPluginFieldsetSettingsExpanded">
165
+ <legend id="settingsLegend">Settings</legend>
166
+ <p id="settingsContent">
167
+ <label for="max_number_live_traffic">Maximum number of entries to store for Live Traffic:</label>
168
+ <input type="text" name="max_number_live_traffic" id="max_number_live_traffic" value="<?php echo $keepNumEntriesLiveTraffic;?>" maxlength="5"/>
169
+
170
+ <label for="refreshRateOption" style="margin-left: 20px;">Refresh rate</label>
171
+ <select name="refreshRateOption" id="refreshRateOption">
172
+ <?php
173
+ foreach($refreshRates as $rate){
174
+ $selected = ($rate == $liveTrafficRefreshRateAjax ? 'selected="selected"' : '');
175
+ if($rate == 0){
176
+ echo '<option value="'.$rate.'" '.$selected.'>Never</option>';
177
+ }
178
+ else { echo '<option value="'.$rate.'" '.$selected.'>'.$rate.' seconds</option>'; }
179
+ }
180
+ ?>
181
+ </select>
182
+ <input type="submit" value="Update settings" class="btn button-primary" name="updateSettingsButton" style="margin-left: 20px;"/>
183
+ <?php if($liveTrafficRefreshRateAjax == 0) :?>
184
+ <input type="button" value="Refresh" class="btn btn-inverse" style="margin-left: 20px;" onclick="javascript: window.location.href=document.URL;"/>
185
+ <?php endif;?>
186
+ <input type="submit" value="Delete all" class="btn btn-danger" name="deleteEntriesButton" style="margin-left: 20px;"/>
187
+ </p>
188
+ </fieldset>
189
+ </form>
190
+ </div>
191
+
192
+
193
+ <p class="clear"></p>
194
+ <table id="wsdTrafficScanTable" cellspacing="0"
195
+ class="wp-list-table widefat wsdTrafficScan"
196
+ data-nonce="<?php echo wp_create_nonce("wsdTrafficScan_nonce");?>"
197
+ data-lastid="<?php echo WsdLiveTraffic::getLastID();?>">
198
+ <thead style="height: 20px;">
199
+ <tr>
200
+ <th class="manage-column column-cb" scope="col">
201
+ <span style="display: block; float: left; font-weight: 800;">Live activity</span>
202
+ <p id="loaderWrapper"></p>
203
+ </th>
204
+ </tr>
205
+ </thead>
206
+ <tbody id="the-list"></tbody>
207
+ </table>
208
+ </div>
209
+ <script type="text/javascript">
210
+ <?php if($forceLoad) echo 'var wsdAjaxForceLoad = 1;'; else echo 'var wsdAjaxForceLoad = 0;'?>
211
+ (function($){
212
+ $(document).ready( function()
213
+ {
214
+ function _createLoader($){
215
+ var imgPath = "<?php echo WsdUtil::imageUrl('ajax-loader.gif') ?>";
216
+ var text = "<?php echo __('Loading data...');?>";
217
+ return $('<span id="ajaxLoaderRemove"><img src="'+imgPath+'" title="'+text+'" alt="'+text+'"/><span>'+text+'</span></span>');
218
+ }
219
+ function _showLoader($parentElement, $loader){ $parentElement.append($loader); }
220
+ function _hideLoader(stringId) { $('#'+stringId).remove(); }
221
+
222
+ var loader = _createLoader($);
223
+
224
+ var $table = $("#wsdTrafficScanTable"),
225
+ nonce = $table.attr("data-nonce"),
226
+ $tbody = $('#the-list', $table)
227
+ ,lastID = $table.attr("data-lastid")
228
+ ,loaderWrapper = $('#loaderWrapper');
229
+
230
+ function wsdpluginLoadData()
231
+ {
232
+ _showLoader(loaderWrapper, loader);
233
+ $.ajax({
234
+ type : "post",
235
+ dataType : "json",
236
+ cache: false,
237
+ url : "<?php echo admin_url( 'admin-ajax.php' );?>",
238
+ data : {'action': "ajaxGetTrafficData", 'nonce': nonce, 'lastID' : lastID, 'forceLoad': wsdAjaxForceLoad, 'maxEntries' : <?php echo $keepNumEntriesLiveTraffic;?>},
239
+ success: function(response) {
240
+ _hideLoader('ajaxLoaderRemove');
241
+ if(response.type == "success") {
242
+ if(response.data.length > 20){ $tbody.html(response.data); }
243
+ }
244
+ else { alert("An error occurred while trying to load data. Please try again in a few seconds."); }
245
+ }
246
+ });
247
+ wsdAjaxForceLoad = 0;
248
+ }
249
+
250
+ wsdpluginLoadData();
251
+ <?php //if refresh rate is == 0 -> disable
252
+ if($liveTrafficRefreshRateAjax > 0) :
253
+ ?>
254
+ window.setInterval(function(){wsdpluginLoadData(); }, <?php echo $liveTrafficRefreshRateAjax * 1000 ?>);
255
+ <?php endif; ?>
256
+
257
+ // settings
258
+ var settingsLegend = $('#settingsLegend');
259
+ var settingsContent = $('#settingsContent');
260
+ settingsLegend.toggle(
261
+ function(){
262
+ settingsContent.hide();
263
+ settingsLegend.parent().removeClass('wsdPluginFieldsetSettingsExpanded').addClass('wsdPluginFieldsetSettingsCollapsed');
264
+ },
265
+ function(){
266
+ settingsLegend.parent().removeClass('wsdPluginFieldsetSettingsCollapsed').addClass('wsdPluginFieldsetSettingsExpanded');
267
+ settingsContent.show();
268
+ }
269
+ );
270
+ });
271
+ })(jQuery);
272
+ </script>
res/pages/scanner.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <?php if(! WsdUtil::isAdministrator()) { return; } ?>
3
+ <div class="wrap wsdplugin_content">
4
+ <h2><?php echo WSS_PLUGIN_NAME.' - '. __('WordPress Scanner');?></h2>
5
+
6
+ <p class="clear"></p>
7
+ <p style="margin-left: 15px;">
8
+ <?php echo __("This page displays various information after scanning your WordPress website"); ?>:
9
+ </p>
10
+
11
+ <div class="metabox-holder">
12
+
13
+ <div style="width:49.8%; float: left;" class="postbox">
14
+ <h3 class="hndle" style="cursor: default;"><span><?php echo __('Server Report');?></span></h3>
15
+ <div class="inside acx-section-box">
16
+ <?php
17
+ echo WsdUtil::loadTemplate('box-server-results');
18
+ ?>
19
+ </div>
20
+ </div>
21
+ <div style="width:49.8%; float: right;" class="postbox">
22
+ <h3 class="hndle" style="cursor: default;"><span><?php echo __('WordPress Scan Report');?></span></h3>
23
+ <div class="inside acx-section-box">
24
+ <?php
25
+ echo WsdUtil::loadTemplate('box-scan-results-wp');
26
+ ?>
27
+ </div>
28
+ </div>
29
+
30
+ <div style="width:99.8%; clear: both;" class="inner-sidebar1 postbox">
31
+ <h3 class="hndle" style="cursor: default;"><span><?php echo __('File Scan Report');?></span></h3>
32
+ <div class="inside">
33
+ <?php
34
+ echo WsdUtil::loadTemplate('box-scan-results-file');
35
+ ?>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </div>
res/pages/settings.php ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <?php if(! WsdUtil::isAdministrator()) { return; } ?>
3
+ <?php
4
+ $rm = strtoupper($_SERVER['REQUEST_METHOD']);
5
+ //#! get settings
6
+ $settings = WsdPlugin::getSettings();
7
+
8
+ $rssWidgetData = get_option('WSD-RSS-WGT-DISPLAY');
9
+ $rssWidgetChecked = false;
10
+ if(!empty($rssWidgetData) && ($rssWidgetData == 'yes')){
11
+ $rssWidgetChecked = true;
12
+ }
13
+
14
+ if('POST' == $rm)
15
+ {
16
+ // check nonce
17
+ if(isset($_POST['wsdplugin_update_settings_field'])){
18
+ if(!wp_verify_nonce($_POST['wsdplugin_update_settings_field'],'wsdplugin_update_settings')){
19
+ wp_die(__('Invalid request.'));
20
+ }
21
+ }
22
+ else {wp_die(__('Invalid request.'));}
23
+
24
+ //#! UPDATE SETTINGS
25
+ if(isset($_POST['updateSettingsButton']))
26
+ {
27
+ // validate and save settings
28
+ $postData = $_POST['chk_options'];
29
+ parse_str($postData, $checkboxes);
30
+
31
+ if(empty($checkboxes)){
32
+ foreach($settings as &$entry){
33
+ $entry['value'] = 0;
34
+ }
35
+ }
36
+ else {
37
+ foreach($checkboxes as $method => $value){
38
+ $settings[$method]['value'] = $value;
39
+ }
40
+ }
41
+
42
+ // rss widget
43
+ if(empty($_POST['chk_rss_wgt_display'])){
44
+ // hide
45
+ $rssWidgetChecked = false;
46
+ update_option('WSD-RSS-WGT-DISPLAY', 'no');
47
+ }
48
+ else {
49
+ // show
50
+ $rssWidgetChecked = true;
51
+ update_option('WSD-RSS-WGT-DISPLAY', 'yes');
52
+ }
53
+
54
+ update_option(WSS_PLUGIN_SETTINGS_OPTION_NAME, $settings);
55
+ $settings = get_option(WSS_PLUGIN_SETTINGS_OPTION_NAME);
56
+ }
57
+ //#! DELETE OPTIONS
58
+ elseif(isset($_POST['deleteRssDataButton']))
59
+ {
60
+ delete_option('wsd_feed_data');
61
+ }
62
+ }
63
+ ?>
64
+ <div class="wrap wsdplugin_content">
65
+ <h2><?php echo WSS_PLUGIN_NAME.' - '. __('Settings');?></h2>
66
+
67
+ <p class="clear"></p>
68
+ <div style="clear: both; display: block;">
69
+ <div class="metabox-holder">
70
+ <div class="inner-sidebar1 postbox">
71
+ <h3 class="hndle" style="cursor: default;"><span><?php echo __('Settings');?></span></h3>
72
+ <div class="inside acx-section-box" style="padding-left:0;">
73
+ <form method="post">
74
+ <?php wp_nonce_field('wsdplugin_update_settings','wsdplugin_update_settings_field'); ?>
75
+ <?php
76
+ $i = 0;
77
+ foreach($settings as $k => $entry){
78
+ if(is_array($entry))
79
+ {
80
+ $chkID = "chk-$i";
81
+ echo '<div class="acx-section-box wsdplugin-overflow">';
82
+ echo '<label for="'.$chkID.'" class="wsdplugin-overflow">';
83
+ echo '<span class="chk-settings wsdplugin_checkbox'.($entry['value'] ? ' wsdplugin_checkbox-active' : '').'" id="'.$chkID.'" data-bind="'.$entry['name'].'"><a>&nbsp;</a></span>';
84
+ echo '<span>'.$entry['desc'].'</span>';
85
+ echo '</label>';
86
+ echo '</div>';
87
+ $i++;
88
+ }
89
+ }
90
+ ?>
91
+ <?php
92
+ // the rss dashboard widget
93
+ // all the below settings must have present the chk-extra class
94
+ echo '<div class="acx-section-box wsdplugin-overflow">';
95
+ echo '<label for="wsd_feed_data" class="wsdplugin-overflow">';
96
+ echo '<span class="chk-extra wsdplugin_checkbox'.($rssWidgetChecked ? ' wsdplugin_checkbox-active' : '').'" id="wsd_feed_data"><a>&nbsp;</a></span>';
97
+ echo '<span>'.__('Show the RSS widget in the dashboard').'</span>';
98
+ echo '</label>';
99
+ echo '</div>';
100
+ ?>
101
+
102
+ <input type="hidden" name="chk_options" id="chk_options" />
103
+ <input type="hidden" name="chk_rss_wgt_display" id="chk_rss_wgt_display" />
104
+ <div class="acx-section-box wsdplugin-overflow">
105
+ <input type="button" id="_resetButton" class="button button-secondary" style="width: 70px;"/>
106
+ <input type="submit" value="Update settings" class="button button-primary" name="updateSettingsButton"/>
107
+ <input type="submit" value="Delete rss data" class="button button-primary" name="deleteRssDataButton"/>
108
+ </div>
109
+ </form>
110
+ </div>
111
+ </div>
112
+ </div>
113
+
114
+ </div>
115
+ </div>
116
+ <script type="text/javascript">
117
+ jQuery(document).ready(function($){
118
+ var resetButton = $('#_resetButton');
119
+ var oneChecked = false;
120
+ var checkboxes = $('.wsdplugin_checkbox');
121
+ var entriesLiveTrafficInput = $('#max_number_live_traffic');
122
+
123
+ // update state + bind click listeners
124
+ $.each(checkboxes, function(i,v){
125
+ var self = $(v);
126
+ if(self.hasClass('wsdplugin_checkbox-active')){
127
+ oneChecked = true;
128
+ }
129
+ self.parent('label').on('click', function(){
130
+ if(self.hasClass('wsdplugin_checkbox-active')){
131
+ self.removeClass('wsdplugin_checkbox-active');
132
+ }
133
+ else { self.addClass('wsdplugin_checkbox-active'); }
134
+ });
135
+ });
136
+
137
+ // update reset button
138
+ if(oneChecked){ resetButton.val('Clear all'); }
139
+ else { resetButton.val('Select all'); }
140
+
141
+ resetButton.click(function(){
142
+ $(this).text(function(i, text){
143
+ if($(this).val() == 'Clear all'){
144
+ $.each(checkboxes,function(i,v){
145
+ $(v).removeClass('wsdplugin_checkbox-active');
146
+ });
147
+ $(this).val('Select all');
148
+ }
149
+ else {
150
+ $.each(checkboxes,function(i,v){
151
+ $(v).addClass('wsdplugin_checkbox-active',true);
152
+ });
153
+ $(this).val('Clear all');
154
+ }
155
+ });
156
+ });
157
+
158
+ $('form').submit(function(){
159
+ $('#chk_options').val('');
160
+ var data = $('.chk-settings').map(function(){
161
+ var self = $(this);
162
+ return {name: self.attr('data-bind'), value: self.hasClass('wsdplugin_checkbox-active')?1:0};
163
+ }).get();
164
+ $('#chk_options').val($.param(data));
165
+ $('#chk_rss_wgt_display').val($('.chk-extra').hasClass('wsdplugin_checkbox-active')?1:0);
166
+ });
167
+ });
168
+ </script>
res/pages/tpl/box-available-backups.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <?php
3
+ /*
4
+ * DISPLAY AVAILABLE DOWNLOADS
5
+ *======================================================
6
+ */
7
+ ?>
8
+ <?php
9
+ $files = WsdUtil::getAvailableBackupFiles();
10
+
11
+ if (empty($files))
12
+ {
13
+ echo '<p>',__("You don't have any backup files yet!"),'</p>';
14
+ }
15
+ else {
16
+ echo '<div class="acx-section-box">';
17
+ echo '<ul id="bck-list" class="acx-common-list">';
18
+ foreach($files as $fileName) {
19
+ echo '<li>';
20
+ echo '<a href="',WSS_PLUGIN_URL.'res/backups/',$fileName,'" title="',__('Click to download'),'">',$fileName,'</a>';
21
+ echo '</li>';
22
+ }
23
+ echo '</ul>';
24
+ echo '</div>';
25
+ }
26
+ ?>
res/pages/tpl/box-banners.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <?php if(! WsdUtil::isAdministrator()) { return; } ?>
3
+ <div id="wsd-banner-rotator" class="wsdplugin-overflow">
4
+ <div style="width:800px; margin: 0 auto;">
5
+ <a href="//www.acunetix.com/" style="border:none;text-decoration: none;" target="_blank" title="Visit www.acunetix.com (opens in a new window/tab)">
6
+ <img src="//www.acunetix.com/assets/banner.jpg" alt="" title=""/>
7
+ </a>
8
+ </div>
9
+ </div>
res/pages/tpl/box-database-backup.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+
3
+
4
+ <div class="">
5
+ <blockquote>
6
+ <p><?php echo __('Your WordPress database contains every post, every comment and every link you have on your blog. If your database gets erased or corrupted, you stand to lose everything you have written. There are many reasons why this could happen and not all are things you can control. But what you can do is <strong>back up your data</strong>.'); ?></p>
7
+ <p style="text-align: center;"><?php echo __('<strong>Please backup your database before using this tool!</strong>');?></p>
8
+ <p style="text-align: right;"><cite><a href="http://codex.wordpress.org/WordPress_Backups" target="_blank">Wordpress</a></cite></p>
9
+ </blockquote>
10
+ </div>
11
+
12
+ <?php
13
+ /*
14
+ * Check if the backups directory is writable
15
+ *======================================================
16
+ */
17
+ $wsd_bckDirPath = WSS_PLUGIN_DIR.'res/backups/';
18
+ if (is_dir($wsd_bckDirPath) && is_writable($wsd_bckDirPath)) :
19
+ ?>
20
+
21
+
22
+ <?php
23
+ if ($_SERVER['REQUEST_METHOD'] == 'POST')
24
+ {
25
+ if (isset($_POST['wsd_db_backup']))
26
+ {
27
+
28
+ if ('' <> ($fname = WsdUtil::backupDatabase())) {
29
+ echo '<p class="acx-info-box">';
30
+ echo '<span>',__('Database successfully backed up!'),'</span>';
31
+ echo '<br/><span>',__('Download backup file'),': </span>';
32
+ echo '<a href="',WSS_PLUGIN_URL.'res/backups/',$fname,'" style="color:#000">',$fname,'</a>';
33
+ echo '</p>';
34
+ }
35
+ else {
36
+ echo '<p class="acx-info-box">';
37
+ echo __('The database could not be backed up!');
38
+ echo '<br/>',__("A possible error might be that you didn't set up writing permissions for the backups directory!");
39
+ echo '</p>';
40
+ }
41
+ }
42
+ }
43
+ ?>
44
+ <div class="acx-section-box">
45
+ <form action="#bckdb" method="post">
46
+ <input type="hidden" name="wsd_db_backup"/>
47
+ <input type="submit" class="button-primary" name="backupDatabaseButton" value="<?php echo __('Backup now!');?>"/>
48
+ </form>
49
+ </div>
50
+
51
+ <?php else : //!! The directory is not writable. Display the info message
52
+
53
+ echo '<p class="acx-info-box">';
54
+ printf(__('<strong>Important</strong>: The <code title="%s">backups</code> directory <strong>MUST</strong> be writable in order to use this feature!')
55
+ ,WSS_PLUGIN_DIR.'res/backups');
56
+ echo '</p>';
57
+ endif; ?>
res/pages/tpl/box-database-change-prefix.php ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <?php
3
+ /*
4
+ * =====================================================================================
5
+ * Because this feature is error prone and the blog can go "bye-bye" in a second,
6
+ * ensure we've checked EVERYTHING before displaying the form
7
+ * =====================================================================================
8
+ */
9
+ global $table_prefix;
10
+
11
+ //## Assume FALSE
12
+ $showPage = false; // whether or not to display this page
13
+ $isWPConfigWritable = false; // whether or not the wp-config file is writable
14
+ $cdtpIsPostBack = false; // whether or not the form was posted back.
15
+ $acxInfoMessage = $wsd_Message = ''; // Hold the error/info messages generated on form postback
16
+ $old_prefix = $table_prefix;
17
+ $new_prefix = ''; // leave empty. it will be populated at runtime
18
+ $canAlter = false; // Assume the user doesn't have ALTER rights
19
+
20
+ $wpConfigFile = trailingslashit(ABSPATH).'wp-config.php';
21
+ $acx_dbRights = WsdInfoServer::getDatabaseUserAccessRights();
22
+
23
+ if (is_writable($wpConfigFile)){
24
+ $isWPConfigWritable = true;
25
+ }
26
+
27
+ if ($acx_dbRights['rightsEnough']) {
28
+ $canAlter = true;
29
+ }
30
+
31
+ //!! Check wp-config.php file and rights first
32
+ if ($isWPConfigWritable && $canAlter){
33
+ $showPage = true;
34
+ }
35
+
36
+ // Check if user has enough rights to alter the Table structure
37
+ if ($acx_dbRights['rightsEnough'])
38
+ {
39
+ $_canAlter = '<span style="color: #060; font-weight: 900;">('.__('Yes').')</span>';
40
+ }
41
+ else { $_canAlter = '<span style="color: #f00; font-weight: 900;">('.__('No').')</span>'; }
42
+
43
+ if ($isWPConfigWritable)
44
+ {
45
+ $wpConfigFileinfo = '<span style="color: #060; font-weight: 900;">('.__('Yes').')</span>';
46
+ }
47
+ else { $wpConfigFileinfo = '<span style="color: #f00; font-weight: 900;">('.__('No').')</span>'; }
48
+ ?>
49
+
50
+ <div class="acx-section-box">
51
+ <p><?php echo __('Change your database table prefix to avoid zero-day SQL Injection attacks.');?></p>
52
+ <h4 style="margin-top: 15px;"><?php echo __('Before running this script');?>:</h4>
53
+ <ul class="acx-common-list" style="margin-top: 20px;">
54
+ <li><?php echo __('The <code>wp-config.php</code> file must be <strong>writable</strong>.').' '.$wpConfigFileinfo;?></li>
55
+ <li><?php echo __("The database user you're using to connect to database must have <strong>ALTER</strong> rights.").' '.$_canAlter;?></li>
56
+ </ul>
57
+ </div>
58
+
59
+ <?php
60
+ /*
61
+ * If the user doesn't have ALTER rights or the wp-config file is not writable
62
+ *============================================================================
63
+ */
64
+ //@ if all good but we cannot use the "file' function, stop here
65
+ if ($showPage && !function_exists('file'))
66
+ {
67
+ echo '<p class="acx-info-box">';
68
+ echo '<span class="acx-icon-alert-info">';
69
+ echo __('In order to alter the <code>wp-config.php</code> file we need the <strong>file</strong> function which seems to be blacklisted by your server administrator!');
70
+ echo '</span>';
71
+ echo '</p>';
72
+
73
+ return;
74
+ }
75
+
76
+ //@ If we cannot load the page
77
+ if ( ! $showPage )
78
+ {
79
+ echo '<p class="acx-info-box">';
80
+ if (!$canAlter) {
81
+ echo '<span class="acx-icon-alert-critical">';
82
+ echo __('The User used to access the database must have <strong>ALTER</strong> rights in order to perform this action!');
83
+ echo '</span><br/>';
84
+ }
85
+ if (!$isWPConfigWritable) {
86
+ echo '<span>';
87
+ echo __('The <strong>wp-config</strong> file <strong>MUST</strong> be writable!');
88
+ echo '</span>';
89
+ }
90
+ echo '</p>';
91
+
92
+ //!! Stop here, no need to load the rest of the page
93
+ return;
94
+ }
95
+ ?>
96
+
97
+ <?php
98
+ /*
99
+ * Issue the file permissions warning ONLY IF wp-config IS WRITABLE,
100
+ * otherwise the form gets confusing displaying so many info messages...
101
+ *======================================================================
102
+ */
103
+ if ($isWPConfigWritable)
104
+ {
105
+ echo '<p class="acx-info-box">';
106
+ echo '<span class="acx-icon-alert-info">';
107
+ echo __('It is a security risk to have your files <strong>writable</strong>!
108
+ Please make sure that <strong>after</strong> running this script, the <code>wp-config.php</code> file\'s permissions are set to 0644 or to a more restrictive one. See: <a href="http://codex.wordpress.org/Changing_File_Permissions" target="_blank">http://codex.wordpress.org/Changing_File_Permissions</a> for more information.');
109
+ echo '</span>';
110
+ echo '</p>';
111
+ }
112
+ //@ If the user has too many rights
113
+ if (!empty($acx_dbRights['rightsTooMuch'])) {
114
+ echo '<p class="acx-info-box">';
115
+ echo '<span class="acx-icon-alert-info">'. __("Your currently used User to access the Wordpress Database <code>holds too many rights</code>. We suggest that you limit his rights or to use another User with more limited rights instead, to increase your website's Security.").'</span>';
116
+ echo '</p>';
117
+ }
118
+ ?>
119
+
120
+ <?php
121
+ /*
122
+ * VALIDATE FORM
123
+ *======================================================
124
+ */
125
+ if ($_SERVER['REQUEST_METHOD'] == 'POST')
126
+ {
127
+ if (!empty($_POST['newPrefixInput']) && isset($_POST['changePrefixButton']))
128
+ {
129
+ $cdtpIsPostBack = true;
130
+
131
+ if (function_exists('wp_nonce_field')) {
132
+ check_admin_referer('prefix-changer-change_prefix');
133
+ }
134
+
135
+ //@@ Double check the request
136
+ if (!$isWPConfigWritable || !$canAlter)
137
+ {
138
+
139
+ $e = __('Please correct the following errors').':<br/>';
140
+ $e .= '<br/>'.__('The User used to access the database must have <strong>ALTER</strong> rights in order to perform this action!');
141
+ $e .= '<br/>'.__('The <strong>wp-config</strong> file <strong>MUST</strong> be writable!');
142
+
143
+ wp_die($e);
144
+ }
145
+
146
+ $wpdb = $GLOBALS['wpdb'];
147
+ if (empty($wpdb))
148
+ {
149
+ wp_die(__('An internal error has occurred (empty $wpdb). Please inform the plug-in author about this error. Thank you!'));
150
+ }
151
+
152
+ $new_prefix = $_POST['newPrefixInput'];
153
+
154
+ // validate prefix
155
+ if(! preg_match('/^[a-zA-Z_][a-zA-Z0-9_]+$/', $new_prefix)){
156
+ $acxInfoMessage .= sprintf('Invalid table name prefix: %s', htmlentities($new_prefix));
157
+ $new_prefix = $old_prefix;
158
+ }
159
+ else
160
+ {
161
+ if (empty($acx_dbRights['rightsEnough']))
162
+ {
163
+ $wsd_Message .= '<span class="acx-icon-alert-critical">'. __('The User which is used to access your Wordpress Database, hasn\'t enough rights (is missing the <code>ALTER</code> right) to alter the Table structure.
164
+ Please visit the <a href="http://www.websitedefender.com/category/faq/" target=_blank">WebsiteDefender WP Security Scan WordPress plugin documentation</a> website for more information.
165
+ If the user <code>has ALTER</code> rights and the tool is still not working, please <a href="http://www.websitedefender.com/support/" target="_blank">contact us</a> for assistance!').'</span>';
166
+ }
167
+
168
+ if (strlen($new_prefix) < strlen($_POST['newPrefixInput'])){
169
+ $acxInfoMessage .= __('You used some characters disallowed in Table names. The sanitized prefix will be used instead').': '.$new_prefix;
170
+ }
171
+ if ($new_prefix == $old_prefix) {
172
+ if (!empty($acxInfoMessage)) { $acxInfoMessage .= '<br/>'; }
173
+ $acxInfoMessage .= __('No change! Please select a different table prefix value.');
174
+ }
175
+ else
176
+ {
177
+ // Get the list of tables to modify
178
+ $tables = WsdUtil::getTablesToAlter();
179
+ if (empty($tables))
180
+ {
181
+ if (!empty($acxInfoMessage)) { $acxInfoMessage .= '<br/>'; }
182
+ $acxInfoMessage .= __("Internal Error: We couldn't retrieve the list of tables from the database! Please inform the plug-in author about this error! Thank you!");
183
+ }
184
+ else
185
+ {
186
+ $result = WsdUtil::renameTables($tables, $old_prefix, $new_prefix);
187
+
188
+ // check for errors
189
+ if (!empty($result))
190
+ {
191
+ if (!empty($acxInfoMessage)) { $acxInfoMessage .= '<br/>'; }
192
+ $acxInfoMessage .= '<span class="acx-notice-success acx-icon-alert-success">'.__('All tables have been successfully updated!').'</span>';
193
+
194
+ // try to rename the fields
195
+ $acxInfoMessage .= WsdUtil::renameDbFields($old_prefix, $new_prefix);
196
+
197
+ if (0 < WsdUtil::updateWpConfigTablePrefix($wpConfigFile, $new_prefix))
198
+ {
199
+ $acxInfoMessage .= '<br/><span class="acx-notice-success acx-icon-alert-success">'.__('The <strong>wp-config</strong> file has been successfully updated!').'</span>';
200
+ }
201
+ else {
202
+ $acxInfoMessage .= '<br/>'.__('The <strong>wp-config</strong> file could not be updated! You have to manually update the <strong>$table_prefix</strong> variable to the one you have specified').': '.$new_prefix;
203
+ }
204
+ }// End if tables successfully renamed
205
+ else { $acxInfoMessage .= '<br/><strong>'.__('An error has occurred and the tables could not be updated!').'</strong>'; }
206
+ }// End if there are tables to rename
207
+ }// End checks
208
+ }
209
+ }// End if (!empty($_POST['newPrefixInput']))
210
+ }// End if postback
211
+ else { $new_prefix = $old_prefix; }
212
+
213
+ if(empty($new_prefix)){
214
+ $new_prefix = $old_prefix;
215
+ }
216
+ ?>
217
+
218
+ <?php
219
+ /*
220
+ * Dsplay the form
221
+ *=======================================================
222
+ */
223
+ ?>
224
+ <div class="acx-section-box">
225
+ <form action="#cdtp" method="post" name="prefixchanging">
226
+ <?php if (function_exists('wp_nonce_field')) { wp_nonce_field('prefix-changer-change_prefix'); } ?>
227
+ <p><?php echo sprintf(__('Change the current: <input type="text" name="newPrefixInput" value="%s" size="20" maxlength="15"/> table prefix to something different.'), $new_prefix); ?></p>
228
+ <p><?php echo __('Allowed characters: all latin alphanumeric as well as the <strong>_</strong> (underscore).');?></p>
229
+ <input type="submit" class="button-primary" name="changePrefixButton" value="<?php echo __('Start Renaming');?>" />
230
+ </form>
231
+ </div>
232
+ <div id="cdtp">
233
+ <?php
234
+ // Display status information
235
+ if ($cdtpIsPostBack){
236
+ if (!empty($acxInfoMessage)){ echo '<p class="acx-info-box">',$acxInfoMessage,'</p>'; }
237
+ if (!empty($wsd_Message)) { echo '<p class="acx-info-box">',$wsd_Message,'</p>'; }
238
+ }
239
+ else {
240
+ if (!empty($wsd_Message)) { echo '<p class="acx-info-box">',$wsd_Message,'</p>'; }
241
+ }
242
+ ?>
243
+ </div>
res/pages/tpl/box-scan-results-file.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; }
2
+ /*
3
+ * Displays the File scan results info
4
+ */
5
+ global $acxFileList;
6
+ ?>
7
+ <?php
8
+ $acx_isPostBack = false;
9
+ $acx_message = '';
10
+
11
+ //@ IF POSTBACK
12
+ if(! WsdUtil::isWinOs()){
13
+ if ($_SERVER['REQUEST_METHOD'] == 'POST')
14
+ {
15
+ // check nonce
16
+ if(isset($_POST['wsdplugin_update_paths_field'])){
17
+ if(!wp_verify_nonce($_POST['wsdplugin_update_paths_field'],'wsdplugin_update_paths')){
18
+ wp_die(__('Invalid request.'));
19
+ }
20
+ }
21
+ else {wp_die(__('Invalid request.'));}
22
+
23
+ $acx_isPostBack = true;
24
+
25
+ $result = WsdUtil::changeFilePermissions($acxFileList);
26
+
27
+ if (empty($result)) {
28
+ $acx_message = __('No changes applied. You are running PHP on a Windows server thus chmod cannot be used');
29
+ }
30
+ else { $acx_message = __('Successful changes').': '.$result['success'].', '.__('Failed').': '.$result['failed']; }
31
+ }
32
+ }
33
+ ?>
34
+ <?php
35
+ //@ Check the files
36
+ if (empty($acxFileList)) {
37
+ echo __('There are currently no files set for scanning!');
38
+ }
39
+ else
40
+ {
41
+ echo '<form method="post">';
42
+ wp_nonce_field('wsdplugin_update_paths','wsdplugin_update_paths_field');
43
+ echo '<table class="widefat acx-table" cellpadding="0" cellspacing="0">';
44
+ echo '<thead class="widget-top">';
45
+ echo '<tr>';
46
+ echo '<td></td>';
47
+ echo '<td><strong>',__('Name'),'</strong></td>';
48
+ echo '<td><strong>',__('Path'),'</strong></td>';
49
+ echo '<td><strong>',__('Current permissions'),'</strong></td>';
50
+ echo '<td><strong>',__('Suggested permissions'),'</strong></td>';
51
+ echo '</tr>';
52
+ echo '</thead>';
53
+ echo '<tbody>';
54
+ foreach($acxFileList as $fileName => $v)
55
+ {
56
+ $filePath = $v['filePath'];
57
+ $p = WsdUtil::getFilePermissions($filePath);
58
+ $sp = $v['suggestedPermissions'];
59
+
60
+ $cssClass = ((octdec($p) == octdec($sp)) ? 'success' : 'error');
61
+
62
+ echo '<tr>';
63
+ echo '<td class="td_'.$cssClass.'"></td>';
64
+ echo '<td>',$fileName,'</td>';
65
+ echo '<td>',(empty($filePath) ? 'Not Found' : WsdUtil::normalizePath($filePath)),'</td>';
66
+ //@ Current
67
+ if ($p > octdec('0')) {
68
+ echo '<td>',$p,'</td>';
69
+ }
70
+ else { echo '<td>',__('Not Found'),'</td>'; }
71
+
72
+ //@ Suggested
73
+ if (file_exists($filePath))
74
+ {
75
+ echo '<td>',$sp,'</td>';
76
+ }
77
+ else
78
+ {
79
+ if (is_file($filePath)) {
80
+ echo '<td>0644</td>';
81
+ }
82
+ elseif (is_dir($filePath)) { echo '<td class="center">0755</td>'; }
83
+ else {
84
+ echo '<td>',$sp,'</td>';
85
+ }
86
+ }
87
+ echo '</tr>';
88
+ }
89
+ echo '</tbody>';
90
+ echo '</table>';
91
+
92
+ if(! WsdUtil::isWinOs()){
93
+ echo '<div class="wsdplugin-overflow"><p style="text-align: right; clear: both; margin: 7px 0 0 0;" class="wsdplugin-overflow">';
94
+ //@@ Display action result
95
+ if ($acx_isPostBack && !empty($acx_message)){
96
+ echo '<p class="acx-info-box" style="float: left; width: 70%; margin: 0 0; padding-top: 3px; padding-bottom: 3px;">'.$acx_message.'</p>';
97
+ }
98
+ echo '<input type="submit" value="Apply suggested permissions" class="button-primary" style="float: right;" /></div>';
99
+ }
100
+ echo '</form>';
101
+
102
+ echo '<p class="acx-info-box" style="margin: 7px 0 7px 0;">';
103
+ echo __('Our suggested permissions are still secure but more permissive in order not to break some servers\' setups.
104
+ If your existent file permissions are more restrictive, ex: 0750 instead of the suggested 0755 then you have no reason to
105
+ change it to the suggested 0755 permissions.');
106
+ echo '</p>';
107
+ }
108
+ ?>
res/pages/tpl/box-scan-results-wp.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <ul class="acx-common-list">
3
+ <?php
4
+ // display wp info
5
+ $class = new ReflectionClass('WsdInfo');
6
+ $methods = $class->getMethods();
7
+ if(! empty($methods)){
8
+ foreach($methods as $method){
9
+ echo '<li><p>'.call_user_func(array($method->class, $method->name)).'</p></li>';
10
+ }
11
+ }
12
+ ?>
13
+ </ul>
res/pages/tpl/box-server-results.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php if(! WsdUtil::canLoad()) { return; } ?>
2
+ <?php echo WsdInfoServer::getServerInfo();?>
3
+
res/pages/tpl/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php /* here, only to prevent directory listing */
screenshot-1.jpg CHANGED
Binary file
screenshot-2.jpg CHANGED
Binary file
screenshot-3.jpg ADDED
Binary file
screenshot-4.jpg ADDED
Binary file
securityscan.php DELETED
@@ -1,268 +0,0 @@
1
- <?php
2
- /*
3
- Plugin Name: WP Security Scan
4
- Plugin URI: http://www.websitedefender.com/news/free-wordpress-security-scan-plugin/
5
-
6
- Description: Perform security scan of WordPress installation.
7
- Author: WebsiteDefender
8
- Version: 3.0.8
9
- Author URI: http://www.websitedefender.com/
10
- */
11
- /*
12
- * $rev #1 07/17/2011 {c}
13
- * $rev #2 07/26,27/2011 {c}
14
- * $rev #3 08/05/2011 {c}
15
- * $rev #4 08/26/2011 {c}
16
- * $rev #5 09/12/2011 {c}
17
- * $rev #6 09/20/2011 {c}
18
- * $rev #7 09/30/2011 {c}
19
- * $rev #8 10/03/2011 {c}
20
- */
21
- /*
22
- Copyright (C) 2008-2010 Acunetix / http://www.websitedefender.com/
23
- (info AT websitedefender DOT com)
24
-
25
-
26
- This program is free software; you can redistribute it and/or modify
27
- it under the terms of the GNU General Public License as published by
28
- the Free Software Foundation; either version 3 of the License, or
29
- (at your option) any later version.
30
-
31
- This program is distributed in the hope that it will be useful,
32
- but WITHOUT ANY WARRANTY; without even the implied warranty of
33
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
- GNU General Public License for more details.
35
-
36
- You should have received a copy of the GNU General Public License
37
- along with this program. If not, see <http://www.gnu.org/licenses/>.
38
- */
39
- if ( ! defined('WP_CONTENT_URL')) {
40
- define( 'WP_CONTENT_URL', get_option( 'siteurl' ) . '/wp-content' );
41
- }
42
- if ( ! defined('WP_CONTENT_DIR')) {
43
- define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
44
- }
45
- if ( ! defined('WP_PLUGIN_URL')) {
46
- define( 'WP_PLUGIN_URL', WP_CONTENT_URL. '/plugins' );
47
- }
48
- if ( ! defined('WP_PLUGIN_DIR')) {
49
- define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' );
50
- }
51
-
52
- delete_option('wsd_feed_data');
53
-
54
- if(!function_exists('json_encode') || !class_exists('Services_JSON')) {
55
- @require_once(WP_PLUGIN_DIR . "/wp-security-scan/libs/json.php");
56
- }
57
- require_once(WP_PLUGIN_DIR . "/wp-security-scan/libs/functions.php");
58
-
59
- if (!defined('WSD_RECAPTCHA_API_SERVER')) {
60
- @require_once(WP_PLUGIN_DIR . "/wp-security-scan/libs/recaptchalib.php");
61
- }
62
- require_once(WP_PLUGIN_DIR . "/wp-security-scan/libs/wsd.php");
63
-
64
- //menus
65
- require_once(WP_PLUGIN_DIR . "/wp-security-scan/inc/admin/security.php");
66
- require_once(WP_PLUGIN_DIR . "/wp-security-scan/inc/admin/scanner.php");
67
- require_once(WP_PLUGIN_DIR . "/wp-security-scan/inc/admin/pwtool.php");
68
- require_once(WP_PLUGIN_DIR . "/wp-security-scan/inc/admin/plugin_options.php");
69
- require_once(WP_PLUGIN_DIR . "/wp-security-scan/inc/admin/db.php");
70
- require_once(WP_PLUGIN_DIR . "/wp-security-scan/inc/admin/support.php");
71
- require_once(WP_PLUGIN_DIR . "/wp-security-scan/inc/admin/templates/header.php");
72
- require_once(WP_PLUGIN_DIR . "/wp-security-scan/inc/admin/templates/footer.php");
73
-
74
-
75
- //## this is the container for header scripts
76
- add_action('admin_head', 'mrt_hd');
77
- // # $rev #2 {c}
78
- add_action('admin_init', 'wps_admin_init_load_resources');
79
-
80
- //before sending headers
81
- add_action("init",'mrt_wpdberrors',1);
82
-
83
- //after executing a query
84
- add_action("parse_query",'mrt_wpdberrors',1);
85
-
86
- //## add the sidebar menu
87
- add_action('admin_menu', 'add_men_pg');
88
-
89
- add_action("init", 'mrt_remove_wp_version',1); //comment out this line to make ddsitemapgen work
90
-
91
- //before rendering each admin init
92
- add_action('admin_init','mrt_wpss_admin_init');
93
-
94
- // Check to see whether or not we should display the dashboard widget
95
- //@ $rev4
96
- $plugin1 = 'websitedefender-wordpress-security';
97
- $plugin2 = 'secure-wordpress';
98
- if (! in_array($plugin1.'/'.$plugin1.'.php', apply_filters('active_plugins', get_option('active_plugins')))
99
- || ! in_array($plugin2.'/'.$plugin2.'.php', apply_filters('active_plugins', get_option('active_plugins'))))
100
- {
101
- define('WPSS_WSD_BLOG_FEED', 'http://www.websitedefender.com/feed/');
102
- @require_once('libs/wpssUtil.php');
103
- //@@ Hook into the 'wp_dashboard_setup' action to create the dashboard widget
104
- add_action('wp_dashboard_setup', "wpssUtil::addDashboardWidget");
105
- }
106
- unset($plugin1,$plugin2);
107
- //@===
108
-
109
- function mrt_wpss_admin_init(){
110
- wp_enqueue_style('wsd_style', WP_PLUGIN_URL . '/wp-security-scan/css/wsd.css');
111
- /* #r5# */
112
- $h6 = 'swp-dashboard';
113
- wp_register_style($h6, WP_PLUGIN_URL . '/wp-security-scan/css/acx-wp-dashboard.css');
114
- wp_enqueue_style($h6);
115
- }
116
-
117
- remove_action('wp_head', 'wp_generator');
118
- function add_men_pg() {
119
- if (function_exists('add_menu_page'))
120
- {
121
- add_menu_page('WSD security', 'WSD security', 'edit_pages', __FILE__, 'mrt_opt_mng_pg', WP_PLUGIN_URL.'/wp-security-scan/images/wsd-logo-small.png');
122
- add_submenu_page(__FILE__, 'Scanner', 'Scanner', 'edit_pages', 'scanner', 'mrt_sub0');
123
- add_submenu_page(__FILE__, 'Password Tool', 'Password Tool', 'edit_pages', 'passwordtool', 'mrt_sub1');
124
- add_submenu_page(__FILE__, 'Database', 'Database', 'edit_pages', 'database', 'mrt_sub3');
125
- add_submenu_page(__FILE__, 'Options', 'Options', 'edit_pages', 'plugin_options', 'mrt_sub4');
126
- add_submenu_page(__FILE__, 'Support', 'Support', 'edit_pages', 'support', 'mrt_sub2');
127
- }
128
- }
129
-
130
- //## @since v3.0.8
131
- //Display the "Settings" menu on plug-in page
132
- add_filter( 'plugin_action_links_'.plugin_basename(__FILE__), 'wpss_admin_plugin_actions', -10);
133
-
134
-
135
- function wpss_admin_head() {
136
- $scheme = 'http';
137
- if ( is_ssl() ) {
138
- $scheme = 'https';
139
- }
140
- }
141
- add_action( 'admin_head', 'wpss_admin_head' );
142
-
143
-
144
- // function for WP < 2.8
145
- function get_plugins_url($path = '', $plugin = '') {
146
-
147
- if ( function_exists('plugin_url') )
148
- return plugins_url($path, $plugin);
149
-
150
- if ( function_exists('is_ssl') )
151
- $scheme = ( is_ssl() ? 'https' : 'http' );
152
- else
153
- $scheme = 'http';
154
- if ( function_exists('plugins_url') )
155
- $url = plugins_url();
156
- else
157
- $url = WP_PLUGIN_URL;
158
- if ( 0 === strpos($url, 'http') ) {
159
- if ( function_exists('is_ssl') && is_ssl() )
160
- $url = str_replace( 'http://', "{$scheme}://", $url );
161
- }
162
-
163
- if ( !empty($plugin) && is_string($plugin) )
164
- {
165
- $folder = dirname(plugin_basename($plugin));
166
- if ('.' != $folder)
167
- $url .= '/' . ltrim($folder, '/');
168
- }
169
-
170
- if ( !empty($path) && is_string($path) && strpos($path, '..') === false )
171
- $url .= '/' . ltrim($path, '/');
172
-
173
- return apply_filters('plugins_url', $url, $path, $plugin);
174
- }
175
-
176
- function wpss_mrt_meta_box()
177
- {
178
- ?>
179
- <div id="wsd-initial-scan" class="wsd-inside">
180
- <div class="wsd-initial-scan-section"><?php mrt_check_version();?></div>
181
-
182
- <div class="wsd-initial-scan-section"><?php mrt_check_table_prefix();?></div>
183
-
184
- <div class="wsd-initial-scan-section"><?php mrt_version_removal();?></div>
185
-
186
- <div class="wsd-initial-scan-section"><?php mrt_errorsoff();?></div>
187
- <?php
188
- global $wpdb;
189
-
190
- echo '<div class="scanpass">WP ID META tag removed form WordPress core</div>';
191
-
192
- echo '<div class="wsd-initial-scan-section">';
193
- $name = $wpdb->get_var("SELECT user_login FROM $wpdb->users WHERE user_login='admin'");
194
- if ($name == "admin") {
195
- echo '<font color="red">"admin" user exists.</font>';
196
- }
197
- else { echo '<span class="scanpass">No user "admin".</span>'; }
198
- echo '</div>';
199
-
200
- echo '<div class="wsd-initial-scan-section">';
201
- if (file_exists('.htaccess')) {
202
- echo '<span class="scanpass">.htaccess file found in wp-admin/</span>';
203
- }
204
- else { echo '<span style="color:#f00;">
205
- The file .htaccess does not exist in the wp-admin section.
206
- Read more why you should have a .htaccess file in the WP-admin area
207
- <a href="http://www.websitedefender.com/wordpress-security/htaccess-files-wordpress-security/"
208
- title="Why you should have a .htaccess file in the WP-admin area" target="_blank">here</a>.
209
- </span>'; }
210
- echo '</div>';
211
-
212
- ?>
213
-
214
- <div class="mrt_wpss_note">
215
- <em>**WP Security Scan plugin <strong>must</strong> remain active for security features to persist**</em>
216
- </div>
217
- </div>
218
- <?php
219
- }
220
-
221
-
222
- function wpss_mrt_meta_box2()
223
- {
224
- ?>
225
- <ul id="wsd-information-scan-list"">
226
- <?php mrt_get_serverinfo(); ?>
227
- </ul>
228
- <?php
229
- }
230
-
231
-
232
- // $rev #2: only load if they're not already.
233
- function wps_admin_init_load_resources()
234
- {
235
- wp_enqueue_script('acx-json', WP_PLUGIN_URL.'/wp-security-scan/js/json.js');
236
- wp_enqueue_script('acx-md5', WP_PLUGIN_URL.'/wp-security-scan/js/md5.js');
237
- wp_enqueue_script('wsd-scripts', WP_PLUGIN_URL.'/wp-security-scan/js/scripts.js');
238
- wp_enqueue_script('wsd-wsd', WP_PLUGIN_URL.'/wp-security-scan/js/wsd.js');
239
- }
240
-
241
- function mrt_hd()
242
- {
243
- ?>
244
- <script type="text/javascript">
245
- var wordpress_site_name = "<?php echo htmlentities(get_bloginfo('siteurl'));?>"
246
- </script>
247
- <script type="text/javascript">
248
- var _wsdPassStrengthProvider = null;
249
-
250
- jQuery(document).ready(function($) {
251
- _wsdPassStrengthProvider = new wsdPassStrengthProvider($);
252
- _wsdPassStrengthProvider.init();
253
-
254
- $('#wpss_mrt_1.postbox h3, #wpss_mrt_2.postbox h3, #wpss_mrt_3.postbox h3').click(function() {
255
- var parent = $(this).parent();
256
- if (parent) parent.toggleClass('closed');
257
- });
258
- $('#wpss_mrt_1.postbox .handlediv, #wpss_mrt_2.postbox .handlediv, #wpss_mrt_3.postbox .handlediv').click(function() {
259
- var parent = $(this).parent();
260
- if (parent) parent.toggleClass('closed');
261
- });
262
- $('#wpss_mrt_1.postbox.close-me, #wpss_mrt_2.postbox.close-me, #wpss_mrt_3.postbox.close-me').each(function() {
263
- $(this).addClass("closed");
264
- });
265
- });
266
- </script>
267
- <?php }
268
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
uninstall.php DELETED
@@ -1,12 +0,0 @@
1
- <?php if( !defined( 'ABSPATH') && !defined('WP_UNINSTALL_PLUGIN') ) { exit(); }
2
- /*
3
- * Delete stored options from the options table
4
- */
5
- delete_option('wsd_feed_data');
6
-
7
- // this is a shared option so if there are
8
- // any other plug-ins installed, then don't
9
- // delete it.
10
- $__1 = ABSPATH.'wp-content/plugins/websitedefender-wordpress-security';
11
- $__2 = ABSPATH.'wp-content/plugins/secure-wordpress';
12
- if (!is_dir($__1) || !is_dir($__2)) { delete_option('wsd_feed_data'); }
 
 
 
 
 
 
 
 
 
 
 
 
wss-settings.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(! defined('WSS_PLUGIN_PREFIX')) exit;
2
+ /**
3
+ * Informational alert. Value: 0
4
+ */
5
+ define('WSS_PLUGIN_ALERT_INFO', 0);
6
+ /**
7
+ * Low alert. Value: 1
8
+ */
9
+ define('WSS_PLUGIN_ALERT_LOW', 1);
10
+ /**
11
+ * Medium alert. Value: 2
12
+ */
13
+ define('WSS_PLUGIN_ALERT_MEDIUM', 2);
14
+ /**
15
+ * Critical alert. Value: 3
16
+ */
17
+ define('WSS_PLUGIN_ALERT_CRITICAL', 3);
18
+
19
+ define('WSS_PLUGIN_ALERT_TYPE_OVERWRITE', 0);
20
+ define('WSS_PLUGIN_ALERT_TYPE_STACK', 1);
21
+
22
+ //#! The max number of stacked alerts to keep
23
+ define('WSS_PLUGIN_ALERT_STACK_MAX_KEEP', 10);
24
+
25
+ //#! Database settings
26
+ define('WSS_PLUGIN_ALERT_TABLE_NAME', '_wsd_plugin_alerts');
27
+ //
28
+ define('WSS_PLUGIN_LIVE_TRAFFIC_TABLE_NAME', '_wsd_plugin_live_traffic');
29
+
30
+ define('WSS_PLUGIN_BACKUPS_DIR', WSS_PLUGIN_DIR.'res/backups/');
31
+
32
+ define('WSS_PLUGIN_TEXT_DOMAIN', 'WSDWP_SECURITY');
33
+
34
+ define('WSS_PLUGIN_SETTINGS_OPTION_NAME', 'wsdplugin_settings');
35
+
36
+ /**
37
+ * Set the path to the WebsiteDefender.com feed
38
+ */
39
+ define('WSS_PLUGIN_BLOG_FEED','http://www.acunetix.com/blog/');
40
+
41
+ /**
42
+ * Sets the list of files to check for permissions
43
+ * @type array
44
+ */
45
+ $_wsdplugin_base_path = trailingslashit(ABSPATH);
46
+ $_wsdplugin_wpAdmin = $_wsdplugin_base_path.'wp-admin';
47
+ $_wsdplugin_wpContent = $_wsdplugin_base_path.'wp-content';
48
+ $_wsdplugin_wpIncludes = $_wsdplugin_base_path.'wp-includes';
49
+ $_wsdpluginWpConfigPath ='';
50
+ //$_wsdplugin_base_path.'wp-config.php';
51
+ if(! is_file($_wsdpluginWpConfigPath)){
52
+ // try one level up
53
+ $_tmpPath = realpath($_wsdplugin_base_path.'../wp-config.php');
54
+ if(is_file($_tmpPath)){
55
+ $_wsdpluginWpConfigPath = $_tmpPath;
56
+ }
57
+ // not found
58
+ else { $_wsdpluginWpConfigPath = ''; }
59
+ }
60
+
61
+ $acxFileList = array(
62
+ //@@ Directories
63
+ 'root directory' => array( 'filePath' => $_wsdplugin_base_path, 'suggestedPermissions' => '0755'),
64
+ 'wp-admin' => array( 'filePath' => $_wsdplugin_wpAdmin, 'suggestedPermissions' => '0755'),
65
+ 'wp-content' => array( 'filePath' => $_wsdplugin_wpContent, 'suggestedPermissions' => '0755'),
66
+ 'wp-includes' => array( 'filePath' => $_wsdplugin_wpIncludes, 'suggestedPermissions' => '0755'),
67
+
68
+ //@@ Files
69
+ '.htaccess' => array( 'filePath' => $_wsdplugin_base_path.'.htaccess', 'suggestedPermissions' => '0644'),
70
+ 'readme.html' => array( 'filePath' => $_wsdplugin_base_path.'readme.html', 'suggestedPermissions' => '0400'),
71
+ 'wp-config.php' => array( 'filePath' => $_wsdpluginWpConfigPath, 'suggestedPermissions' => '0644'),
72
+ 'wp-admin/index.php' => array( 'filePath' => $_wsdplugin_wpAdmin.'/index.php', 'suggestedPermissions' => '0644'),
73
+ 'wp-admin/.htaccess' => array( 'filePath' => $_wsdplugin_wpAdmin.'/.htaccess', 'suggestedPermissions' => '0644'),
74
+ );