parent
a79bc1898a
commit
8f3108148b
9 changed files with 209 additions and 103 deletions
|
@ -52,6 +52,7 @@ allowhotlink = true
|
||||||
- ```-xframeoptions "..." ``` -- X-Frame-Options header (default is "SAMEORIGIN")
|
- ```-xframeoptions "..." ``` -- X-Frame-Options header (default is "SAMEORIGIN")
|
||||||
- ```-remoteuploads``` -- (optionally) enable remote uploads (/upload?url=https://...)
|
- ```-remoteuploads``` -- (optionally) enable remote uploads (/upload?url=https://...)
|
||||||
- ```-nologs``` -- (optionally) disable request logs in stdout
|
- ```-nologs``` -- (optionally) disable request logs in stdout
|
||||||
|
- ```-force-random-filename``` -- (optionally) force the use of random filenames
|
||||||
|
|
||||||
#### Storage backends
|
#### Storage backends
|
||||||
The following storage backends are available:
|
The following storage backends are available:
|
||||||
|
|
11
pages.go
11
pages.go
|
@ -21,8 +21,9 @@ const (
|
||||||
|
|
||||||
func indexHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
func indexHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
err := renderTemplate(Templates["index.html"], pongo2.Context{
|
err := renderTemplate(Templates["index.html"], pongo2.Context{
|
||||||
"maxsize": Config.maxSize,
|
"maxsize": Config.maxSize,
|
||||||
"expirylist": listExpirationTimes(),
|
"expirylist": listExpirationTimes(),
|
||||||
|
"forcerandom": Config.forceRandomFilename,
|
||||||
}, r, w)
|
}, r, w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
@ -31,7 +32,8 @@ func indexHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func pasteHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
func pasteHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
err := renderTemplate(Templates["paste.html"], pongo2.Context{
|
err := renderTemplate(Templates["paste.html"], pongo2.Context{
|
||||||
"expirylist": listExpirationTimes(),
|
"expirylist": listExpirationTimes(),
|
||||||
|
"forcerandom": Config.forceRandomFilename,
|
||||||
}, r, w)
|
}, r, w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
oopsHandler(c, w, r, RespHTML, "")
|
oopsHandler(c, w, r, RespHTML, "")
|
||||||
|
@ -40,7 +42,8 @@ func pasteHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func apiDocHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
func apiDocHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
err := renderTemplate(Templates["API.html"], pongo2.Context{
|
err := renderTemplate(Templates["API.html"], pongo2.Context{
|
||||||
"siteurl": getSiteURL(r),
|
"siteurl": getSiteURL(r),
|
||||||
|
"forcerandom": Config.forceRandomFilename,
|
||||||
}, r, w)
|
}, r, w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
oopsHandler(c, w, r, RespHTML, "")
|
oopsHandler(c, w, r, RespHTML, "")
|
||||||
|
|
|
@ -65,6 +65,7 @@ var Config struct {
|
||||||
s3Region string
|
s3Region string
|
||||||
s3Bucket string
|
s3Bucket string
|
||||||
s3ForcePathStyle bool
|
s3ForcePathStyle bool
|
||||||
|
forceRandomFilename bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var Templates = make(map[string]*pongo2.Template)
|
var Templates = make(map[string]*pongo2.Template)
|
||||||
|
@ -268,6 +269,8 @@ func main() {
|
||||||
"S3 bucket to use for files and metadata")
|
"S3 bucket to use for files and metadata")
|
||||||
flag.BoolVar(&Config.s3ForcePathStyle, "s3-force-path-style", false,
|
flag.BoolVar(&Config.s3ForcePathStyle, "s3-force-path-style", false,
|
||||||
"Force path-style addressing for S3 (e.g. https://s3.amazonaws.com/linx/example.txt)")
|
"Force path-style addressing for S3 (e.g. https://s3.amazonaws.com/linx/example.txt)")
|
||||||
|
flag.BoolVar(&Config.forceRandomFilename, "force-random-filename", false,
|
||||||
|
"Force all uploads to use a random filename")
|
||||||
|
|
||||||
iniflags.Parse()
|
iniflags.Parse()
|
||||||
|
|
||||||
|
|
|
@ -763,6 +763,32 @@ func TestPutRandomizedUpload(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPutForceRandomUpload(t *testing.T) {
|
||||||
|
mux := setup()
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
oldFRF := Config.forceRandomFilename
|
||||||
|
Config.forceRandomFilename = true
|
||||||
|
filename := "randomizeme.file"
|
||||||
|
|
||||||
|
req, err := http.NewRequest("PUT", "/upload/"+filename, strings.NewReader("File content"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// while this should also work without this header, let's try to force
|
||||||
|
// the randomized filename off to be sure
|
||||||
|
req.Header.Set("Linx-Randomize", "no")
|
||||||
|
|
||||||
|
mux.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
if w.Body.String() == Config.siteURL+filename {
|
||||||
|
t.Fatal("Filename was not random")
|
||||||
|
}
|
||||||
|
|
||||||
|
Config.forceRandomFilename = oldFRF
|
||||||
|
}
|
||||||
|
|
||||||
func TestPutNoExtensionUpload(t *testing.T) {
|
func TestPutNoExtensionUpload(t *testing.T) {
|
||||||
mux := setup()
|
mux := setup()
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
@ -1013,6 +1039,55 @@ func TestPutAndOverwrite(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPutAndOverwriteForceRandom(t *testing.T) {
|
||||||
|
var myjson RespOkJSON
|
||||||
|
|
||||||
|
mux := setup()
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
oldFRF := Config.forceRandomFilename
|
||||||
|
Config.forceRandomFilename = true
|
||||||
|
|
||||||
|
req, err := http.NewRequest("PUT", "/upload", strings.NewReader("File content"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Accept", "application/json")
|
||||||
|
|
||||||
|
mux.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
err = json.Unmarshal([]byte(w.Body.String()), &myjson)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite it
|
||||||
|
w = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("PUT", "/upload/"+myjson.Filename, strings.NewReader("New file content"))
|
||||||
|
req.Header.Set("Linx-Delete-Key", myjson.Delete_Key)
|
||||||
|
mux.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
if w.Code != 200 {
|
||||||
|
t.Fatal("Status code was not 200, but " + strconv.Itoa(w.Code))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure it's the new file
|
||||||
|
w = httptest.NewRecorder()
|
||||||
|
req, err = http.NewRequest("GET", "/"+Config.selifPath+myjson.Filename, nil)
|
||||||
|
mux.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
if w.Code == 404 {
|
||||||
|
t.Fatal("Status code was 404")
|
||||||
|
}
|
||||||
|
|
||||||
|
if w.Body.String() != "New file content" {
|
||||||
|
t.Fatal("File did not contain 'New file content")
|
||||||
|
}
|
||||||
|
|
||||||
|
Config.forceRandomFilename = oldFRF
|
||||||
|
}
|
||||||
|
|
||||||
func TestPutAndSpecificDelete(t *testing.T) {
|
func TestPutAndSpecificDelete(t *testing.T) {
|
||||||
var myjson RespOkJSON
|
var myjson RespOkJSON
|
||||||
|
|
||||||
|
|
|
@ -1,51 +1,54 @@
|
||||||
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
|
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
|
||||||
|
|
||||||
Dropzone.options.dropzone = {
|
Dropzone.options.dropzone = {
|
||||||
init: function() {
|
init: function() {
|
||||||
var dzone = document.getElementById("dzone");
|
var dzone = document.getElementById("dzone");
|
||||||
dzone.style.display = "block";
|
dzone.style.display = "block";
|
||||||
},
|
},
|
||||||
addedfile: function(file) {
|
addedfile: function(file) {
|
||||||
var upload = document.createElement("div");
|
var upload = document.createElement("div");
|
||||||
upload.className = "upload";
|
upload.className = "upload";
|
||||||
|
|
||||||
var fileLabel = document.createElement("span");
|
var fileLabel = document.createElement("span");
|
||||||
fileLabel.innerHTML = file.name;
|
fileLabel.innerHTML = file.name;
|
||||||
file.fileLabel = fileLabel;
|
file.fileLabel = fileLabel;
|
||||||
upload.appendChild(fileLabel);
|
upload.appendChild(fileLabel);
|
||||||
|
|
||||||
var fileActions = document.createElement("div");
|
var fileActions = document.createElement("div");
|
||||||
fileActions.className = "right";
|
fileActions.className = "right";
|
||||||
file.fileActions = fileActions;
|
file.fileActions = fileActions;
|
||||||
upload.appendChild(fileActions);
|
upload.appendChild(fileActions);
|
||||||
|
|
||||||
var cancelAction = document.createElement("span");
|
var cancelAction = document.createElement("span");
|
||||||
cancelAction.className = "cancel";
|
cancelAction.className = "cancel";
|
||||||
cancelAction.innerHTML = "Cancel";
|
cancelAction.innerHTML = "Cancel";
|
||||||
cancelAction.addEventListener('click', function(ev) {
|
cancelAction.addEventListener('click', function(ev) {
|
||||||
this.removeFile(file);
|
this.removeFile(file);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
file.cancelActionElement = cancelAction;
|
file.cancelActionElement = cancelAction;
|
||||||
fileActions.appendChild(cancelAction);
|
fileActions.appendChild(cancelAction);
|
||||||
|
|
||||||
var progress = document.createElement("span");
|
var progress = document.createElement("span");
|
||||||
file.progressElement = progress;
|
file.progressElement = progress;
|
||||||
fileActions.appendChild(progress);
|
fileActions.appendChild(progress);
|
||||||
|
|
||||||
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.progressElement.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) {
|
||||||
formData.append("randomize", document.getElementById("randomize").checked);
|
var randomize = document.getElementById("randomize");
|
||||||
formData.append("expires", document.getElementById("expires").value);
|
if(randomize != null) {
|
||||||
},
|
formData.append("randomize", randomize.checked);
|
||||||
success: function(file, resp) {
|
}
|
||||||
|
formData.append("expires", document.getElementById("expires").value);
|
||||||
|
},
|
||||||
|
success: function(file, resp) {
|
||||||
file.fileActions.removeChild(file.progressElement);
|
file.fileActions.removeChild(file.progressElement);
|
||||||
|
|
||||||
var fileLabelLink = document.createElement("a");
|
var fileLabelLink = document.createElement("a");
|
||||||
|
@ -59,61 +62,61 @@ Dropzone.options.dropzone = {
|
||||||
var deleteAction = document.createElement("span");
|
var deleteAction = document.createElement("span");
|
||||||
deleteAction.innerHTML = "Delete";
|
deleteAction.innerHTML = "Delete";
|
||||||
deleteAction.className = "cancel";
|
deleteAction.className = "cancel";
|
||||||
deleteAction.addEventListener('click', function(ev) {
|
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("Linx-Delete-Key", resp.delete_key);
|
xhr.setRequestHeader("Linx-Delete-Key", resp.delete_key);
|
||||||
xhr.onreadystatechange = function(file) {
|
xhr.onreadystatechange = function(file) {
|
||||||
if (xhr.readyState == 4 && xhr.status === 200) {
|
if (xhr.readyState == 4 && xhr.status === 200) {
|
||||||
var text = document.createTextNode("Deleted ");
|
var text = document.createTextNode("Deleted ");
|
||||||
file.fileLabel.insertBefore(text, file.fileLabelLink);
|
file.fileLabel.insertBefore(text, file.fileLabelLink);
|
||||||
file.fileLabel.className = "deleted";
|
file.fileLabel.className = "deleted";
|
||||||
file.fileActions.removeChild(file.cancelActionElement);
|
file.fileActions.removeChild(file.cancelActionElement);
|
||||||
}
|
}
|
||||||
}.bind(this, file);
|
}.bind(this, file);
|
||||||
xhr.send();
|
xhr.send();
|
||||||
});
|
});
|
||||||
file.fileActions.removeChild(file.cancelActionElement);
|
file.fileActions.removeChild(file.cancelActionElement);
|
||||||
file.cancelActionElement = deleteAction;
|
file.cancelActionElement = deleteAction;
|
||||||
file.fileActions.appendChild(deleteAction);
|
file.fileActions.appendChild(deleteAction);
|
||||||
},
|
},
|
||||||
error: function(file, resp, xhrO) {
|
error: function(file, resp, xhrO) {
|
||||||
file.fileActions.removeChild(file.cancelActionElement);
|
file.fileActions.removeChild(file.cancelActionElement);
|
||||||
file.fileActions.removeChild(file.progressElement);
|
file.fileActions.removeChild(file.progressElement);
|
||||||
|
|
||||||
if (file.status === "canceled") {
|
if (file.status === "canceled") {
|
||||||
file.fileLabel.innerHTML = file.name + ": Canceled ";
|
file.fileLabel.innerHTML = file.name + ": Canceled ";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (resp.error) {
|
if (resp.error) {
|
||||||
file.fileLabel.innerHTML = file.name + ": " + resp.error;
|
file.fileLabel.innerHTML = file.name + ": " + resp.error;
|
||||||
}
|
}
|
||||||
else if (resp.includes("<html")) {
|
else if (resp.includes("<html")) {
|
||||||
file.fileLabel.innerHTML = file.name + ": Server Error";
|
file.fileLabel.innerHTML = file.name + ": Server Error";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
file.fileLabel.innerHTML = file.name + ": " + resp;
|
file.fileLabel.innerHTML = file.name + ": " + resp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file.fileLabel.className = "error";
|
file.fileLabel.className = "error";
|
||||||
},
|
},
|
||||||
|
|
||||||
maxFilesize: Math.round(parseInt(document.getElementById("dropzone").getAttribute("data-maxsize"), 10) / 1024 / 1024),
|
maxFilesize: Math.round(parseInt(document.getElementById("dropzone").getAttribute("data-maxsize"), 10) / 1024 / 1024),
|
||||||
previewsContainer: "#uploads",
|
previewsContainer: "#uploads",
|
||||||
parallelUploads: 5,
|
parallelUploads: 5,
|
||||||
headers: {"Accept": "application/json"},
|
headers: {"Accept": "application/json"},
|
||||||
dictDefaultMessage: "Click or Drop file(s) or Paste image",
|
dictDefaultMessage: "Click or Drop file(s) or Paste image",
|
||||||
dictFallbackMessage: ""
|
dictFallbackMessage: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
document.onpaste = function(event) {
|
document.onpaste = function(event) {
|
||||||
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
|
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
|
||||||
for (index in items) {
|
for (index in items) {
|
||||||
var item = items[index];
|
var item = items[index];
|
||||||
if (item.kind === "file") {
|
if (item.kind === "file") {
|
||||||
Dropzone.forElement("#dropzone").addFile(item.getAsFile());
|
Dropzone.forElement("#dropzone").addFile(item.getAsFile());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// @end-license
|
// @end-license
|
||||||
|
|
|
@ -25,8 +25,10 @@
|
||||||
|
|
||||||
<p><strong>Optional headers with the request</strong></p>
|
<p><strong>Optional headers with the request</strong></p>
|
||||||
|
|
||||||
|
{% if not forcerandom %}
|
||||||
<p>Randomize the filename<br/>
|
<p>Randomize the filename<br/>
|
||||||
<code>Linx-Randomize: yes</code></p>
|
<code>Linx-Randomize: yes</code></p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<p>Specify a custom deletion key<br/>
|
<p>Specify a custom deletion key<br/>
|
||||||
<code>Linx-Delete-Key: mysecret</code></p>
|
<code>Linx-Delete-Key: mysecret</code></p>
|
||||||
|
@ -56,30 +58,30 @@
|
||||||
|
|
||||||
{% if using_auth %}
|
{% if using_auth %}
|
||||||
<pre><code>$ curl -H "Linx-Api-Key: mysecretkey" -T myphoto.jpg {{ siteurl }}upload/
|
<pre><code>$ curl -H "Linx-Api-Key: mysecretkey" -T myphoto.jpg {{ siteurl }}upload/
|
||||||
{{ siteurl }}myphoto.jpg</code></pre>
|
{{ siteurl }}{% if not forcerandom %}myphoto.jpg{% else %}7z4h4ut.jpg{% endif %}</code></pre>
|
||||||
{% else %}
|
{% else %}
|
||||||
<pre><code>$ curl -T myphoto.jpg {{ siteurl }}upload/
|
<pre><code>$ curl -T myphoto.jpg {{ siteurl }}upload/
|
||||||
{{ siteurl }}myphoto.jpg</code></pre>
|
{{ siteurl }}{% if not forcerandom %}myphoto.jpg{% else %}wtq7pan.jpg{% endif %}</code></pre>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<p>Uploading myphoto.jpg with an expiry of 20 minutes</p>
|
<p>Uploading myphoto.jpg with an expiry of 20 minutes</p>
|
||||||
|
|
||||||
{% if using_auth %}
|
{% if using_auth %}
|
||||||
<pre><code>$ curl -H "Linx-Api-Key: mysecretkey" -H "Linx-Expiry: 1200" -T myphoto.jpg {{ siteurl }}upload/
|
<pre><code>$ curl -H "Linx-Api-Key: mysecretkey" -H "Linx-Expiry: 1200" -T myphoto.jpg {{ siteurl }}upload/
|
||||||
{{ siteurl }}myphoto.jpg</code></pre>
|
{{ siteurl }}{% if not forcerandom %}myphoto.jpg{% else %}jm295snf.jpg{% endif %}</code></pre>
|
||||||
{% else %}
|
{% else %}
|
||||||
<pre><code>$ curl -H "Linx-Expiry: 1200" -T myphoto.jpg {{ siteurl }}upload/
|
<pre><code>$ curl -H "Linx-Expiry: 1200" -T myphoto.jpg {{ siteurl }}upload/
|
||||||
{{ siteurl }}myphoto.jpg</code></pre>
|
{{ siteurl }}{% if not forcerandom %}myphoto.jpg{% else %}1doym9u2.jpg{% endif %}</code></pre>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<p>Uploading myphoto.jpg with a random filename and getting a json response:</p>
|
<p>Uploading myphoto.jpg with a random filename and getting a json response:</p>
|
||||||
|
|
||||||
{% if using_auth %}
|
{% if using_auth %}
|
||||||
<pre><code>$ curl -H "Linx-Api-Key: mysecretkey" -H "Accept: application/json" -H "Linx-Randomize: yes" -T myphoto.jpg {{ siteurl }}upload/
|
<pre><code>$ curl -H "Linx-Api-Key: mysecretkey" -H "Accept: application/json"{% if not forcerandom %} -H "Linx-Randomize: yes"{% endif %} -T myphoto.jpg {{ siteurl }}upload/
|
||||||
{"delete_key":"...","expiry":"0","filename":"f34h4iu.jpg","mimetype":"image/jpeg",
|
{"delete_key":"...","expiry":"0","filename":"f34h4iu.jpg","mimetype":"image/jpeg",
|
||||||
"sha256sum":"...","size":"...","url":"{{ siteurl }}f34h4iu.jpg"}</code></pre>
|
"sha256sum":"...","size":"...","url":"{{ siteurl }}f34h4iu.jpg"}</code></pre>
|
||||||
{% else %}
|
{% else %}
|
||||||
<pre><code>$ curl -H "Accept: application/json" -H "Linx-Randomize: yes" -T myphoto.jpg {{ siteurl }}upload/
|
<pre><code>$ curl -H "Accept: application/json"{% if not forcerandom %} -H "Linx-Randomize: yes"{% endif %} -T myphoto.jpg {{ siteurl }}upload/
|
||||||
{"delete_key":"...","expiry":"0","filename":"f34h4iu.jpg","mimetype":"image/jpeg",
|
{"delete_key":"...","expiry":"0","filename":"f34h4iu.jpg","mimetype":"image/jpeg",
|
||||||
"sha256sum":"...","size":"...","url":"{{ siteurl }}f34h4iu.jpg"}</code></pre>
|
"sha256sum":"...","size":"...","url":"{{ siteurl }}f34h4iu.jpg"}</code></pre>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="choices">
|
<div id="choices">
|
||||||
<label><input name="randomize" id="randomize" type="checkbox" checked /> Randomize filename</label>
|
<label>{% if not forcerandom %}<input name="randomize" id="randomize" type="checkbox" checked /> Randomize filename{% endif %}</label>
|
||||||
<div id="expiry">
|
<div id="expiry">
|
||||||
<label>File expiry:
|
<label>File expiry:
|
||||||
<select name="expires" id="expires">
|
<select name="expires" id="expires">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<div id="main" class="paste">
|
<div id="main" class="paste">
|
||||||
<div id="info">
|
<div id="info">
|
||||||
<div>
|
<div>
|
||||||
<span class="hint--top hint--bounce" data-hint="Leave empty for random filename"><input class="codebox" name='filename' id="filename" type='text' value="" placeholder="filename" /></span>.<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>
|
{% if not forcerandom %}<span class="hint--top hint--bounce" data-hint="Leave empty for random filename"><input class="codebox" name='filename' id="filename" type='text' value="" placeholder="filename" /></span>{% endif %}.<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>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="submit" value="Paste">
|
<input type="submit" value="Paste">
|
||||||
|
|
29
upload.go
29
upload.go
|
@ -222,11 +222,14 @@ func processUpload(upReq UploadRequest) (upload Upload, err error) {
|
||||||
return upload, FileTooLargeError
|
return upload, FileTooLargeError
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the appropriate filename, then write to disk
|
// Determine the appropriate filename
|
||||||
barename, extension := barePlusExt(upReq.filename)
|
barename, extension := barePlusExt(upReq.filename)
|
||||||
|
randomize := false
|
||||||
|
|
||||||
|
// Randomize the "barename" (filename without extension) if needed
|
||||||
if upReq.randomBarename || len(barename) == 0 {
|
if upReq.randomBarename || len(barename) == 0 {
|
||||||
barename = generateBarename()
|
barename = generateBarename()
|
||||||
|
randomize = true
|
||||||
}
|
}
|
||||||
|
|
||||||
var header []byte
|
var header []byte
|
||||||
|
@ -259,16 +262,32 @@ func processUpload(upReq UploadRequest) (upload Upload, err error) {
|
||||||
if merr == nil {
|
if merr == nil {
|
||||||
if upReq.deleteKey == metad.DeleteKey {
|
if upReq.deleteKey == metad.DeleteKey {
|
||||||
fileexists = false
|
fileexists = false
|
||||||
|
} else if Config.forceRandomFilename == true {
|
||||||
|
// the file exists
|
||||||
|
// the delete key doesn't match
|
||||||
|
// force random filenames is enabled
|
||||||
|
randomize = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if Config.forceRandomFilename == true {
|
||||||
|
// the file doesn't exist
|
||||||
|
// force random filenames is enabled
|
||||||
|
randomize = true
|
||||||
|
|
||||||
|
// set fileexists to true to generate a new barename
|
||||||
|
fileexists = true
|
||||||
}
|
}
|
||||||
|
|
||||||
for fileexists {
|
for fileexists {
|
||||||
counter, err := strconv.Atoi(string(barename[len(barename)-1]))
|
if randomize {
|
||||||
if err != nil {
|
barename = generateBarename()
|
||||||
barename = barename + "1"
|
|
||||||
} else {
|
} else {
|
||||||
barename = barename[:len(barename)-1] + strconv.Itoa(counter+1)
|
counter, err := strconv.Atoi(string(barename[len(barename)-1]))
|
||||||
|
if err != nil {
|
||||||
|
barename = barename + "1"
|
||||||
|
} else {
|
||||||
|
barename = barename[:len(barename)-1] + strconv.Itoa(counter+1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
upload.Filename = strings.Join([]string{barename, extension}, ".")
|
upload.Filename = strings.Join([]string{barename, extension}, ".")
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue