diff --git a/.gitignore b/.gitignore index 25b0cd6..c6750eb 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,5 @@ linx-genkey files/ meta/ binaries/ +custom_pages/ authfile diff --git a/README.md b/README.md index 84da53d..98bf585 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ allowhotlink = true - ```-remoteuploads``` -- (optionally) enable remote uploads (/upload?url=https://...) - ```-nologs``` -- (optionally) disable request logs in stdout - ```-force-random-filename``` -- (optionally) force the use of random filenames +- ```-custompagespath "custom_pages"``` -- (optionally) specify path to directory containing markdown pages (must end in .md) that will be added to the site navigation (this can be useful for providing contact/support information and so on). For example, custom_pages/My_Page.md will become My Page in the site navigation #### Require API Keys for uploads - ```-authfile path/to/authfile``` -- (optionally) require authorization for upload/delete by providing a newline-separated file of scrypted auth keys diff --git a/custom_pages.go b/custom_pages.go new file mode 100644 index 0000000..105a04a --- /dev/null +++ b/custom_pages.go @@ -0,0 +1,40 @@ +package main + +import ( + "io/ioutil" + "log" + "path" + "strings" + + "github.com/microcosm-cc/bluemonday" + "github.com/russross/blackfriday" +) + +func initializeCustomPages(customPagesDir string) { + files, err := ioutil.ReadDir(customPagesDir) + if err != nil { + log.Fatal("Error reading the custom pages directory: ", err) + } + + for _, file := range files { + fileName := file.Name() + + if len(fileName) <= 3 { + continue + } + + if strings.EqualFold(string(fileName[len(fileName)-3:len(fileName)]), ".md") { + contents, err := ioutil.ReadFile(path.Join(customPagesDir, fileName)) + if err != nil { + log.Fatalf("Error reading file %s", fileName) + } + + unsafe := blackfriday.MarkdownCommon(contents) + html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) + + fileName := fileName[0 : len(fileName)-3] + customPages[fileName] = string(html) + customPagesNames[fileName] = strings.ReplaceAll(fileName, "_", " ") + } + } +} diff --git a/pages.go b/pages.go index 6fcc934..ae8de42 100644 --- a/pages.go +++ b/pages.go @@ -50,6 +50,21 @@ func apiDocHandler(c web.C, w http.ResponseWriter, r *http.Request) { } } +func makeCustomPageHandler(fileName string) func(c web.C, w http.ResponseWriter, r *http.Request) { + return func(c web.C, w http.ResponseWriter, r *http.Request) { + err := renderTemplate(Templates["custom_page.html"], pongo2.Context{ + "siteurl": getSiteURL(r), + "forcerandom": Config.forceRandomFilename, + "contents": customPages[fileName], + "filename": fileName, + "pagename": customPagesNames[fileName], + }, r, w) + if err != nil { + oopsHandler(c, w, r, RespHTML, "") + } + } +} + func notFoundHandler(c web.C, w http.ResponseWriter, r *http.Request) { w.WriteHeader(404) err := renderTemplate(Templates["404.html"], pongo2.Context{}, r, w) diff --git a/server.go b/server.go index 661c2ea..e1f0c0a 100644 --- a/server.go +++ b/server.go @@ -70,6 +70,7 @@ var Config struct { s3ForcePathStyle bool forceRandomFilename bool accessKeyCookieExpiry uint64 + customPagesDir string } var Templates = make(map[string]*pongo2.Template) @@ -80,6 +81,8 @@ var timeStartedStr string var remoteAuthKeys []string var metaStorageBackend backends.MetaStorageBackend var storageBackend backends.StorageBackend +var customPages = make(map[string]string) +var customPagesNames = make(map[string]string) func setup() *web.Mux { mux := web.New() @@ -227,6 +230,14 @@ func setup() *web.Mux { mux.Get(selifIndexRe, unauthorizedHandler) mux.Get(torrentRe, fileTorrentHandler) + if Config.customPagesDir != "" { + initializeCustomPages(Config.customPagesDir) + for fileName := range customPagesNames { + mux.Get(Config.sitePath+fileName, makeCustomPageHandler(fileName)) + mux.Get(Config.sitePath+fileName+"/", makeCustomPageHandler(fileName)) + } + } + mux.NotFound(notFoundHandler) return mux @@ -298,6 +309,8 @@ func main() { flag.BoolVar(&Config.forceRandomFilename, "force-random-filename", false, "Force all uploads to use a random filename") flag.Uint64Var(&Config.accessKeyCookieExpiry, "access-cookie-expiry", 0, "Expiration time for access key cookies in seconds (set 0 to use session cookies)") + flag.StringVar(&Config.customPagesDir, "custompagespath", "", + "path to directory containing .md files to render as custom pages") iniflags.Parse() diff --git a/static/images/404.jpg b/static/images/404.jpg index 16ed400..57bf16f 100644 Binary files a/static/images/404.jpg and b/static/images/404.jpg differ diff --git a/templates.go b/templates.go index ccd90c7..7d38b51 100644 --- a/templates.go +++ b/templates.go @@ -52,6 +52,7 @@ func populateTemplatesMap(tSet *pongo2.TemplateSet, tMap map[string]*pongo2.Temp "404.html", "oops.html", "access.html", + "custom_page.html", "display/audio.html", "display/image.html", @@ -85,6 +86,8 @@ func renderTemplate(tpl *pongo2.Template, context pongo2.Context, r *http.Reques context["sitepath"] = Config.sitePath context["selifpath"] = Config.selifPath + context["custom_pages_names"] = customPagesNames + var a string if Config.authFile == "" { a = "none" diff --git a/templates/404.html b/templates/404.html index 3b3d64e..bfdf439 100644 --- a/templates/404.html +++ b/templates/404.html @@ -1,7 +1,9 @@ {% extends "base.html" %} +{% block title %}{{sitename}} - 404 Not Found{% endblock %} + {% block content %}
-{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/templates/API.html b/templates/API.html index 11d9ab1..d58e398 100644 --- a/templates/API.html +++ b/templates/API.html @@ -1,59 +1,64 @@ {% extends "base.html" %} +{% block title %}{{sitename}} - API{% endblock %} + {% block head %} {% endblock %} {% block content %}
-
+

API

Client

-

To simplify uploading and deleting files, you can use linx-client, which uses this API.

+

To simplify uploading and deleting files, you can use linx-client, which uses this API.

{% if auth != "none" %}

Keys

-

This instance uses API Keys, therefore you will need to provide a key for uploading and deleting files.
To do so, add the Linx-Api-Key header with your key.

+

This instance uses API Keys, therefore you will need to provide a key for uploading and deleting + files.
To do so, add the Linx-Api-Key header with your key.

{% endif %}

Uploading a file

-

To upload a file, make a PUT request to {{ siteurl }}upload/ and you will get the url of your upload back.

+

To upload a file, make a PUT request to {{ siteurl }}upload/ and you will get the url of + your upload back.

Optional headers with the request

-{% if not forcerandom %} -

Randomize the filename
- Linx-Randomize: yes

-{% endif %} + {% if not forcerandom %} +

Randomize the filename
+ Linx-Randomize: yes

+ {% endif %} -

Specify a custom deletion key
- Linx-Delete-Key: mysecret

+

Specify a custom deletion key
+ Linx-Delete-Key: mysecret

-

Protect file with password
- Linx-Access-Key: mysecret

+

Protect file with password
+ Linx-Access-Key: mysecret

-

Specify an expiration time (in seconds)
- Linx-Expiry: 60

+

Specify an expiration time (in seconds)
+ Linx-Expiry: 60

-

Get a json response
- Accept: application/json

+

Get a json response
+ Accept: application/json

The json response will then contain:

-

“url”: the publicly available upload url
- “direct_url”: the url to access the file directly
- “filename”: the (optionally generated) filename
- “delete_key”: the (optionally generated) deletion key,
- “access_key”: the (optionally supplied) access key,
- “expiry”: the unix timestamp at which the file will expire (0 if never)
- “size”: the size in bytes of the file
- “mimetype”: the guessed mimetype of the file
- “sha256sum”: the sha256sum of the file,

+

“url”: the publicly available upload url
+ “direct_url”: the url to access the file directly
+ “filename”: the (optionally generated) filename
+ “delete_key”: the (optionally generated) deletion key,
+ “access_key”: the (optionally supplied) access key,
+ “expiry”: the unix timestamp at which the file will expire (0 if never)
+ “size”: the size in bytes of the file
+ “mimetype”: the guessed mimetype of the file
+ “sha256sum”: the sha256sum of the file,

Examples

@@ -92,7 +97,8 @@

Overwriting a file

-

To overwrite a file you uploaded, simply provide the Linx-Delete-Key header with the original file's deletion key.

+

To overwrite a file you uploaded, simply provide the Linx-Delete-Key header with the + original file's deletion key.

Example

@@ -108,7 +114,8 @@

Deleting a file

-

To delete a file you uploaded, make a DELETE request to {{ siteurl }}yourfile.ext with the delete key set as the Linx-Delete-Key header.

+

To delete a file you uploaded, make a DELETE request to {{ siteurl }}yourfile.ext with the + delete key set as the Linx-Delete-Key header.

Example

@@ -124,16 +131,17 @@ DELETED

Information about a file

-

To retrieve information about a file, make a GET request the public url with Accept: application/json headers and you will receive a json response containing:

+

To retrieve information about a file, make a GET request the public url with + Accept: application/json headers and you will receive a json response containing:

-

“url”: the publicly available upload url
- “direct_url”: the url to access the file directly
- “filename”: the (optionally generated) filename
- “expiry”: the unix timestamp at which the file will expire (0 if never)
- “size”: the size in bytes of the file
- “mimetype”: the guessed mimetype of the file
- “sha256sum”: the sha256sum of the file,

+

“url”: the publicly available upload url
+ “direct_url”: the url to access the file directly
+ “filename”: the (optionally generated) filename
+ “expiry”: the unix timestamp at which the file will expire (0 if never)
+ “size”: the size in bytes of the file
+ “mimetype”: the guessed mimetype of the file
+ “sha256sum”: the sha256sum of the file,

Example

@@ -141,6 +149,6 @@ DELETED
$ curl -H "Accept: application/json" {{ siteurl }}myphoto.jpg
 {"expiry":"0","filename":"myphoto.jpg","mimetype":"image/jpeg","sha256sum":"...","size":"..."}
-
+
-{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/templates/access.html b/templates/access.html index c61cf51..908ed06 100644 --- a/templates/access.html +++ b/templates/access.html @@ -1,5 +1,7 @@ {% extends "base.html" %} +{% block title %}{{sitename}} - Password protected file{% endblock %} + {% block content %}
@@ -9,4 +11,4 @@

-{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index cda6746..86c5a29 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,5 +1,6 @@ + {% block title %}{{ sitename }}{% endblock %} @@ -16,12 +17,15 @@ {% block content %}{% endblock %} @@ -33,4 +37,5 @@ - + + \ No newline at end of file diff --git a/templates/custom_page.html b/templates/custom_page.html new file mode 100644 index 0000000..ac00341 --- /dev/null +++ b/templates/custom_page.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} + +{% block title %}{{sitename}} - {{ pagename }}{% endblock %} + +{% block head %} + +{% endblock %} + +{% block content %} +
+
+
+

{{ pagename }}

+ + {{ contents|safe }} +
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/display/base.html b/templates/display/base.html index 935979f..d60f4d8 100644 --- a/templates/display/base.html +++ b/templates/display/base.html @@ -1,36 +1,36 @@ {% extends "../base.html" %} -{% block title %}{{ filename }}{% endblock %} +{% block title %}{{sitename}} - {{ filename }}{% endblock %} {% block bodymore %}{% endblock %} {% block content %} -
-
- {{ filename }} -
- -
- {% if expiry %} - file expires in {{ expiry }} | - {% endif %} - {% block infomore %}{% endblock %} - {{ size }} | - torrent | - get -
- - {% block infoleft %}{% endblock %} +
+
+ {{ filename }}
-
- -
- {% block main %}{% endblock %} -
- +
+ {% if expiry %} + file expires in {{ expiry }} | + {% endif %} + {% block infomore %}{% endblock %} + {{ size }} | + torrent | + get
- -{% endblock %} + {% block infoleft %}{% endblock %} +
+ +
+ +
+ {% block main %}{% endblock %} +
+ +
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/paste.html b/templates/paste.html index eead748..84335d1 100644 --- a/templates/paste.html +++ b/templates/paste.html @@ -1,33 +1,40 @@ {% extends "base.html" %} +{% block title %}{{sitename}} - Paste{% endblock %} + {% block content %} -
-
-
-
- {% if not forcerandom %}{% endif %}. -
-
- - - - - - -
+ +
+
+
+ {% if not forcerandom %}{% endif %}.
+
+ + + -
- + +
- + +
+ +
+
+ -{% endblock %} +{% endblock %} \ No newline at end of file