diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..e187950
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,19 @@
+{
+ "name": "aftercase/ponepaste",
+ "description": "PonePaste can store green",
+ "minimum-stability": "stable",
+ "license": "proprietary",
+ "authors": [
+ {
+ "name": "aftercase"
+ },
+ {
+ "name": "appledash"
+ }
+ ],
+ "require": {
+ "scrivo/highlight.php": "v9.18.1.7",
+ "ext-pdo": "*",
+ "ext-openssl": "*"
+ }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..0aa237f
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,95 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "6150c75f4650b6bf4b3f2cb2cbce0bda",
+ "packages": [
+ {
+ "name": "scrivo/highlight.php",
+ "version": "v9.18.1.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/scrivo/highlight.php.git",
+ "reference": "05996fcc61e97978d76ca7d1ac14b65e7cd26f91"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/05996fcc61e97978d76ca7d1ac14b65e7cd26f91",
+ "reference": "05996fcc61e97978d76ca7d1ac14b65e7cd26f91",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-mbstring": "*",
+ "php": ">=5.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8|^5.7",
+ "sabberworm/php-css-parser": "^8.3",
+ "symfony/finder": "^2.8|^3.4",
+ "symfony/var-dumper": "^2.8|^3.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "Highlight\\": "",
+ "HighlightUtilities\\": ""
+ },
+ "files": [
+ "HighlightUtilities/functions.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Geert Bergman",
+ "homepage": "http://www.scrivo.org/",
+ "role": "Project Author"
+ },
+ {
+ "name": "Vladimir Jimenez",
+ "homepage": "https://allejo.io",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Martin Folkers",
+ "homepage": "https://twobrain.io",
+ "role": "Contributor"
+ }
+ ],
+ "description": "Server side syntax highlighter that supports 185 languages. It's a PHP port of highlight.js",
+ "keywords": [
+ "code",
+ "highlight",
+ "highlight.js",
+ "highlight.php",
+ "syntax"
+ ],
+ "support": {
+ "issues": "https://github.com/scrivo/highlight.php/issues",
+ "source": "https://github.com/scrivo/highlight.php"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/allejo",
+ "type": "github"
+ }
+ ],
+ "time": "2021-07-09T00:30:39+00:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": [],
+ "plugin-api-version": "2.1.0"
+}
diff --git a/config/green.lang.json b/config/green.lang.json
new file mode 100644
index 0000000..ea878ba
--- /dev/null
+++ b/config/green.lang.json
@@ -0,0 +1,10 @@
+{
+ "aliases": ["greentext"],
+ "contains": [
+ {
+ "className": "comment",
+ "begin": ">",
+ "end": "$"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/includes/common.php b/includes/common.php
index 53db32d..e5dbb28 100644
--- a/includes/common.php
+++ b/includes/common.php
@@ -2,7 +2,7 @@
if (!defined('IN_PONEPASTE')) {
die('This file may not be accessed directly.');
}
-
+require_once(__DIR__ . '/../vendor/autoload.php');
require_once(__DIR__ . '/config.php');
require_once(__DIR__ . '/functions.php');
require_once(__DIR__ . '/DatabaseHandle.class.php');
@@ -53,7 +53,7 @@ function getSiteTotal_unique_views(DatabaseHandle $conn) : int {
* @return string HTML-escaped string
*/
function pp_html_escape(string $unescaped) : string {
- return htmlentities($unescaped, ENT_QUOTES, 'UTF-8', false);
+ return htmlspecialchars($unescaped, ENT_QUOTES, 'UTF-8', false);
}
function updatePageViews(DatabaseHandle $conn) : void {
diff --git a/paste.php b/paste.php
index 8d265b4..149b8d2 100644
--- a/paste.php
+++ b/paste.php
@@ -24,10 +24,13 @@ require_once('includes/functions.php');
require_once('includes/Tag.class.php');
require_once('includes/passwords.php');
+
require_once('includes/Parsedown/Parsedown.php');
require_once('includes/Parsedown/ParsedownExtra.php');
require_once('includes/Parsedown/SecureParsedown.php');
+use Highlight\Highlighter;
+
function rawView($content, $p_code) {
if ($p_code) {
header('Content-Type: text/plain');
@@ -41,10 +44,11 @@ $paste_id = intval(trim($_REQUEST['id']));
updatePageViews($conn);
+// This is used in the theme files.
+$totalpastes = getSiteTotalPastes($conn);
+
// Get paste favorite count
-$query = $conn->prepare('SELECT COUNT(*) FROM pins WHERE paste_id = ?');
-$query->execute([$paste_id]);
-$fav_count = intval($query->fetch(PDO::FETCH_NUM)[0]);
+$fav_count = $conn->querySelectOne('SELECT COUNT(*) FROM pins WHERE paste_id = ?', [$paste_id], PDO::FETCH_NUM)[0];
// Get paste info
$row = $conn->querySelectOne(
@@ -54,9 +58,6 @@ $row = $conn->querySelectOne(
WHERE pastes.id = ?', [$paste_id]);
-// This is used in the theme files.
-$totalpastes = getSiteTotalPastes($conn);
-
$notfound = null;
$is_private = false;
@@ -64,156 +65,150 @@ if ($row === null) {
header('HTTP/1.1 404 Not Found');
$notfound = $lang['notfound']; // "Not found";
goto Not_Valid_Paste;
-} else {
- $paste_owner_id = (int) $row['user_id'];
- $paste_title = $row['title'];
- $paste_code = $row['code'];
+}
- $paste = [
- 'title' => $paste_title,
- 'created_at' => (new DateTime($row['created_at']))->format('jS F Y h:i:s A'),
- 'updated_at' => (new DateTime($row['updated_at']))->format('jS F Y h:i:s A'),
- 'user_id' => $paste_owner_id,
- 'member' => $row['member'],
- 'views' => $row['views'],
- 'code' => $paste_code,
- 'tags' => getPasteTags($conn, $paste_id)
- ];
+$paste_owner_id = (int) $row['user_id'];
+$paste_title = $row['title'];
+$paste_code = $row['code'];
+$using_highlighter = $paste_code !== 'pastedown';
- $p_content = $row['content'];
- $p_visible = $row['visible'];
- $p_expiry = Trim($row['expiry']);
- $p_password = $row['password'];
- $p_encrypt = (bool) $row['encrypt'];
+$paste = [
+ 'title' => $paste_title,
+ 'created_at' => (new DateTime($row['created_at']))->format('jS F Y h:i:s A'),
+ 'updated_at' => (new DateTime($row['updated_at']))->format('jS F Y h:i:s A'),
+ 'user_id' => $paste_owner_id,
+ 'member' => $row['member'],
+ 'views' => $row['views'],
+ 'code' => $paste_code,
+ 'tags' => getPasteTags($conn, $paste_id)
+];
+
+$p_content = $row['content'];
+$p_visible = $row['visible'];
+$p_expiry = $row['expiry'];
+$p_password = $row['password'];
+$p_encrypt = (bool) $row['encrypt'];
- $is_private = $row['visible'] === '2';
- $private_error = false;
+$is_private = $row['visible'] === '2';
- if ($is_private && (!$current_user || $current_user->user_id !== $paste_owner_id)) {
- $notfound = $lang['privatepaste']; //" This is a private paste. If you created this paste, please login to view it.";
- $private_error = true;
+if ($is_private && (!$current_user || $current_user->user_id !== $paste_owner_id)) {
+ $notfound = $lang['privatepaste']; //" This is a private paste. If you created this paste, please login to view it.";
+ goto Not_Valid_Paste;
+}
+
+/* Verify paste password */
+$password_required = $p_password !== null && $p_password !== 'NONE';
+$password_valid = true;
+$password_candidate = '';
+
+if ($password_required) {
+ if (!empty($_POST['mypass'])) {
+ $password_candidate = $_POST['mypass'];
+ } else if (!empty($_GET['password'])) {
+ $password_candidate = @base64_decode($_GET['password']);
+ }
+
+ if (empty($password_candidate)) {
+ $password_valid = false;
+ $error = $lang['pwdprotected']; // 'Password protected paste';
+ goto Not_Valid_Paste;
+ } elseif (!pp_password_verify($password_candidate, $p_password)) {
+ $password_valid = false;
+ $error = $lang['wrongpassword']; // 'Wrong password';
goto Not_Valid_Paste;
- }
-
- if (!empty($p_expiry) && $p_expiry !== 'SELF') {
- $input_time = $p_expiry;
- $current_time = mktime(date("H"), date("i"), date("s"), date("n"), date("j"), date("Y"));
- if ($input_time < $current_time) {
- $notfound = $lang['expired'];
- $p_private_error = 1;
- goto Not_Valid_Paste;
- }
- }
-
- if ($p_encrypt == 1) {
- $p_content = openssl_decrypt($p_content, PP_ENCRYPTION_ALGO, PP_ENCRYPTION_KEY);
- }
-
- $op_content = trim(htmlspecialchars_decode($p_content));
-
- // Download the paste
- if (isset($_GET['download'])) {
- if ($p_password == "NONE" || $p_password === null) {
- doDownload($paste_id, $paste_title, $p_member, $op_content, $paste_code);
- exit();
- } else {
- if (isset($_GET['password'])) {
- if (pp_password_verify($_GET['password'], $p_password)) {
- doDownload($paste_id, $paste_title, $p_member, $op_content, $paste_code);
- exit();
- } else {
- $error = $lang['wrongpassword']; // 'Wrong password';
- }
- } else {
- $error = $lang['pwdprotected']; // 'Password protected paste';
- }
- }
- }
-
- // Raw view
- if (isset($_GET['raw'])) {
- if ($p_password == "NONE" || $p_password === null) {
- rawView($op_content, $paste_code);
- exit();
- } else {
- if (isset($_GET['password'])) {
- if (pp_password_verify($_GET['password'], $p_password)) {
- rawView($op_content, $paste_code);
- exit();
- } else {
- $error = $lang['wrongpassword']; // 'Wrong password';
- }
- } else {
- $error = $lang['pwdprotected']; // 'Password protected paste';
- }
- }
- }
-
- // Preprocess
- $highlight = array();
- $prefix_size = strlen('!highlight!');
- $lines = explode("\n", $p_content);
- $p_content = "";
- foreach ($lines as $idx => $line) {
- if (substr($line, 0, $prefix_size) == '!highlight!') {
- $highlight[] = $idx + 1;
- $line = substr($line, $prefix_size);
- }
- $p_content .= $line . "\n";
- }
-
- $p_content = rtrim($p_content);
-
- // Apply syntax highlight
- $p_content = htmlspecialchars_decode($p_content);
- if ($paste_code === "pastedown") {
- $Parsedown = new Parsedown();
- $Parsedown->setSafeMode(true);
- $p_content = $Parsedown->text($p_content);
- } else {
- $geshi = new GeSHi($p_content, $paste_code, 'includes/geshi/');
-
- $geshi->enable_classes();
- $geshi->set_header_type(GESHI_HEADER_DIV);
- $geshi->set_line_style('color: #aaaaaa; width:auto;');
- $geshi->set_code_style('color: #757584;');
- if (count($highlight)) {
- $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
- $geshi->highlight_lines_extra($highlight);
- $geshi->set_highlight_lines_extra_style('color:#399bff;background:rgba(38,92,255,0.14);');
- } else {
- $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, 2);
- }
- $p_content = $geshi->parse_code();
- $style = $geshi->get_stylesheet();
- $ges_style = '';
- }
-
- // Embed view after GeSHI is applied so that $p_code is syntax highlighted as it should be.
- if (isset($_GET['embed'])) {
- if ($p_password == "NONE" || $p_password === null) {
- embedView($paste_id, $paste_title, $p_content, $paste_code, $title, $baseurl, $ges_style, $lang);
- exit();
- } else {
- if (isset($_GET['password'])) {
- if (pp_password_verify($_GET['password'], $p_password)) {
- embedView($paste_id, $paste_title, $p_content, $paste_code, $title, $p_baseurl, $ges_style, $lang);
- exit();
- } else {
- $error = $lang['wrongpassword']; // 'Wrong password';
- }
- } else {
- $error = $lang['pwdprotected']; // 'Password protected paste';
- }
- }
}
}
-require_once('theme/' . $default_theme . '/header.php');
-if ($p_password == "NONE" || $p_password === null) {
- // No password & diplay the paste
+if (!empty($p_expiry) && $p_expiry !== 'SELF') {
+ $input_time = $p_expiry;
+ $current_time = mktime(date("H"), date("i"), date("s"), date("n"), date("j"), date("Y"));
+ if ($input_time < $current_time) {
+ $notfound = $lang['expired'];
+ goto Not_Valid_Paste;
+ }
+}
+if ($p_encrypt == 1) {
+ $p_content = openssl_decrypt($p_content, PP_ENCRYPTION_ALGO, PP_ENCRYPTION_KEY);
+}
+
+$op_content = trim(htmlspecialchars_decode($p_content));
+
+// Download the paste
+if (isset($_GET['download'])) {
+ doDownload($paste_id, $paste_title, $p_member, $op_content, $paste_code);
+ exit();
+}
+
+// Raw view
+if (isset($_GET['raw'])) {
+ rawView($op_content, $paste_code);
+ exit();
+}
+
+// Preprocess
+$highlight = array();
+$prefix_size = strlen('!highlight!');
+$lines = explode("\n", $p_content);
+$p_content = "";
+foreach ($lines as $idx => $line) {
+ if (substr($line, 0, $prefix_size) == '!highlight!') {
+ $highlight[] = $idx + 1;
+ $line = substr($line, $prefix_size);
+ }
+ $p_content .= $line . "\n";
+}
+
+$p_content = rtrim($p_content);
+
+// Apply syntax highlight
+$p_content = htmlspecialchars_decode($p_content);
+if ($paste_code === "pastedown") {
+ $parsedown = new Parsedown();
+ $parsedown->setSafeMode(true);
+ $p_content = $parsedown->text($p_content);
+} else {
+ Highlighter::registerLanguage('green', 'config/green.lang.json');
+ $hl = new Highlighter();
+ $highlighted = $hl->highlight($paste_code == 'text' ? 'plaintext' : $paste_code, $p_content)->value;
+ $lines = HighlightUtilities\splitCodeIntoArray($highlighted);
+ //$highlight = new Highlighter();
+ //$p_content = $highlight->highlight($paste_code, $p_content)->value;
+
+ //$p_content = linkify($p_content);
+
+ $geshi = new GeSHi($p_content, $paste_code, 'includes/geshi/');
+
+ $geshi->enable_classes();
+ $geshi->set_header_type(GESHI_HEADER_DIV);
+ $geshi->set_line_style('color: #aaaaaa; width:auto;');
+ $geshi->set_code_style('color: #757584;');
+ if (count($highlight)) {
+ $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
+ $geshi->highlight_lines_extra($highlight);
+ $geshi->set_highlight_lines_extra_style('color:#399bff;background:rgba(38,92,255,0.14);');
+ } else {
+ $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, 2);
+ }
+ $p_content = $geshi->parse_code();
+ $style = $geshi->get_stylesheet();
+ $ges_style = '';
+}
+
+// Embed view after highlighting is applied so that $p_code is syntax highlighted as it should be.
+if (isset($_GET['embed'])) {
+ embedView($paste_id, $paste_title, $p_content, $paste_code, $title, $baseurl, $ges_style, $lang);
+ exit();
+}
+
+require_once('theme/' . $default_theme . '/header.php');
+if ($password_required && $password_valid) {
+ /* base64 here means that the password is exposed in the URL, technically - how to handle this better? */
+ $p_download = "paste.php?download&id=$paste_id&password=" . base64_encode($password_candidate);
+ $p_raw = "paste.php?raw&id=$paste_id&password=" . base64_encode($password_candidate);
+ $p_embed = "paste.php?embed&id=$paste_id&password=" . base64_encode($password_candidate);
+} else {
// Set download URL
if (PP_MOD_REWRITE) {
$p_download = "download/$paste_id";
@@ -224,49 +219,24 @@ if ($p_password == "NONE" || $p_password === null) {
$p_raw = "paste.php?raw&id=$paste_id";
$p_embed = "paste.php?embed&id=$paste_id";
}
-
-
- // View counter
- if (@$_SESSION['not_unique'] !== $paste_id) {
- $_SESSION['not_unique'] = $paste_id;
- $conn->query("UPDATE pastes SET views = (views + 1) where id = ?", [$paste_id]);
- }
-
- // Theme
- require_once('theme/' . $default_theme . '/view.php');
- if ($p_expiry == "SELF") {
- $conn->query('DELETE FROM pastes WHERE id = ?', [$paste_id]);
- }
-} else {
- $p_download = "paste.php?download&id=$paste_id&password=" . pp_password_hash(isset($_POST['mypass']));
- $p_raw = "paste.php?raw&id=$paste_id&password=" . pp_password_hash(isset($_POST['mypass']));
- // Check password
- if (isset($_POST['mypass'])) {
- if (pp_password_verify($_POST['mypass'], $p_password)) {
- // Theme
- require_once('theme/' . $default_theme . '/view.php');
- if ($p_expiry == "SELF") {
- $conn->prepare('DELETE FROM pastes WHERE id = ?')
- ->execute([$paste_id]);
- }
- } else {
- $error = $lang['wrongpwd']; //"Password is wrong";
- require_once('theme/' . $default_theme . '/errors.php');
- }
- } else {
- // Display errors
- require_once('theme/' . $default_theme . '/errors.php');
- }
}
+// View counter
+if (@$_SESSION['not_unique'] !== $paste_id) {
+ $_SESSION['not_unique'] = $paste_id;
+ $conn->query("UPDATE pastes SET views = (views + 1) where id = ?", [$paste_id]);
+}
+
+require_once('theme/' . $default_theme . '/view.php');
+
Not_Valid_Paste:
-// Private paste not valid
-if ($is_private || $notfound) {
+
+if ($is_private || $notfound || !$password_valid) {
// Display errors
require_once('theme/' . $default_theme . '/header.php');
require_once('theme/' . $default_theme . '/errors.php');
}
// Footer
-require_once('theme/' . $default_theme . '/footer.php');
+ require_once('theme/' . $default_theme . '/footer.php');
diff --git a/theme/bulma/view.php b/theme/bulma/view.php
index 8faeaff..bba41d4 100644
--- a/theme/bulma/view.php
+++ b/theme/bulma/view.php
@@ -74,6 +74,9 @@ function setupTagsInput() {
})(jQuery);
});
+
+
+
- Bulma theme
@@ -98,8 +101,6 @@ $selectedloader = "$bg[$i]"; // set variable equal to which random filename was
?>