From ea3052fb3a55167c92db81199e780f72ac0f5948 Mon Sep 17 00:00:00 2001 From: eleksir Date: Fri, 17 Mar 2017 19:56:33 +0300 Subject: [PATCH] Initial commit --- README.md | 118 +++++++++++++++++ index.php | 374 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 492 insertions(+) create mode 100644 README.md create mode 100644 index.php diff --git a/README.md b/README.md new file mode 100644 index 0000000..356a739 --- /dev/null +++ b/README.md @@ -0,0 +1,118 @@ +## Paste. ## + +This is pastebin replacement. It does not use ads, it is opensource it is relatively small. +And it has minimal pastebin API stub, at least pastebinit can paste to it with minimal config changes. +Besides pastebinit there are 2 cli clients available on main page of this app. + +### How do I get set up? ### + +This paste utilizes PDO SQLite driver, well, at least for now :) and mbstrings. +Tested php versions are 5.6.30 and 7.0.12. Paste uses **paste/paste.sqlite** file as db. + +Tested on apache/fcgid (windows) for dev and nginx/php-fpm for prod. + +Default installation assumes that paste runs as / app on site, but you can change it (BASEURL) in index.php. + +Nginx config snippet: +``` +# limit paste size to ~ 200k +client_max_body_size 256k; + +location /raw { + rewrite "^\/raw\/([a-z|A-Z]*)$" /index.php?$1; +} + +rewrite "^/([a-z|A-Z]*)$" /index.php?$1; + +location / { + root /var/www/htdocs/empty; + + index index.php; + location ~ \.php$ { + if ($request_method !~ ^(GET|HEAD|POST)$ ) { + return 499; + } + + root /var/www/htdocs; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini + fastcgi_index index.php; + include fastcgi.conf; + fastcgi_pass php; + } +} +``` + +Database initialises automatically :) + +### Contribution guidelines ### + +Clean code, preferably with comments for some quirky places. + +### PasteBinIt configuration ### + +default pastebin site, __~/.pastebinit.xml__: +``` + + http://your.site + Stephane Graber + stgraber@stgraber.org + text + +``` +and how to work with it __~/.pastebinit.d/your.site.conf__: +``` +[pastebin] +basename = your.site +regexp = http://((([a-zA-Z0-9\-_\.]*)(your\.site))) + +[format] +content = api_paste_code +user = api_paste_name +subdomain = api_paste_subdomain +private = api_paste_private +expiry = api_paste_expire_date +format = api_paste_format +email = api_paste_email +page = page +submit = submit +regexp = regexp +api_dev_key = api_dev_key +api_option = api_option + +[defaults] +submit = submit +format = text +private = 0 +expiry = 1M +subdomain = +email = +api_dev_key = 253ce2f0a45140ee0a44ca99aa492260 +api_option = paste +page = / +regexp = (.*) +``` + +FYI difference between pastebin and paste are minimal: + +```diff +diff -ruN pastebin.com.conf your.site.conf +--- pastebin.com.conf ++++ your.site.conf +@@ -1,6 +1,6 @@ + [pastebin] +-basename = pastebin.com +-regexp = http://((([a-zA-Z0-9\-_\.]*)(pastebin\.com))) ++basename = your.site ++regexp = http://((([a-zA-Z0-9\-_\.]*)(your\.site))) + + [format] + content = api_paste_code +@@ -25,5 +25,5 @@ + email = + api_dev_key = 253ce2f0a45140ee0a44ca99aa492260 + api_option = paste +-page = /api/api_post.php ++page = / + regexp = (.*) +``` \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..cc4223a --- /dev/null +++ b/index.php @@ -0,0 +1,374 @@ + + + + + + Paste. + + +

Paste

+
+
+ for + +
+
%s

\n", $text); + } +?> +

+ Console client can be found here: e    thanks sprunge.us for their client :)
+ More minimalist console client can be found here: d
+
+ 2015 +

+ + + +#!/bin/bash + +usage() { +description | fmt -s >&2 +} + +description() { +cat << HERE + +DESCRIPTION + Upload data and fetch URL from the pastebin + +USAGE + $0 filename.txt + $0 text string + $0 < filename.txt + piped_data | $0 + +NOTES +-------------------------------------------------------------------------- +* INPUT METHODS * +$0 can accept piped data, STDIN redirection [&2 + if [ "$*" ]; then + echo Arguments present... >&2 + if [ -f "$*" ]; then + echo Uploading the contents of "$*"... >&2 + cat "$*" + else + echo Uploading the text: \""$*"\"... >&2 + echo "$*" + fi | curl -F "exs=<-" + else + echo No arguments found, printing USAGE and exiting. >&2 + usage + fi +else + echo Using input from a pipe or STDIN redirection... >&2 + while read -r line ; do + echo $line + done | curl -F "exs=<-" +fi + +#!/usr/bin/env bash + +if [[ "$1" == "--help" ]]; then + echo "Usage: $0 < file" + echo " echo foo | $0" +elif [[ -f "$1" ]]; then + curl -F "exs=<-" "" <"$1" +else + curl -F "exs=<-" "" +fi + +exit 0 +'; +exec( + "CREATE TABLE IF NOT EXISTS paste ( + id TEXT PRIMARY KEY, + paste TEXT, + time INTEGER, + etime INTEGER + )" + ); + + if($r === false) { + $e = $r->errorInfo(); + showindex($e[2]); + } + + $dbh = null; +} + +function query_db($id) { + if (! file_exists(DBPATH)) { + init_db(); + return false; + } + + $dbh = new PDO("sqlite:" . DBPATH); + $sth = $dbh->query("SELECT paste FROM paste WHERE id='$id'"); + + if ($sth === false) { + $e = $r->errorInfo(); + showindex($e[2]); + exit; + } + + $sth->setFetchMode(PDO::FETCH_ASSOC); + $data = $sth->fetch(); + $dbh = null; + + if ($data === false) { + return($data); + } else { + if (isset($data['etime']) and ($data['etime'] < time())){ + return false; + } + + $data = $data['paste']; + return($data); # false if no data or no key in db + } +} + +function store_data($paste) { + if (! file_exists(DBPATH)) { init_db(); } + $dbh = new PDO("sqlite:" . DBPATH); + $q = 0; + + do { + if ($q > 100) { # assume key-value space depleted if we try more than 100 times + $q = false; + break; + } + $id = gen_id(); + $q++; + } while (! $dbh->query("SELECT id FROM paste WHERE id='$id'")); + + if($q === false) { + return('Storage depleted.'); + } + + $ctime = time(); + $etime = $ctime + 14515200; + + if(isset($_POST['etime'])) { + switch ($_POST['etime']) { + case '1': # 1 hour + $etime = $ctime + 3600; + break; + + case '2': # 12 hours + $etime = $ctime + 43200; + break; + + case '3': # 1 day + $etime = $ctime + 86400; + break; + + case '4': # 1 week + $etime = $ctime + 604800; + break; + + case '5': # 1 month + $etime = $ctime + 2419200; + break; + + case '6': # 3 months + $etime = $ctime + 7257600; + break; + + case '7': # 6 months + $etime = $ctime + 14515200; + break; + + case '8': # 1 year + $etime = $ctime + 29030400; + break; + + case '9': # 2 years + $etime = $ctime + 58060800; + break; + + case '10': # 3 years + $etime = $ctime + 87091200; + break; + + case '13': # forever + $etime = "null"; + break; + } + } + + $sth = $dbh->prepare("INSERT INTO paste VALUES('$id', '$paste', $ctime, $etime)"); + $sth->execute(); + + if ($sth === false) { + $e = $sth->errorInfo(); + showindex($e[2]); + exit; + } + + $dbh = null; + return($id); +} + +$text = ''; + +if (($_SERVER['REQUEST_METHOD'] === 'GET') or ($_SERVER['REQUEST_METHOD'] === 'HEAD')) { + # substr returns empty string (boolean false) on error + $str = $_SERVER['REQUEST_URI']; $str = substr($str, mb_strlen(BASEURL, 'UTF-8')); + + if ($str == 'e') { + eclient(); + exit; + } elseif ($str == 'd') { + dclient(); + exit; + } + + # pastebin returns raw pate when paste' key prepended with /raw/, let's handle it + if (preg_match('/^raw\//', $str) == 1) { + $str = substr($str, mb_strlen('raw/', 'UTF-8')); + } + + if ((mb_strlen($str, 'UTF-8') >= KEY_MIN) and ((mb_strlen($str, 'UTF-8') <= KEY_MAX))) { + if (preg_match('/^[a-z|A-Z]+$/', $str) == 1) { + $response = query_db($str); + + if ($response === false) { + $text = 'No such paste.'; + } else { + header('Content-Type: text/plain'); + print base64_decode($response); + exit; + } + } + } + +} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { + if (isset($_POST['exs']) and ($_POST['exs'] != '')) { + $text = APP_ADDRESS . store_data(base64_encode($_POST['exs'])); + } elseif (isset($_POST['api_option'])){ # some pastebin API compatibility stuff + if ($_POST['api_option'] == 'paste') { + if ((isset($_POST['api_paste_code'])) and ($_POST['api_paste_code'] != '')) { + header('Content-Type: text/plain; charset=utf-8'); + print mb_convert_encoding(APP_ADDRESS . store_data(base64_encode($_POST['api_paste_code'])), 'UTF-8', 'auto'); + exit; + } + } elseif ($_POST['api_option'] == 'show_paste') { + if (isset($_POST['api_paste_key'])) { + $str = $_POST['api_paste_key']; + + if ((mb_strlen($str, 'UTF-8') >= KEY_MIN) and ((mb_strlen($str, 'UTF-8') <= KEY_MAX))) { + if (preg_match('/^[a-z|A-Z]+$/', $str) == 1) { + $response = query_db($str); + + if ($response === false) { + header('Content-Type: text/plain; charset=utf-8'); + print "Bad API request, invalid permission to view this paste or invalid api_paste_key"; + exit; + } else { + header('Content-Type: text/plain'); + print base64_decode($response); + exit; + } + } + } + } + } + } +} else { + # ??? +} + +showindex($text); +?> \ No newline at end of file