Compare commits
4 Commits
747f1305ed
...
e41e0888fa
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e41e0888fa | ||
![]() |
d2144c7f5e | ||
![]() |
90c72c4cf9 | ||
![]() |
85a16d2e0d |
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*~
|
||||||
|
*.fasl
|
||||||
|
bin/*
|
91
main.lisp
Normal file
91
main.lisp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
(ql:quickload "hunchentoot")
|
||||||
|
(ql:quickload "easy-routes")
|
||||||
|
(ql:quickload "djula")
|
||||||
|
(ql:quickload "frugal-uuid")
|
||||||
|
|
||||||
|
(setf *default-pathname-defaults* (uiop:getcwd))
|
||||||
|
|
||||||
|
;;;; if you're gonna run a public instance, change to the url other people
|
||||||
|
;;;; will use to connect!
|
||||||
|
(defvar *server-external-address*
|
||||||
|
"http://localhost:8080/"
|
||||||
|
;;"https://paste.emin.software/"
|
||||||
|
)
|
||||||
|
(defvar *server* nil)
|
||||||
|
|
||||||
|
;; we probably don't actually need a template for the root,
|
||||||
|
;; it's more or less static anyhow.
|
||||||
|
;; i guess retrieving a paste is the only place that actually needs
|
||||||
|
;; the dynamic templating thingy
|
||||||
|
|
||||||
|
(defparameter *root-template*
|
||||||
|
(uiop:read-file-string "root.html"))
|
||||||
|
|
||||||
|
(defparameter *paste-template*
|
||||||
|
(uiop:read-file-string "paste.html"))
|
||||||
|
|
||||||
|
;; google code
|
||||||
|
;; holy hell, actual business logic
|
||||||
|
|
||||||
|
(defun get-paste-contents (id)
|
||||||
|
"read file lmao. also do some checks. we don't want LFI"
|
||||||
|
(let ((path (probe-file (concatenate 'string "bin/" id))))
|
||||||
|
(if (and path
|
||||||
|
(not (search "." id))
|
||||||
|
(not (search "/" id)))
|
||||||
|
(uiop:read-file-string path)
|
||||||
|
nil)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(defun render-root ()
|
||||||
|
(djula:render-template*
|
||||||
|
(djula:compile-string *root-template*)
|
||||||
|
nil))
|
||||||
|
(defun render-paste (id)
|
||||||
|
(djula:render-template*
|
||||||
|
(djula:compile-string *paste-template*)
|
||||||
|
nil
|
||||||
|
:contents (or (get-paste-contents id) "err: paste not found")
|
||||||
|
:link-home *server-external-address*
|
||||||
|
:link-bin (concatenate 'string *server-external-address* "bin/" id)
|
||||||
|
:link-raw (concatenate 'string *server-external-address* "raw/" id)))
|
||||||
|
|
||||||
|
(defun new-paste-file ()
|
||||||
|
(let ((id (fuuid:to-string (fuuid:make-v1))))
|
||||||
|
(if (get-paste-contents id)
|
||||||
|
(new-paste-file)
|
||||||
|
id)))
|
||||||
|
|
||||||
|
(defun create-new-paste (contents)
|
||||||
|
"Returns the url to the new paste"
|
||||||
|
(let ((path (new-paste-file)))
|
||||||
|
(with-open-file (s (concatenate 'string "bin/" path) :direction :output)
|
||||||
|
(princ contents s))
|
||||||
|
path))
|
||||||
|
|
||||||
|
|
||||||
|
(easy-routes:defroute root ("/" :method :get) ()
|
||||||
|
(render-root))
|
||||||
|
|
||||||
|
(easy-routes:defroute paste ("/bin/:n") ()
|
||||||
|
(render-paste n))
|
||||||
|
|
||||||
|
(easy-routes:defroute raw ("/raw/:n") ()
|
||||||
|
(get-paste-contents n))
|
||||||
|
|
||||||
|
;; todo: handle new pastes TODO: doesn't work, fix.
|
||||||
|
(easy-routes:defroute new ("/new" :method :post) (content)
|
||||||
|
(let ((path (create-new-paste content)))
|
||||||
|
(format t "created new bin ~a~%" path)
|
||||||
|
(hunchentoot:redirect (concatenate 'string "/bin/" path))))
|
||||||
|
|
||||||
|
|
||||||
|
(defun start-server (&key (port 8080))
|
||||||
|
(format t "Starting server on port ~a~%" port)
|
||||||
|
(force-output)
|
||||||
|
(setf *server* (make-instance 'easy-routes:easy-routes-acceptor :port port))
|
||||||
|
(hunchentoot:start *server*))
|
||||||
|
(defun stop-server ()
|
||||||
|
(hunchentoot:stop *server*))
|
49
paste.html
Normal file
49
paste.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title> bin </title>
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
background-color: #4E5A52;
|
||||||
|
color: #FFFDD0;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
margin: 0;
|
||||||
|
padding: 5px;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
border: 3px solid #FFFDD0;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
margin: auto;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
main a {
|
||||||
|
margin-left: 5%;
|
||||||
|
color: #FFFDD0;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<a href="{{link-home}}"> home </a>
|
||||||
|
<a href="{{link-bin}}"> bin </a>
|
||||||
|
<a href="{{link-raw}}"> raw </a>
|
||||||
|
<br />
|
||||||
|
</main>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<pre><code>{{ contents }}</code></pre>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
53
root.html
Normal file
53
root.html
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>lispy pasty thingy</title>
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
background-color: #4E5A52;
|
||||||
|
color: #FFFDD0;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
margin: 0;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
border: 3px solid #FFFDD0;
|
||||||
|
padding: 0px;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 80%;
|
||||||
|
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
form {
|
||||||
|
border: 3px solid #FFFDD0;
|
||||||
|
padding: 2px;
|
||||||
|
margin-top: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 80%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}*/
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p> This is a simple pastebin-like web app written in Common Lisp.
|
||||||
|
Simply type something into the box below, submit, and share the link
|
||||||
|
with your friends.
|
||||||
|
<br>
|
||||||
|
Pastes are anonymous, no authentication is needed.</p>
|
||||||
|
|
||||||
|
<form method="post" action="/new">
|
||||||
|
<textarea name="content" rows="7" cols="50"></textarea> <br />
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user