pax_global_header 0000666 0000000 0000000 00000000064 12722727034 0014520 g ustar 00root root 0000000 0000000 52 comment=39aecfdfc0aa09df28d26fa139f7032d983e4b7a
.gitignore 0000664 0000000 0000000 00000000006 12722727034 0013050 0 ustar 00root root 0000000 0000000 geshi
README.txt 0000664 0000000 0000000 00000001033 12722727034 0012557 0 ustar 00root root 0000000 0000000 *** SMF Powered PasteBin ***
I've never been good at writing these, so here it goes.
See license.txt for the license this script uses.
*** Install ***
1. Upload files
2. Modify settings.php to accommodate your needs.
a. When using SMF as the database, you muse set the correct path in smf_dir to your SMF install.
b. When using SMF as the database, you must set the smf_paste_board to a valid board id.
3. Done.
*** Geshi ***
You can download and install the geshi syntax highlighter. Just need to set that up in settings once you do. __integrate.php 0000664 0000000 0000000 00000001120 12722727034 0014047 0 ustar 00root root 0000000 0000000 showRecent();
// Handles the actions.
if (isset($_POST['submit']))
$pasteBin->action_paste();
elseif (isset($_GET['view']))
$pasteBin->action_view($_GET['view']);
else
$pasteBin->action_index();
// Shutdown.
if (!defined('PB_CONTINUE'))
exit;
/*
* Main PasteBin class
*/
class pB
{
/*
* Some basic stuff.
*/
public $title = 'PasteBin';
private $action = 'index';
private $geshi_languages = array();
private $db = null;
private $usr = null;
private $tpl = null;
private $antispam = null;
private $warnings = array();
/*
* Setup the settings when creating the object.
*/
public function __construct()
{
// Load up any settings that apply only to this pastebin.
if (file_exists(dirname(__FILE__) . '/settings-' . pathinfo(basename($_SERVER['SCRIPT_FILENAME']), PATHINFO_FILENAME) . '.php'))
require_once(dirname(__FILE__) . '/settings-' . pathinfo(basename($_SERVER['SCRIPT_FILENAME']), PATHINFO_FILENAME). '.php');
// This will get some of our handler going.
$this->startHandler('db', 'db', 'pDB');
$this->startHandler('user', 'usr', 'pUser');
$this->startHandler('tpl', 'tpl', 'pTPL');
$this->startHandler('spam', 'antispam', 'pAS');
// Start getting things going.
$this->loadLanguage();
$this->loadGeshi();
}
/*
* Setup a handler for usage.
* @param $file String The main name of the handler we are loading.
* @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.
* @param $class_name String The name of the class this will load.
* @param $extension String When we use this, we ignore using $var as extension of the class we are loading.
*/
public function startHandler($file, $var, $class_name, $extension = '')
{
if (!file_exists(pBS::get('sources') . '/'. $file . '.php'))
$this->error('Failed to start Handler (' . $var . ') as file (' . $file . ' ) does not exist.');
if (empty($extension))
$extension = pBS::get($var);
require_once(pBS::get('sources') . '/'. $file . '.php');
if (file_exists(pBS::get('sources') . '/'. $file . '-' . $extension . '.php'))
{
require_once(pBS::get('sources') . '/'. $file . '-' . $extension . '.php');
$class = $class_name . '_' . pBS::get($var);
if (class_exists($class))
$this->{$var} = new $class;
else
$this->error($var . ' Handler is defined but no such class exists.');
// If this had a classActive method, we need to verify this before we go on.
if (method_exists($this->{$var}, 'classActive') && ($result = $this->{$var}->classActive()) !== true)
{
// If the result returned nothing, we got no fall back.
if (empty($result))
$this->error('Invalid Handler setup for ' . $file);
$this->startHandler($file, $var, $class_name, $result);
}
}
else
$this->error('No ' . $var . ' handler is defined.');
}
/*
* Load up the language, taking into account a session or selection.
*/
public function loadLanguage()
{
if (isset($_SESSION['user_language']))
$language = $_SESSION['user_language'];
// allow_url_include shouldn't be enabled!
elseif (isset($_GET['lang']) && file_exists(pBS::get('languages') . '/' . strtolower(htmlspecialchars($_GET['lang'])) . '.php'))
{
if (strpos($_GET['lang'], 'http://') !== false || strpos($_GET['lang'], 'ftp://') !== false)
$this->error('Invalid string in url.');
$language = strtolower(htmlspecialchars($_GET['lang']));
}
elseif ($this->usr->id() > 0 && file_exists(pBS::get('languages') . '/' . $this->usr->language() . '.php'))
$language = $this->usr->language();
else
$language = pBS::get('default_language');
// Load the language.
require(pBS::get('languages') . '/' . $language . '.php');
}
/*
* Setup GeSHI.
*/
public function loadGeshi()
{
if (!pBS::get('use_geshi'))
return false;
if (!($dir = @opendir(pBS::get('geshi_location') . '/geshi')))
return false;
$languages = array();
while ($file = readdir($dir))
{
if (substr ($file, 0, 1) == '.' || !stristr($file, '.') || $file == 'css-gen.cfg' )
continue;
$languages[] = substr($file, 0, strpos($file, '.'));
}
closedir($dir);
sort($languages);
$this->geshi_languages = $languages;
}
/*
* Handle a fatal Error.
* @param $msg String The error message to display.
*/
public function error($msg)
{
// Debug this if we want to debug it.
if (pBS::get('debug'))
{
echo '
';
debug_print_backtrace();
echo '
';
}
exit($msg);
}
/*
* Format a URL for output.
* @param $act string The action we want to use.
* @param $sa string The value of the action.
* @param $extras array An array of key => value containing extras to add to the url.
* @return string The formated URL, ready for output in links.
*/
public function URL($act, $sa = '', $extras = array())
{
static $url_prefix;
// Build the first part of the url.
if (empty($url_prefix))
{
$url_prefix = 'http' . (isset($_SERVER['HTTPS']) ? 's': '') . '://' . $_SERVER['HTTP_HOST'];
if ($_SERVER['SERVER_PORT'] != 80)
$url_perfix .= ':' . $_SERVER['SERVER_PORT'];
if (pBS::get('url_sef'))
$url_prefix .= pBS::get('sef_base');
elseif (pBS::get('use_portal'))
$url_prefix .= pBS::get('portal_url');
else
$url_prefix .= str_replace($_SERVER['DOCUMENT_ROOT'], '', __FILE__) . '?';
}
// Special cases we do certain things to the url.
if ($act == 'index' && $url_prefix{strlen($url_prefix) -1} == '?')
return substr($url_prefix, 0, -1);
elseif ($act == 'index')
return $url_prefix;
elseif ($act == 'post')
return $url_prefix . '/?';
$url = $url_prefix;
if ($sa == '')
$url .= '?' . $act;
elseif (pBS::get('url_sef'))
$url .= '/' . $sa;
else
$url .= $act . '=' . $sa;
if (!empty($extras))
{
foreach ($extras AS $k => $v)
{
if (pBS::get('url_sef') && !empty($v))
$url .= '/' . $v;
elseif (!empty($v))
$url .= ';' . $k . '=' . $v;
}
}
// This may happen with a portal.
if (pBS::get('use_portal'))
$url = str_replace('?;', '?', $url);
return $url;
}
/*
* Show a new past form.
*/
public function action_index()
{
$this->title = pBL('index_title');
if (is_callable(array($this->tpl, 'htmlHead')))
{
echo '
';
$this->tpl->htmlHead($this->title);
echo '
';
}
// Trying to save this paste?
if (isset($_POST['save']))
$warnings = $this->makePaste(0);
// Show any errors.
if (!empty($warnings))
echo '
', implode(' ', $warnings), '
';
$this->postForm((!empty($_POST['code']) ? $_POST['code'] : ''));
if (is_callable(array($this->tpl, 'htmlFooter')))
{
echo '
';
$this->tpl->htmlFooter();
echo '
';
}
}
/*
* Show a paste.
* @param $id int The id of the paste.
*/
public function action_view($id)
{
$this->title = pBL('view_title', $id);
if (is_callable(array($this->tpl, 'htmlHead')))
{
echo '
';
$this->tpl->htmlHead($this->title);
echo '
';
}
// Give admins a hint what the key is.
if (!empty($this->warnings))
echo '
This paste has failed to be created because:
', implode(' ', $this->warnings), '
';
$paste = $this->showPaste($id);
// Give admins a hint what the key is.
if (!empty($paste['key']) && $this->usr->is_admin())
echo '
Key: ', $paste['key'], '
';
if (!empty($paste['parsed']))
echo '
', pBL('formated_paste'), '
', $paste['parsed'], '
';
$this->postForm($paste['body'], $id, $paste['use_geshi'], $paste['language']);
if (is_callable(array($this->tpl, 'htmlFooter')))
{
echo '
';
$this->tpl->htmlFooter();
echo '
';
}
}
/*
* Actually make the paste.
*/
public function action_paste()
{
$do_create = true;
if ($this->usr->id() > 0 && (empty($_POST['name']) || empty($_POST['email'])))
{
$this->warnings[] = 'Missing information (Username/email)';
$do_create = false;
}
if (empty($_POST['code']))
{
$this->warnings[] = 'Nothing entered into the code box';
$do_create = false;
}
if (pBS::get('human_check') && $this->antispam->verify($this->warnings) === false)
$do_create = false;
if (!empty($this->warnings) && isset($_POST['iHateU']))
$this->warnings[] = 'I do not like you either';
// Get the data ready.
$data = array(
'paste_id' => !empty($_POST['view']) ? $_POST['view'] : 0,
'new_key' => isset($_POST['force_new_pw']) && $this->usr->is_admin(),
'name' => !empty($_POST['name']) ? $_POST['name'] : 'Guest',
'email' => !empty($_POST['email']) ? $_POST['email'] : 'guest@noemail.com',
'use_geshi' => !empty($_POST['use_geshi']),
'language' => !empty($_POST['type']) ? $_POST['type'] : 'php',
'body' => $_POST['code']
);
// Do a test.
$this->db->addPasteTest($data, $do_create, $this->warnings);
if (!$do_create)
{
if (!empty($_POST['view']))
$this->action_view($_POST['view']);
else
$this->action_index();
return false;
}
// Valid Numbers only.
$result = $this->db->addPaste($data);
// Send us there.
redirectexit($this->URL('view', $result['id'], array(
'update' => isset($result['updated']) ? 't' . time() : '',
'key' => !empty($result['key']) ? $result['key'] : '',
)));
}
/*
* Show some recent pastes.
*/
public function showRecent()
{
$recent_limit = $this->usr->is_admin() ? pBS::get('recent_limit_admin') : pBS::get('recent_limit');
$recent = array();
if ($recent_limit > 0)
$recent = $this->db->fetchRecent($recent_limit);
// Start to wrap it in a template if needed.
if (is_callable(array($this->tpl, 'recentTop')))
{
echo '
';
$this->tpl->recentTop();
echo '
';
}
// Output this.
echo '
';
// Close up the wrapper.
if (is_callable(array($this->tpl, 'recentBottom')))
{
echo '
';
$this->tpl->recentBottom();
echo '
';
}
}
/*
* Shows a form for making/editing a paste.
* @param $code string A string containing the actual code for the code box.
* @param $id (optiona) int The id of the paste.
* @param $use_geshi (optiona) bool Whether to use geshi or not.
* @param $geshi_language (optional) string The default language to use, ie php.
*/
public function postForm($code, $id = 0, $use_geshi = true, $geshi_language = 'php')
{
if (is_callable(array($this->tpl, 'postTop')))
{
echo '
';
$this->tpl->postTop();
echo '
';
}
echo '
';
if (is_callable(array($this->tpl, 'postBottom')))
{
echo '
';
$this->tpl->postBottom();
echo '
';
}
}
/*
* Shows an existing paste.
* @param $id int The id of the paste to load up.
*/
public function showPaste($id)
{
// Get it from the database.
$paste = $this->db->fetchPaste($id);
// The fetch threw an error.
if (isset($paste['error']))
$this->error($paste['error'], !empty($paste['fatal']) ? true : false);
if (!$this->usr->is_admin() && !empty($paste['key']) && (empty($_REQUEST['key']) || $paste['key'] != $_REQUEST['key']))
$this->error(pBL('error_no_access'), true);
elseif (empty($paste['approved']))
$this->error(pBL('error_approval'), true);
if (pBS::get('use_geshi') && !empty($paste['use_geshi']))
{
$type = !empty($paste['language']) ? $paste['language'] : 'php';
include_once(pBS::get('geshi_location') . '/geshi.php');
$geshi = new GeSHi('', $type);
$geshi->set_header_type(GESHI_HEADER_PRE);
$geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
$geshiErr = new GeSHi($paste['body'], $type);
$geshiErr->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS, 2);
$topic_parsed = $geshiErr->parse_code();
$topic_parsed = str_replace('<?php', '<?php', $topic_parsed);
$paste['parsed'] = $topic_parsed;
}
return $paste;
}
}
/*
* This is a function that passes the language calls to the
* language class without using ugly $$var in the template.
*/
function pBL($string)
{
$args = func_get_args();
if (count($args) == 1)
return pBL::$$string;
else
{
// Override it.
$args[0] = pBL::$$string;
return call_user_func_array('sprintf', $args);
}
}
languages/ 0000775 0000000 0000000 00000000000 12722727034 0013032 5 ustar 00root root 0000000 0000000 languages/english.php 0000664 0000000 0000000 00000002202 12722727034 0015170 0 ustar 00root root 0000000 0000000 nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pb.css 0000664 0000000 0000000 00000000436 12722727034 0012202 0 ustar 00root root 0000000 0000000 .container_text
{
font-weight: bold;
}
#settings_container
{
list-style-type: none;
}
#formated_paste
{
overflow: auto;
}
pre div
{
display: inline !important;
}
#code_value textarea
{
width: 100%;
}
/* For when in SMF */
#content_section #code_value textarea
{
width: 80%;
}
private.php 0000664 0000000 0000000 00000000066 12722727034 0013251 0 ustar 00root root 0000000 0000000 ';
}
require_once(pBS::get('smf_dir') . '/SSI.php');
require_once($sourcedir . '/Subs-Post.php');
}
/*
* Fetches the most recent from the SMF database.
* @param $limit int The limit on the recent pastes
*/
public function fetchRecent($limit)
{
$request = smcFunc::db_query('', '
SELECT t.id_topic as topic_id
FROM {db_prefix}topics AS t
WHERE t.id_board = {int:paste_board}
ORDER BY id_last_msg DESC
LIMIT {int:limit_recent}',
array(
'paste_board' => pBS::get('smf_paste_board'),
'limit_recent' => $limit,
));
while($re = smcFunc::db_fetch_assoc($request))
$recent[] = $re['topic_id'];
smcFunc::db_free_result($request);
$recent = array_unique($recent);
return $recent;
}
/*
* Fetches all the information abouta a paste.
* @param $id int The id of the paste.
*/
public function fetchPaste($id)
{
// Do the query..
$request = smcFunc::db_query('', '
SELECT id_msg, id_topic, id_board as board_id, body, subject, approved
FROM {db_prefix}messages
WHERE id_topic = {int:id_topic}
AND id_board = {int:paste_board}
ORDER BY poster_time DESC',
array(
'paste_board' => pBS::get('smf_paste_board'),
'id_topic' => $id,
));
$topic = smcFunc::db_fetch_assoc($request);
smcFunc::db_free_result($request);
// Need to check their access.
if ($topic['board_id'] != pBS::get('smf_paste_board'))
return array('error' => pBL('error_no_access'));
$ops = explode(':v:', $topic['subject']);
unset($ops[0]);
foreach($ops as $op)
{
$temp = explode('-', $op);
$Paste[$temp[0]] = $temp[1];
}
// This is how the data should return.
return array(
'id' => $topic['id_topic'],
'key' => isset($Paste['p']) ? $Paste['p'] : '',
'board_id' => $topic['board_id'],
'approved' => $topic['approved'],
'use_geshi' => $Paste['use_geshi'],
'language' => $Paste['type'],
'body' => htmlspecialchars_decode($topic['body']),
'parsed' => '',
);
}
/*
* Tests adding/updating a paste to the database.
* @param $data array The data we are testing.
$data[paste_id] Int The id of the paste, default is 0.
$data[new_key] Bool To force a new key or not.
$data[name] String The name of the paster.
$data[email] String the email of the paster.
$data[use_geshi] Bool If we should use geshi highlighting or not.
$data[language] String The language of the code, default is php.
$data[body] String the actual contents of the paste.
* @param $do_create Should we create this or not? Only set this to false when we shouldn't.
*/
public function addPasteTest(&$data, &$do_create)
{
}
/*
* Actually adding/updating a paste to the database.
* @param $data array The data we are testing.
* $data[paste_id] Int The id of the paste, default is 0.
* $data[new_key] Bool To force a new key or not.
* $data[name] String The name of the paster.
* $data[email] String the email of the paster.
* $data[use_geshi] Bool If we should use geshi highlighting or not.
* $data[language] String The language of the code, default is php.
* $data[body] String the actual contents of the paste.
* @return $result array The data we are returning.
* $result[id] int The id of the paste.
* $result[key] String The key of the paste, default is empty.
* $result[updated] Bool Whether this was an update or not.
*/
public function addPaste($data)
{
// Fetch any data we need to know.
if (!empty($data['paste_id']))
$paste = $this->fetchPaste($data['paste_id']);
// Try to keep the key correct unless it should change.
if ((pBS::get('private') && empty($paste['key'])) || (!empty($paste['key']) && userInfo::_()->is_admin && isset($_POST['force_new_pw'])))
$data['key'] = $this->generateKey();
elseif (!empty($paste['key']))
$data['key'] = $paste['key'];
if (function_exists('wp_magic_quotes'))
{
$data['body'] = stripslashes($data['body']);
}
// Options needed for our post.
$topicOptions = array(
'id' => (!empty($paste['id']) ? $paste['id'] : 0) ,
'board' => pBS::get('smf_paste_board'),
'mark_as_read' => false,
);
$posterOptions = array(
'id' => (isset(userInfo::_()->id) ? userInfo::_()->id: 0),
'name' => $data['name'],
'email' => $data['email'],
'ip' => userInfo::_()->ip,
'update_post_count' => (pBS::get('smf_increase_postcout') && isset(userInfo::_()->id) ? 1 : 0),
);
$msgOptions = array(
'id' => 0,
'subject' => 'Paste-' . time() . ':v:use_geshi-' . (!empty($data['use_geshi']) ? 1 : 0) . ':v:type-' . (!empty($data['language']) ? $data['language'] : 'php') . (!empty($data['key']) ? ':v:p-' . $data['key'] : ''),
'body' => htmlspecialchars($data['body']),
'approved' => pBS::get('smf_post_approval') ? 0 : 1,
);
// Actually create the paste.
createPost($msgOptions, $topicOptions, $posterOptions);
// Return some info
return array(
'id' => $topicOptions['id'],
'key' => isset($data['key']) ? $data['key'] : '',
'updated' => $data['id'] ? true : false,
);
}
}
/*
* smcFunc as a class. Uses callStatic to emulate it.
*/
class smcFunc
{
public static function __callStatic($name, $arguments)
{
global $smcFunc;
return call_user_func_array($smcFunc[$name], $arguments);
}
}
sources/db.php 0000664 0000000 0000000 00000000735 12722727034 0013652 0 ustar 00root root 0000000 0000000 ';
}
} sources/spam-recaptcha.php 0000664 0000000 0000000 00000004615 12722727034 0016156 0 ustar 00root root 0000000 0000000 pBS::get('recaptcha_private_key'),
'remoteip' => $_SERVER['REMOTE_ADDR'],
'challenge' => $this->cleanInput($_POST['recaptcha_challenge_field']),
'response' => $this->cleanInput($_POST['recaptcha_response_field'])
));
// Connect to the collection script.
$response = '';
$fp = @fsockopen('www.google.com', 80, $errno, $errstr);
if ($fp)
{
$out = 'POST /recaptcha/api/verify HTTP/1.1' . "\r\n";
$out .= 'Host: www.google.com' . "\r\n";
$out .= "User-Agent: reCAPTCHA/PHP\r\n";
$out .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n";
$out .= 'Content-Length: ' . strlen($data) . "\r\n\r\n";
$out .= $data . "\r\n";
$out .= 'Connection: Close' . "\r\n\r\n";
fwrite($fp, $out);
while (!feof($fs))
$response .= fgets($fs, 1160);
fclose($fp);
$response = explode("\r\n\r\n", $response, 2);
if (trim($response[0]) == 'true')
return true;
else
{
$warnings[] = $response[1];
return false;
}
}
else
{
$warnings[] = 'Could not connect to the remote ReCaptcha service, verification failed';
return false;
}
}
/*
* For the template.
*/
public function template()
{
echo '
';
}
private function cleanInput($var)
{
return urlencode(stripslashes($var));
}
} sources/spam.php 0000664 0000000 0000000 00000001103 12722727034 0014213 0 ustar 00root root 0000000 0000000
';
}
/*
* Custom code before the bottom part of recent.
*/
public function recentBottom()
{
echo '
';
}
} sources/tpl-wp.php 0000664 0000000 0000000 00000002472 12722727034 0014510 0 ustar 00root root 0000000 0000000
';
$specialPage['sidebar'] = ob_get_contents();
ob_end_clean();
}
} sources/tpl.php 0000664 0000000 0000000 00000000461 12722727034 0014060 0 ustar 00root root 0000000 0000000 usr = userInfo::_();
}
/*
* The users ID.
* @return int The id of the user.
*/
public function id()
{
return $this->usr->id;
}
/*
* The users language
* @return String english version of the language (ie german).
*/
public function language()
{
return $this->usr->language;
}
/*
* Is the user a guest?
* @return bool True if guest, false otherwise
*/
public function is_guest()
{
return $this->usr->is_guest;
}
/*
* Is the user an admin?
* @return bool True if admin, false otherwise
*/
public function is_admin()
{
return $this->usr->is_admin;
}
/*
* What is their name?
* @return String The name of the user. Guest is fine.
*/
public function name()
{
return $this->usr->name;
}
/*
* What is their email?
* @return String The email of the user. A default one is fine.
*/
public function email()
{
return $this->usr->email;
}
}
/*
* userInfo as a class. We kinda do a poor method, but its the best way for now.
*/
class userInfo
{
public static $instanceID = 0;
public static function _()
{
if (self::$instanceID == 0)
self::$instanceID = new userInfo;
return self::$instanceID;
}
public function __set($key, $value)
{
global $user_info;
$user_info[$key] = $value;
}
public function __get($key)
{
global $user_info;
return isset($user_info[$key]) ? $user_info[$key] : null;
}
public function __isset($key)
{
global $user_info;
return isset($user_info[$key]);
}
public function __unset($key)
{
global $user_info;
unset($user_info[$key], $user_info[$key]);
}
} sources/user.php 0000664 0000000 0000000 00000000461 12722727034 0014237 0 ustar 00root root 0000000 0000000