Merge pull request #36 from mutantmonkey/csp
Add support for Content-Security-Policy and X-Frame-Options
This commit is contained in:
commit
7152adb902
|
@ -0,0 +1,40 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cspHeader = "Content-Security-Policy"
|
||||||
|
frameOptionsHeader = "X-Frame-Options"
|
||||||
|
)
|
||||||
|
|
||||||
|
type csp struct {
|
||||||
|
h http.Handler
|
||||||
|
opts CSPOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
type CSPOptions struct {
|
||||||
|
policy string
|
||||||
|
frame string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c csp) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// only add a CSP if one is not already set
|
||||||
|
if existing := w.Header().Get(cspHeader); existing == "" {
|
||||||
|
w.Header().Add(cspHeader, c.opts.policy)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set(frameOptionsHeader, c.opts.frame)
|
||||||
|
|
||||||
|
c.h.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContentSecurityPolicy(o CSPOptions) func(http.Handler) http.Handler {
|
||||||
|
fn := func(h http.Handler) http.Handler {
|
||||||
|
return csp{h, o}
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim:set ts=8 sw=8 noet:
|
|
@ -0,0 +1,38 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/zenazn/goji"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testCSPHeaders = map[string]string{
|
||||||
|
"Content-Security-Policy": "default-src 'none'; style-src 'self';",
|
||||||
|
"X-Frame-Options": "SAMEORIGIN",
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContentSecurityPolicy(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", "/", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
goji.Use(ContentSecurityPolicy(CSPOptions{
|
||||||
|
policy: testCSPHeaders["Content-Security-Policy"],
|
||||||
|
frame: testCSPHeaders["X-Frame-Options"],
|
||||||
|
}))
|
||||||
|
|
||||||
|
goji.DefaultMux.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
for k, v := range testCSPHeaders {
|
||||||
|
if w.HeaderMap[k][0] != v {
|
||||||
|
t.Fatalf("%s header did not match expected value set by middleware", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim:set ts=8 sw=8 noet:
|
|
@ -26,6 +26,8 @@ func fileServeHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Security-Policy", Config.fileContentSecurityPolicy)
|
||||||
|
|
||||||
http.ServeFile(w, r, filePath)
|
http.ServeFile(w, r, filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
server.go
34
server.go
|
@ -19,15 +19,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var Config struct {
|
var Config struct {
|
||||||
bind string
|
bind string
|
||||||
filesDir string
|
filesDir string
|
||||||
metaDir string
|
metaDir string
|
||||||
noLogs bool
|
noLogs bool
|
||||||
allowHotlink bool
|
allowHotlink bool
|
||||||
siteName string
|
siteName string
|
||||||
siteURL string
|
siteURL string
|
||||||
fastcgi bool
|
fastcgi bool
|
||||||
remoteUploads bool
|
remoteUploads bool
|
||||||
|
contentSecurityPolicy string
|
||||||
|
fileContentSecurityPolicy string
|
||||||
|
xFrameOptions string
|
||||||
}
|
}
|
||||||
|
|
||||||
var Templates = make(map[string]*pongo2.Template)
|
var Templates = make(map[string]*pongo2.Template)
|
||||||
|
@ -37,6 +40,11 @@ var timeStarted time.Time
|
||||||
var timeStartedStr string
|
var timeStartedStr string
|
||||||
|
|
||||||
func setup() {
|
func setup() {
|
||||||
|
goji.Use(ContentSecurityPolicy(CSPOptions{
|
||||||
|
policy: Config.contentSecurityPolicy,
|
||||||
|
frame: Config.xFrameOptions,
|
||||||
|
}))
|
||||||
|
|
||||||
if Config.noLogs {
|
if Config.noLogs {
|
||||||
goji.Abandon(middleware.Logger)
|
goji.Abandon(middleware.Logger)
|
||||||
}
|
}
|
||||||
|
@ -126,6 +134,14 @@ func main() {
|
||||||
"serve through fastcgi")
|
"serve through fastcgi")
|
||||||
flag.BoolVar(&Config.remoteUploads, "remoteuploads", false,
|
flag.BoolVar(&Config.remoteUploads, "remoteuploads", false,
|
||||||
"enable remote uploads")
|
"enable remote uploads")
|
||||||
|
flag.StringVar(&Config.contentSecurityPolicy, "contentSecurityPolicy",
|
||||||
|
"default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; referrer none;",
|
||||||
|
"value of default Content-Security-Policy header")
|
||||||
|
flag.StringVar(&Config.fileContentSecurityPolicy, "fileContentSecurityPolicy",
|
||||||
|
"default-src 'none'; img-src 'self'; object-src 'self'; media-src 'self'; sandbox; referrer none;",
|
||||||
|
"value of Content-Security-Policy header for file access")
|
||||||
|
flag.StringVar(&Config.xFrameOptions, "xFrameOptions", "SAMEORIGIN",
|
||||||
|
"value of X-Frame-Options header")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
setup()
|
setup()
|
||||||
|
|
|
@ -80,6 +80,16 @@ body {
|
||||||
padding: 5px 5px 5px 5px;
|
padding: 5px 5px 5px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#info #filename,
|
||||||
|
#editform #filename {
|
||||||
|
width: 232px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#info #extension,
|
||||||
|
#editform #extension {
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
#info .float-left {
|
#info .float-left {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
|
@ -181,7 +191,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.clear {
|
.clear {
|
||||||
clear:both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
#upload_header {
|
#upload_header {
|
||||||
|
@ -248,6 +258,66 @@ body {
|
||||||
padding-top: 1px;
|
padding-top: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.oopscontent {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oopscontent img {
|
||||||
|
width: 400px;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor {
|
||||||
|
width: 705px;
|
||||||
|
height: 450px;
|
||||||
|
border-color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content display {{{ */
|
||||||
|
.display-audio,
|
||||||
|
.display-file {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-image {
|
||||||
|
margin-bottom: -6px;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-pdf {
|
||||||
|
width: 910px;
|
||||||
|
height: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-video {
|
||||||
|
width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollable {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.storycontent {
|
||||||
|
background-color: #f0e0d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editform,
|
||||||
|
#editform .editor {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#codeb {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor {
|
||||||
|
display: none;
|
||||||
|
border: 0;
|
||||||
|
width: 794px;
|
||||||
|
height: 800px;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* cat.js */
|
/* cat.js */
|
||||||
.qq-uploader { position:relative; width: 100%;}
|
.qq-uploader { position:relative; width: 100%;}
|
||||||
|
|
||||||
|
|
|
@ -7,21 +7,26 @@ function init() {
|
||||||
var editA = document.createElement('a');
|
var editA = document.createElement('a');
|
||||||
|
|
||||||
editA.setAttribute("href", "#");
|
editA.setAttribute("href", "#");
|
||||||
editA.setAttribute("onclick", "edit();return false;");
|
editA.addEventListener('click', function(ev) {
|
||||||
|
edit(ev);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
editA.innerHTML = "edit";
|
editA.innerHTML = "edit";
|
||||||
|
|
||||||
var separator = document.createTextNode(" | ");
|
var separator = document.createTextNode(" | ");
|
||||||
navlist.insertBefore(editA, navlist.firstChild);
|
navlist.insertBefore(editA, navlist.firstChild);
|
||||||
navlist.insertBefore(separator, navlist.children[1]);
|
navlist.insertBefore(separator, navlist.children[1]);
|
||||||
|
|
||||||
|
document.getElementById('save').addEventListener('click', paste);
|
||||||
|
document.getElementById('wordwrap').addEventListener('click', wrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function edit() {
|
function edit(ev) {
|
||||||
|
|
||||||
navlist.remove();
|
navlist.remove();
|
||||||
document.getElementById("filename").remove();
|
document.getElementById("filename").remove();
|
||||||
document.getElementById("foarm").style.display = "block";
|
document.getElementById("editform").style.display = "block";
|
||||||
|
|
||||||
var normalcontent = document.getElementById("normal-content");
|
var normalcontent = document.getElementById("normal-content");
|
||||||
normalcontent.removeChild(document.getElementById("normal-code"));
|
normalcontent.removeChild(document.getElementById("normal-code"));
|
||||||
|
@ -31,14 +36,13 @@ function edit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function paste() {
|
function paste(ev) {
|
||||||
var editordiv = document.getElementById("editor");
|
var editordiv = document.getElementById("editor");
|
||||||
document.getElementById("newcontent").value = editordiv.value;
|
document.getElementById("newcontent").value = editordiv.value;
|
||||||
document.forms["reply"].submit();
|
document.forms["reply"].submit();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrap() {
|
function wrap(ev) {
|
||||||
if (document.getElementById("wordwrap").checked) {
|
if (document.getElementById("wordwrap").checked) {
|
||||||
document.getElementById("codeb").style.wordWrap = "break-word";
|
document.getElementById("codeb").style.wordWrap = "break-word";
|
||||||
document.getElementById("codeb").style.whiteSpace = "pre-wrap";
|
document.getElementById("codeb").style.whiteSpace = "pre-wrap";
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
hljs.tabReplace = ' ';
|
||||||
|
hljs.initHighlightingOnLoad();
|
|
@ -5,33 +5,36 @@ Dropzone.options.dropzone = {
|
||||||
var upload = document.createElement("div");
|
var upload = document.createElement("div");
|
||||||
upload.className = "upload";
|
upload.className = "upload";
|
||||||
|
|
||||||
var left = document.createElement("span");
|
var fileLabel = document.createElement("span");
|
||||||
left.innerHTML = file.name;
|
fileLabel.innerHTML = file.name;
|
||||||
file.leftElement = left;
|
file.fileLabel = fileLabel;
|
||||||
upload.appendChild(left);
|
upload.appendChild(fileLabel);
|
||||||
|
|
||||||
var right = document.createElement("div");
|
var fileActions = document.createElement("div");
|
||||||
right.className = "right";
|
fileActions.className = "right";
|
||||||
var rightleft = document.createElement("span");
|
file.fileActions = fileActions;
|
||||||
rightleft.className = "cancel";
|
upload.appendChild(fileActions);
|
||||||
rightleft.innerHTML = "Cancel";
|
|
||||||
rightleft.onclick = function(ev) {
|
var cancelAction = document.createElement("span");
|
||||||
this.removeFile(file);
|
cancelAction.className = "cancel";
|
||||||
}.bind(this);
|
cancelAction.innerHTML = "Cancel";
|
||||||
|
cancelAction.addEventListener('click', function(ev) {
|
||||||
|
this.removeFile(file);
|
||||||
|
}.bind(this));
|
||||||
|
file.cancelActionElement = cancelAction;
|
||||||
|
fileActions.appendChild(cancelAction);
|
||||||
|
|
||||||
|
var progress = document.createElement("span");
|
||||||
|
file.progressElement = progress;
|
||||||
|
fileActions.appendChild(progress);
|
||||||
|
|
||||||
var rightright = document.createElement("span");
|
|
||||||
right.appendChild(rightleft);
|
|
||||||
file.rightLeftElement = rightleft;
|
|
||||||
right.appendChild(rightright);
|
|
||||||
file.rightRightElement = rightright;
|
|
||||||
file.rightElement = right;
|
|
||||||
upload.appendChild(right);
|
|
||||||
file.uploadElement = upload;
|
file.uploadElement = upload;
|
||||||
|
|
||||||
document.getElementById("uploads").appendChild(upload);
|
document.getElementById("uploads").appendChild(upload);
|
||||||
},
|
},
|
||||||
uploadprogress: function(file, p, bytesSent) {
|
uploadprogress: function(file, p, bytesSent) {
|
||||||
p = parseInt(p);
|
p = parseInt(p);
|
||||||
file.rightRightElement.innerHTML = p + "%";
|
file.progressElement.innerHTML = p + "%";
|
||||||
file.uploadElement.setAttribute("style", 'background-image: -webkit-linear-gradient(left, #F2F4F7 ' + p + '%, #E2E2E2 ' + p + '%); background-image: -moz-linear-gradient(left, #F2F4F7 ' + p + '%, #E2E2E2 ' + p + '%); background-image: -ms-linear-gradient(left, #F2F4F7 ' + p + '%, #E2E2E2 ' + p + '%); background-image: -o-linear-gradient(left, #F2F4F7 ' + p + '%, #E2E2E2 ' + p + '%); background-image: linear-gradient(left, #F2F4F7 ' + p + '%, #E2E2E2 ' + p + '%)');
|
file.uploadElement.setAttribute("style", 'background-image: -webkit-linear-gradient(left, #F2F4F7 ' + p + '%, #E2E2E2 ' + p + '%); background-image: -moz-linear-gradient(left, #F2F4F7 ' + p + '%, #E2E2E2 ' + p + '%); background-image: -ms-linear-gradient(left, #F2F4F7 ' + p + '%, #E2E2E2 ' + p + '%); background-image: -o-linear-gradient(left, #F2F4F7 ' + p + '%, #E2E2E2 ' + p + '%); background-image: linear-gradient(left, #F2F4F7 ' + p + '%, #E2E2E2 ' + p + '%)');
|
||||||
},
|
},
|
||||||
sending: function(file, xhr, formData) {
|
sending: function(file, xhr, formData) {
|
||||||
|
@ -39,36 +42,48 @@ Dropzone.options.dropzone = {
|
||||||
formData.append("expires", document.getElementById("expires").selectedOptions[0].value);
|
formData.append("expires", document.getElementById("expires").selectedOptions[0].value);
|
||||||
},
|
},
|
||||||
success: function(file, resp) {
|
success: function(file, resp) {
|
||||||
file.rightLeftElement.innerHTML = "";
|
file.fileActions.removeChild(file.progressElement);
|
||||||
file.leftElement.innerHTML = '<a target="_blank" href="' + resp.url + '">' + resp.url + '</a>';
|
|
||||||
file.rightRightElement.innerHTML = "Delete";
|
var fileLabelLink = document.createElement("a");
|
||||||
file.rightRightElement.className = "cancel";
|
fileLabelLink.href = resp.url;
|
||||||
file.rightRightElement.onclick = function(ev) {
|
fileLabelLink.target = "_blank";
|
||||||
|
fileLabelLink.innerHTML = resp.url;
|
||||||
|
file.fileLabel.innerHTML = "";
|
||||||
|
file.fileLabelLink = fileLabelLink;
|
||||||
|
file.fileLabel.appendChild(fileLabelLink);
|
||||||
|
|
||||||
|
var deleteAction = document.createElement("span");
|
||||||
|
deleteAction.innerHTML = "Delete";
|
||||||
|
deleteAction.className = "cancel";
|
||||||
|
deleteAction.addEventListener('click', function(ev) {
|
||||||
xhr = new XMLHttpRequest();
|
xhr = new XMLHttpRequest();
|
||||||
xhr.open("DELETE", resp.url, true);
|
xhr.open("DELETE", resp.url, true);
|
||||||
xhr.setRequestHeader("X-Delete-Key", resp.delete_key);
|
xhr.setRequestHeader("X-Delete-Key", resp.delete_key);
|
||||||
xhr.onreadystatechange = function(file) {
|
xhr.onreadystatechange = function(file) {
|
||||||
if (xhr.status === 200) {
|
if (xhr.readyState == 4 && xhr.status === 200) {
|
||||||
file.leftElement.innerHTML = 'Deleted <a target="_blank" href="' + resp.url + '">' + resp.url + '</a>';
|
var text = document.createTextNode("Deleted ");
|
||||||
file.leftElement.className = "deleted";
|
file.fileLabel.insertBefore(text, file.fileLabelLink);
|
||||||
file.rightRightElement.onclick = null;
|
file.fileLabel.className = "deleted";
|
||||||
file.rightRightElement.innerHTML = "";
|
file.fileActions.removeChild(file.cancelActionElement);
|
||||||
}
|
}
|
||||||
}.bind(this, file);
|
}.bind(this, file);
|
||||||
xhr.send();
|
xhr.send();
|
||||||
}.bind(this);
|
});
|
||||||
|
file.fileActions.removeChild(file.cancelActionElement);
|
||||||
|
file.cancelActionElement = deleteAction;
|
||||||
|
file.fileActions.appendChild(deleteAction);
|
||||||
},
|
},
|
||||||
error: function(file, resp, xhrO) {
|
error: function(file, resp, xhrO) {
|
||||||
file.rightLeftElement.onclick = null;
|
file.fileActions.removeChild(file.cancelActionElement);
|
||||||
file.rightLeftElement.innerHTML = "";
|
file.fileActions.removeChild(file.progressElement);
|
||||||
file.rightRightElement.innerHTML = "";
|
|
||||||
if (file.status === "canceled") {
|
if (file.status === "canceled") {
|
||||||
file.leftElement.innerHTML = file.name + ": Canceled ";
|
file.fileLabel.innerHTML = file.name + ": Canceled ";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
file.leftElement.innerHTML = file.name + ": " + resp.error;
|
file.fileLabel.innerHTML = file.name + ": " + resp.error;
|
||||||
}
|
}
|
||||||
file.leftElement.className = "error";
|
file.fileLabel.className = "error";
|
||||||
},
|
},
|
||||||
|
|
||||||
maxFilesize: 4096,
|
maxFilesize: 4096,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<a href="/"><img style="border:0;" src='/static/images/404.jpg' width='400'></a>
|
<a href="/"><img src='/static/images/404.jpg'></a>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<audio controls style='width: 500px;' preload='auto'>
|
<audio class="display-audio" controls preload='auto'>
|
||||||
<source src='/selif/{{ filename }}'>
|
<source src='/selif/{{ filename }}'>
|
||||||
<a href='/selif/{{ filename }}'>Download it instead</a>
|
<a href='/selif/{{ filename }}'>Download it instead</a>
|
||||||
</audio>
|
</audio>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,20 @@
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
{% if extra.extension == "story" %}
|
{% if extra.extension == "story" %}
|
||||||
<link href="/static/css/highlight/story.css" rel="stylesheet" type="text/css" />
|
<link href="/static/css/highlight/story.css" rel="stylesheet" type="text/css">
|
||||||
{% else %}
|
{% else %}
|
||||||
<link href="/static/css/highlight/tomorrow.css" rel="stylesheet" type="text/css" />
|
<link href="/static/css/highlight/tomorrow.css" rel="stylesheet" type="text/css">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block innercontentmore %} style="overflow: auto;" {% endblock %}
|
{% block innercontentmore %} class="scrollable"{% endblock %}
|
||||||
{% block mainmore %} {% if extra.extension == "story" %} style="background-color: #f0e0d6;"{% endif %} {% endblock %}
|
{% block mainmore %} {% if extra.extension == "story" %} class="storycontent"{% endif %} {% endblock %}
|
||||||
|
|
||||||
{% block infoleft %}
|
{% block infoleft %}
|
||||||
<div id="foarm" style="display: none;">
|
<div id="editform">
|
||||||
<form id="reply" action='/upload' method='post' >
|
<form id="reply" action='/upload' method='post' >
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<select id="expiry" name="expires">
|
<select id="expiry" name="expires">
|
||||||
<option disabled=disabled>Expires:</option>
|
<option disabled=disabled>Expires:</option>
|
||||||
<option value="0">never</option>
|
<option value="0">never</option>
|
||||||
<option value="60">a minute</option>
|
<option value="60">a minute</option>
|
||||||
|
@ -25,36 +25,32 @@
|
||||||
<option value="604800">a week</option>
|
<option value="604800">a week</option>
|
||||||
<option value="2419200">a month</option>
|
<option value="2419200">a month</option>
|
||||||
<option value="29030400">a year</option>
|
<option value="29030400">a year</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<button id="save" onclick="paste()">save</button>
|
<button id="save">save</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input style ="width:232px;" class="codebox" name='filename' id="filename" type='text' value="" placeholder="filename (empty for random filename)" />.<input id="extension" class="codebox" style="width:30px;" name='extension' type='text' value="{{ extra.extension }}" placeholder="txt" />
|
<input class="codebox" name='filename' id="filename" type='text' value="" placeholder="filename (empty for random filename)">.<input id="extension" class="codebox" name='extension' type='text' value="{{ extra.extension }}" placeholder="txt">
|
||||||
<textarea name='content' id="newcontent" class="editor" style="display: none;"></textarea>
|
<textarea name='content' id="newcontent" class="editor"></textarea>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{%block infomore %}
|
{%block infomore %}
|
||||||
<label>wrap <input id="wordwrap" type="checkbox" onclick="wrap()" checked /></label> |
|
<label>wrap <input id="wordwrap" type="checkbox" checked></label> |
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div id="normal-content" class="normal {% if extra.lang_hl != "story" %}fixed{% endif %}">
|
<div id="normal-content" class="normal {% if extra.lang_hl != "story" %}fixed{% endif %}">
|
||||||
<pre id="normal-code"><code id="codeb" style="white-space: pre-wrap;" class="{{ extra.lang_hl }}">{{ extra.contents }}</pre></code>
|
<pre id="normal-code"><code id="codeb" class="{{ extra.lang_hl }}">{{ extra.contents }}</code></pre>
|
||||||
<textarea id="editor" style="display: none; height: 800px; font-size: 11px;">{{ extra.contents }}</textarea>
|
<textarea id="editor">{{ extra.contents }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% if extra.lang_hl != "text" %}
|
{% if extra.lang_hl != "text" %}
|
||||||
<script src="/static/js/highlight/highlight.pack.js"></script>
|
<script src="/static/js/highlight/highlight.pack.js"></script>
|
||||||
<script>
|
<script src="/static/js/bin_hljs.js"></script>
|
||||||
hljs.tabReplace = ' ';
|
|
||||||
hljs.initHighlightingOnLoad();
|
|
||||||
</script>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bin.js"></script>
|
<script src="/static/js/bin.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div class="normal" style="width: 500px;">
|
<div class="normal display-file">
|
||||||
<p class="center">You are requesting <a href="/selif/{{ filename }}">{{ filename }}</a>, <a href="/selif/{{ filename }}">click here</a> to download.</p>
|
<p class="center">You are requesting <a href="/selif/{{ filename }}">{{ filename }}</a>, <a href="/selif/{{ filename }}">click here</a> to download.</p>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<a href="/selif/{{ filename }}">
|
<a href="/selif/{{ filename }}">
|
||||||
<img style="margin-bottom: -6px; max-width: 800px;" src="/selif/{{ filename }}" />
|
<img class="display-image" src="/selif/{{ filename }}" />
|
||||||
</a>
|
</a>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<object data="/selif/{{ filename }}"
|
<object class="display-pdf" data="/selif/{{ filename }}" type="application/pdf">
|
||||||
type="application/pdf"
|
|
||||||
width=910
|
|
||||||
height=800>
|
|
||||||
|
|
||||||
<p>It appears your Web browser is not configured to display PDF files.
|
<p>It appears your Web browser is not configured to display PDF files.
|
||||||
No worries, just <a href="/selif/{{ filename }}">click here to download the PDF file.</a></p>
|
No worries, just <a href="/selif/{{ filename }}">click here to download the PDF file.</a></p>
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div id='video'>
|
<video class="display-video" controls autoplay>
|
||||||
<video controls autoplay width="800">
|
<source src="/selif/{{ filename }}"/>
|
||||||
<source src="/selif/{{ filename }}"/>
|
<a href='/selif/{{ filename }}'>Download it instead</a>
|
||||||
</video>
|
</video>
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
<div id="expiry">
|
<div id="expiry">
|
||||||
<label>File expiry:
|
<label>File expiry:
|
||||||
<select name="expires" id="expires">
|
<select name="expires" id="expires">
|
||||||
</label>
|
|
||||||
<option value="0">never</option>
|
<option value="0">never</option>
|
||||||
<option value="60">a minute</option>
|
<option value="60">a minute</option>
|
||||||
<option value="300">5 minutes</option>
|
<option value="300">5 minutes</option>
|
||||||
|
@ -30,13 +29,14 @@
|
||||||
<option value="2419200">a month</option>
|
<option value="2419200">a month</option>
|
||||||
<option value="29030400">a year</option>
|
<option value="29030400">a year</option>
|
||||||
</select>
|
</select>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<label><input name="randomize" id="randomize" type="checkbox" checked /> Randomize filename</label>
|
<label><input name="randomize" id="randomize" type="checkbox" checked /> Randomize filename</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="clear"></div>
|
<div class="clear"></div>
|
||||||
</form>
|
</form>
|
||||||
<div id="uploads"></div>
|
<div id="uploads"></div>
|
||||||
<div style="clear:both;"></div>
|
<div class="clear"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/dropzone.js"></script>
|
<script src="/static/js/dropzone.js"></script>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id='inner_content' style='width: 400px'>
|
<div id='inner_content' class='oopscontent'>
|
||||||
<p>{{ msg }}</p>
|
<p>{{ msg }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<form id="reply" action='/upload' method='post'>
|
<form id="reply" action='/upload' method='post'>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id="info" class="ninfo">
|
<div id="info" class="ninfo">
|
||||||
<input style ="width:232px;" class="codebox" name='filename' id="filename" type='text' value="" placeholder="filename (empty for random filename)" />.<span class="hint--top hint--bounce" data-hint="Enable syntax highlighting by adding the extension"><input id="extension" class="codebox" style="width:40px;" name='extension' type='text' value="" placeholder="txt" /></span>
|
<input class="codebox" name='filename' id="filename" type='text' value="" placeholder="filename (empty for random filename)" />.<span class="hint--top hint--bounce" data-hint="Enable syntax highlighting by adding the extension"><input id="extension" class="codebox" name='extension' type='text' value="" placeholder="txt" /></span>
|
||||||
|
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<select id="expiry" name="expires">
|
<select id="expiry" name="expires">
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="inner_content">
|
<div id="inner_content">
|
||||||
<textarea name='content' id="content" class="editor" style="width: 705px; height: 450px; border-color: #cccccc;"></textarea>
|
<textarea name='content' id="content" class="editor"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue