+ Added a spam handler with basic and recaptcha support + Added ability to show warnings and other non fatal errors ! Moved all handlers to be loaded by a main startHandler function
Jeremy D

Jeremy D commited on 2012-02-17 20:59:11
Showing 8 changed files, with 275 additions and 55 deletions.

... ...
@@ -23,7 +23,7 @@ $pasteBin->showRecent();
23 23
 // Handles the actions.
24 24
 if (isset($_POST['submit']))
25 25
 	$pasteBin->action_paste();
26
-if (isset($_GET['view']))
26
+elseif (isset($_GET['view']))
27 27
 	$pasteBin->action_view($_GET['view']);
28 28
 else
29 29
 	$pasteBin->action_index();
... ...
@@ -46,6 +46,8 @@ class pB
46 46
 	private $db = null;
47 47
 	private $usr = null;
48 48
 	private $tpl = null;
49
+	private $antispam = null;
50
+	private $warnings = array();
49 51
 
50 52
 	/*
51 53
 	* Setup the settings when creating the object.
... ...
@@ -56,54 +58,55 @@ class pB
56 58
 		if (file_exists(dirname(__FILE__) . '/settings-' . pathinfo(basename($_SERVER['SCRIPT_FILENAME']), PATHINFO_FILENAME) . '.php'))
57 59
 			require_once(dirname(__FILE__) . '/settings-' . pathinfo(basename($_SERVER['SCRIPT_FILENAME']), PATHINFO_FILENAME). '.php');
58 60
 
59
-		// Start up our database.
60
-		require_once(pBS::get('sources') . '/db.php');
61
-		if (file_exists(pBS::get('sources') . '/db-' . pBS::get('db') . '.php'))
62
-		{
63
-			require_once(pBS::get('sources') . '/db-' . pBS::get('db') . '.php');
61
+		// This will get some of our handler going.
62
+		$this->startHandler('db', 'db', 'pDB');
63
+		$this->startHandler('user', 'usr', 'pUser');
64
+		$this->startHandler('tpl', 'tpl', 'pTPL');
65
+		$this->startHandler('spam', 'antispam', 'pAS');
64 66
 
65
-			$class = 'pDB_' . pBS::get('db');
66
-			if (class_exists($class))
67
-				$this->db = new $class;
68
-			else
69
-				$this->error('Database is defined but no such class exists.');
67
+		// Start getting things going.
68
+		$this->loadLanguage();
69
+		$this->loadGeshi();
70 70
 	}
71
-		else
72
-			$this->error('No database handler is defined.');
73 71
 
74
-		// Start up our User handler.
75
-		require_once(pBS::get('sources') . '/user.php');
76
-		if (file_exists(pBS::get('sources') . '/user-' . pBS::get('user') . '.php'))
72
+	/*
73
+	* Setup a handler for usage.
74
+	* @param $file String The main name of the handler we are loading.
75
+	* @param $var String The variable we will store this under.  As well this is the setting name we look for when loading that extra class.
76
+	* @param $class_name String The name of the class this will load.
77
+	* @param $extension String When we use this, we ignore using $var as extension of the class we are loading.
78
+	*/
79
+	public function startHandler($file, $var, $class_name, $extension = '')
80
+	{
81
+		if (!file_exists(pBS::get('sources') . '/'. $file . '.php'))
82
+			$this->error('Failed to start Handler (' . $var . ') as file (' . $file . ' ) does not exist.');
83
+
84
+		if (empty($extension))
85
+			$extension = pBS::get($var);
86
+
87
+		require_once(pBS::get('sources') . '/'. $file . '.php');
88
+		if (file_exists(pBS::get('sources') . '/'. $file . '-' . $extension . '.php'))
77 89
 		{
78
-			require_once(pBS::get('sources') . '/user-' . pBS::get('user') . '.php');
90
+			require_once(pBS::get('sources') . '/'. $file . '-' . $extension . '.php');
79 91
 
80
-			$class = 'pUser_' . pBS::get('user');
92
+			$class = $class_name . '_' . pBS::get($var);
81 93
 			if (class_exists($class))
82
-				$this->usr = new $class;
83
-			else
84
-				$this->error('User is defined but no such class exists.');
85
-		}
94
+				$this->{$var} = new $class;
86 95
 			else
87
-			$this->error('No user handler is defined.');
96
+				$this->error($var . ' Handler is defined but no such class exists.');
88 97
 
89
-		// Start up our Template handler.
90
-		require_once(pBS::get('sources') . '/tpl.php');
91
-		if (file_exists(pBS::get('sources') . '/tpl-' . pBS::get('tpl') . '.php'))
98
+			// If this had a classActive method, we need to verify this before we go on.
99
+			if (method_exists($this->{$var}, 'classActive') && ($result = $this->{$var}->classActive()) !== true)
92 100
 			{
93
-			require_once(pBS::get('sources') . '/tpl-' . pBS::get('tpl') . '.php');
101
+				// If the result returned nothing, we got no fall back.
102
+				if (empty($result))
103
+					$this->error('Invalid Handler setup for ' . $file);
94 104
 
95
-			$class = 'pTPL_' . pBS::get('tpl');
96
-			if (class_exists($class))
97
-				$this->tpl = new $class;
98
-			else
99
-				$this->error('Template is defined but no such class exists.');
105
+				$this->startHandler($file, $var, $class_name, $result);
106
+			}
100 107
 		}
101 108
 		else
102
-			$this->error('No template handler is defined.');
103
-
104
-		// Start getting things going.
105
-		$this->loadLanguage();
106
-		$this->loadGeshi();
109
+			$this->error('No ' . $var . ' handler is defined.');
107 110
 	}
108 111
 
109 112
 	/*
... ...
@@ -268,6 +271,14 @@ class pB
268 271
 		if (is_callable(array($this->tpl, 'htmlHead')))
269 272
 			$this->tpl->htmlHead($this->title);
270 273
 
274
+		// Give admins a hint what the key is.
275
+		if (!empty($this->warnings))
276
+			echo '
277
+			<div class="alert alert-error">
278
+			<h4 class="alert-heading">This paste has failed to be created because:</h4>
279
+			', implode('<br />', $this->warnings), '
280
+			</div>';
281
+
271 282
 		$paste = $this->showPaste($id);
272 283
 
273 284
 		// Give admins a hint what the key is.
... ...
@@ -296,10 +307,22 @@ class pB
296 307
 		$do_create = true;
297 308
 
298 309
 		if ($this->usr->id() > 0 && (empty($_POST['name']) || empty($_POST['email'])))
310
+		{
311
+			$this->warnings[] = 'Missing information (Username/email)';
299 312
 			$do_create = false;
313
+		}
300 314
 
301 315
 		if (empty($_POST['code']))
316
+		{
317
+			$this->warnings[] = 'Nothing entered into the code box';
302 318
 			$do_create = false;
319
+		}
320
+
321
+		if (pBS::get('human_check') && $this->antispam->verify(&$this->warnings) === false)
322
+			$do_create = false;
323
+
324
+		if (!empty($this->warnings) && isset($_POST['iHateU']))
325
+			$this->warnings[] = 'I do not like you either';
303 326
 
304 327
 		// Get the data ready.
305 328
 		$data = array(
... ...
@@ -313,12 +336,10 @@ class pB
313 336
 		);
314 337
 
315 338
 		// Do a test.
316
-		$this->db->addPasteTest(&$data, &$do_create);
339
+		$this->db->addPasteTest(&$data, &$do_create, &$this->warnings);
317 340
 
318 341
 		if (!$do_create)
319 342
 		{
320
-			$this->warningss[] = 'Missing information (Username/email)';
321
-
322 343
 			if (!empty($_POST['view']))
323 344
 				$this->action_view($_POST['view']);
324 345
 			else
... ...
@@ -453,8 +474,11 @@ class pB
453 474
 					<li><input type="checkbox" name="force_new_pw" /><strong>', pBL('force_new_key'), '</strong></li>';
454 475
 
455 476
 		if (pBS::get('human_check'))
456
-			echo '
457
-					<li>', pBS::get('human_question'), ':<input type="text" name="ru_human" value="', isset($_POST['ru_human']) ? $_POST['ru_human'] : '', '" /></li>';
477
+		{
478
+			echo '<li>';
479
+			$this->antispam->template();
480
+			echo '</li>';
481
+		}
458 482
 
459 483
 		echo '
460 484
 				</ul>';
... ...
@@ -22,11 +22,15 @@ class pBS
22 22
 	private static $db = 'smf';
23 23
 
24 24
 	/* User Handler. */
25
-	private static $user = 'smf';
25
+	private static $usr = 'smf';
26 26
 
27 27
 	/* Template Handler. */
28 28
 	private static $tpl = 'wp';
29 29
 
30
+	/* Template Handler. */
31
+//	private static $antispam = 'recaptcha';
32
+	private static $antispam = 'basic';
33
+
30 34
 	/* Any preloader file needed? */
31 35
 	private static $preload = '__integrate.php';
32 36
 
... ...
@@ -64,15 +68,21 @@ class pBS
64 68
 	/* GESHI: The default language to use. */
65 69
 	private static $geshi_default = 'php';
66 70
 
67
-	/* HUMAN CHECK: Enable the human check? */
71
+	/* ANTI-SPAM (BASIC): Enable the human check? */
68 72
 	private static $human_check = true;
69 73
 
70
-	/* HUMAN CHECK: The question to ask. */
74
+	/* ANTI-SPAM (BASIC): The question to ask. */
71 75
 	private static $human_question = 'A duck, cat and a goose walk into a bar. How many animals walked into a bar?';
72 76
 
73
-	/* HUMAN CHECK: The answer they need to provide. */
77
+	/* ANTI-SPAM (BASIC): The answer they need to provide. */
74 78
 	private static $human_answer = '3';
75 79
 
80
+	/* ANTI-SPAM (RECAPTCHA): If using Recaptcha as your anti-spam handler enter your key here */
81
+	private static $recaptcha_key = '';
82
+
83
+	/* ANTI-SPAM (RECAPTCHA): If using Recaptcha as your anti-spam handler enter your private key here */
84
+	private static $recaptcha_private_key = '';
85
+	
76 86
 	/* SMF: When we are using SMF, we need to know where it is. */
77 87
 	private static $smf_dir = '../forum/';
78 88
 
... ...
@@ -111,7 +111,7 @@ class pDB_smf extends pDB
111 111
 			'approved' => $topic['approved'],
112 112
 			'use_geshi' => $Paste['use_geshi'],
113 113
 			'language' => $Paste['type'],
114
-			'body' => $topic['body'],
114
+			'body' => htmlspecialchars_decode($topic['body']),
115 115
 			'parsed' => '',
116 116
 		);	
117 117
 	}
... ...
@@ -159,6 +159,11 @@ class pDB_smf extends pDB
159 159
 		elseif (!empty($paste['key']))
160 160
 			$data['key'] = $paste['key'];
161 161
 
162
+		if (function_exists('wp_magic_quotes'))
163
+		{
164
+			$data['body'] = stripslashes($data['body']);
165
+		}
166
+
162 167
 		// Options needed for our post.
163 168
 		$topicOptions = array(
164 169
 			'id'		=> (!empty($paste['id']) ? $paste['id'] : 0) ,
... ...
@@ -0,0 +1,53 @@
1
+<?php
2
+/*
3
+ * SMF PasteBin
4
+ * Author: SleePy (JeremyD)
5
+ * Repository: https://github.com/jdarwood007/pastebin
6
+ * License: BSD 3 Clause; See license.txt
7
+*/
8
+if (!defined('SMFPasteBin')) { exit('[' . basename(__FILE__) . '] Direct access restricted');}
9
+
10
+/*
11
+* Basic Anti-Spam handler for Pastebin.
12
+*/
13
+class pAS_basic extends pAS
14
+{
15
+	/*
16
+	* Test whether this anti-spam method is enabled or not.
17
+	*/
18
+	public function classActive()
19
+	{
20
+		if (pBS::get('human_check') === false || pBS::get('human_question') === null || pBS::get('human_answer') === null)
21
+			return false;
22
+		return true;
23
+	}
24
+
25
+	/*
26
+	* Verify the that we correctly entered the anti-spam stuff.
27
+	*/
28
+	public function verify($warnings)
29
+	{
30
+		// Luck you, get a free pass.
31
+		if (pBS::get('human_check') === false)
32
+			return true;
33
+
34
+		if (!isset($_POST['ru_human']) || $_POST['ru_human'] != pBS::get('human_answer'))
35
+		{
36
+			$warnings[] = 'Invalid human verification';
37
+			return false;
38
+		}
39
+
40
+		return true;
41
+	}
42
+
43
+	/*
44
+	* For the template.
45
+	*/
46
+	public function template()
47
+	{
48
+		if (pBS::get('human_check') === false)
49
+			return;
50
+
51
+			echo pBS::get('human_question'), ':<input type="text" name="ru_human" value="', isset($_POST['ru_human']) ? $_POST['ru_human'] : '', '" />';
52
+	}
53
+}
0 54
\ No newline at end of file
... ...
@@ -0,0 +1,91 @@
1
+<?php
2
+/*
3
+ * SMF PasteBin
4
+ * Author: SleePy (JeremyD)
5
+ * Repository: https://github.com/jdarwood007/pastebin
6
+ * License: BSD 3 Clause; See license.txt
7
+*/
8
+if (!defined('SMFPasteBin')) { exit('[' . basename(__FILE__) . '] Direct access restricted');}
9
+
10
+/*
11
+* Basic Anti-Spam handler for Pastebin.
12
+*/
13
+class pAS_recaptcha extends pAS
14
+{
15
+	/*
16
+	* Test whether this anti-spam method is enabled or not.
17
+	*/
18
+	public function classActive()
19
+	{
20
+		if (pBS::get('recaptcha_key') === null || pBS::get('recaptcha_private_key') === null)
21
+			return false;
22
+		return true;
23
+	}
24
+
25
+	/*
26
+	* Verify the that we correctly entered the anti-spam stuff.
27
+	*/
28
+	public function verify($warnings)
29
+	{
30
+		$data = implode('&', array(
31
+			'privatekey' => pBS::get('recaptcha_private_key'),
32
+			'remoteip' => $_SERVER['REMOTE_ADDR'],
33
+			'challenge' => $this->cleanInput($_POST['recaptcha_challenge_field']),
34
+			'response' => $this->cleanInput($_POST['recaptcha_response_field'])
35
+		));
36
+
37
+
38
+		// Connect to the collection script.
39
+		$response = '';
40
+		$fp = @fsockopen('www.google.com', 80, $errno, $errstr);
41
+		if ($fp)
42
+		{
43
+			$out = 'POST /recaptcha/api/verify HTTP/1.1' . "\r\n";
44
+			$out .= 'Host: www.google.com' . "\r\n";
45
+			$out .= "User-Agent: reCAPTCHA/PHP\r\n";
46
+			$out .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n";
47
+			$out .= 'Content-Length: ' . strlen($data) . "\r\n\r\n";
48
+			$out .= $data . "\r\n";
49
+			$out .= 'Connection: Close' . "\r\n\r\n";
50
+			fwrite($fp, $out);
51
+
52
+			while (!feof($fs))
53
+				$response .= fgets($fs, 1160);
54
+			fclose($fp);
55
+
56
+			$response = explode("\r\n\r\n", $response, 2);
57
+
58
+			if (trim($response[0]) == 'true')
59
+				return true;
60
+			else
61
+			{
62
+				$warnings[] = $response[1];
63
+				return false;
64
+			}
65
+		}
66
+		else
67
+		{
68
+			$warnings[] = 'Could not connect to the remote ReCaptcha service, verification failed';
69
+			return false;
70
+		}
71
+	}
72
+
73
+	/*
74
+	* For the template.
75
+	*/
76
+	public function template()
77
+	{
78
+		echo '
79
+		<script type="text/javascript" src="http://www.google.com/recaptcha/api/challenge?k=', pBS::get('recaptcha_key'), '"></script>
80
+		<noscript>
81
+			<iframe src="http://www.google.com/recaptcha/api/noscript?k=', pBS::get('recaptcha_key') , '" height="300" width="500" frameborder="0"></iframe><br>
82
+			<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
83
+			<input type="hidden" name="recaptcha_response_field" value="manual_challenge" />
84
+		</noscript>';
85
+	}
86
+
87
+	private function cleanInput($var)
88
+	{
89
+		return urlencode(stripslashes($var));
90
+	}
91
+}
0 92
\ No newline at end of file
... ...
@@ -0,0 +1,35 @@
1
+<?php
2
+/*
3
+ * SMF PasteBin
4
+ * Author: SleePy (JeremyD)
5
+ * Repository: https://github.com/jdarwood007/pastebin
6
+ * License: BSD 3 Clause; See license.txt
7
+*/
8
+if (!defined('SMFPasteBin')) { exit('[' . basename(__FILE__) . '] Direct access restricted');}
9
+
10
+/*
11
+* Basic Anti-Spam handler for Pastebin.
12
+*/
13
+class pAS
14
+{
15
+	/*
16
+	* Setup the anti-spam method, for basic we do nothing.
17
+	*/
18
+	public function setup()
19
+	{	
20
+	}
21
+
22
+	/*
23
+	* Verify the that we correctly entered the anti-spam stuff.
24
+	*/
25
+	public function verify($warnings)
26
+	{
27
+	}
28
+
29
+	/*
30
+	* For the template.
31
+	*/
32
+	public function template()
33
+	{
34
+	}
35
+}
0 36
\ No newline at end of file
... ...
@@ -29,6 +29,7 @@ class pTPL_smf extends pTPL
29 29
 
30 30
 	/*
31 31
 	* Do the header.
32
+	* @param $title String the page title.
32 33
 	* @Note: Because we used ssi earlier to star the SMF theme, we have nothing to do here.
33 34
 	*/
34 35
 	public function htmlHead($title)
... ...
@@ -13,21 +13,22 @@ if (!defined('SMFPasteBin')) { exit('[' . basename(__FILE__) . '] Direct access
13 13
 class pTPL_wp extends pTPL
14 14
 {
15 15
 	/*
16
-	* Do the header.
16
+	* Lets get things cooking.
17 17
 	*/
18
-	public function htmlHead($title)
18
+	public function __construct()
19 19
 	{
20
-		global $specialPage;
21
-
22
-		$specialPage['title'] = $title;
20
+		wp_enqueue_style('pastebin', pBS::get('css'));
23 21
 	}
24 22
 
25 23
 	/*
26
-	* Lets get things cooking.
24
+	* Do the header.
25
+	* @param $title String the page title.
27 26
 	*/
28
-	public function __construct()
27
+	public function htmlHead($title)
29 28
 	{
30
-		wp_enqueue_style('pastebin', pBS::get('css'));
29
+		global $specialPage;
30
+
31
+		$specialPage['title'] = $title;
31 32
 	}
32 33
 
33 34
 	/*
34 35