diff --git a/.htaccess b/.htaccess
deleted file mode 100644
index 39c72ad..0000000
--- a/.htaccess
+++ /dev/null
@@ -1,52 +0,0 @@
-Options +FollowSymLinks
-RewriteEngine on
-
- RewriteCond %{REQUEST_FILENAME} !-f
- RewriteCond %{REQUEST_FILENAME} !-d
- RewriteRule ^page/([a-zA-Z0-9]+)/? pages.php?page=$1 [L]
- RewriteRule ^archive archive.php [L]
- RewriteRule ^discover discover.php [L]
- RewriteRule ^profile profile.php [L]
- RewriteRule ^user/([^/]+)/?$ user.php?user=$1 [L]
- RewriteRule ^user/([^/]+)/([^/]+)/?$ user.php?user=$1&q=$2 [L]
- RewriteRule ^contact contact.php [L]
- RewriteRule ^download/(.*)$ paste.php?download&id=$1 [L]
- RewriteRule ^raw/(.*)$ paste.php?raw&id=$1 [L]
- RewriteRule ^embed/(.*)$ paste.php?embed&id=$1 [L]
- RewriteRule ^report report.php [L]
- RewriteRule ^event event.php [L]
-Options +FollowSymLinks
-RewriteBase /
-RewriteCond %{HTTP_USER_AGENT} "=Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0" [OR]
-RewriteCond %{HTTP_USER_AGENT} "=Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0" [OR]
-RewriteCond %{HTTP_USER_AGENT} "=Mozilla/5.0 (Windows NT 6.2; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0" [OR]
-RewriteCond %{HTTP_USER_AGENT} "=Mozilla/5.0 (Windows NT 6.2; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0" [OR]
-RewriteCond %{HTTP_USER_AGENT} "=Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36" [OR]
-RewriteCond %{HTTP_USER_AGENT} "=Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0" [OR]
-RewriteCond %{HTTP_USER_AGENT} "=Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0" [OR]
-RewriteCond %{HTTP_USER_AGENT} Mb2345Browser|LieBaoFast|zh-CN|MicroMessenger|zh_CN|Kinza|Datanyze|serpstatbot|spaziodati|OPPO\sA33|AspiegelBot|aspiegel|PetalBot|SemrushBot/7~bl [NC]
-RewriteRule ^ - [F,L]
-
-
-
-
- RewriteCond %{REQUEST_FILENAME} !-f
- RewriteCond %{REQUEST_FILENAME} !-d
- RewriteRule ^(.*)$ paste.php?id=$1 [L]
-
-
-# compress text, html, javascript, css, xml:
-AddOutputFilterByType DEFLATE text/plain
-AddOutputFilterByType DEFLATE text/html
-AddOutputFilterByType DEFLATE text/xml
-AddOutputFilterByType DEFLATE text/css
-AddOutputFilterByType DEFLATE application/xml
-AddOutputFilterByType DEFLATE application/xhtml+xml
-AddOutputFilterByType DEFLATE application/rss+xml
-AddOutputFilterByType DEFLATE application/javascript
-AddOutputFilterByType DEFLATE application/x-javascript
-
-# Or, compress certain file types by extension:
-
-SetOutputFilter DEFLATE
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 8f2e46c..b155986 100644
--- a/README.md
+++ b/README.md
@@ -5,4 +5,4 @@ punishedponepaste
# Building the JS
When you change the JS, you need to rebuild it. `assets/bundle.js` is used in dev, `assets/bundle.min.js` is used in production.
-You need Yarn (version 1, not version 2 - 2 may work but I haven't tried it.) After that, whenever you change anything under `js/`, you need to run `yarn rollup --config`. Good luck!
\ No newline at end of file
+You need Yarn (version 1, not version 2 - 2 may work, but I haven't tried it.) After that, whenever you change anything under `js/`, you need to run `yarn rollup --config`. Good luck!
\ No newline at end of file
diff --git a/includes/Helpers/SessionHelper.php b/includes/Helpers/SessionHelper.php
index 0b45518..a13970f 100644
--- a/includes/Helpers/SessionHelper.php
+++ b/includes/Helpers/SessionHelper.php
@@ -7,6 +7,7 @@ use PonePaste\Models\UserSession;
class SessionHelper {
public const REMEMBER_TOKEN_COOKIE = '_ponepaste_token';
+ public const CSRF_TOKEN_KEY = 'csrf_token';
public static function currentUser() {
$session_user = SessionHelper::currentUserFromPhpSession();
@@ -60,7 +61,6 @@ class SessionHelper {
return null;
}
-
return User::find(intval($_SESSION['user_id']));
}
}
\ No newline at end of file
diff --git a/includes/Models/Paste.php b/includes/Models/Paste.php
index df2a1b9..4241dc3 100644
--- a/includes/Models/Paste.php
+++ b/includes/Models/Paste.php
@@ -33,8 +33,6 @@ class Paste extends Model {
$this->tags()->attach($tag);
}
- // FIXME: We need to get rid of tagsys.
- $this->tagsys = implode(',', $tags);
$this->save();
}
diff --git a/includes/captcha.php b/includes/captcha.php
index 032b6c2..bc1775c 100644
--- a/includes/captcha.php
+++ b/includes/captcha.php
@@ -89,7 +89,7 @@ function captcha($color, $mode, $mul, $allowed) : array {
}
// Generate HTML for image src
- $image_src = substr(__FILE__, strlen(realpath($_SERVER['DOCUMENT_ROOT']))) . '?_CAPTCHA&t=' . urlencode(microtime());
+ $image_src = substr(__FILE__, strlen(realpath($_SERVER['DOCUMENT_ROOT']))) . '?_CAPTCHA&_R=' . urlencode(rand());
$image_src = '/' . ltrim(preg_replace('/\\\\/', '/', $image_src), '/');
$_SESSION['_CAPTCHA']['config'] = serialize($captcha_config);
@@ -125,7 +125,6 @@ if (!function_exists('hex2rgb')) {
// Draw the image
if (isset($_GET['_CAPTCHA'])) {
-
session_start();
$captcha_config = unserialize(@$_SESSION['_CAPTCHA']['config']);
@@ -178,5 +177,4 @@ if (isset($_GET['_CAPTCHA'])) {
// Output image
header("Content-type: image/png");
imagepng($captcha);
-
-}
\ No newline at end of file
+}
diff --git a/includes/common.php b/includes/common.php
index 86b210c..508898d 100644
--- a/includes/common.php
+++ b/includes/common.php
@@ -5,6 +5,7 @@ if (!defined('IN_PONEPASTE')) {
require_once(__DIR__ . '/../vendor/autoload.php');
require_once(__DIR__ . '/config.php');
require_once(__DIR__ . '/functions.php');
+require_once(__DIR__ . '/passwords.php');
require_once(__DIR__ . '/DatabaseHandle.class.php');
use Illuminate\Database\Capsule\Manager as Capsule;
@@ -154,6 +155,33 @@ function updatePageViews() : void {
}
}
+function setupCsrfToken() : string {
+ if (isset($_SESSION[SessionHelper::CSRF_TOKEN_KEY])) {
+ return $_SESSION[SessionHelper::CSRF_TOKEN_KEY];
+ }
+
+ $token = pp_random_token();
+ $_SESSION[SessionHelper::CSRF_TOKEN_KEY] = $token;
+
+ return $token;
+}
+
+function verifyCsrfToken($token = null) : bool {
+ if ($token === null) {
+ $token = $_POST[SessionHelper::CSRF_TOKEN_KEY];
+ }
+
+ if (empty($token) || empty($_SESSION[SessionHelper::CSRF_TOKEN_KEY])) {
+ return false;
+ }
+
+ $success = hash_equals($_SESSION[SessionHelper::CSRF_TOKEN_KEY], $token);
+
+ unset($_SESSION[SessionHelper::CSRF_TOKEN_KEY]);
+
+ return $success;
+}
+
session_start();
/* Set up the database and Eloquent ORM */
@@ -215,6 +243,8 @@ $total_unique_views = PageView::select('tvisit')->orderBy('id', 'desc')->first()
$current_user = SessionHelper::currentUser();
+//SessionHelper::setupCsrfToken();
+
$script_bundles = [];
/* Security headers */
diff --git a/includes/functions.php b/includes/functions.php
index 854d845..9a2db76 100644
--- a/includes/functions.php
+++ b/includes/functions.php
@@ -55,13 +55,6 @@ function tagsToHtmlUser(string | array | Collection $tags, $profile_username) :
return $output;
}
-function getevent($conn, $event_name, $count) {
- $query = $conn->prepare("SELECT id, visible, title, date, now_time, views, member FROM pastes WHERE visible='1' AND tagsys LIKE '%?%'
- ORDER BY RAND () LIMIT 0, ?");
- $query->execute([$event_name, $count]);
- return $query->fetchAll();
-}
-
function linkify($value, $protocols = array('http', 'mail'), array $attributes = array()) {
// Link attributes
$attr = '';
@@ -150,7 +143,7 @@ function truncate(string $input, int $maxWords, int $maxChars) : string {
return $result . ($input == $result ? '' : '[...]');
}
-function embedView($paste_id, $p_title, $content, $p_code, $title, $baseurl, $lang) {
+function embedView($paste_id, $p_title, $content, $title) {
$stats = false;
if ($content) {
// Build the output
diff --git a/index.php b/index.php
index 4cff16a..a398311 100644
--- a/index.php
+++ b/index.php
@@ -75,6 +75,11 @@ updatePageViews();
// POST Handler
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ if (!verifyCsrfToken()) {
+ $error = 'Incorrect CSRF token (do you have cookies enabled?)';
+ goto OutPut;
+ }
+
$error = validatePasteFields();
if ($error !== null) {
@@ -172,6 +177,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
}
+
OutPut:
+$csrf_token = setupCsrfToken();
$page_template = 'main';
require_once('theme/' . $default_theme . '/common.php');
diff --git a/js/data_tables.js b/js/data_tables.js
index f5a2f17..9f88b0c 100644
--- a/js/data_tables.js
+++ b/js/data_tables.js
@@ -224,6 +224,10 @@ class DataTable {
}
const dumbFilterCallback = (datum, query) => {
+ if (!query) {
+ return true;
+ }
+
if (datum.title.indexOf(query) !== -1) {
return true;
}
diff --git a/js/user_profile.js b/js/user_profile.js
index aa8a0f7..3134047 100644
--- a/js/user_profile.js
+++ b/js/user_profile.js
@@ -2,6 +2,16 @@ import { escape, whenReady } from './dom';
import { DataTable, dumbFilterCallback } from './data_tables';
import { globalSetup } from './main';
+const getUserInfo = () => {
+ const elem = document.getElementById('js-data-holder');
+
+ if (!elem) {
+ return { userId: null, csrfToken: null };
+ }
+
+ return { userId: elem.dataset.userId, csrfToken: elem.dataset.csrfToken };
+};
+
const parsePasteInfo = (elem) => {
if (!elem.dataset.pasteInfo) {
return null;
@@ -40,12 +50,23 @@ whenReady(() => {
`;
}).join('');
+ const userData = getUserInfo();
+
+ const deleteElem = true ? `
+
+ | ` : '';
+
return `
${escape(rowData.title)} |
${rowData.created_at} |
${rowData.visibility} |
${rowData.views || 0} |
${tags} |
+ ${deleteElem}
`;
},
filterCallback: dumbFilterCallback,
diff --git a/pages.php b/pages.php
index 41fff06..26469b2 100644
--- a/pages.php
+++ b/pages.php
@@ -7,13 +7,16 @@ use PonePaste\Models\Page;
updatePageViews();
+$page_title = 'Page not found';
+
if (isset($_GET['page'])) {
$page = Page::select('page_title', 'page_content', 'last_date')
->where('page_name', $_GET['page'])
->first();
- $page_title = $page->page_title;
-} else {
- $page_title = 'Page not found';
+
+ if (isset($page)) {
+ $page_title = $page->page_title;
+ }
}
$page_template = 'pages';
diff --git a/paste.php b/paste.php
index 6b0f114..d904732 100644
--- a/paste.php
+++ b/paste.php
@@ -2,7 +2,6 @@
define('IN_PONEPASTE', 1);
require_once('includes/common.php');
require_once('includes/functions.php');
-require_once('includes/passwords.php');
use Highlight\Highlighter;
use PonePaste\Models\Paste;
@@ -55,6 +54,13 @@ if (!$paste) {
goto Not_Valid_Paste;
}
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ if (!verifyCsrfToken()) {
+ $notfound = 'Invalid CSRF token (do you have cookies enabled?)';
+ goto Not_Valid_Paste;
+ }
+}
+
$paste_owner_id = $paste->user->id;
$paste_title = $paste->title;
$paste_code = $paste->code;
@@ -72,7 +78,6 @@ $fav_count = $paste->favouriters()->count();
'tags' => getPasteTags($conn, $paste_id)
];*/
-//$p_member = $row['member'];
$p_content = $paste->content;
$p_visible = $paste->visible;
$p_expiry = $paste->expiry;
@@ -80,7 +85,6 @@ $p_password = $paste->password;
$p_encrypt = (bool) $paste->encrypt;
$paste_is_favourited = $current_user !== null && $current_user->favourites->where('paste_id', $paste->id)->count() === 1;
-
$is_private = $p_visible === '2';
if ($is_private && (!$current_user || $current_user->id !== $paste_owner_id)) {
@@ -88,6 +92,19 @@ if ($is_private && (!$current_user || $current_user->id !== $paste_owner_id)) {
goto Not_Valid_Paste;
}
+/* Paste deletion */
+if (isset($_POST['delete'])) {
+ if (!$current_user || ($current_user->id !== $paste_owner_id)) {
+ $notfound = 'You cannot delete someone else\'s paste!';
+ goto Not_Valid_Paste;
+ }
+
+ $paste->delete();
+ flashSuccess('Paste deleted.');
+ header('Location: ' . urlForMember($current_user));
+ die();
+}
+
/* Verify paste password */
$password_required = $p_password !== null && $p_password !== 'NONE';
$password_valid = true;
@@ -191,7 +208,7 @@ if ($paste_code === "pastedown") {
// 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, $lang);
+ embedView($paste_id, $paste_title, $p_content, $title);
exit();
}
@@ -230,5 +247,7 @@ if ($is_private || $notfound || !$password_valid) {
// Display errors
$page_template = 'errors';
}
+
+$csrf_token = setupCsrfToken();
require_once('theme/' . $default_theme . '/common.php');
diff --git a/profile.php b/profile.php
index ef6b505..7041bfc 100644
--- a/profile.php
+++ b/profile.php
@@ -6,7 +6,6 @@ require_once('includes/passwords.php');
use PonePaste\Models\Paste;
-// Check if already logged in
if ($current_user === null) {
header("Location: ./login.php");
die();
@@ -19,7 +18,9 @@ $user_ip = $current_user->ip;
$user_password = $current_user->password;
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
- if (isset($_POST['cpassword'])) {
+ if (!verifyCsrfToken()) {
+ $error = 'Invalid CSRF token (do you have cookies enabled?)';
+ } else if (isset($_POST['cpassword'])) {
$user_new_full = trim(htmlspecialchars($_POST['full']));
$user_old_pass = $_POST['old_password'];
if (pp_password_verify($user_old_pass, $user_password)) {
@@ -40,8 +41,8 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
updatePageViews();
$total_user_pastes = Paste::where('user_id', $current_user->id)->count();
+$csrf_token = setupCsrfToken();
-// Theme
$page_template = 'profile';
$page_title = 'My Profile';
require_once('theme/' . $default_theme . '/common.php');
diff --git a/report.php b/report.php
deleted file mode 100644
index a2230f5..0000000
--- a/report.php
+++ /dev/null
@@ -1,15 +0,0 @@
-username : 'Guest';
-$p_pastereport = $_POST['reppasteid'];
-$p_reasonrep = preg_replace("/[^0-9]/", "", $p_reasonrep);
-
-$conn->prepare('INSERT INTO user_reports (m_report, p_report, t_report, rep_reason) VALUES (?, ?, NOW(), ?)')
- ->execute([$p_memreport, $p_pastereport, $p_reasonrep]);
-$repmes = "Paste has been reported.";
-
diff --git a/theme/bulma/common.php b/theme/bulma/common.php
index e364de7..2ce6f91 100644
--- a/theme/bulma/common.php
+++ b/theme/bulma/common.php
@@ -125,6 +125,10 @@ $flashes = getFlashes();
+
+
+
+
diff --git a/theme/bulma/event.php b/theme/bulma/event.php
index 628a140..fa36f19 100644
--- a/theme/bulma/event.php
+++ b/theme/bulma/event.php
@@ -57,132 +57,9 @@
-
Entries Deadline
-
-
- Days,
- Hours,
- Minutes,
- Seconds Remaining
-
-
-
+
No event right now!
-
-
Welcome to Ponepaste /pj50kb/ Pastejam
-
- No context 50kb Challenge
-
- What is the PasteJam 50kb challange?
-
The PasteJam 50kb challenge is a competition that last for two weeks that any one
- can join.
-
What do I win?
-
>A fucking badge, plus the best pony game the host can
- find.
-

-
Note: This is a steam game, winner will be sent a cdkey
-
-
What do I have to do?
-
A prompt is given and you have to write a 50kb greentext or prose.
-
Does it have to be exactly 50kb
-
As close as possible. This is more of a guide due to magin of error.
-
What will happen if I submit a paste thats under 50kb?
-
Again, As close as possible.
-
Can I ask for feedback for my green/prose?
-
From other anons on /mlp/ is fine.
-
Can I write anything?
-
As long it follows the prompt, mlp related and follows Ponepaste rules.
-
How is the prompt chosen?
-
Hand picked homonyms.
-
How do I submit?
-
Make a UNLISTED paste with /pj50kb/ in the title and tag.
-
How is the winner chosen?
-
By a vote after the closing date
-
When is the closing date?
-
28th of May
-
When does the voting start?
-
28th of May, to gives (you) time to read.
-
Where do I vote?
-
Here, on this page.
-
How long will the vote last?
-
Two weeks. Vote ends on 11th of June, 8pm UTC
-
What will I be voting on?
-
How well the story is written, how unique the idea is and how it fits the
- prompt.
-
Can the entry be a sequel/ side arc of one of their existing greens?
-
It must be a stand alone story.
-
-
-
-
Prompt:
-
- Listen to the prompt:
-
-
-
-
-
-
-
-
Submitted Entries
-
-
-
-
-
-
Note:
-
-
- No one has been nominated for the Wooden Spoon Award.
-
-
-
-
-
-
-
-
diff --git a/theme/bulma/main.php b/theme/bulma/main.php
index 63319a1..719a6b5 100644
--- a/theme/bulma/main.php
+++ b/theme/bulma/main.php
@@ -298,12 +298,15 @@
+
+
+
diff --git a/theme/bulma/profile.php b/theme/bulma/profile.php
index 74c20c7..22ed474 100644
--- a/theme/bulma/profile.php
+++ b/theme/bulma/profile.php
@@ -4,7 +4,9 @@
Total Pastes: = $total_user_pastes ?>
-
username) . '" target="_self">My Pastes'; ?>
+
My Profile
-