Merged in feature/HTTPASTE-46/view (pull request #48)
Feature/HTTPASTE-46/view
This commit is contained in:
commit
afafbd6459
29 changed files with 387 additions and 231 deletions
66
Pipfile.lock
generated
66
Pipfile.lock
generated
|
|
@ -292,6 +292,50 @@
|
|||
"markers": "python_version >= '3.6'",
|
||||
"version": "==21.3"
|
||||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
"sha256:01ce45deec9df310cbbee11104bae1a2a43308dd9c317f99235b6d3080ddd66e",
|
||||
"sha256:0c51cb9edac8a5abd069fd0758ac0a8bfe52c261ee0e330f363548aca6893595",
|
||||
"sha256:17869489de2fce6c36690a0c721bd3db176194af5f39249c1ac56d0bb0fcc512",
|
||||
"sha256:21dee8466b42912335151d24c1665fcf44dc2ee47e021d233a40c3ca5adae59c",
|
||||
"sha256:25023a6209a4d7c42154073144608c9a71d3512b648a2f5d4465182cb93d3477",
|
||||
"sha256:255c9d69754a4c90b0ee484967fc8818c7ff8311c6dddcc43a4340e10cd1636a",
|
||||
"sha256:35be4a9f65441d9982240e6966c1eaa1c654c4e5e931eaf580130409e31804d4",
|
||||
"sha256:3f42364485bfdab19c1373b5cd62f7c5ab7cc052e19644862ec8f15bb8af289e",
|
||||
"sha256:3fddcdb619ba04491e8f771636583a7cc5a5051cd193ff1aa1ee8616d2a692c5",
|
||||
"sha256:463acf531f5d0925ca55904fa668bb3461c3ef6bc779e1d6d8a488092bdee378",
|
||||
"sha256:4fe29a070de394e449fd88ebe1624d1e2d7ddeed4c12e0b31624561b58948d9a",
|
||||
"sha256:55dd1cf09a1fd7c7b78425967aacae9b0d70125f7d3ab973fadc7b5abc3de652",
|
||||
"sha256:5a3ecc026ea0e14d0ad7cd990ea7f48bfcb3eb4271034657dc9d06933c6629a7",
|
||||
"sha256:5cfca31ab4c13552a0f354c87fbd7f162a4fafd25e6b521bba93a57fe6a3700a",
|
||||
"sha256:66822d01e82506a19407d1afc104c3fcea3b81d5eb11485e593ad6b8492f995a",
|
||||
"sha256:69e5ddc609230d4408277af135c5b5c8fe7a54b2bdb8ad7c5100b86b3aab04c6",
|
||||
"sha256:6b6d4050b208c8ff886fd3db6690bf04f9a48749d78b41b7a5bf24c236ab0165",
|
||||
"sha256:7a053bd4d65a3294b153bdd7724dce864a1d548416a5ef61f6d03bf149205160",
|
||||
"sha256:82283af99c1c3a5ba1da44c67296d5aad19f11c535b551a5ae55328a317ce331",
|
||||
"sha256:8782189c796eff29dbb37dd87afa4ad4d40fc90b2742704f94812851b725964b",
|
||||
"sha256:8d79c6f468215d1a8415aa53d9868a6b40c4682165b8cb62a221b1baa47db458",
|
||||
"sha256:97bda660702a856c2c9e12ec26fc6d187631ddfd896ff685814ab21ef0597033",
|
||||
"sha256:a325ac71914c5c043fa50441b36606e64a10cd262de12f7a179620f579752ff8",
|
||||
"sha256:a336a4f74baf67e26f3acc4d61c913e378e931817cd1e2ef4dfb79d3e051b481",
|
||||
"sha256:a598d8830f6ef5501002ae85c7dbfcd9c27cc4efc02a1989369303ba85573e58",
|
||||
"sha256:a5eaf3b42df2bcda61c53a742ee2c6e63f777d0e085bbc6b2ab7ed57deb13db7",
|
||||
"sha256:aea7ce61328e15943d7b9eaca87e81f7c62ff90f669116f857262e9da4057ba3",
|
||||
"sha256:af79d3fde1fc2e33561166d62e3b63f0cc3e47b5a3a2e5fea40d4917754734ea",
|
||||
"sha256:c24f718f9dd73bb2b31a6201e6db5ea4a61fdd1d1c200f43ee585fc6dcd21b34",
|
||||
"sha256:c5b0ff59785d93b3437c3703e3c64c178aabada51dea2a7f2c5eccf1bcf565a3",
|
||||
"sha256:c7110ec1701b0bf8df569a7592a196c9d07c764a0a74f65471ea56816f10e2c8",
|
||||
"sha256:c870193cce4b76713a2b29be5d8327c8ccbe0d4a49bc22968aa1e680930f5581",
|
||||
"sha256:c9efef876c21788366ea1f50ecb39d5d6f65febe25ad1d4c0b8dff98843ac244",
|
||||
"sha256:de344bcf6e2463bb25179d74d6e7989e375f906bcec8cb86edb8b12acbc7dfef",
|
||||
"sha256:eb1b89b11256b5b6cad5e7593f9061ac4624f7651f7a8eb4dfa37caa1dfaa4d0",
|
||||
"sha256:ed742214068efa95e9844c2d9129e209ed63f61baa4d54dbf4cf8b5e2d30ccf2",
|
||||
"sha256:f401ed2bbb155e1ade150ccc63db1a4f6c1909d3d378f7d1235a44e90d75fb97",
|
||||
"sha256:fb89397013cf302f282f0fc998bb7abf11d49dcff72c8ecb320f76ea6e2c5717"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==9.1.0"
|
||||
},
|
||||
"protobuf": {
|
||||
"hashes": [
|
||||
"sha256:001c2160c03b6349c04de39cf1a58e342750da3632f6978a1634a3dcca1ec10e",
|
||||
|
|
@ -339,11 +383,11 @@
|
|||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea",
|
||||
"sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"
|
||||
"sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954",
|
||||
"sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.7"
|
||||
"markers": "python_full_version >= '3.6.8'",
|
||||
"version": "==3.0.8"
|
||||
},
|
||||
"pyrsistent": {
|
||||
"hashes": [
|
||||
|
|
@ -501,11 +545,11 @@
|
|||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea",
|
||||
"sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"
|
||||
"sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954",
|
||||
"sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.7"
|
||||
"markers": "python_full_version >= '3.6.8'",
|
||||
"version": "==3.0.8"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
|
|
@ -533,11 +577,11 @@
|
|||
},
|
||||
"virtualenv": {
|
||||
"hashes": [
|
||||
"sha256:1e8588f35e8b42c6ec6841a13c5e88239de1e6e4e4cedfd3916b306dc826ec66",
|
||||
"sha256:8e5b402037287126e81ccde9432b95a8be5b19d36584f64957060a3488c11ca8"
|
||||
"sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a",
|
||||
"sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==20.14.0"
|
||||
"version": "==20.14.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ install_requires =
|
|||
connexion>=2.13.0,<3
|
||||
cryptography>=36.0.2,<37
|
||||
pygments>=2.11.2,<3
|
||||
Pillow>=9.1.0,<10
|
||||
zip_safe = true
|
||||
package_dir =
|
||||
=src
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ def search(**kwargs):
|
|||
|
||||
variables = {
|
||||
'paste_index_url': '/ui/paste',
|
||||
'man_page': man_page
|
||||
'user_index_url': '/ui/user',
|
||||
'man_page': man_page,
|
||||
'user': kwargs.get('user'),
|
||||
'delete_session_url': '/ui/user/session/delete'
|
||||
}
|
||||
|
||||
return template.render(**variables), 200
|
||||
|
|
@ -5,6 +5,9 @@ from connexion import request
|
|||
|
||||
from httpaste.helper.template import views
|
||||
from httpaste.helper.url import url_query_string, url_append_query_param
|
||||
from httpaste.helper.syntax import syntax_shortnames, format_shortnames
|
||||
from httpaste.helper.http import mime_types
|
||||
|
||||
from httpaste.controller.paste import post as post_raw
|
||||
from httpaste.controller.paste import get as get_raw
|
||||
|
||||
|
|
@ -54,8 +57,6 @@ def get(**kwargs):
|
|||
|
||||
template = views.get_template("viewport/ui/paste/get.html")
|
||||
|
||||
|
||||
|
||||
base_path = f'paste/public/{kwargs["id"]}'
|
||||
|
||||
if kwargs.get('user'):
|
||||
|
|
@ -86,7 +87,10 @@ def get(**kwargs):
|
|||
'syntax': kwargs.get('syntax', ''),
|
||||
'mime': kwargs.get('mime', ''),
|
||||
'preview': kwargs.get('preview', True)
|
||||
}
|
||||
},
|
||||
'syntax_shortnames': syntax_shortnames(),
|
||||
'format_shortnames': format_shortnames(),
|
||||
'mime_types': mime_types()
|
||||
}
|
||||
|
||||
return template.render(**variables)
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
from httpaste.helper.template import views
|
||||
from httpaste import __doc__ as man_page
|
||||
|
||||
def search(**kwargs):
|
||||
|
||||
template = views.get_template("viewport/ui/user/search.html")
|
||||
|
||||
variables = {
|
||||
'delete_session_url': '/ui/user/session/delete'
|
||||
}
|
||||
|
||||
return template.render(**variables), 200
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
from mimetypes import types_map as mime_types_map
|
||||
|
||||
class BadRequestError(RuntimeError):
|
||||
def __init__(self, msg=None):
|
||||
|
|
@ -62,3 +63,11 @@ class NotFoundError(RuntimeError):
|
|||
"status": 404,
|
||||
"title": "Not Found",
|
||||
}, 404
|
||||
|
||||
|
||||
def mime_types():
|
||||
|
||||
types = list(set(mime_types_map.values()))
|
||||
types.sort()
|
||||
|
||||
return types
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
from pygments.lexers import get_lexer_by_name, find_lexer_class_by_name
|
||||
from pygments.formatters import find_formatter_class, HtmlFormatter
|
||||
from pygments.lexers import (get_lexer_by_name, find_lexer_class_by_name, get_all_lexers)
|
||||
from pygments.formatters import (find_formatter_class, HtmlFormatter, get_all_formatters)
|
||||
|
||||
|
||||
def highlight(
|
||||
|
|
@ -18,3 +18,13 @@ def highlight(
|
|||
formatter = find_formatter_class(format_alias)(linenos=linenos)
|
||||
|
||||
return highlight(data, get_lexer_by_name(lexer_alias), formatter)
|
||||
|
||||
|
||||
def syntax_shortnames():
|
||||
|
||||
return {l[0]:l[1][0] for l in get_all_lexers() if len(l[1]) > 0}
|
||||
|
||||
|
||||
def format_shortnames():
|
||||
|
||||
return [f.aliases[0] for f in get_all_formatters()]
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
from jinja2 import Environment, PackageLoader, select_autoescape
|
||||
|
||||
views = Environment(
|
||||
loader=PackageLoader("httpaste", "views"),
|
||||
loader=PackageLoader("httpaste", "view"),
|
||||
autoescape=select_autoescape()
|
||||
)
|
||||
|
|
@ -388,6 +388,9 @@
|
|||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/mime"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/ui_preview"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
|
@ -422,6 +425,22 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/ui/user": {
|
||||
"get": {
|
||||
"description": "get a public paste",
|
||||
"security": [
|
||||
{}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "paste data. content type may vary.",
|
||||
"content": {
|
||||
"text/html": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ui/user/session/delete": {
|
||||
"get": {
|
||||
"description": "get a public paste",
|
||||
|
|
|
|||
39
src/httpaste/view/container/get_paste_form.html
Normal file
39
src/httpaste/view/container/get_paste_form.html
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<form class="color-theme font-theme" action="{{preview_url}}" method="get" enctype="multipart/form-data">
|
||||
<details>
|
||||
<summary>
|
||||
<label for="syntax">Syntax</label>
|
||||
<!--<input type="text" name="syntax" value="{{ query['syntax'] }}"/>-->
|
||||
|
||||
<select name="syntax">
|
||||
<option {{ 'selected=""'if not query['syntax'] }} value>Disabled</option>
|
||||
{% for name, shortname in syntax_shortnames.items() %}
|
||||
<option value="{{shortname}}" {{ 'selected=""'if query['syntax'] == shortname }}>{{ name }}</option>
|
||||
{% endfor %}</select>
|
||||
</summary>
|
||||
<small>language to highlight syntax for</small>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<label for="format">Format</label>
|
||||
<select name="format">
|
||||
<option {{ 'selected=""'if not query['format'] }} value>Disabled</option>
|
||||
{% for shortname in format_shortnames %}
|
||||
<option value="{{shortname}}" {{ 'selected=""'if query['format'] == shortname }}>{{ shortname }}</option>
|
||||
{% endfor %}</select>
|
||||
</summary>
|
||||
<small>output format of highlighted syntax</small>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<label for="mime">Content-Type (MIME)</label>
|
||||
<select name="mime">
|
||||
<option {{ 'selected=""'if not query['mime'] }} value>Disabled</option>
|
||||
{% for mime in mime_types %}
|
||||
<option value="{{mime}}" {{ 'selected=""'if query['mime'] == mime }}>{{ mime }}</option>
|
||||
{% endfor %}</select>
|
||||
</summary>
|
||||
<small>content-type Header the server should return</small>
|
||||
</details>
|
||||
<input type="text" name="preview" value="{{ query['preview'] }}" style="display: none"/>
|
||||
<input type="submit" value="☝ Refresh"/>
|
||||
</form>
|
||||
26
src/httpaste/view/container/post_paste_form.html
Normal file
26
src/httpaste/view/container/post_paste_form.html
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<form class="color-theme font-theme" action="{{paste_form_url}}" method="post" enctype="multipart/form-data" target="_top">
|
||||
<details>
|
||||
<summary>
|
||||
<label for="data">Data
|
||||
<textarea name="data" cols="60" rows="10" style="width:100%"></textarea><br/>
|
||||
<input type="file" id="myfile" name="data"/>
|
||||
</label>
|
||||
</summary>
|
||||
<small>
|
||||
Either supply a past text, or upload a file.
|
||||
</small>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<label for="lifetime">Lifetime
|
||||
<input type="number" id="lname" name="lifetime" value="5">
|
||||
</label>
|
||||
</summary>
|
||||
<small>
|
||||
Set a paste’s lifetime to make it expire after a specified amount of time.
|
||||
The lifetime must be provided in minutes and cannot be less than 1 (, unless lesser than 0).
|
||||
A lifetime of 0 will evaluate to a lifetime 1. A lifetime of less than 0 will make the paste expire after first read.
|
||||
</small>
|
||||
</details>
|
||||
<input type="submit" value="☝ Paste"/>
|
||||
</form>
|
||||
16
src/httpaste/view/frame/base.html
Normal file
16
src/httpaste/view/frame/base.html
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
29
src/httpaste/view/frame/decorated.html
Normal file
29
src/httpaste/view/frame/decorated.html
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
|
||||
html {
|
||||
background-color: #DDD;
|
||||
padding: 0 1em 0 1em;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
form > *, menu > li {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
{% block header %}{% endblock %}
|
||||
</header>
|
||||
<hr/>
|
||||
<main>
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
36
src/httpaste/view/viewport/ui/paste/get.html
Normal file
36
src/httpaste/view/viewport/ui/paste/get.html
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{% extends 'frame/decorated.html' %}
|
||||
{% block header %}
|
||||
<h1><a href="/">httpaste</a> - <a href="/ui/paste">Paste</a> - Conditioner</h1>
|
||||
<p>
|
||||
Preview and conditon an existing paste
|
||||
</p>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
{% if query['preview'] %}
|
||||
Preview
|
||||
<iframe src="{{paste_url}}" title="as" style="resize:both; width: 100%"></iframe>
|
||||
{% else %}
|
||||
<p><b>Preview is disabled.</b>
|
||||
<br/>
|
||||
This probably happened because the paste is set to expire after read.
|
||||
<br/>
|
||||
<i>You can still proceed to condition the paste URL.</i>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% include 'container/get_paste_form.html' %}
|
||||
<hr/>
|
||||
<figure>
|
||||
<figcaption><strong>URLs</strong></figcaption>
|
||||
<dl>
|
||||
<dt>Formatted</dt>
|
||||
<dd>
|
||||
<a href="{{paste_url}}" target="_blank">{{paste_url}}</a>
|
||||
</dd>
|
||||
<dt>Raw</dt>
|
||||
<dd>
|
||||
<a href="{{raw_paste_url}}" target="_blank">{{raw_paste_url}}</a>
|
||||
</dd>
|
||||
</dl>
|
||||
</figure>
|
||||
{% endblock %}
|
||||
14
src/httpaste/view/viewport/ui/paste/private/search.html
Normal file
14
src/httpaste/view/viewport/ui/paste/private/search.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{% extends 'frame/decorated.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1><a href="/">httpaste</a> - <a href="/ui/paste">Paste</a> - Private</h1>
|
||||
|
||||
<p>
|
||||
Private pastes are authenticated
|
||||
</p>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% include 'container/post_paste_form.html' %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
14
src/httpaste/view/viewport/ui/paste/public/search.html
Normal file
14
src/httpaste/view/viewport/ui/paste/public/search.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{% extends 'frame/decorated.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1><a href="/">httpaste</a> - <a href="/ui/paste">Paste</a> - Public</h1>
|
||||
<p>
|
||||
Public pastes are not indexed and can only be accessed by knowing their respective
|
||||
paste id.
|
||||
</p>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% include 'container/post_paste_form.html' %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
36
src/httpaste/view/viewport/ui/paste/search.html
Normal file
36
src/httpaste/view/viewport/ui/paste/search.html
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{% extends 'frame/decorated.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1><a href="/">httpaste</a> - Paste</h1>
|
||||
|
||||
<p>
|
||||
All pastes are symetrically encrypted server-side with an HMAC derived key
|
||||
and SHA-256 hashing, a server-side salt and a randomly generated password.
|
||||
Public paste’s passwords are derived from their ids. Private paste’s passwords
|
||||
are randomly generated and stored inside a symetrically encrypted personal database,
|
||||
with the encryption key also being derived through the same HMAC mechanism,
|
||||
where a HTTP basic authentication act as the master password.
|
||||
Paste ids, usernames, and any other identifiable attributes are only stored
|
||||
inside the storage backend as keyed and salted BLAKE2 hashes.
|
||||
</p>
|
||||
<p><strong>Note:</strong>
|
||||
The initial creation of a private paste will prompt for login credentials.
|
||||
If the login credentials are not known, they will be created automatically.
|
||||
If it is required to authenticate with other credentials, clear your local
|
||||
HTTP authentication cache.
|
||||
</p>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<figure>
|
||||
<figcaption><strong>Navigation</strong></figcaption>
|
||||
<menu>
|
||||
<li>
|
||||
<a href="{{create_private_paste_url}}">Create a Private Paste</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{create_public_paste_url}}">Create a Public Paste</a>
|
||||
</li>
|
||||
</menu>
|
||||
</figure>
|
||||
|
||||
{% endblock %}
|
||||
41
src/httpaste/view/viewport/ui/search.html
Normal file
41
src/httpaste/view/viewport/ui/search.html
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{% extends 'frame/decorated.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1><a href="/">httpaste</a> - versatile HTTP pastebin</h1>
|
||||
<p>
|
||||
This is the user interface of the hosted version of <a href="https://victorykit.bitbucket.io/httpaste" target="_blank">httpaste</a>,
|
||||
a program which offers an HTTP interface for storing public and private data (a.k.a. pastes),
|
||||
commonly referred to as a pastebin application. It is inspired by
|
||||
<a href='http://sprunge.us' target='_blank'>sprunge.us</a> and <a href='http://ix.io' target="_blank">ix.io</a>.
|
||||
It aims for a higher degree of privacy control than available commercial pastebin products.
|
||||
</p>
|
||||
<p>
|
||||
httpaste features include:
|
||||
<ul>
|
||||
<li>Authenticated private and unlisted public pasting</li>
|
||||
<li>Lifetime control (including Burn-After-Read expiration)</li>
|
||||
<li>Encoded and Binary Data Upload</li>
|
||||
<li>Syntax Higlighting</li>
|
||||
<li>Output Formatting</li>
|
||||
<li>Output Content-Type Control</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
A pseudo man page for CLI usage is available via HTTP GET of this host's root document.
|
||||
(e.g. `<code>$ curl httpaste.it</code>`)
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<figure>
|
||||
<figcaption><strong>Navigation</strong></figcaption>
|
||||
<menu>
|
||||
<li>
|
||||
<a href="{{paste_index_url}}">Paste</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{user_index_url}}">User</a>
|
||||
</li>
|
||||
</menu>
|
||||
</figure>
|
||||
{% endblock %}
|
||||
16
src/httpaste/view/viewport/ui/user/search.html
Normal file
16
src/httpaste/view/viewport/ui/user/search.html
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{% extends 'frame/decorated.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1><a href="/">httpaste</a> - User</h1>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<figure>
|
||||
<figcaption><strong>Navigation</strong></figcaption>
|
||||
<menu>
|
||||
<li>
|
||||
<a href="{{delete_session_url}}" target="_blank">Clear Local HTTP Authentication Cache</a>
|
||||
</li>
|
||||
</menu>
|
||||
</figure>
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<form class="color-theme font-theme" action="{{preview_url}}" method="get" enctype="multipart/form-data">
|
||||
<details>
|
||||
<summary>
|
||||
<label for="syntax">Syntax</label>
|
||||
<input type="text" name="syntax" value="{{ query['syntax'] }}"/>
|
||||
|
||||
</summary>
|
||||
<a href="https://pygments.org/docs/lexers/" target="_blank">Pygments lexer short name</a> <i>(e.g. 'terraform', 'python')</i>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<label for="format">Format</label>
|
||||
<input type="text" name="format" value="{{ query['format'] }}"/>
|
||||
</summary>
|
||||
<a href="https://pygments.org/docs/formatters/" target="_blank">Pygments formatter short name</a> <i>(e.g. 'html', 'terminal256')</i>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<label for="mime">Content-Type (MIME)</label>
|
||||
<input type="text" name="mime" value="{{ query['mime'] }}"/>
|
||||
</summary>
|
||||
Content-Type Header the server should return
|
||||
</details>
|
||||
<input type="text" name="preview" value="{{ query['preview'] }}" class="hidden"/>
|
||||
<input type="submit" value="☝ Refresh"/>
|
||||
</form>
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
<form class="color-theme font-theme" action="{{paste_form_url}}" method="post" enctype="multipart/form-data" target="_top">
|
||||
<details>
|
||||
<summary>
|
||||
<label for="data">Data</label>
|
||||
<div><textarea name="data" cols="60" rows="10" style="width:100%"></textarea><br/>
|
||||
<input type="file" id="myfile" name="data"/>
|
||||
</div>
|
||||
</summary>
|
||||
Either supply a past text, or upload a file.
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<label for="lifetime">Lifetime</label>
|
||||
<input type="number" id="lname" name="lifetime" value="5">
|
||||
</summary>
|
||||
Set a paste’s lifetime to make it expire after a specified amount of time.<br/>
|
||||
The lifetime must be provided in minutes and cannot be less than 1<br/>(, unless lesser than 0).<br/>
|
||||
A lifetime of 0 will evaluate to a lifetime 1.
|
||||
</details>
|
||||
<input type="submit" value="☝ Paste"/>
|
||||
</form>
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<style>
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: left;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.color-theme details {
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
.font-theme details {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.color-theme details > summary {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.font-theme details > summary {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
details {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
details > summary {
|
||||
list-style-type: '?';
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.iframe {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
{% extends 'frame/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<a href="/">Return</a>
|
||||
<h1>Paste Conditioner</h1>
|
||||
{% if query['preview'] %}
|
||||
Preview
|
||||
<iframe src="{{paste_url}}" title="as" style="resize:both; width: 100%"></iframe>
|
||||
<hr/>
|
||||
{% else %}
|
||||
<p><b>Preview is disabled.</b>
|
||||
<br/>
|
||||
This probably happened because the paste is set to expire after read.
|
||||
<br/>
|
||||
<i>You can still proceed to condition the paste URL.</i>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% include 'container/get_paste_form.html' %}
|
||||
<div style="justify-content: center">
|
||||
<hr/>
|
||||
<h3>Paste URLs</h3>
|
||||
Formatted: <a href="{{paste_url}}" target="_top">{{paste_url}}</a>
|
||||
<br/>
|
||||
Raw: <a href="{{raw_paste_url}}" target="_top">{{raw_paste_url}}</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{% extends 'frame/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'container/post_paste_form.html' %}
|
||||
{% endblock %}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{% extends 'frame/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'container/post_paste_form.html' %}
|
||||
{% endblock %}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<a href="{{create_private_paste_url}}">Create a Private Paste</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="{{create_public_paste_url}}">Create a Public Paste</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="{{ delete_session_url }}" target="_blank" style="text-align: center">
|
||||
Flush Local HTTP Authentication Cache
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
{% extends 'frame/decorated.html' %}
|
||||
|
||||
{% block content %}
|
||||
<header style="display: flex; justify-content: center">
|
||||
<details>
|
||||
<summary style="text-align: center"><a href="/">httpaste - versatile HTTP pastebin (User Interface)</a></summary>
|
||||
<textarea readonly="true" style="width: 100%">{{ man_page }}</textarea>
|
||||
</details>
|
||||
</header>
|
||||
<iframe src="{{ paste_index_url }}" title="" class="iframe"></iframe>
|
||||
{% endblock %}
|
||||
Loading…
Add table
Add a link
Reference in a new issue