@ -0,0 +1,8 @@
|
|||||||
|
FROM continuumio/conda-ci-linux-64-python3.8
|
||||||
|
USER root
|
||||||
|
COPY . /app/
|
||||||
|
RUN conda install -c anaconda tensorflow=2.2.0 pip
|
||||||
|
RUN pip install -r /app/requirements.txt
|
||||||
|
EXPOSE 5000
|
||||||
|
WORKDIR /app
|
||||||
|
ENTRYPOINT ["python3","app.py"]
|
@ -0,0 +1,29 @@
|
|||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2021, Cesura
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder 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.
|
@ -0,0 +1,66 @@
|
|||||||
|
![logo](https://i.imgur.com/W22RFJZ.png)
|
||||||
|
|
||||||
|
A lightweight, self-hosted paste platform
|
||||||
|
|
||||||
|
# Features
|
||||||
|
* Self-contained system without external database dependencies
|
||||||
|
* Automatic programming language detection
|
||||||
|
* Optional on-disk encryption
|
||||||
|
* Optional single use pastes
|
||||||
|
* IP/network whitelisting and blocking
|
||||||
|
* Endpoint rate limiting
|
||||||
|
* Fully configurable via environment variables
|
||||||
|
* Included script for uploading files/content from stdin
|
||||||
|
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
### Browser
|
||||||
|
![screenshot1](https://i.imgur.com/rQ5ZIg7.png)
|
||||||
|
![screenshot2](https://i.imgur.com/zaDpBaX.png)
|
||||||
|
![screenshot3](https://i.imgur.com/XDlJDZS.png)
|
||||||
|
### CLI
|
||||||
|
![screenshot4](https://i.imgur.com/FFWGe43.png)
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
### Docker
|
||||||
|
It is highly recommended that you use the official Docker image to run Pastey. To do so, simply run:
|
||||||
|
```
|
||||||
|
$ docker run -d -p 5000:5000 -v /path/to/local/dir:/app/data cesura/pastey:latest
|
||||||
|
```
|
||||||
|
Change **/path/to/local/dir** to a local folder you would like to use for persistent paste storage. It will be mounted in the container at **/app/data**.
|
||||||
|
|
||||||
|
Pastey will then be accessable at *http://localhost:5000*
|
||||||
|
|
||||||
|
|
||||||
|
### Local
|
||||||
|
Requirements:
|
||||||
|
* Python 3.8
|
||||||
|
* AVX-enabled processor (or a Python environment configured to use Anaconda's TensorFlow)
|
||||||
|
|
||||||
|
```
|
||||||
|
$ git clone https://github.com/Cesura/pastey.git && cd pastey
|
||||||
|
$ pip3 install -r requirements.txt
|
||||||
|
$ python3 app.py
|
||||||
|
```
|
||||||
|
# Configuration
|
||||||
|
Here is a list of the available configuration options:
|
||||||
|
| Environment Variable | config.py Variable | Description | Default Value |
|
||||||
|
|-----------------------------|----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|
|
||||||
|
| PASTEY_DATA_DIRECTORY | data_directory | Local directory for paste storage | ./data |
|
||||||
|
| PASTEY_LISTEN_ADDRESS | listen_address | Address to listen on | 0.0.0.0 |
|
||||||
|
| PASTEY_LISTEN_PORT | listen_port | Port to listen on | 5000 |
|
||||||
|
| PASTEY_USE_WHITELIST | use_whitelist | Enable/disable whitelisting for admin tasks (view recent, delete, config) | True |
|
||||||
|
| PASTEY_WHITELIST_CIDR | whitelist_cidr | List of whitelisted IP addresses or networks (in CIDR format). When passed as an environment variable, it should be a comma-separated list. | [ '127.0.0.1/32' , '10.0.0.0/8' , '172.16.0.0/12' , '192.168.0.0/16' ] |
|
||||||
|
| PASTEY_BLACKLIST_CIDR | blacklist_cidr | List of blocked IP addresses or networks (in CIDR format). When passed as an environment variable, it should be a comma-separated list. | [] |
|
||||||
|
| PASTEY_RESTRICT_PASTING | restrict_pasting | Enable/disable restricting of pasting to whitelisted users | False |
|
||||||
|
| PASTEY_RESTRICT_RAW_PASTING | restrict_raw_pasting | Enable/disable restricting of pasting via /raw to whitelisted users | True |
|
||||||
|
| PASTEY_RATE_LIMIT | rate_limit | Rate limit for pasting, for non-whitelisted users | 5/hour |
|
||||||
|
| PASTEY_GUESS_THRESHOLD | guess_threshold | Threshold for automatic language detection guesses. If a result is below this value, it is treated as Plaintext. | 0.20 |
|
||||||
|
| PASTEY_RECENT_PASTES | recent_pastes | Number of recent pastes to show on the home page | 10 |
|
||||||
|
| PASTEY_BEHIND_PROXY | behind_proxy | Inform Pastey if it is behind a reverse proxy (nginx, etc.). If this is the case, it will rely on HTTP headers X-Real-IP or X-Forwarded-For. NOTE: Make sure your proxy config sets these values | False |
|
||||||
|
|
||||||
|
### Docker configuration
|
||||||
|
For Docker environments, it is recommended that the options be passed to the container on startup:
|
||||||
|
```
|
||||||
|
$ docker run -d -p 5000:5000 -e PASTEY_LISTEN_PORT=80 -e PASTEY_BEHIND_PROXY="True" cesura/pastey:latest
|
||||||
|
```
|
@ -0,0 +1,323 @@
|
|||||||
|
from flask import Flask, render_template, request, redirect, abort
|
||||||
|
from flask_limiter import Limiter
|
||||||
|
from flask_limiter.util import get_remote_address
|
||||||
|
from guesslang import Guess
|
||||||
|
from datetime import datetime
|
||||||
|
from urllib.parse import quote
|
||||||
|
from cryptography.fernet import Fernet
|
||||||
|
import ipaddress
|
||||||
|
import uuid
|
||||||
|
import json
|
||||||
|
from os import path, remove, environ
|
||||||
|
from pathlib import Path
|
||||||
|
from config import config
|
||||||
|
from distutils.util import strtobool
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
limiter = Limiter(
|
||||||
|
app,
|
||||||
|
key_func=get_remote_address
|
||||||
|
)
|
||||||
|
guess = Guess()
|
||||||
|
|
||||||
|
# Pastey version
|
||||||
|
pastey_version = "0.2"
|
||||||
|
loaded_config = {}
|
||||||
|
|
||||||
|
# Check environment variable overrides
|
||||||
|
config.data_directory = environ["PASTEY_DATA_DIRECTORY"] if "PASTEY_DATA_DIRECTORY" in environ else config.data_directory
|
||||||
|
config.listen_address = environ["PASTEY_LISTEN_ADDRESS"] if "PASTEY_LISTEN_ADDRESS" in environ else config.listen_address
|
||||||
|
config.listen_port = environ["PASTEY_LISTEN_PORT"] if "PASTEY_LISTEN_PORT" in environ else config.listen_port
|
||||||
|
config.use_whitelist = bool(strtobool(environ["PASTEY_USE_WHITELIST"])) if "PASTEY_USE_WHITELIST" in environ else config.use_whitelist
|
||||||
|
config.restrict_pasting = bool(strtobool(environ["PASTEY_RESTRICT_PASTING"])) if "PASTEY_RESTRICT_PASTING" in environ else config.restrict_pasting
|
||||||
|
config.restrict_raw_pasting = bool(strtobool(environ["PASTEY_RESTRICT_RAW_PASTING"])) if "PASTEY_RESTRICT_RAW_PASTING" in environ else config.restrict_raw_pasting
|
||||||
|
config.rate_limit = environ["PASTEY_RATE_LIMIT"] if "PASTEY_RATE_LIMIT" in environ else config.rate_limit
|
||||||
|
config.guess_threshold = float(environ["PASTEY_GUESS_THRESHOLD"]) if "PASTEY_GUESS_THRESHOLD" in environ else config.guess_threshold
|
||||||
|
config.recent_pastes = int(environ["PASTEY_RECENT_PASTES"]) if "PASTEY_RECENT_PASTES" in environ else config.recent_pastes
|
||||||
|
config.whitelist_cidr = environ["PASTEY_WHITELIST_CIDR"].split(",") if "PASTEY_WHITELIST_CIDR" in environ else config.whitelist_cidr
|
||||||
|
config.blacklist_cidr = environ["PASTEY_BLACKLIST_CIDR"].split(",") if "PASTEY_BLACKLIST_CIDR" in environ else config.blacklist_cidr
|
||||||
|
config.behind_proxy = bool(strtobool(environ["PASTEY_BEHIND_PROXY"])) if "PASTEY_BEHIND_PROXY" in environ else config.behind_proxy
|
||||||
|
|
||||||
|
# Check request IP is in config whitelist
|
||||||
|
def verify_whitelist(ip):
|
||||||
|
address = ipaddress.ip_address(ip)
|
||||||
|
|
||||||
|
# Check blacklist
|
||||||
|
for network in config.blacklist_cidr:
|
||||||
|
if address in ipaddress.IPv4Network(network):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not config.use_whitelist:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Check whitelist
|
||||||
|
for network in config.whitelist_cidr:
|
||||||
|
if address in ipaddress.IPv4Network(network):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Solve anomalies in icon naming
|
||||||
|
def get_icon(language):
|
||||||
|
if language == "C#":
|
||||||
|
return "csharp"
|
||||||
|
elif language == "C++":
|
||||||
|
return "cplusplus"
|
||||||
|
elif language == "Jupyter Notebook":
|
||||||
|
return "jupyter"
|
||||||
|
else:
|
||||||
|
return language.lower()
|
||||||
|
|
||||||
|
# For handling reverse proxy configurations
|
||||||
|
# Note that these are HTTP headers and are generally untrustworthy
|
||||||
|
# Make sure your proxy configuration is either setting or clearing these
|
||||||
|
def get_source_ip(request):
|
||||||
|
if config.behind_proxy:
|
||||||
|
if 'X-Real-IP' in request.headers:
|
||||||
|
return request.headers['X-Real-IP']
|
||||||
|
elif 'X-Forwarded-For' in request.headers:
|
||||||
|
return request.headers['X-Forwarded-For']
|
||||||
|
|
||||||
|
return request.remote_addr
|
||||||
|
|
||||||
|
########## Paste functions ##########
|
||||||
|
|
||||||
|
# Get recent n pastes, defined in config by recent_pastes
|
||||||
|
def get_recent(limit=config.recent_pastes):
|
||||||
|
paths = sorted(Path(config.data_directory).iterdir(), key=path.getmtime, reverse=True)
|
||||||
|
|
||||||
|
recent_pastes = []
|
||||||
|
i = 0
|
||||||
|
while i < limit and i < len(paths):
|
||||||
|
with open(paths[i]) as fp:
|
||||||
|
paste = json.loads(fp.read())
|
||||||
|
paste['unique_id'] = path.basename(paths[i])
|
||||||
|
paste['content'] = '\n'.join(paste['content'].splitlines()[0:10])
|
||||||
|
paste['icon'] = get_icon(paste['language'])
|
||||||
|
|
||||||
|
if paste['encrypted']:
|
||||||
|
paste['content'] = "[Encrypted]"
|
||||||
|
|
||||||
|
recent_pastes.append(paste)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return recent_pastes
|
||||||
|
|
||||||
|
# Get paste by ID
|
||||||
|
def get_paste(unique_id, key=""):
|
||||||
|
if path.exists(config.data_directory + "/" + unique_id):
|
||||||
|
with open(config.data_directory + "/" + unique_id, "r") as fp:
|
||||||
|
paste = json.loads(fp.read())
|
||||||
|
|
||||||
|
# Check remaining uses, and decrement
|
||||||
|
# -1 = unlimited uses
|
||||||
|
if paste['uses'] != -1:
|
||||||
|
paste['uses'] -= 1
|
||||||
|
if paste['uses'] == 0:
|
||||||
|
delete_paste(unique_id)
|
||||||
|
else:
|
||||||
|
with open(config.data_directory + "/" + unique_id, "w") as fp:
|
||||||
|
fp.write(json.dumps(paste))
|
||||||
|
|
||||||
|
# Decrypt content, if necessary
|
||||||
|
try:
|
||||||
|
if key != "":
|
||||||
|
cipher_suite = Fernet(key.encode('utf-8'))
|
||||||
|
paste['content'] = cipher_suite.decrypt(paste['content'].encode('utf-8')).decode('utf-8')
|
||||||
|
except Exception as e:
|
||||||
|
return 401
|
||||||
|
|
||||||
|
return paste
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Delete paste by ID
|
||||||
|
def delete_paste(unique_id):
|
||||||
|
paste = config.data_directory + "/" + unique_id
|
||||||
|
if path.exists(paste):
|
||||||
|
remove(paste)
|
||||||
|
|
||||||
|
# Create new paste
|
||||||
|
def new_paste(title, content, source_ip, single=False, encrypt=False):
|
||||||
|
unique_id = str(uuid.uuid4())
|
||||||
|
while path.exists(config.data_directory + "/" + unique_id):
|
||||||
|
unique_id = str(uuid.uuid4())
|
||||||
|
|
||||||
|
# Attempt to guess programming language
|
||||||
|
guesses = guess.probabilities(content)
|
||||||
|
language = guesses[0][0] if guesses[0][1] > config.guess_threshold and guesses[0][0] != "SQL" else "Plaintext"
|
||||||
|
|
||||||
|
# Check if encryption is necessary
|
||||||
|
key = ""
|
||||||
|
if encrypt:
|
||||||
|
init_key = Fernet.generate_key()
|
||||||
|
cipher_suite = Fernet(init_key)
|
||||||
|
content = cipher_suite.encrypt(content.encode('utf-8')).decode('utf-8')
|
||||||
|
key = init_key.decode('utf-8')
|
||||||
|
|
||||||
|
# Check if single use is set
|
||||||
|
uses = 2 if single else -1
|
||||||
|
|
||||||
|
output = {
|
||||||
|
"timestamp": datetime.now().strftime("%a, %d %b %Y at %H:%M:%S"),
|
||||||
|
"language": language,
|
||||||
|
"source_ip": source_ip,
|
||||||
|
"title": title,
|
||||||
|
"content": content,
|
||||||
|
"encrypted": encrypt,
|
||||||
|
"uses": uses
|
||||||
|
}
|
||||||
|
|
||||||
|
# Write to output file
|
||||||
|
with open(config.data_directory + "/" + unique_id, "w+") as fp:
|
||||||
|
fp.write(json.dumps(output))
|
||||||
|
|
||||||
|
return unique_id, key
|
||||||
|
|
||||||
|
########## Routes ##########
|
||||||
|
|
||||||
|
# Home page
|
||||||
|
@app.route("/")
|
||||||
|
def home():
|
||||||
|
whitelisted = verify_whitelist(get_source_ip(request))
|
||||||
|
pastes = []
|
||||||
|
|
||||||
|
if whitelisted:
|
||||||
|
pastes=get_recent()
|
||||||
|
|
||||||
|
return render_template("index.html", pastes=pastes, whitelisted=whitelisted)
|
||||||
|
|
||||||
|
# New paste page
|
||||||
|
@app.route("/new")
|
||||||
|
def new():
|
||||||
|
whitelisted = verify_whitelist(get_source_ip(request))
|
||||||
|
return render_template("new.html", whitelisted=whitelisted)
|
||||||
|
|
||||||
|
# Config page
|
||||||
|
@app.route("/config")
|
||||||
|
def config_page():
|
||||||
|
whitelisted = verify_whitelist(get_source_ip(request))
|
||||||
|
if not whitelisted:
|
||||||
|
abort(401)
|
||||||
|
|
||||||
|
return render_template("config.html", config_items=loaded_config,
|
||||||
|
script_url=request.url.rsplit('/', 1)[0] + "/pastey", whitelisted=whitelisted)
|
||||||
|
|
||||||
|
# View paste page
|
||||||
|
@app.route("/view/<unique_id>")
|
||||||
|
def view(unique_id):
|
||||||
|
whitelisted = verify_whitelist(get_source_ip(request))
|
||||||
|
|
||||||
|
content = get_paste(unique_id)
|
||||||
|
if content is not None:
|
||||||
|
return render_template("view.html", paste=content, url=request.url, whitelisted=whitelisted)
|
||||||
|
else:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
# View paste page (encrypted)
|
||||||
|
@app.route("/view/<unique_id>/<key>")
|
||||||
|
def view_key(unique_id, key):
|
||||||
|
whitelisted = verify_whitelist(get_source_ip(request))
|
||||||
|
content = get_paste(unique_id, key=key)
|
||||||
|
|
||||||
|
if content == 401:
|
||||||
|
abort(401)
|
||||||
|
elif content is not None:
|
||||||
|
return render_template("view.html", paste=content, url=request.url, whitelisted=whitelisted)
|
||||||
|
else:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
|
||||||
|
# Delete paste
|
||||||
|
@app.route("/delete/<unique_id>")
|
||||||
|
def delete(unique_id):
|
||||||
|
if not verify_whitelist(get_source_ip(request)):
|
||||||
|
abort(401)
|
||||||
|
|
||||||
|
delete_paste(unique_id)
|
||||||
|
return redirect("/")
|
||||||
|
|
||||||
|
@app.route("/pastey")
|
||||||
|
def pastey_script():
|
||||||
|
return render_template('pastey.sh', endpoint=request.url.rsplit('/', 1)[0] + "/raw"), 200, {
|
||||||
|
'Content-Disposition': 'attachment; filename="pastey"',
|
||||||
|
'Content-Type': 'text/plain'
|
||||||
|
}
|
||||||
|
|
||||||
|
# POST new paste
|
||||||
|
@app.route('/paste', methods = ['POST'])
|
||||||
|
@limiter.limit(config.rate_limit, exempt_when=lambda: verify_whitelist(get_source_ip(request)))
|
||||||
|
def paste():
|
||||||
|
source_ip = get_source_ip(request)
|
||||||
|
|
||||||
|
# Check if restrict pasting to whitelist CIDRs is enabled
|
||||||
|
if config.restrict_pasting and not verify_whitelist(source_ip):
|
||||||
|
abort(401)
|
||||||
|
|
||||||
|
content = request.form['content']
|
||||||
|
|
||||||
|
# Check if content is empty
|
||||||
|
if request.form['content'].strip() == "":
|
||||||
|
return redirect("/new")
|
||||||
|
else:
|
||||||
|
|
||||||
|
# Verify form options
|
||||||
|
title = request.form['title'] if request.form['title'].strip() != "" else "Untitled"
|
||||||
|
single = True if 'single' in request.form else False
|
||||||
|
encrypt = True if 'encrypt' in request.form else False
|
||||||
|
|
||||||
|
# Create paste
|
||||||
|
unique_id, key = new_paste(title, content, source_ip, single=single, encrypt=encrypt)
|
||||||
|
if encrypt:
|
||||||
|
return redirect("/view/" + unique_id + "/" + quote(key))
|
||||||
|
else:
|
||||||
|
return redirect("/view/" + unique_id)
|
||||||
|
|
||||||
|
# POST new raw paste
|
||||||
|
@app.route('/raw', methods = ['POST'])
|
||||||
|
@limiter.limit(config.rate_limit, exempt_when=lambda: verify_whitelist(get_source_ip(request)))
|
||||||
|
def raw():
|
||||||
|
source_ip = get_source_ip(request)
|
||||||
|
|
||||||
|
# Check if restrict pasting to whitelist CIDRs is enabled
|
||||||
|
if config.restrict_raw_pasting and not verify_whitelist(source_ip):
|
||||||
|
abort(401)
|
||||||
|
|
||||||
|
# Create paste
|
||||||
|
unique_id, key = new_paste("Untitled", request.data.decode('utf-8'), source_ip, single=False, encrypt=False)
|
||||||
|
link = request.url.rsplit('/', 1)[0] + "/view/" + unique_id
|
||||||
|
|
||||||
|
return link, 200
|
||||||
|
|
||||||
|
|
||||||
|
# Custom 404 handler
|
||||||
|
@app.errorhandler(404)
|
||||||
|
def page_not_found(e):
|
||||||
|
whitelisted = verify_whitelist(get_source_ip(request))
|
||||||
|
return render_template('404.html', whitelisted=whitelisted), 404
|
||||||
|
|
||||||
|
# Custom 401 handler
|
||||||
|
@app.errorhandler(401)
|
||||||
|
def unauthorized(e):
|
||||||
|
whitelisted = verify_whitelist(get_source_ip(request))
|
||||||
|
return render_template('401.html', whitelisted=whitelisted), 401
|
||||||
|
|
||||||
|
# Main loop
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
# Print configuration
|
||||||
|
print("=====================================")
|
||||||
|
print("Pastey version ", pastey_version)
|
||||||
|
print("USING THE FOLLOWING CONFIGURATION:")
|
||||||
|
print("=====================================")
|
||||||
|
for option in dir(config):
|
||||||
|
if not option.startswith("__"):
|
||||||
|
loaded_config[option] = eval("config.%s" % option)
|
||||||
|
print(option, ": ", loaded_config[option])
|
||||||
|
print("=====================================")
|
||||||
|
|
||||||
|
# Register error handlers
|
||||||
|
app.register_error_handler(404, page_not_found)
|
||||||
|
app.register_error_handler(401, unauthorized)
|
||||||
|
|
||||||
|
app.run(host=config.listen_address, port=config.listen_port)
|
@ -0,0 +1,37 @@
|
|||||||
|
# Data directory
|
||||||
|
data_directory = "./data"
|
||||||
|
|
||||||
|
# Listen address
|
||||||
|
listen_address = "0.0.0.0"
|
||||||
|
|
||||||
|
# Listen port
|
||||||
|
listen_port = 5000
|
||||||
|
|
||||||
|
# Use whitelisting
|
||||||
|
# Whitelisted IPs can view recent pastes on the home page, as well as delete pastes
|
||||||
|
# For limiting pasting to whitelisted users, enable the "restrict_pasting" option below
|
||||||
|
use_whitelist = True
|
||||||
|
|
||||||
|
# Whitelist CIDR
|
||||||
|
whitelist_cidr = ['127.0.0.1/32', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16']
|
||||||
|
|
||||||
|
# Blacklist CIDR
|
||||||
|
blacklist_cidr = []
|
||||||
|
|
||||||
|
# Restrict pasting functionality to whitelisted IPs
|
||||||
|
restrict_pasting = False
|
||||||
|
|
||||||
|
# Restrict raw pasting to whitelisted IPs
|
||||||
|
restrict_raw_pasting = True
|
||||||
|
|
||||||
|
# Rate limit for pasting (ignored for whitelisted users)
|
||||||
|
rate_limit = "5/hour"
|
||||||
|
|
||||||
|
# Guess threshold for automatic language detection
|
||||||
|
guess_threshold = 0.20
|
||||||
|
|
||||||
|
# Number of recent pastes to show on the home page
|
||||||
|
recent_pastes = 10
|
||||||
|
|
||||||
|
# Try to use X-Real-IP or X-Forwarded-For HTTP headers
|
||||||
|
behind_proxy = False
|
@ -0,0 +1,4 @@
|
|||||||
|
flask
|
||||||
|
Flask-Limiter==1.4
|
||||||
|
guesslang
|
||||||
|
cryptography
|
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 123 KiB |
@ -0,0 +1 @@
|
|||||||
|
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:700}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:700}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:700}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
|
@ -0,0 +1,18 @@
|
|||||||
|
.prettyprint ol.linenums > li { list-style-type: decimal; }
|
||||||
|
|
||||||
|
#intro {
|
||||||
|
margin-top: 58px;
|
||||||
|
}
|
||||||
|
@media (max-width: 991px) {
|
||||||
|
#intro {
|
||||||
|
margin-top: 45px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.paste-checkbox {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
font-size: 60px;
|
||||||
|
}
|
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 6.8 KiB |
@ -0,0 +1,6 @@
|
|||||||
|
function copyToClipboard() {
|
||||||
|
var copyText = document.getElementById("paste-url");
|
||||||
|
copyText.select();
|
||||||
|
copyText.setSelectionRange(0, 99999);
|
||||||
|
document.execCommand("copy");
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
!function(){var r=null;
|
||||||
|
(function(){function X(e){function j(){try{J.doScroll("left")}catch(e){P(j,50);return}w("poll")}function w(j){if(!(j.type=="readystatechange"&&x.readyState!="complete")&&((j.type=="load"?n:x)[z](i+j.type,w,!1),!m&&(m=!0)))e.call(n,j.type||j)}var Y=x.addEventListener,m=!1,C=!0,t=Y?"addEventListener":"attachEvent",z=Y?"removeEventListener":"detachEvent",i=Y?"":"on";if(x.readyState=="complete")e.call(n,"lazy");else{if(x.createEventObject&&J.doScroll){try{C=!n.frameElement}catch(A){}C&&j()}x[t](i+"DOMContentLoaded",
|
||||||
|
w,!1);x[t](i+"readystatechange",w,!1);n[t](i+"load",w,!1)}}function Q(){S&&X(function(){var e=K.length;$(e?function(){for(var j=0;j<e;++j)(function(e){P(function(){n.exports[K[e]].apply(n,arguments)},0)})(j)}:void 0)})}for(var n=window,P=n.setTimeout,x=document,J=x.documentElement,L=x.head||x.getElementsByTagName("head")[0]||J,z="",A=x.scripts,m=A.length;--m>=0;){var M=A[m],T=M.src.match(/^[^#?]*\/run_prettify\.js(\?[^#]*)?(?:#.*)?$/);if(T){z=T[1]||"";M.parentNode.removeChild(M);break}}var S=!0,D=
|
||||||
|
[],N=[],K=[];z.replace(/[&?]([^&=]+)=([^&]+)/g,function(e,j,w){w=decodeURIComponent(w);j=decodeURIComponent(j);j=="autorun"?S=!/^[0fn]/i.test(w):j=="lang"?D.push(w):j=="skin"?N.push(w):j=="callback"&&K.push(w)});m=0;for(z=D.length;m<z;++m)(function(){var e=x.createElement("script");e.onload=e.onerror=e.onreadystatechange=function(){if(e&&(!e.readyState||/loaded|complete/.test(e.readyState)))e.onerror=e.onload=e.onreadystatechange=r,--R,R||P(Q,0),e.parentNode&&e.parentNode.removeChild(e),e=r};e.type=
|
||||||
|
"text/javascript";e.src="https://google-code-prettify.googlecode.com/svn/loader/lang-"+encodeURIComponent(D[m])+".js";L.insertBefore(e,L.firstChild)})(D[m]);for(var R=D.length,A=[],m=0,z=N.length;m<z;++m)A.push("https://google-code-prettify.googlecode.com/svn/loader/skins/"+encodeURIComponent(N[m])+".css");A.push("https://google-code-prettify.googlecode.com/svn/loader/prettify.css");(function(e){function j(m){if(m!==w){var n=x.createElement("link");n.rel="stylesheet";n.type="text/css";if(m+1<w)n.error=
|
||||||
|
n.onerror=function(){j(m+1)};n.href=e[m];L.appendChild(n)}}var w=e.length;j(0)})(A);var $=function(){window.PR_SHOULD_USE_CONTINUATION=!0;var e;(function(){function j(a){function d(f){var b=f.charCodeAt(0);if(b!==92)return b;var a=f.charAt(1);return(b=i[a])?b:"0"<=a&&a<="7"?parseInt(f.substring(1),8):a==="u"||a==="x"?parseInt(f.substring(2),16):f.charCodeAt(1)}function h(f){if(f<32)return(f<16?"\\x0":"\\x")+f.toString(16);f=String.fromCharCode(f);return f==="\\"||f==="-"||f==="]"||f==="^"?"\\"+f:
|
||||||
|
f}function b(f){var b=f.substring(1,f.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),f=[],a=b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,g=b.length;a<g;++a){var k=b[a];if(/\\[bdsw]/i.test(k))c.push(k);else{var k=d(k),o;a+2<g&&"-"===b[a+1]?(o=d(b[a+2]),a+=2):o=k;f.push([k,o]);o<65||k>122||(o<65||k>90||f.push([Math.max(65,k)|32,Math.min(o,90)|32]),o<97||k>122||f.push([Math.max(97,k)&-33,Math.min(o,122)&-33]))}}f.sort(function(f,a){return f[0]-
|
||||||
|
a[0]||a[1]-f[1]});b=[];g=[];for(a=0;a<f.length;++a)k=f[a],k[0]<=g[1]+1?g[1]=Math.max(g[1],k[1]):b.push(g=k);for(a=0;a<b.length;++a)k=b[a],c.push(h(k[0])),k[1]>k[0]&&(k[1]+1>k[0]&&c.push("-"),c.push(h(k[1])));c.push("]");return c.join("")}function e(f){for(var a=f.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],g=0,k=0;g<c;++g){var o=a[g];o==="("?++k:"\\"===o.charAt(0)&&(o=+o.substring(1))&&(o<=k?d[o]=-1:a[g]=h(o))}for(g=
|
||||||
|
1;g<d.length;++g)-1===d[g]&&(d[g]=++j);for(k=g=0;g<c;++g)o=a[g],o==="("?(++k,d[k]||(a[g]="(?:")):"\\"===o.charAt(0)&&(o=+o.substring(1))&&o<=k&&(a[g]="\\"+d[o]);for(g=0;g<c;++g)"^"===a[g]&&"^"!==a[g+1]&&(a[g]="");if(f.ignoreCase&&F)for(g=0;g<c;++g)o=a[g],f=o.charAt(0),o.length>=2&&f==="["?a[g]=b(o):f!=="\\"&&(a[g]=o.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var j=0,F=!1,l=!1,I=0,c=a.length;I<c;++I){var p=a[I];if(p.ignoreCase)l=
|
||||||
|
!0;else if(/[a-z]/i.test(p.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){F=!0;l=!1;break}}for(var i={b:8,t:9,n:10,v:11,f:12,r:13},q=[],I=0,c=a.length;I<c;++I){p=a[I];if(p.global||p.multiline)throw Error(""+p);q.push("(?:"+e(p)+")")}return RegExp(q.join("|"),l?"gi":"g")}function m(a,d){function h(a){var c=a.nodeType;if(c==1){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)h(c);c=a.nodeName.toLowerCase();if("br"===c||"li"===c)e[l]="\n",F[l<<1]=j++,F[l++<<1|1]=a}}else if(c==
|
||||||
|
3||c==4)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[\t\n\r ]+/g," "),e[l]=c,F[l<<1]=j,j+=c.length,F[l++<<1|1]=a)}var b=/(?:^|\s)nocode(?:\s|$)/,e=[],j=0,F=[],l=0;h(a);return{a:e.join("").replace(/\n$/,""),d:F}}function n(a,d,h,b){d&&(a={a:d,e:a},h(a),b.push.apply(b,a.g))}function x(a){for(var d=void 0,h=a.firstChild;h;h=h.nextSibling)var b=h.nodeType,d=b===1?d?a:h:b===3?S.test(h.nodeValue)?a:d:d;return d===a?void 0:d}function C(a,d){function h(a){for(var l=a.e,j=[l,"pln"],c=
|
||||||
|
0,p=a.a.match(e)||[],m={},q=0,f=p.length;q<f;++q){var B=p[q],y=m[B],u=void 0,g;if(typeof y==="string")g=!1;else{var k=b[B.charAt(0)];if(k)u=B.match(k[1]),y=k[0];else{for(g=0;g<i;++g)if(k=d[g],u=B.match(k[1])){y=k[0];break}u||(y="pln")}if((g=y.length>=5&&"lang-"===y.substring(0,5))&&!(u&&typeof u[1]==="string"))g=!1,y="src";g||(m[B]=y)}k=c;c+=B.length;if(g){g=u[1];var o=B.indexOf(g),H=o+g.length;u[2]&&(H=B.length-u[2].length,o=H-g.length);y=y.substring(5);n(l+k,B.substring(0,o),h,j);n(l+k+o,g,A(y,
|
||||||
|
g),j);n(l+k+H,B.substring(H),h,j)}else j.push(l+k,y)}a.g=j}var b={},e;(function(){for(var h=a.concat(d),l=[],i={},c=0,p=h.length;c<p;++c){var m=h[c],q=m[3];if(q)for(var f=q.length;--f>=0;)b[q.charAt(f)]=m;m=m[1];q=""+m;i.hasOwnProperty(q)||(l.push(m),i[q]=r)}l.push(/[\S\s]/);e=j(l)})();var i=d.length;return h}function t(a){var d=[],h=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,
|
||||||
|
r,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,r,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,r,"\"'"]);a.verbatimStrings&&h.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,r]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,r,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,
|
||||||
|
r,"#"]),h.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,r])):d.push(["com",/^#[^\n\r]*/,r,"#"]));a.cStyleComments&&(h.push(["com",/^\/\/[^\n\r]*/,r]),h.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,r]));if(b=a.regexLiterals){var e=(b=b>1?"":"\n\r")?".":"[\\S\\s]";h.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+
|
||||||
|
("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+e+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+e+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&h.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&h.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),r]);d.push(["pln",/^\s+/,r," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");h.push(["lit",/^@[$_a-z][\w$@]*/i,r],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,r],["pln",/^[$_a-z][\w$@]*/i,r],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,
|
||||||
|
r,"0123456789"],["pln",/^\\[\S\s]?/,r],["pun",RegExp(b),r]);return C(d,h)}function z(a,d,h){function b(a){var c=a.nodeType;if(c==1&&!j.test(a.className))if("br"===a.nodeName)e(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&h){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(l.createTextNode(d),a.nextSibling),e(a),c||a.parentNode.removeChild(a)}}
|
||||||
|
function e(a){function b(a,c){var d=c?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),h=a.nextSibling;f.appendChild(d);for(var e=h;e;e=h)h=e.nextSibling,f.appendChild(e)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var j=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,l=a.ownerDocument,i=l.createElement("li");a.firstChild;)i.appendChild(a.firstChild);for(var c=[i],p=0;p<c.length;++p)b(c[p]);d===(d|0)&&c[0].setAttribute("value",
|
||||||
|
d);var n=l.createElement("ol");n.className="linenums";for(var d=Math.max(0,d-1|0)||0,p=0,q=c.length;p<q;++p)i=c[p],i.className="L"+(p+d)%10,i.firstChild||i.appendChild(l.createTextNode("\u00a0")),n.appendChild(i);a.appendChild(n)}function i(a,d){for(var h=d.length;--h>=0;){var b=d[h];U.hasOwnProperty(b)?V.console&&console.warn("cannot override language handler %s",b):U[b]=a}}function A(a,d){if(!a||!U.hasOwnProperty(a))a=/^\s*</.test(d)?"default-markup":"default-code";return U[a]}function D(a){var d=
|
||||||
|
a.h;try{var h=m(a.c,a.i),b=h.a;a.a=b;a.d=h.d;a.e=0;A(d,b)(a);var e=/\bMSIE\s(\d+)/.exec(navigator.userAgent),e=e&&+e[1]<=8,d=/\n/g,i=a.a,j=i.length,h=0,l=a.d,n=l.length,b=0,c=a.g,p=c.length,t=0;c[p]=j;var q,f;for(f=q=0;f<p;)c[f]!==c[f+2]?(c[q++]=c[f++],c[q++]=c[f++]):f+=2;p=q;for(f=q=0;f<p;){for(var x=c[f],y=c[f+1],u=f+2;u+2<=p&&c[u+1]===y;)u+=2;c[q++]=x;c[q++]=y;f=u}c.length=q;var g=a.c,k;if(g)k=g.style.display,g.style.display="none";try{for(;b<n;){var o=l[b+2]||j,H=c[t+2]||j,u=Math.min(o,H),E=l[b+
|
||||||
|
1],W;if(E.nodeType!==1&&(W=i.substring(h,u))){e&&(W=W.replace(d,"\r"));E.nodeValue=W;var Z=E.ownerDocument,s=Z.createElement("span");s.className=c[t+1];var z=E.parentNode;z.replaceChild(s,E);s.appendChild(E);h<o&&(l[b+1]=E=Z.createTextNode(i.substring(u,o)),z.insertBefore(E,s.nextSibling))}h=u;h>=o&&(b+=2);h>=H&&(t+=2)}}finally{if(g)g.style.display=k}}catch(v){V.console&&console.log(v&&v.stack||v)}}var V=window,G=["break,continue,do,else,for,if,return,while"],O=[[G,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
|
||||||
|
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],J=[O,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],K=[O,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],
|
||||||
|
L=[K,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],O=[O,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],M=[G,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
|
||||||
|
N=[G,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],R=[G,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],G=[G,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],Q=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,
|
||||||
|
S=/\S/,T=t({keywords:[J,L,O,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",M,N,G],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),U={};i(T,["default-code"]);i(C([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",
|
||||||
|
/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);i(C([["pln",/^\s+/,r," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,r,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],
|
||||||
|
["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);i(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);i(t({keywords:J,hashComments:!0,cStyleComments:!0,types:Q}),["c","cc","cpp","cxx","cyc","m"]);i(t({keywords:"null,true,false"}),["json"]);i(t({keywords:L,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:Q}),
|
||||||
|
["cs"]);i(t({keywords:K,cStyleComments:!0}),["java"]);i(t({keywords:G,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);i(t({keywords:M,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);i(t({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);i(t({keywords:N,
|
||||||
|
hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);i(t({keywords:O,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);i(t({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);i(t({keywords:R,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]);
|
||||||
|
i(C([],[["str",/^[\S\s]+/]]),["regex"]);var X=V.PR={createSimpleLexer:C,registerLangHandler:i,sourceDecorator:t,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:function(a,d,e){var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";b=b.firstChild;e&&z(b,e,!0);D({h:d,j:e,c:b,i:1});return b.innerHTML},
|
||||||
|
prettyPrint:e=e=function(a,d){function e(){for(var b=V.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;p<j.length&&c.now()<b;p++){for(var d=j[p],m=k,l=d;l=l.previousSibling;){var n=l.nodeType,s=(n===7||n===8)&&l.nodeValue;if(s?!/^\??prettify\b/.test(s):n!==3||/\S/.test(l.nodeValue))break;if(s){m={};s.replace(/\b(\w+)=([\w%+\-.:]+)/g,function(a,b,c){m[b]=c});break}}l=d.className;if((m!==k||f.test(l))&&!w.test(l)){n=!1;for(s=d.parentNode;s;s=s.parentNode)if(g.test(s.tagName)&&s.className&&f.test(s.className)){n=
|
||||||
|
!0;break}if(!n){d.className+=" prettyprinted";n=m.lang;if(!n){var n=l.match(q),A;if(!n&&(A=x(d))&&u.test(A.tagName))n=A.className.match(q);n&&(n=n[1])}if(y.test(d.tagName))s=1;else var s=d.currentStyle,v=i.defaultView,s=(s=s?s.whiteSpace:v&&v.getComputedStyle?v.getComputedStyle(d,r).getPropertyValue("white-space"):0)&&"pre"===s.substring(0,3);v=m.linenums;if(!(v=v==="true"||+v))v=(v=l.match(/\blinenums\b(?::(\d+))?/))?v[1]&&v[1].length?+v[1]:!0:!1;v&&z(d,v,s);t={h:n,c:d,j:v,i:s};D(t)}}}p<j.length?
|
||||||
|
P(e,250):"function"===typeof a&&a()}for(var b=d||document.body,i=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],j=[],m=0;m<b.length;++m)for(var l=0,n=b[m].length;l<n;++l)j.push(b[m][l]);var b=r,c=Date;c.now||(c={now:function(){return+new Date}});var p=0,t,q=/\blang(?:uage)?-([\w.]+)(?!\S)/,f=/\bprettyprint\b/,w=/\bprettyprinted\b/,y=/pre|xmp/i,u=/^code$/i,g=/^(?:pre|code|xmp)$/i,k={};e()}};typeof define==="function"&&define.amd&&
|
||||||
|
define("google-code-prettify",[],function(){return X})})();return e}();R||P(Q,0)})();}()
|
@ -0,0 +1,72 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||||
|
<title>Unauthorized | Pastey</title>
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.11.2/css/all.css" />
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" />
|
||||||
|
<link rel="stylesheet" href="/static/css/mdb.min.css" />
|
||||||
|
<link rel="stylesheet" href="/static/css/style.css" />
|
||||||
|
|
||||||
|
<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<!-- Navbar -->
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top">
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<!-- Navbar logo -->
|
||||||
|
<a class="navbar-brand" href="/">
|
||||||
|
<img src="/static/img/pastey.png" height="26" alt="" loading="lazy" style="margin-top: -3px;" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/new">New Paste</a>
|
||||||
|
</li>
|
||||||
|
{% if whitelisted %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/config">Config</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul class="navbar-nav d-flex flex-row">
|
||||||
|
<li class="nav-item me-3 me-lg-0">
|
||||||
|
<a class="nav-link" href="https://github.com/Cesura/pastey" rel="nofollow" target="_blank">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<!-- Navbar -->
|
||||||
|
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
<div id="intro" class="p-5 text-center bg-light">
|
||||||
|
<h1 class="error">401 Unauthorized</h1>
|
||||||
|
</div>
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!--Main layout-->
|
||||||
|
<main class="my-5">
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<!--Main layout-->
|
||||||
|
|
||||||
|
<!--JS-->
|
||||||
|
<script type="text/javascript" src="/static/js/mdb.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,72 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||||
|
<title>Not Found | Pastey</title>
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.11.2/css/all.css" />
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" />
|
||||||
|
<link rel="stylesheet" href="/static/css/mdb.min.css" />
|
||||||
|
<link rel="stylesheet" href="/static/css/style.css" />
|
||||||
|
|
||||||
|
<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<!-- Navbar -->
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top">
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<!-- Navbar logo -->
|
||||||
|
<a class="navbar-brand" href="/">
|
||||||
|
<img src="/static/img/pastey.png" height="26" alt="" loading="lazy" style="margin-top: -3px;" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/new">New Paste</a>
|
||||||
|
</li>
|
||||||
|
{% if whitelisted %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/config">Config</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul class="navbar-nav d-flex flex-row">
|
||||||
|
<li class="nav-item me-3 me-lg-0">
|
||||||
|
<a class="nav-link" href="https://github.com/Cesura/pastey" rel="nofollow" target="_blank">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<!-- Navbar -->
|
||||||
|
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
<div id="intro" class="p-5 text-center bg-light">
|
||||||
|
<h1 class="error">404 Not Found</h1>
|
||||||
|
</div>
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!--Main layout-->
|
||||||
|
<main class="my-5">
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<!--Main layout-->
|
||||||
|
|
||||||
|
<!--JS-->
|
||||||
|
<script type="text/javascript" src="/static/js/mdb.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,113 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||||
|
<title>Config | Pastey</title>
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.11.2/css/all.css" />
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" />
|
||||||
|
<link rel="stylesheet" href="/static/css/mdb.min.css" />
|
||||||
|
<link rel="stylesheet" href="/static/css/style.css" />
|
||||||
|
|
||||||
|
<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<!-- Navbar -->
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top">
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<!-- Navbar logo -->
|
||||||
|
<a class="navbar-brand" href="/">
|
||||||
|
<img src="/static/img/pastey.png" height="26" alt="" loading="lazy" style="margin-top: -3px;" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/new">New Paste</a>
|
||||||
|
</li>
|
||||||
|
{% if whitelisted %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" aria-current="page" href="/config">Config</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul class="navbar-nav d-flex flex-row">
|
||||||
|
<li class="nav-item me-3 me-lg-0">
|
||||||
|
<a class="nav-link" href="https://github.com/Cesura/pastey" rel="nofollow" target="_blank">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<!-- Navbar -->
|
||||||
|
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
<div id="intro" class="p-5 text-center bg-light">
|
||||||
|
<h1 class="mb-3 h2">Config</h1>
|
||||||
|
</div>
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!--Main layout-->
|
||||||
|
<main class="my-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Option</th>
|
||||||
|
<th scope="col">Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for key, value in config_items.items() %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{{ key}}</th>
|
||||||
|
<td>{{ value }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div><br />
|
||||||
|
|
||||||
|
<div class="row text-center">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<h1 class="mb-3 h4">Download Script</h1>
|
||||||
|
<p>Pastey provides a script that can be used to paste output directly from the command line:</p>
|
||||||
|
<pre>$ cat /var/log/nginx.log | pastey</pre>
|
||||||
|
<pre>$ echo "Hello, Pastey!" | pastey</pre>
|
||||||
|
<p style="font-weight:bold;">Download the following, make it executable, and put it in your system PATH to be used anywhere!</p>
|
||||||
|
</div>
|
||||||
|
</div><br />
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3"></div>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<input class="form-control" id="paste-url" type="text" value="{{ script_url }}" readonly />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-1">
|
||||||
|
<a href="{{ script_url }}">
|
||||||
|
<button type="button" class="btn btn-success">Download</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<!--Main layout-->
|
||||||
|
|
||||||
|
<!--JS-->
|
||||||
|
<script type="text/javascript" src="/static/js/mdb.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,97 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||||
|
<title>Home | Pastey</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.11.2/css/all.css" />
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" />
|
||||||
|
<link rel="stylesheet" href="/static/css/mdb.min.css" />
|
||||||
|
<link rel="stylesheet" href="/static/css/style.css" />
|
||||||
|
<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<!-- Navbar -->
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top">
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<!-- Navbar logo -->
|
||||||
|
<a class="navbar-brand" href="/">
|
||||||
|
<img src="/static/img/pastey.png" height="26" alt="" loading="lazy" style="margin-top: -3px;" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" aria-current="page" href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/new">New Paste</a>
|
||||||
|
</li>
|
||||||
|
{% if whitelisted %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/config">Config</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul class="navbar-nav d-flex flex-row">
|
||||||
|
<li class="nav-item me-3 me-lg-0">
|
||||||
|
<a class="nav-link" href="https://github.com/Cesura/pastey" rel="nofollow" target="_blank">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<!-- Navbar -->
|
||||||
|
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
<div id="intro" class="p-5 text-center bg-light">
|
||||||
|
<h1 class="mb-3 h2">Welcome to Pastey</h1>
|
||||||
|
<p class="mb-3">A lightweight, self-hosted paste platform</p>
|
||||||
|
<a class="btn btn-primary m-2" href="/new" role="button" rel="nofollow">New Paste</a>
|
||||||
|
</div>
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!--Main layout-->
|
||||||
|
<main class="my-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12 mb-4">
|
||||||
|
<section>
|
||||||
|
<!-- Paste -->
|
||||||
|
{% for paste in pastes %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4 mb-4">
|
||||||
|
<div class="bg-image hover-overlay shadow-1-strong rounded ripple" data-mdb-ripple-color="light">
|
||||||
|
<img src="/static/img/language/{{ paste.icon }}.png" class="img-fluid" />
|
||||||
|
<a href="/view/{{ paste.unique_id }}">
|
||||||
|
<div class="mask" style="background-color: rgba(251, 251, 251, 0.15);"></div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-8 mb-4">
|
||||||
|
<a class="btn btn-danger m-2" href="/delete/{{ paste.unique_id }}" role="button" style="float:right;">Delete</a>
|
||||||
|
|
||||||
|
<h5>{{ paste.title }}</h5>
|
||||||
|
<pre style="overflow-x:hidden;">{{ paste.content }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!--JS-->
|
||||||
|
<script type="text/javascript" src="/static/js/mdb.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,117 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||||
|
<title>New | Pastey</title>
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.11.2/css/all.css" />
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" />
|
||||||
|
<link rel="stylesheet" href="/static/css/mdb.min.css" />
|
||||||
|
<link rel="stylesheet" href="/static/css/style.css" />
|
||||||
|
|
||||||
|
<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<!-- Navbar -->
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top">
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<!-- Navbar logo -->
|
||||||
|
<a class="navbar-brand" href="/">
|
||||||
|
<img src="/static/img/pastey.png" height="26" alt="" loading="lazy" style="margin-top: -3px;" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" aria-current="page" href="/new">New Paste</a>
|
||||||
|
</li>
|
||||||
|
{% if whitelisted %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/config">Config</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul class="navbar-nav d-flex flex-row">
|
||||||
|
<li class="nav-item me-3 me-lg-0">
|
||||||
|
<a class="nav-link" href="https://github.com/Cesura/pastey" rel="nofollow" target="_blank">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<!-- Navbar -->
|
||||||
|
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
<div id="intro" class="p-5 text-center bg-light">
|
||||||
|
<h1 class="mb-3 h2">New Paste</h1>
|
||||||
|
</div>
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!--Main layout-->
|
||||||
|
<main class="my-5">
|
||||||
|
<div class="container">
|
||||||
|
<form action="/paste" method="POST">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-4">
|
||||||
|
<div class="md-form">
|
||||||
|
<div class="form-outline">
|
||||||
|
<input type="text" id="title" name="title" class="form-control" />
|
||||||
|
<label class="form-label" for="title">Paste Title</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12 mb-4">
|
||||||
|
<div class="md-form">
|
||||||
|
<textarea name="content" id="content" class="md-textarea form-control" rows="20"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<div class="form-check paste-checkbox">
|
||||||
|
<input class="form-check-input" type="checkbox" value="" id="encrypt" name="encrypt"
|
||||||
|
data-mdb-toggle="tooltip" title="Your paste's content will not be accessible without its accompanying decryption key" />
|
||||||
|
<label class="form-check-label" for="encrypt">
|
||||||
|
Encrypt
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-2">
|
||||||
|
<div class="form-check paste-checkbox">
|
||||||
|
<input class="form-check-input" type="checkbox" value="" id="single" name="single"
|
||||||
|
data-mdb-toggle="tooltip" title="After generation, the paste will be viewable one time before deletion" />
|
||||||
|
<label class="form-check-label" for="single">
|
||||||
|
Single Use
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4"></div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<button type="submit" class="btn btn-primary btn-block">Paste</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<!--Main layout-->
|
||||||
|
|
||||||
|
<!--JS-->
|
||||||
|
<script type="text/javascript" src="/static/js/mdb.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if ! command -v curl &> /dev/null ; then
|
||||||
|
echo "Please install curl to use this script"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PASTEY_ENDPOINT="{{ endpoint }}"
|
||||||
|
PASTEY_CONTENT=$(</dev/stdin)
|
||||||
|
|
||||||
|
# Submit paste
|
||||||
|
PASTEY_LINK=$(curl -s -X POST -H "Content-Type: text/plain" --data "${PASTEY_CONTENT}" "${PASTEY_ENDPOINT}")
|
||||||
|
|
||||||
|
# Print link
|
||||||
|
echo "${PASTEY_LINK}"
|
@ -0,0 +1,105 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||||
|
<title>{{ paste.title }} | Pastey</title>
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.11.2/css/all.css" />
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" />
|
||||||
|
<link rel="stylesheet" href="/static/css/mdb.min.css" />
|
||||||
|
<link rel="stylesheet" href="/static/css/prettify.min.css" />
|
||||||
|
<link rel="stylesheet" href="/static/css/style.css" />
|
||||||
|
|
||||||
|
<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
|
||||||
|
<!-- Navbar -->
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top">
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<!-- Navbar logo -->
|
||||||
|
<a class="navbar-brand" href="/">
|
||||||
|
<img src="/static/img/pastey.png" height="26" alt="" loading="lazy" style="margin-top: -3px;" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/new" rel="nofollow">New Paste</a>
|
||||||
|
</li>
|
||||||
|
{% if whitelisted %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/config">Config</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul class="navbar-nav d-flex flex-row">
|
||||||
|
<li class="nav-item me-3 me-lg-0">
|
||||||
|
<a class="nav-link" href="https://github.com/Cesura/pastey" rel="nofollow" target="_blank">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<!-- Navbar -->
|
||||||
|
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
<div id="intro" class="p-5 text-center bg-light">
|
||||||
|
{% if paste.encrypted %}
|
||||||
|
<img src="/static/img/encrypted.png" width="30px" height="30px" /><br /><br />
|
||||||
|
{% else %}
|
||||||
|
<img src="/static/img/unencrypted.png" width="30px" height="30px" /><br /><br />
|
||||||
|
{% endif %}
|
||||||
|
<h1 class="mb-3 h2">{{ paste.title }}</h1>
|
||||||
|
<span style="font-weight:bold;">Format: </span><span>{{ paste.language }}</span><br />
|
||||||
|
<span style="font-weight:bold;">Date: </span><span>{{ paste.timestamp }}</span><br /><br />
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3"></div>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<input class="form-control" id="paste-url" type="text" value="{{ url }}" readonly />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-1">
|
||||||
|
<button type="button" class="btn btn-success" onclick="copyToClipboard()">Copy Link</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if paste.uses == 0 %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<br /><span class="badge rounded-pill bg-warning text-dark">Warning: this paste has been set to single use. It will be deleted and unaccessible upon page reload.</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<!-- Jumbotron -->
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!--Main layout-->
|
||||||
|
<main class="my-5">
|
||||||
|
<div class="container">
|
||||||
|
<form action="/paste" method="POST">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12 mb-4">
|
||||||
|
<pre class="prettyprint linenums">{{ paste.content }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<!--Main layout-->
|
||||||
|
|
||||||
|
<!--JS-->
|
||||||
|
<script type="text/javascript" src="/static/js/mdb.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/js/common.js"></script>
|
||||||
|
<script src="/static/js/prettify.min.js"></script>
|
||||||
|
<script src="/static/js/run_prettify.js"></script></body>
|
||||||
|
</html>
|