...
 
Commits (6)
#!/usr/bin/env python3
import subprocess, json, sys, os
import argparse
"""
Wrapper to create_gif.sh for indexalist.py
Outputs meta data with thumb_gif and thumb
"""
ap = argparse.ArgumentParser("")
ap.add_argument("command")
ap.add_argument("path")
args = ap.parse_args()
rc = subprocess.call([args.command, args.path])
if rc == 0:
basename = os.path.basename(args.path)
data = {}
data['thumb'] = ".thumbs/{0}.1.jpg".format(basename)
data['thumbgif'] = ".thumbs/{0}.gif".format(basename)
print (json.dumps(data, indent=2))
#!/bin/bash
vid=$1
pdir=`dirname "$1"`
base=`basename "$1"`
cd "$pdir"
mkdir -p .thumbs
ffmpeg -ss 0.5 -i "$base" -t 5 -vf "scale=150:-1, fps=1" -f image2 ".thumbs/${base}.%d.jpg";
convert -delay 20 -loop 0 ".thumbs/${base}.%d.jpg[1-5]" ".thumbs/${base}.gif";
#!/usr/bin/env python3
import subprocess, json, sys, os
import argparse
"""
Wrapper to create_gif.sh for indexalist.py
Outputs meta data with thumb_gif and thumb
"""
ap = argparse.ArgumentParser("")
ap.add_argument("command")
ap.add_argument("path")
args = ap.parse_args()
rc = subprocess.call([args.command, args.path])
if rc == 0:
basename = os.path.basename(args.path)
data = {}
data['thumb'] = ".thumbs/{0}.jpg".format(basename)
print (json.dumps(data, indent=2))
#!/bin/bash
src=$1
pdir=`dirname "$1"`
base=`basename "$1"`
cd "$pdir"
mkdir -p .thumbs
convert -background white -alpha remove -resize 150x "${base}[0]" ".thumbs/${base}.jpg"
#!/usr/bin/env python3
from __future__ import print_function
import subprocess, re, json
sizepat = re.compile(r"Video:.*?(\d\d+)x(\d\d+)") # hack: avoids 0x445 by requiring 2 or more nums
def extract_size (text):
m = sizepat.search(text)
if m:
return [int(x) for x in m.groups()]
return (None, None)
def extract_metadata (text):
ret = {}
for line in text.splitlines():
if ':' in line:
(name, value) = line.split(':', 1)
if not name.endswith("http") and (name.upper() == name):
ret[name.strip().lower()] = value.strip()
return ret
timecodepat = re.compile(r"Duration: (\d+):(\d+):(\d+)\.(\d+)")
def extract_duration (text):
m = timecodepat.search(text)
if m:
parts = m.groups()
return (int(parts[0])*3600) + (int(parts[1])*60) + int(parts[2]) + float("0."+parts[-1])
def get_info(url, data=None):
popen = subprocess.Popen(["ffmpeg", "-i", url], stderr=subprocess.PIPE)
o = popen.communicate()[1].decode("utf-8")
if data == None:
data = {}
dur = extract_duration(o)
if dur and dur >= 0.05:
data['duration'] = dur
size = extract_size(o)
if size and size[0] != None:
data['framesize'] = "{0}x{1}".format(*size)
data['width'] = size[0]
data['height'] = size[1]
data['metadata'] = extract_metadata(o)
return data
if __name__ == "__main__":
from argparse import ArgumentParser
ap = ArgumentParser("")
ap.add_argument('input')
ap.add_argument("--framerate", type=float, default=None)
ap.add_argument("--format", default=None, help="format string, ex {duration} for duration")
args = ap.parse_args()
data = get_info(args.input)
if args.framerate:
import math
data['frames'] = int(math.floor(data['duration'] * args.framerate)) - 1
if args.format:
f = re.sub(r"{(.+?)}", r"{0[\1]}", args.format)
print (f.format(data))
else:
print (json.dumps(data, indent=2))
{
"children": [
{
"name": "__pycache__"
},
{
"mtime": 1519989488.2939024,
"filesize": 548,
"sha1": "f258efa1154fd9514e7474b5d546e1222533ea8b",
"name": "create_gif.py",
"mimetype": "text/x-python"
},
{
"mtime": 1520003405.06143,
"filesize": 260,
"sha1": "5270a25e9910fae5ccb31354cfe4a6c3a46ed3ac",
"name": "create_gif.sh",
"mimetype": "text/x-shellscript"
},
{
"mtime": 1519989488.2939024,
"filesize": 488,
"sha1": "71e2bb54bd9210a80a0034e9c102dfec87d91ab2",
"name": "create_thumb.py",
"mimetype": "text/x-python"
},
{
"mtime": 1520008647.6012518,
"filesize": 176,
"sha1": "2f834054d6ac0a0779e42bc128a455e7ebf6e757",
"name": "create_thumb.sh",
"mimetype": "text/x-shellscript"
},
{
"mtime": 1519997603.0656269,
"filesize": 2027,
"sha1": "8c9a9e891fc980b7cba7b82dd724caaaaaf6f677",
"name": "ffmpeginfo.py",
"mimetype": "text/x-python"
},
{
"mtime": 1520257707.4407973,
"filesize": 2439,
"sha1": "9f16b244fcc9a1102a0a002ec6fd379091ea7a8a",
"name": "index.template.html",
"mimetype": "text/html"
},
{
"mtime": 1520008303.1332636,
"filesize": 127,
"sha1": "df3f56fef133796f40996a0a8ed157be0d211972",
"name": "index2.template.html",
"mimetype": "text/html"
},
{
"mtime": 1520009185.4292338,
"filesize": 9315,
"sha1": "d5cb9c2d80682c7b639d7ad6c19bcfbaf49e4b16",
"name": "indexalist.py",
"mimetype": "text/x-python"
},
{
"mtime": 1519993486.1777666,
"filesize": 2392,
"sha1": "7e8152f7e337e71eb3eb91aaed7bfb17a742ece2",
"name": "jinjafilters.py",
"mimetype": "text/x-python"
},
{
"mtime": 1520008002.049274,
"filesize": 3113,
"sha1": "344ce38f3fc4c67c7400a97fdb1fa514f0fb9609",
"name": "make_directory_index.py",
"mimetype": "text/x-python"
},
{
"mtime": 1520008016.6292734,
"filesize": 110,
"sha1": "3c2427482fe3070256f66c84f71687f5049d3197",
"name": "make_directory_index.sh",
"mimetype": "text/x-shellscript"
},
{
"mtime": 1520008020.0732732,
"filesize": 124,
"sha1": "97c3626945df78f50dbab3a9b6e0d2213fb466e9",
"name": "make_directory_index2.sh",
"mimetype": "text/x-shellscript"
},
{
"mtime": 1520009635.6252184,
"filesize": 715,
"sha1": "70ecc1998f8d4fa122d13547ce8bc08284e92865",
"name": "makefile",
"mimetype": "text/plain"
},
{
"mtime": 1519993721.3737586,
"filesize": 1108,
"sha1": "835f2b937f7a650d8d25f0783759b73882e20702",
"name": "multi.py",
"mimetype": "text/x-python"
},
{
"mtime": 1520009681.3732169,
"filesize": 364,
"sha1": "23d697d4ef122acb2243e118c0a2287fbfe45b46",
"name": "rebuild_all_indexes.py",
"mimetype": "text/x-python"
}
]
}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>{{path}}</title>
<script type="text/javascript" src="/lib/tablesorter/jquery-latest.js"></script>
<script type="text/javascript" src="/lib/tablesorter/jquery.tablesorter.js"></script>
<link rel="stylesheet" type="text/css" href="/lib/tablesorter/themes/pink/style.css" />
<link rel="stylesheet" type="text/css" href="/lib/index.css" />
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
document.domain = 'constantvzw.org';
</script>
<h1>{{path}}</h1>
<p class="description">{% if description %}<div class="description">{{description|multi|markdown}}</div>{% endif %}
<div class="edit"><a class="edit" href="/cgi-bin/aa/indexedit.cgi">edit</a></div>
</p>
{% block headerlinks %}{% if has_folders %}<p class="headerlinks"><a href="index2.html">+++</a></p>{% endif %}{% endblock %}
<table class="tablesorter">
<thead>
<tr>
<th>Name</th>
<th>Last modified</th>
<th>Size</th>
<th>Type</th>
<th>Duration</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href=".."><img src="/lib/icons/back.gif" /><br>Parent Directory</a></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
{% for c in children %}<tr>
<td class="name">
<div class="icon"><a href="{{c.url}}">{% if c.thumbgif %}<img src="{{c.thumbgif}}" border="0" />{% elif c.thumb %}<img src="{{c.thumb}}" />{% elif not c.filesize %}<img src="/lib/icons/inode-directory.png" border="0" />{% else %}&nbsp;{% endif %}</a></div>
<a href="{{c.url}}">{{c.name}}</a>
</td>
<td class="timestamp">{% if c.mtime %}{{c.mtime|datetimeformat}}{% else %}&mdash;{% endif %}</td>
<td class="size">{% if c.filesize %}{{c.filesize|humanize_bytes}}{% else %}&mdash;{% endif %}</td>
<td class="type">{{c.mimetype}}</td>
<td class="duration">{% if c.duration %}{{c.duration|timecode}}{% else %}&mdash;{% endif %}</td>
<td class="description">{% if c.description %}{{c.description|multi|markdown}}{% else %}&mdash;{% endif %}<a href="/cgi-bin/aa/indexedit.cgi?url={{c.url|urlencode}}">edit</a></td>
</tr>{% endfor %}
</tbody>
</table>
<script>
$(document).ready(function() { $("table").tablesorter(); });
</script>
</body>
</html>
{% extends "index.template.html" %}
{% block headerlinks%}<p class="headerlinks"><a href="index.html">---</a></p>{% endblock %}
\ No newline at end of file
......@@ -2,11 +2,26 @@
from __future__ import print_function
import os, stat, datetime, sys, hashlib, json, subprocess, magic
from fnmatch import fnmatch
# import ffmpeginfo
"""
todo: add --force (for use in a command pipeline when you want to redo something for all files ?!)
index:
indexalist.py . \
--exclude .thumbs \
--exclude index.html \
--update "video/*" ffmpeginfo.py \
--update "video/*" create_gif.py create_gif.sh \
--update "image/*" create_thumb.py create_thumb.sh \
--update "application/pdf" create_thumb.py create_thumb.sh \
--update "directory/*" make_directory_index.py
index-force:
indexalist.py . \
--exclude .thumbs \
--exclude index.html \
--force \
--update "directory/*" make_directory_index.py
"""
def githash(path, block_size=2**20):
......@@ -49,19 +64,21 @@ def file_changed (path, node):
def apply_hook (code, path, node, hook):
# print ("apply_hook", code, path, node, hook, file=sys.stderr)
if type(hook) == list:
for h in hook:
h(code, path, node)
elif hook != None:
hook(code, path, node)
def walk (path, entering=False, jsonpath="index.json", exclude=None, hook=None):
def walk (path, entering=False, jsonpath="index.json", exclude=None, hook=None, force=False, all=False):
"""
path should be a working/complete (relative) path
all paths stored in the json file are RELATIVE to their context -- ie filenames only
the idea is that fullpaths can be calculated by their context
"""
# print ("*", path, file=sys.stderr)
# Load this path's index.json (or start a new one)
node = node_for_path(path, jsonpath)
changed = False
......@@ -77,9 +94,14 @@ def walk (path, entering=False, jsonpath="index.json", exclude=None, hook=None):
### CHECK EXCLUDE LIST
xclude = False
# exclude dot files unless --all is specified
if not all and child.startswith("."):
xclude = True
# exclude the index.json file itself
if child == jsonpath:
xclude = True
elif exclude != None:
# Honor the --exclude options
for x in exclude:
if fnmatch(child, x):
xclude = True
......@@ -94,13 +116,13 @@ def walk (path, entering=False, jsonpath="index.json", exclude=None, hook=None):
del oldchildrenbykey[child]
if os.path.isfile(childpath):
if file_changed(childpath, node=oldchild):
if force or file_changed(childpath, node=oldchild):
print ("Mf", childpath)
apply_hook("Mf", childpath, oldchild, hook)
changed=True
else:
# SUBDIRECTORY... recurse
if walk(childpath, jsonpath=jsonpath, exclude=exclude):
if walk(childpath, jsonpath=jsonpath, exclude=exclude, hook=hook, force=force, all=all):
changed = True
else:
# idiomatic create to allow node to be "dict-like" objects
......@@ -112,7 +134,7 @@ def walk (path, entering=False, jsonpath="index.json", exclude=None, hook=None):
apply_hook("Nf", childpath, newnode, hook)
else:
# newnode['is_directory'] = True
walk(childpath, entering=True, jsonpath=jsonpath, exclude=exclude)
walk(childpath, entering=True, jsonpath=jsonpath, exclude=exclude, hook=hook, force=force, all=all)
print ("Nd", childpath)
# issue here ... the node is the parent node ... not the index.json within the directory itself
# (as might be expected) ... as it's already been saved
......@@ -165,11 +187,14 @@ def apply_hook_args (path, node, mimetype, hookargs):
for key, value in outdata.items():
node[key] = value
except ValueError:
print ("didn't find JSON in hook output", file=sys.stderr)
# print ("didn't find JSON in hook output", file=sys.stderr)
pass
def hook (code, path, node, **args):
if code[1] == "f":
# print ("HOOK", code, path, node, file=sys.stderr)
if code[0] == "D" and node and 'mimetype' in node:
mimetype = node['mimetype']
elif code[1] == "f" and os.path.isfile(path):
mimetype = magic.from_file(path, mime=True)
else:
mimetype = "directory/directory"
......@@ -192,8 +217,10 @@ if __name__ == "__main__":
ap = argparse.ArgumentParser("")
ap.add_argument("path", default=".", nargs="?", help="path of directory to index")
ap.add_argument("--json", default=".index.json", help="used as both input (if existing) and output")
ap.add_argument("--json", default="index.json", help="used as both input (if existing) and output")
ap.add_argument("--exclude", default=None, action="append", help="exclude files matching (may be a glob)")
ap.add_argument("--all", default=False, action="store_true", help="match all files (include hidden files)")
ap.add_argument("--force", default=None, action="store_true", help="behave as if all files have been updated (update all)")
# THE HOOKS
ap.add_argument("--create", nargs="+", action="append")
ap.add_argument("--update", nargs="+", action="append")
......@@ -209,5 +236,5 @@ if __name__ == "__main__":
delete=args.delete
)
change = walk(args.path, jsonpath=args.json, exclude=args.exclude, hook=argshook)
change = walk(args.path, jsonpath=args.json, exclude=args.exclude, hook=argshook, force=args.force, all=args.all)
from itertools import zip_longest
from urllib.parse import quote as urlquote
import time
from markdown import markdown as markdown_
def datetimeformat (t, format='%Y-%m-%d %H:%M:%S'):
return time.strftime(format, time.localtime(t))
def grouper(iterable, n, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(fillvalue=fillvalue, *args)
def humanize_bytes(bytesize, precision=2):
"""
Humanize byte size figures
"""
abbrevs = (
(1 << 50, 'PB'),
(1 << 40, 'TB'),
(1 << 30, 'GB'),
(1 << 20, 'MB'),
(1 << 10, 'kB'),
(1, 'bytes')
)
if bytesize == 1:
return '1 byte'
for factor, suffix in abbrevs:
if bytesize >= factor:
break
if factor == 1:
precision = 0
return '%.*f %s' % (precision, bytesize / float(factor), suffix)
import math
def timecode(rawsecs, fract=True, alwaysfract=True, fractdelim='.', alwayshours=True):
# returns a string in HH:MM:SS[.xxx] notation
# if fract is True, uses .xxx if either necessary (non-zero)
# OR alwaysfract is True
hours = math.floor(rawsecs / 3600)
rawsecs -= hours * 3600
mins = math.floor(rawsecs / 60)
rawsecs -= mins * 60
if fract:
secs = math.floor(rawsecs)
rawsecs -= secs
if (rawsecs > 0 or alwaysfract):
fract = "%.03f" % rawsecs
if hours or alwayshours:
return "%02d:%02d:%02d%s%s" % (hours, mins, secs, fractdelim, \
fract[2:])
else:
return "%02d:%02d%s%s" % (mins, secs, fractdelim, fract[2:])
else:
if hours or alwayshours:
return "%02d:%02d:%02d" % (hours, mins, secs)
else:
return "%02d:%02d" % (mins, secs)
else:
secs = round(rawsecs)
if hours or alwayshours:
return "%02d:%02d:%02d" % (hours, mins, secs)
else:
return "%02d:%02d" % (mins, secs)
def markdown (src):
return markdown_(src)
from multi import multi2markup
def multi (src):
return multi2markup(src)
all = {
'datetimeformat': datetimeformat,
'grouper': grouper,
'timecode': timecode,
'humanize_bytes': humanize_bytes,
'urlquote': urlquote,
'markdown': markdown,
'multi': multi
}
\ No newline at end of file
#!/usr/bin/env python3
import subprocess, json, sys, os
import argparse
from jinja2 import Template, DictLoader, Environment, FileSystemLoader
from urllib.parse import quote as urlquote
"""
Wrapper to create_gif.sh for indexalist.py
Outputs meta data with thumb_gif and thumb
"""
ap = argparse.ArgumentParser("")
ap.add_argument("path")
ap.add_argument("--jsonpath", default="index.json")
ap.add_argument("--templatepath", default=None)
ap.add_argument("--template", default="index.template.html")
ap.add_argument("--output", default="index.html")
ap.add_argument("--recursive", default=False, action="store_true")
args = ap.parse_args()
def get_index_json(path):
try:
with open(os.path.join(path, args.jsonpath)) as f:
return json.load(f)
except FileNotFoundError as e:
print ("FILENOTFOUND opening {0}".format(path), file=sys.stderr)
return {'children': []}
# print ("make_directory_index", args.path, file=sys.stderr)
# with open(os.path.join(args.path, args.jsonpath)) as f:
# data = json.load(f)
data = get_index_json(args.path)
def walk (n, all, path):
# set url of node
if 'children' in n:
for cn in n['children']:
if 'filesize' in cn:
# FILE
cn['url'] = n['url'] + urlquote(cn['name'])
if 'thumbgif' in cn:
cn['thumbgif'] = n['url'] + cn['thumbgif']
if 'thumb' in cn:
cn['thumb'] = n['url'] + cn['thumb']
all.append(cn)
else:
# FOLDER
# LOAD its index.json
cpath = os.path.join(path, cn['name'])
nn = get_index_json(cpath)
nn['name'] = cn['name']
nn['url'] = n['url'] + urlquote(cn['name'])+"/"
all.append(nn)
walk(nn, all, cpath)
# CHECK IF THERE ARE FOLDERS
has_folders = len([x for x in data['children'] if 'filesize' not in x]) > 0
data['has_folders'] = has_folders
if args.recursive:
# end result data['children'] as a FLAT list of ALL children... add URL
# how to visit all the children in depth first fashion...
flatnodes = []
data['url'] = ''
walk(data, flatnodes, args.path)
data['children'] = flatnodes
else:
# Add URLs
n = data
n['url'] = ''
for cn in n['children']:
if 'filesize' in cn:
# FILE
cn['url'] = n['url'] + urlquote(cn['name'])
else:
# FOLDER
cn['url'] = n['url'] + urlquote(cn['name'])+"/"
tpath = args.templatepath or os.path.split(os.path.realpath(__file__) )[0]
tname = args.template
# tpath, tname = os.path.split(os.path.expanduser(args.template))
env = Environment(loader=FileSystemLoader(tpath))
import jinjafilters
for name, fn in jinjafilters.all.items():
env.filters[name] = fn
template = env.get_template(tname)
data['path'] = os.path.basename(os.path.abspath(args.path))
# if type(data) == list:
# # print ("Detected list, adding as {0}".format(args.listkey), file=sys.stderr)
# data = {
# args.listkey: data
# }
outpath = os.path.join(args.path, args.output)
with open (outpath, "w") as f:
print (template.render(**data), file=f)
#!/bin/bash
make_directory_index.py --template index.template.html --output index.html "$1"
#!/bin/bash
make_directory_index.py --recursive --template index.template.html --output index2.html "$1"
from __future__ import print_function
import re
# from itertools import tee, zip
def pairwise(iterable):
"s -> (s0, s1), (s2, s3), (s4, s5), ..."
a = iter(iterable)
return zip(a, a)
# def processmulti (text):
# m = re.search(r"<multi>(.*)</multi>", text)
# if m:
# contents = m.group(1)
# ret = {}
# for lang, text in pairwise(re.split("\[(\w+)\]", contents)[1:]):
# # print (lang, text)
# ret[lang] = text
# if 'en' not in ret:
# ret['en'] = text
# if 'nl' not in ret:
# ret['nl'] = text
# if 'fr' not in ret:
# ret['fr'] = text
# return ret
# else:
# return {'en': text, 'fr': text, 'nl': text}
def multi2markup_sub (m):
contents = m.group(1)
ret = {}
langs = []
ret = u""
for lang, text in pairwise(re.split("\[(\w+)\]", contents)[1:]):
ret += "<span lang=\"{0}\">{1}</span>".format(lang, text)
return ret
def multi2markup (text):
return re.sub(r"<multi>([^<]*)</multi>", multi2markup_sub, text, flags=re.I)
\ No newline at end of file
#!/usr/bin/env python3
import argparse
import os
for (b, dd, ff) in os.walk("."):
for d in dd:
if d == ".thumbs":
continue
if d.startswith("."):
continue
dpath = os.path.join(b, d)
print ("make_directory_index.sh \"{0}\"".format(dpath))
print ("make_directory_index2.sh \"{0}\"".format(dpath))
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
python2
"""
from __future__ import print_function
import os, cgi, sys, json
import cgitb; cgitb.enable()
from jinja2 import Template, DictLoader, Environment, FileSystemLoader
from xml.sax.saxutils import escape as xmlescape
from urlparse import urljoin, urlparse
from urllib import quote as urlquote, unquote as urlunquote
# print ("Content-type: text/html;charset=utf-8")
# print ()
fs = cgi.FieldStorage()
referer = fs.getvalue("referer", "").decode("utf-8")
if not referer:
referer = os.environ.get("HTTP_REFERER", "").decode("utf-8")
method = os.environ.get("REQUEST_METHOD", "GET")
docroot = os.environ.get("DOCUMENT_ROOT", "/home/videos")
# URL IS UNICODE
url = fs.getvalue("url")
if url:
url = url.decode("utf-8")
url = urljoin(referer, url)
is_directory = False
else:
is_directory = True
url = referer
# PATH IN CONTRAST IS str/bytes/utf-8 encoded
p = urlparse(url.encode("utf-8"))
path = urlunquote(p.path.lstrip("/"))
path = os.path.join(docroot, path)
filename = os.path.basename(path)
# print (u"url {0}<br>path {1}<br>filename {2}".format(url, path.decode("utf-8"), filename.decode("utf-8")).encode("utf-8"))
if os.path.exists(path):
# print("path found {0}".format(path))
is_directory = False
if os.path.isfile(path):
base = os.path.dirname(path)
jsonpath = os.path.join(base, "index.json")
else:
is_directory = True
jsonpath = os.path.join(path, "index.json")
if os.path.exists(jsonpath):
with open(jsonpath) as f:
jsondata = json.load(f)
node = jsondata
for c in jsondata['children']:
if c['name'].encode("utf-8") == filename:
node = c
break
if node != None:
description = node.get("description", "")
tdata = {}
tdata['url'] = url
tdata['fullpath'] = path.decode("utf-8") # bytes to unicode
tdata['filename'] = os.path.basename(path.rstrip("/")).decode("utf-8")
tdata['description'] = description
tdata['json'] = json.dumps(node, indent=2)
tdata['method'] = method
tdata['referer'] = referer
if 'thumbgif' in node:
tdata['thumbgif'] = urljoin(referer, node['thumbgif'])
if 'thumb' in node:
tdata['thumb'] = urljoin(referer, node['thumb'])
if method == "POST":
submit = fs.getvalue("_submit")
if submit == "cancel":
print ("Location: {0}".format(referer))
print ()
sys.exit()
elif submit == "save":
description = fs.getvalue("description", "").decode("utf-8")
node['description'] = tdata['description'] = description
try:
# VERSION CONTRON ?!
with open(jsonpath, "w") as f:
json.dump(jsondata, f)
tdata['saved'] = True
tdata['message'] = "Saved"
# REDIRECT TO MAKE
print (u"Location: /cgi-bin/aa/make.cgi?url={0}&makefile=indexalist".format(urlquote(referer.encode("utf-8")).decode("utf-8")).encode("utf-8"))
print ()
sys.exit(0)
except IOError as e:
tdata['saved'] = False
tdata['message'] = str(e).decode("utf-8")
# HOW TO TRIGGER A REMAKE
tpath, tname = os.path.split("/usr/lib/cgi-bin/aa/indexedit.template.html")
env = Environment(loader=FileSystemLoader(tpath))
env.filters['xmlescape'] = xmlescape
env.filters['urlquote'] = urlquote
template = env.get_template(tname)
print ("Content-type: text/html;charset=utf-8")
print ()
print(template.render(**tdata).encode("utf-8"))
# print (json.dumps(data, indent=2))
else:
print ("no json<br>")
else:
print ("Content-type: text/html;charset=utf-8")
print ()
print(u"Path not found {0}".format(path).encode("utf-8"))
# print ("<p>docroot:{0}<br>npath: {1}</p>".format(docroot, npath).encode("utf-8"))
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>edit description</title>
<style type="text/css">
textarea {
float: left;
width: 100%;
height: 10em;
resize: vertical;
}
.editrow {
display: flex;
}
.editrow .icon {
flex: 0 1 auto;
}
.editrow .textarea {
flex: 1 1 auto;
}
pre.json {
display: none;
}
pre.json.visible {
display: block;
}
</style>
</head>
<body>
{% if message %}<b>{{message}}</b> {%if saved%}<a href="/cgi-bin/aa/make.cgi?url={{referer|urlquote}}&makefile=indexalist">back to index</a>{%endif%}</div>{% endif %}
<form method="post" action="">
<div class="header">Editing description for <a href="{{url}}">{{filename}}</a></div>
<div class="editrow">
<div class="icon">
<img src="{{thumbgif}}">
</div>
<div class="textarea">
<textarea autofocus name="description">{{description}}</textarea>
<div class="buttons">
<input type="submit" name="_submit" value="save" />
<input type="submit" name="_submit" value="cancel" />
<button onclick="document.querySelector('pre.json').classList.toggle('visible'); return false">JSON</button>
</div>
</div>
</div>
<div class="json">
<pre class="json">{{json}}</pre></div>
<input type="hidden" name="referer" value={{referer|xmlescape}} />
</form>
</body>
</html>
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from __future__ import print_function
import os, cgi, sys
import cgitb; cgitb.enable()
from urlparse import urljoin, urlparse
from urlparse import unquote as urlunquote
import subprocess
"""
make & serve in CGI form
parameters:
url : the URL in question, if partial, will attempt to resolve using HTTP_REFERER
makefile: one of a pre-set list of makefile (nb *not* a path, must appear in the MAKEFILES dict)
what it does:
calls make with the given makefile on the given path
"""
# print ("Content-type: text/html;charset=utf-8")
# print ()
fs = cgi.FieldStorage()
MAKE = "make"
INDEX = "index.html"
MAKEFILES = {
"indexalist": {
"makefile": "/var/www/makefile.indexes",
"cwd": "__filepath__"
}
}
makefile = fs.getvalue("makefile", "default")
referer = os.environ.get("HTTP_REFERER", "").decode("utf-8")
docroot = os.environ.get("DOCUMENT_ROOT", "/home/videos") # leave bytes
url = fs.getvalue("url", "").decode("utf-8") # URL IS UNICODE
url = urljoin(referer, url)
if not url:
print ("Content-type: text/html")
print ()
print ("missing url")
sys.exit(0)
parsed = urlparse(url.encode("utf-8"))
path = urlunquote(parsed.path.lstrip("/")) # PATH IN CONTRAST IS str/bytes/utf-8 encoded
path = os.path.join(docroot, path)
if os.path.isdir(path) and INDEX:
path = os.path.join(path, INDEX)
pargs = [MAKE]
makefile = MAKEFILES[makefile]
pargs.append("-f")
pargs.append(makefile['makefile'])
cwd = makefile['cwd']
if cwd == "__filepath__":
cwd, makepath = os.path.split(path)
else:
makepath = os.path.relpath(path, cwd)
pargs.append(makepath)
# AAAARG, address the problem with python3 scripts running with APACHE cgi env incorrectly set for non utf-8
# SEE: https://stackoverflow.com/questions/9322410/set-encoding-in-python-3-cgi-scripts#19574801
env = dict(os.environ)
env['LANG'] = "en_US.UTF-8"
success = False
try:
output = subprocess.check_output(pargs, stderr=subprocess.STDOUT, cwd=cwd, env=env)
# print ("Content-type: text/html")
# print ()
# print (u"cwd: {0}".format(cwd.decode("utf-8").encode("utf-8")))
# print (u"<div>make {0}</div>".format(makepath.decode("utf-8")).encode("utf-8"))
# print ("""<div>success!</div><pre class="results">{0}</pre>""".format(output))
# print (u"""<a href="{0}">{0}</a>""".format(url).encode("utf-8"))
print ("Location: {0}".format(url))
print ()
except subprocess.CalledProcessError as e:
print ("Content-type: text/html")
print ()
print (u"<div>make {0}</div>".format(makepath.decode("utf-8")).encode("utf-8"))
print ("""<div>failed ({0})</div><pre class="results">{1}</pre>""".format(e.returncode, e.output))
#!/usr/bin/env python3
import subprocess, json, sys, os
import argparse
from jinja2 import Template, DictLoader, Environment, FileSystemLoader
"""
Wrapper to create_gif.sh for indexalist.py
Outputs meta data with thumb_gif and thumb
"""
ap = argparse.ArgumentParser("")
ap.add_argument("path")
ap.add_argument("--jsonpath", default=".index.json")
ap.add_argument("--template", default="~/templates/index.html")
ap.add_argument("--output", default="index.html")
args = ap.parse_args()
print ("DIRECTORY INDEX", args.path, file=sys.stderr)
with open(os.path.join(args.path, args.jsonpath)) as f:
data = json.load(f)
tpath, tname = os.path.split(os.path.expanduser(args.template))
env = Environment(loader=FileSystemLoader(tpath))
import jinjafilters
for name, fn in jinjafilters.all.items():
env.filters[name] = fn
template = env.get_template(tname)
data['path'] = os.path.basename(os.path.abspath(args.path))
# if type(data) == list:
# # print ("Detected list, adding as {0}".format(args.listkey), file=sys.stderr)
# data = {
# args.listkey: data
# }
outpath = os.path.join(args.path, args.output)
with open (outpath, "w") as f:
print (template.render(**data), file=f)
# find all .md files in the directory
img=$(shell ls *.jpg 2> /dev/null)
derimg=$(shell ls *.small.jpg 2> /dev/null)
srcimg=$(filter-out $(derimg),$(img))
index:
indexalist.py . \
--exclude .thumbs \
--exclude index.html \
--exclude index2.html \
--update "video/*" ffmpeginfo.py \
--update "video/*" create_gif.py create_gif.sh \
--update "image/*" create_thumb.py create_thumb.sh \
--update "application/pdf" create_thumb.py create_thumb.sh \
--update "directory/*" make_directory_index.sh \
--update "directory/*" make_directory_index2.sh
imgsmall=$(srcimg:%.jpg=%.small.jpg)
mdsrc=$(shell ls *.md 2> /dev/null)
# map *.mp => *.html for mdsrc
html_from_md=$(mdsrc:%.md=%.html)
all: $(html_from_md) $(imgsmall)
%.small.jpg: %.jpg
convert -resize 240x $< $@
# Implicit rule to know how to make .html from .md
%.html: %.md
pandoc --from markdown \
--to html \
--standalone \
--css styles.css \
$< -o $@
###############################
### INDEX FULES ###############
###############################
%/index.html: %/*
indexical --path $* > $@
index.html: *
indexical --path . > $@
###############################
###############################
###############################
# special rule for debugging variables
print-%:
@echo '$*=$($*)'
index-force:
indexalist.py . \
--exclude .thumbs \
--exclude index.html \
--exclude index2.html \
--force \
--update "directory/*" make_directory_index.sh \
--update "directory/*" make_directory_index2.sh
indexjson=$(shell find . -iname "index.json")
indexhtml=$(indexjson:%.json=%.html)
all: $(indexhtml)
index.html: index.json
make_directory_index.py "."
%/index.html: %/index.json
make_directory_index.py "$*"
# special rule for debugging variables
print-%:
@echo '$*=$($*)'
index.html: index.json
/home/murtaugh/projects/indexalist/bin/make_directory_index.py "."