noirscape 5 months ago
parent
commit
10cf29ca24
4 changed files with 62 additions and 78 deletions
  1. +1
    -0
      .gitignore
  2. +1
    -4
      README.md
  3. +53
    -71
      main.py
  4. +7
    -3
      templates/index.html

+ 1
- 0
.gitignore View File

@@ -5,3 +5,4 @@ elimage.db
__pycache__/
config.py
venv
templates/index-site.html

+ 1
- 4
README.md View File

@@ -29,7 +29,4 @@ Requirement
* Python 3.5+
* The `file` command
* [tornado](https://github.com/facebook/tornado) 3.2+

TODO
====
* record the original image filename
* The `qrencode` command if you want support for QR-code output

+ 53
- 71
main.py View File

@@ -9,13 +9,13 @@ import mimetypes
import subprocess
from functools import lru_cache
from hmac import compare_digest
from pathlib import Path

import tornado.web
import tornado.template
import tornado.gen
import tornado.process

from config import *
import config
from models import model

SCRIPT_PATH = 'elimage'
@@ -39,6 +39,10 @@ def guess_mime_using_file(path):
encoding = None
return mime, encoding

def qrencode(s):
return subprocess.check_output(
['qrencode', '-t', 'UTF8', s]).decode()

mimetypes.guess_type = guess_mime_using_file

def guess_extension(ftype):
@@ -51,34 +55,44 @@ def guess_extension(ftype):
ext = '.jpg'
return ext

@tornado.gen.coroutine
def convert_webp(webp, png):
cmd = ['dwebp', webp, '-o', png]
# cmd = ['convert', '-interlace', 'PNG', webp, png]
logging.info('convert webp to png: %s', webp)
p = tornado.process.Subprocess(cmd, stderr=subprocess.DEVNULL)
yield p.wait_for_exit()
def get_url_prefix(request):
if HTTPS:
return "https" + "://" + request.host + request.uri
else:
return "http" + "://" + request.host + request.uri

class IndexHandler(tornado.web.RequestHandler):
index_template = None
def get(self):
# self.render() would compress whitespace after it meets '{{' even in <pre>
if self.index_template is None:
template_path = Path(self.settings['template_path'])
try:
file_name = os.path.join(self.settings['template_path'], 'index.html')
with open(file_name, 'r') as index_file:
text = index_file.read()
file_name = template_path / 'index-site.html'
try:
with open(file_name) as index_file:
text = index_file.read()
except FileNotFoundError:
file_name = template_path / 'index.html'
with open(file_name) as index_file:
text = index_file.read()

self.__class__.index_template = tornado.template.Template(
text, compress_whitespace=False)
except IOError:
logging.exception('failed to open the file: %s', file_name)
raise tornado.web.HTTPError(404, 'index.html is missing')
else:
self.index_template = tornado.template.Template(
text, compress_whitespace=False)
content = self.index_template.generate(
url=self.request.full_url(),
password_required=bool(self.settings['password'])
)
self.write(content)

url_prefix = get_url_prefix(self.request)

if '?' in url_prefix:
url_prefix = url_prefix.split('?', 1)[0]

content = self.index_template.generate(
url=url_prefix,
password_required=bool(self.settings['password'])
)
self.write(content)

def post(self):
# Check the user has been blocked or not
@@ -102,6 +116,11 @@ class IndexHandler(tornado.web.RequestHandler):
raise tornado.web.HTTPError(400, 'upload your image please')

ret = OrderedDict()
url_prefix = get_url_prefix(self.request)
if '?' in url_prefix:
url_prefix = url_prefix.split('?', 1)[0]
url_prefix = url_prefix.rstrip('/')

for filelist in files.values():
for file in filelist:
m = hashlib.sha1()
@@ -130,19 +149,19 @@ class IndexHandler(tornado.web.RequestHandler):
ext = guess_extension(ftype)
if ext:
f += ext
if HTTPS:
ret[file['filename']] = '%s/%s/%s' % (
("https" + "://" + self.request.host +self.request.uri).rstrip('/'), d, f)
else:
ret[file['filename']] = '%s/%s/%s' % (
("http" + "://" + self.request.host +self.request.uri).rstrip('/'), d, f)
ret[file['filename']] = '%s/%s/%s' % (url_prefix, d, f)

output_qr = self.get_argument('qr', None) is not None
if len(ret) > 1:
for item in ret.items():
self.write('%s: %s\n' % item)
if output_qr:
self.write('%s\n' % qrencode(item[1]))
elif ret:
img_url = tuple(ret.values())[0]
self.write("%s\n" % img_url)
if output_qr:
self.write('%s\n' % qrencode(img_url))
logging.info('%s posted: %s', self.request.remote_ip, ret)

class ToolHandler(tornado.web.RequestHandler):
@@ -164,43 +183,6 @@ class HashHandler(tornado.web.RequestHandler):
else:
self.redirect('/%s/%s%s' % (h[:2], h[2:], ext), permanent=True)

class MyStaticFileHandler(tornado.web.StaticFileHandler):
'''dirty hack for webp images'''

@tornado.gen.coroutine
def head(self, path, ext):
yield self.get(path, ext, include_body=False)

@tornado.gen.coroutine
def get(self, path, ext=None, *, include_body=True):
self.path = self.parse_url_path(path)
absolute_path = self.get_absolute_path(self.root, self.path)
self.absolute_path = self.validate_absolute_path(self.root, absolute_path)
if self.absolute_path is None:
return

content_type = self.get_content_type()
headers = self.request.headers
if self.absolute_path.endswith('.png') or self.request.method != 'GET' \
or content_type != 'image/webp':
yield super().get(path, include_body=include_body)
return

# webp
self.set_header('Vary', 'User-Agent, Accept')
if ('image/webp' in headers.get('Accept', '').lower() \
or 'Gecko' not in headers.get('User-Agent', '') \
) and ext != '.png':
yield super().get(path, include_body=include_body)
return

png_path = self.absolute_path + '.png'
if not os.path.exists(png_path):
yield convert_webp(self.absolute_path, png_path)

path += '.png'
yield super().get(path, include_body=include_body)

def main():
import tornado.httpserver
from tornado.options import define, options
@@ -209,12 +191,12 @@ def main():
import asyncio
AsyncIOMainLoop().install()

define("port", default=DEFAULT_PORT, help="run on the given port", type=int)
define("port", default=config.DEFAULT_PORT, help="run on the given port", type=int)
define("address", default='', help="run on the given address", type=str)
define("datadir", default=DEFAULT_DATA_DIR, help="the directory to put uploaded data", type=str)
define("datadir", default=config.DEFAULT_DATA_DIR, help="the directory to put uploaded data", type=str)
define("fork", default=False, help="fork after startup", type=bool)
define("cloudflare", default=CLOUDFLARE, help="check for Cloudflare IPs", type=bool)
define("password", default=UPLOAD_PASSWORD, help="optional password", type=str)
define("cloudflare", default=config.CLOUDFLARE, help="check for Cloudflare IPs", type=bool)
define("password", default=config.UPLOAD_PASSWORD, help="optional password", type=str)

tornado.options.parse_command_line()
if options.fork:
@@ -230,19 +212,19 @@ def main():
application = tornado.web.Application([
(r"/", IndexHandler),
(r"/" + SCRIPT_PATH, ToolHandler),
(r"/([a-fA-F0-9]{2}/[a-fA-F0-9]{38})(\.\w*)?", MyStaticFileHandler, {
(r"/([a-fA-F0-9]{2}/[a-fA-F0-9]{38})(?:\.\w*)?", tornado.web.StaticFileHandler, {
'path': options.datadir,
}),
(r"/([a-fA-F0-9/]+(?:\.\w*)?)", HashHandler),
],
datadir=options.datadir,
debug=DEBUG,
debug=config.DEBUG,
template_path=os.path.join(os.path.dirname(__file__), "templates"),
password=UPLOAD_PASSWORD,
password=config.UPLOAD_PASSWORD,
)
http_server = tornado.httpserver.HTTPServer(
application,
xheaders=XHEADERS,
xheaders=config.XHEADERS,
)
http_server.listen(options.port, address=options.address)



+ 7
- 3
templates/index.html View File

@@ -1,6 +1,5 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<link rel="icon" href="data:,">
<title>elimage: CLI image pastebin</title>
<pre>
elimage(1) ELIMAGE elimage(1)
@@ -19,12 +18,17 @@ DESCRIPTION
Paste image files with command line. You can give <u>-F</u> more times to paste
more images.

You can also add a <u>?qr</u> parameter to receive a QR code together with your
image URLs like this:

curl -F 'name=@/path/to/image' '{{ url }}?qr'

EXAMPLES
<span style="color:#ffc000" >$</span> curl -F 'name=@screenshot.png' {{ url }}
{% if url.find('vim-cn.com') != -1 or url.find('edisonnotes.com') != -1 %}<a href="{{ url }}97/2d8490849c8fab885218b478cc715ab0f3f4a9">{{ url }}97/2d8490849c8fab885218b478cc715ab0f3f4a9</a>{% else %}{{ url }}97/2d8490849c8fab885218b478cc715ab0f3f4a9{% end %}

URLS
{% if url.find('vim-cn.com') != -1 %}<a href="https://cfp.vim-cn.com/">https://cfp.vim-cn.com/</a>{% else %}<a href="http://paste.edisonnotes.com/">http://paste.edisonnotes.com/</a>{% end %}
<a href="https://cfp.vim-cn.com/">https://cfp.vim-cn.com/</a>
A CLI code pastebin

<a href="https://github.com/Vim-cn/elimage">https://github.com/Vim-cn/elimage</a>
@@ -35,7 +39,7 @@ URLS
TOOLS
<a href="elimage">elimage</a>: script to quickly paste your images

22 Feb 2018 elimage(1)
09 Feb 2019 elimage(1)
</pre>
<script>document.onpaste=function(a){var b=a.clipboardData;if(b.files.length>0){document.getElementsByName('image')[0].files=b.files;document.getElementsByTagName('form')[0].submit()}};</script>
<!-- vim: set fdm=marker et sw=4 syntax=html.tornadotmpl: -->

Loading…
Cancel
Save