Adds a test page Fixes #7
jdarwood007

jdarwood007 commited on 2023-03-13 20:34:47
Showing 5 changed files, with 320 additions and 5 deletions.

... ...
@@ -24,6 +24,7 @@ class SFSA
24 24
 	 */
25 25
 	private $adminPageURL = null;
26 26
 	private $adminLogURL = null;
27
+	private $adminTestURL = null;
27 28
 
28 29
 	/**
29 30
 	 * @var mixed Search area handling.
... ...
@@ -109,7 +110,7 @@ class SFSA
109 110
 	 *
110 111
 	 * @internal
111 112
 	 * @CalledIn SMF 2.0, SMF 2.1
112
-	 * @version 1.0
113
+	 * @version 1.4.0
113 114
 	 * @since 1.0
114 115
 	 * @uses integrate__admin_areas - Hook SMF2.0
115 116
 	 * @uses integrate__admin_areas - Hook SMF2.1
... ...
@@ -124,6 +125,7 @@ class SFSA
124 125
 		{
125 126
 			$this->adminPageURL = $scripturl . '?action=admin;area=modsettings;sa=sfs';
126 127
 			$this->adminLogURL = $scripturl . '?action=admin;area=modsettings;sa=sfslog';
128
+			$this->adminTestURL = $scripturl . '?action=admin;area=modsettings;sa=sfstest';
127 129
 
128 130
 			$admin_areas['config']['areas']['modsettings']['subsections']['sfs'] = array(
129 131
 				$this->SFSclass->txt('sfs_admin_area')
... ...
@@ -131,17 +133,21 @@ class SFSA
131 133
 			$admin_areas['config']['areas']['modsettings']['subsections']['sfslog'] = array(
132 134
 				$this->SFSclass->txt('sfs_admin_logs')
133 135
 			);
136
+			$admin_areas['config']['areas']['modsettings']['subsections']['sfstest'] = array(
137
+				$this->SFSclass->txt('sfs_admin_test')
138
+			);
134 139
 		}
135 140
 		else
136 141
 		{
137 142
 			$this->adminPageURL = $scripturl . '?action=admin;area=modsettings;sa=sfs';
138 143
 			$this->adminLogURL = $scripturl . '?action=admin;area=logs;sa=sfslog';
144
+			$this->adminTestURL = $scripturl . '?action=admin;area=regcenter;sa=sfstest';
139 145
 
140 146
 			$admin_areas['config']['areas']['modsettings']['subsections']['sfs'] = array(
141 147
 				$this->SFSclass->txt('sfs_admin_area')
142 148
 			);
143
-			$admin_areas['maintenance']['areas']['logs']['subsections']['sfslog'] = array(
144
-				$this->SFSclass->txt('sfs_admin_logs')
149
+			$admin_areas['members']['areas']['regcenter']['subsections']['sfstest'] = array(
150
+				$this->SFSclass->txt('sfs_admin_test')
145 151
 			);
146 152
 		}
147 153
 	}
... ...
@@ -174,7 +180,7 @@ class SFSA
174 180
 	 *
175 181
 	 * @internal
176 182
 	 * @CalledIn SMF 2.0, SMF 2.1
177
-	 * @version 1.0
183
+	 * @version 1.4.0
178 184
 	 * @since 1.0
179 185
 	 * @uses integrate_modify_modifications - Hook SMF2.0
180 186
 	 * @uses integrate_modify_modifications - Hook SMF2.1
... ...
@@ -186,7 +192,10 @@ class SFSA
186 192
 
187 193
 		// Only in SMF 2.0 do we drop logs here.
188 194
 		if ($this->SFSclass->versionCheck('2.0', 'smf'))
195
+		{
189 196
 			$subActions['sfslog'] = 'SFSA::startupLogs';
197
+			$subActions['sfstest'] = 'SFSA::startupTest';
198
+		}
190 199
 	}
191 200
 
192 201
 	/**
... ...
@@ -215,7 +224,7 @@ class SFSA
215 224
 	 *
216 225
 	 * @internal
217 226
 	 * @CalledIn SMF 2.0, SMF 2.1
218
-	 * @version 1.0
227
+	 * @version 1.4.0
219 228
 	 * @since 1.0
220 229
 	 * @uses integrate_modify_modifications - Hook SMF2.0
221 230
 	 * @uses integrate_modify_modifications - Hook SMF2.1
... ...
@@ -1151,4 +1160,163 @@ class SFSA
1151 1160
 		else
1152 1161
 			return $this->search_params['type'];
1153 1162
 	}
1163
+
1164
+	/**
1165
+	 * In some software/versions, we can hook into the members registration center section.
1166
+	 * In others we hook into the modifications settings.
1167
+	 *
1168
+	 * @param array $subActions All possible sub actions.
1169
+	 *
1170
+	 * @api
1171
+	 * @CalledIn SMF 2.1
1172
+	 * @See SFSA::startupTest
1173
+	 * @version 1.4.0
1174
+	 * @since 1.4.0
1175
+	 * @uses integrate_manage_registrations - Hook SMF2.1
1176
+	 * @return void No return is generated
1177
+	 */
1178
+	public static function hook_manage_registrations(array &$subActions): bool
1179
+	{
1180
+		global $context;
1181
+
1182
+		// Add our logs sub action.
1183
+		$subActions['sfstest'] = array('SFSA::startupTest', 'admin_forum');
1184
+
1185
+		if (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'sfstest' && allowedTo('admin_forum'))
1186
+			$context['sub_action'] = 'sfstest';
1187
+
1188
+		return self::selfClass()->AddToRegCenterMenu($subActions);
1189
+	}
1190
+
1191
+	/**
1192
+	 * Add the SFS Test to the regcenter menu.
1193
+	 *
1194
+	 * @param array $log_functions All possible log functions.
1195
+	 *
1196
+	 * @CalledIn SMF 2.1
1197
+	 * @See SFSA::startupTest
1198
+	 * @version 1.4.0
1199
+	 * @since 1.4.0
1200
+	 * @return void No return is generated
1201
+	 */
1202
+	public function AddToRegCenterMenu(array &$subActions): bool
1203
+	{
1204
+		global $context;
1205
+
1206
+		$context[$context['admin_menu_name']]['tab_data']['tabs']['sfstest'] = array(
1207
+			'description' => $this->SFSclass->txt('sfs_admin_test_desc'),
1208
+		);
1209
+
1210
+		return true;
1211
+	}
1212
+
1213
+	/**
1214
+	 * Test API startup caller.
1215
+	 * This has a $return_config just for simply complying with properly for searching the admin panel.
1216
+	 *
1217
+	 * @param bool $return_config If true, returns empty array to prevent breaking old SMF installs.
1218
+	 *
1219
+	 * @api
1220
+	 * @CalledIn SMF 2.1
1221
+	 * @See SFSA::loadTestAPI
1222
+	 * @version 1.4.0
1223
+	 * @since 1.4.0
1224
+	 * @uses hook_manage_registrations - Hook SMF2.1
1225
+	 * @uses setupModifyModifications - Injected SMF2.0
1226
+	 * @return void No return is generated
1227
+	 */
1228
+	public static function startupTest(bool $return_config = false): array
1229
+	{
1230
+		return self::selfClass()->loadTestAPI();
1231
+	}
1232
+
1233
+	/**
1234
+	 * Actually do the test API.
1235
+	 * This has a $return_config just for simply complying with properly for searching the admin panel.
1236
+	 *
1237
+	 * @param bool $return_config If true, returns empty array to prevent breaking old SMF installs.
1238
+	 *
1239
+	 * @api
1240
+	 * @CalledIn SMF2.0, SMF 2.1
1241
+	 * @version 1.4.0
1242
+	 * @since 1.4.0
1243
+	 * @uses hook_manage_registrations - Hook SMF2.1
1244
+	 * @uses setupModifyModifications - Injected SMF2.0
1245
+	 * @return void No return is generated
1246
+	 */
1247
+	public function loadTestAPI(bool $return_config = false): array
1248
+	{
1249
+		global $context, $smcFunc, $user_info;
1250
+
1251
+		// No Configs.
1252
+		if ($return_config)
1253
+			return array();
1254
+
1255
+		$context['token_check'] = 'sfs_testapi';
1256
+		$this->SFSclass->loadLanguage();
1257
+
1258
+		// The reuslts output.
1259
+		$context['test_sent'] = isset($_POST['send']);
1260
+		$context['sfs_checks'] = array(
1261
+			'username' => array(
1262
+				0 => array(
1263
+					'enabled' => !empty($modSettings['sfs_usernamecheck']),
1264
+					'value' => !empty($_POST['username']) ? $smcFunc['htmlspecialchars']($_POST['username']) : $user_info['name'],
1265
+					'results' => null
1266
+				),
1267
+			),
1268
+			'email' => array(
1269
+				0 => array(
1270
+					'enabled' => !empty($modSettings['sfs_emailcheck']),
1271
+					'value' => !empty($_POST['email']) ? $smcFunc['htmlspecialchars']($_POST['email']) : $user_info['email'],
1272
+					'results' => null
1273
+				),
1274
+			),
1275
+			'ip' => array(
1276
+				0 => array(
1277
+					'enabled' => !empty($modSettings['sfs_ipcheck']),
1278
+					'value' => !empty($_POST['ip']) ? $smcFunc['htmlspecialchars']($_POST['ip']) : $user_info['ip'],
1279
+					'results' => null
1280
+				),
1281
+			),
1282
+		);
1283
+
1284
+		// Sending the data?
1285
+		if ($context['test_sent'])
1286
+		{
1287
+			//checkSession();
1288
+			//if (!$this->SFSclass->versionCheck('2.0', 'smf'))
1289
+			//	validateToken($context['token_check'], 'post');
1290
+
1291
+			$username = $smcFunc['htmlspecialchars']($_POST['username']);
1292
+			$email = $smcFunc['htmlspecialchars']($_POST['email']);
1293
+			$ip = $smcFunc['htmlspecialchars']($_POST['ip']);
1294
+				
1295
+			$response = $this->SFSclass->TestSFS(array(
1296
+					array('username' => $username),
1297
+					array('email' => $email),
1298
+					array('ip' => $ip),
1299
+			));
1300
+
1301
+			// No checks found? Can't do this.
1302
+			if (empty($response) || !is_array($response) || empty($response['success']))
1303
+				$context['test_api_error'] = $this->SFSclass->txt('sfs_request_failure_nodata');
1304
+			else
1305
+				// Parse all the responses out.
1306
+				foreach($context['sfs_checks'] as $key => &$res)
1307
+					$res[0] += $response[$key][0];
1308
+		}
1309
+
1310
+		// Load our template.
1311
+		loadTemplate('StopForumSpam');
1312
+		$context['sub_template'] = 'sfsa_testapi';
1313
+
1314
+		$context['sfs_test_url'] = $this->adminTestURL;
1315
+		if (!$this->SFSclass->versionCheck('2.0', 'smf'))
1316
+			createToken($context['token_check'], 'post');
1317
+		else
1318
+			unset($context['token_check']);
1319
+
1320
+		return array();
1321
+	}
1154 1322
 }
1155 1323
\ No newline at end of file
... ...
@@ -1459,6 +1459,32 @@ class SFS
1459 1459
 		return true;
1460 1460
 	}
1461 1461
 
1462
+	/**
1463
+	 * The caller for a test check.
1464
+	 *
1465
+	 * @param array $checks The data we are checking.
1466
+	 *
1467
+	 * @api
1468
+	 * @CalledIn SMF 2.0, SMF 2.1
1469
+	 * @version 1.4.0
1470
+	 * @since 1.4.0
1471
+	 * @return array The results of the check.
1472
+	 */
1473
+	public function TestSFS(array $checks): array
1474
+	{
1475
+		$requestURL = $this->buildServerURL();
1476
+
1477
+		// Lets build our data set, always send it as a bulk.
1478
+		$singleCheckFound = $this->buildCheckPath($requestURL, $checks, 'test');
1479
+
1480
+		// No checks found? Can't do this.
1481
+		if (empty($singleCheckFound))
1482
+			return [];
1483
+
1484
+		// Send this off.
1485
+		return $this->sendSFSCheck($requestURL, $checks, 'test');
1486
+	}
1487
+
1462 1488
 	/**
1463 1489
 	 * Get some data
1464 1490
 	 *
... ...
@@ -109,3 +109,113 @@ function template_profile_tracksfs()
109 109
 	</form>';
110 110
 	}
111 111
 }
112
+
113
+function template_sfsa_testapi()
114
+{
115
+	global $context, $txt, $scripturl;
116
+
117
+	echo '
118
+		<div id="admin_form_wrapper">
119
+			<form id="postForm" action="', $context['sfs_test_url'], '" method="post" accept-charset="', $context['character_set'], '" name="postForm">
120
+				<div class="cat_bar">
121
+					<h3 class="catbg">', $txt['sfs_testapi_title'], '</h3>
122
+				</div>
123
+					<dl class="register_form" id="sfs_testapi_form">
124
+						<dt>
125
+							<strong><label for="username_input">', $txt['username'], ':</label></strong>
126
+						</dt>
127
+						<dd>
128
+							<input type="text" name="username" id="username_input" tabindex="', $context['tabindex']++, '" size="50" maxlength="25" value="', $context['sfs_checks']['username'][0]['value'], '">
129
+						</dd>
130
+						<dt>
131
+							<strong><label for="email_input">', $txt['email_address'], ':</label></strong>
132
+						</dt>
133
+						<dd>
134
+							<input type="email" name="email" id="email_input" tabindex="', $context['tabindex']++, '" size="50" value="', $context['sfs_checks']['email'][0]['value'], '">
135
+						</dd>
136
+						<dt>
137
+							<strong><label for="ip_input">', $txt['ip_address'], ':</label></strong>
138
+						</dt>
139
+						<dd>
140
+							<input type="text" name="ip" id="ip_input" tabindex="', $context['tabindex']++, '" size="100" value="', $context['sfs_checks']['ip'][0]['value'], '">
141
+						</dd>
142
+					</dl>
143
+					<div class="flow_auto">
144
+						<input type="submit" name="send" value="', $txt['sfs_testapi_submit'], '" tabindex="', $context['tabindex']++, '" class="button">
145
+						<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">';
146
+
147
+	if (!empty($context['token_check']))
148
+		echo '
149
+		<input type="hidden" name="' . $context[$context['token_check'] . '_token_var'] . '" value="' . $context[$context['token_check'] . '_token'] . '">';
150
+
151
+	echo '
152
+					</div>
153
+				</div><!-- #sfs_testapi_form -->
154
+			</form>
155
+		</div><!-- #admin_form_wrapper -->
156
+	<br class="clear">';
157
+
158
+	// Do not show results yet.
159
+	if (empty($context['test_sent']))
160
+		return;
161
+
162
+	echo '
163
+		<div class="tborder">
164
+			<div class="cat_bar">
165
+				<h3 class="catbg">', $txt['sfs_testapi_results'], '</h3>
166
+			</div>
167
+
168
+			<table class="table_grid">
169
+				<thead>
170
+					<tr class="title_bar">
171
+						<th class="lefttext">', $txt['sfs_check'], '</th>
172
+						<th class="lefttext">', $txt['sfs_value'], '</th>
173
+						<th class="lefttext">', $txt['sfs_result'], '</th>
174
+					</tr>
175
+				</thead>
176
+				<tbody>';
177
+
178
+	foreach ($context['sfs_checks'] as $id_check => $checkGrp)
179
+	{
180
+		foreach ($checkGrp as $check)
181
+		{
182
+			echo '
183
+					<tr class="windowbg">
184
+						<td title="sfs_check_', $id_check, '">
185
+							', $txt['sfs_check_' . $id_check], '
186
+						</td>
187
+						<td>
188
+							', $check['value'], '
189
+						</td>
190
+						<td class="smalltext">
191
+							', (!empty($check['appears']) ? $txt['yes'] : $txt['no']);
192
+
193
+			// Some checks will show the last seen, convert it and show it.
194
+			if (!empty($check['lastseen']))
195
+				echo '<br>' . $txt['sfs_last_seen'] . ': ' . timeformat(strtotime($check['lastseen']));
196
+
197
+			if (!empty($check['confidence']))
198
+				echo '<br>' . $txt['sfs_confidence'] . ': ' . $check['confidence'];
199
+
200
+			if (!empty($check['frequency']))
201
+				echo '<br>' . $txt['sfs_frequency'] . ': ' . $check['frequency'];
202
+
203
+			// IP address may be normalized
204
+			if (!empty($check['torexit']))
205
+				echo '<br>' . $txt['sfs_torexit'];
206
+
207
+			// IP address may be normalized
208
+			if (!empty($check['asn']))
209
+				echo '<br><a href="', $scripturl, '?action=profile;area=tracking;sa=ip;searchip=' . urlencode(str_replace('::*', ':*', !empty($check['normalized']) ? $check['normalized'] . '*' : $check['value'])) . '">', $txt['ip_address'], ' ',  (!empty($check['normalized']) ? $check['normalized'] . '*' : $check['value']), '</a>';
210
+
211
+			echo '
212
+						</td>
213
+					</tr>';
214
+		}
215
+	}
216
+
217
+	echo '
218
+				</tbody>
219
+			</table>';
220
+
221
+}
112 222
\ No newline at end of file
... ...
@@ -3,6 +3,8 @@
3 3
 /* The section Name */
4 4
 $txt['sfs_admin_area'] = 'Stop Forum Spam';
5 5
 $txt['sfs_admin_logs'] = 'SFS Logs';
6
+$txt['sfs_admin_test'] = 'Test SFS';
7
+$txt['sfs_admin_test_desc'] = 'Test Stop Forum Spam API and your configuration';
6 8
 
7 9
 /* Admin Section General header */
8 10
 $txt['sfs_general_title'] = 'General Configuration';
... ...
@@ -60,6 +62,13 @@ $txt['sfs_verOptionsMemExtra'] = 'Member Verification Sections';
60 62
 $txt['sfs_verfOptMemPostThreshold'] = 'Post Count after which we stop these checks.';
61 63
 $txt['sfs_verification_options_membersextra'] = 'Extra sections';
62 64
 
65
+/* Admin section: Test API */
66
+$txt['sfs_testapi_error'] = 'The API failed to communicate with the SFS servers';
67
+$txt['sfs_testapi_title'] = 'Enter test information';
68
+$txt['sfs_testapi_results'] = 'Results of Testing API';
69
+$txt['sfs_value'] = 'Value';
70
+$txt['sfs_testapi_submit'] = 'Send API Test';
71
+
63 72
 /* Request handling */
64 73
 $txt['sfs_request_failure'] = 'SFS Failed with invalid response';
65 74
 $txt['sfs_request_failure_nodata'] = 'SFS Failed as no data was sent';
... ...
@@ -76,6 +76,7 @@
76 76
 			<hook hook="integrate_admin_areas" function="SFSA::hook_admin_areas" />
77 77
 			<hook hook="integrate_modify_modifications" function="SFSA::hook_modify_modifications" />
78 78
 			<hook hook="integrate_manage_logs" function="SFSA::hook_manage_logs" />
79
+			<hook hook="integrate_manage_registrations" function="SFSA::hook_manage_registrations" />
79 80
 
80 81
 			<!-- Profile Section -->
81 82
 			<hook hook="integrate_pre_profile_areas" function="SFS::hook_pre_profile_areas" />
... ...
@@ -99,6 +100,7 @@
99 100
 			<hook hook="integrate_admin_areas" function="SFSA::hook_admin_areas" reverse="true" />
100 101
 			<hook hook="integrate_modify_modifications" function="SFSA::hook_modify_modifications" reverse="true" />
101 102
 			<hook hook="integrate_manage_logs" function="SFSA::hook_manage_logs" reverse="true" />
103
+			<hook hook="integrate_manage_registrations" function="SFSA::hook_manage_registrations" reverse="true" />
102 104
 
103 105
 			<!-- Profile Section -->
104 106
 			<hook hook="integrate_pre_profile_areas" function="SFS::hook_pre_profile_areas" reverse="true" />
105 107