956 lines
30 KiB
Python
956 lines
30 KiB
Python
import os, sys
|
|
from git import *
|
|
import bottle
|
|
from bottle import default_app, get, post, route, run, request, template, static_file, redirect
|
|
from os.path import isdir
|
|
from string import lower, split
|
|
import string
|
|
from urllib import unquote, urlopen
|
|
from urlparse import urlparse
|
|
import shutil
|
|
from datetime import datetime
|
|
import re
|
|
import Image
|
|
from markdown2 import markdown
|
|
import MySQLdb
|
|
from contextlib import closing
|
|
import random
|
|
|
|
|
|
try:
|
|
conn = MySQLdb.connect( host = "localhost",
|
|
user = "brain",
|
|
passwd = "horsebatteries",
|
|
db = "brain")
|
|
cursor = conn.cursor()
|
|
except:
|
|
print 'Cannot connect to database.'
|
|
|
|
|
|
conf = {}
|
|
|
|
conf['repo'] = '/srv/git/documents'
|
|
conf['ext_bundles'] = ['.pages', '.sparsebundle']
|
|
conf['ext_render'] = ['.md','.txt','.jpg','.gif','.png']
|
|
conf['ext_edit'] = ['.md','.txt','.rb','.py','.pl','.sh']
|
|
|
|
def get_secrets(url = False):
|
|
def generate_query():
|
|
if url:
|
|
query = 'SELECT base_url,username,password,id FROM `secrets` WHERE base_url LIKE "%' + url + '";'
|
|
else:
|
|
query = 'SELECT base_url,username,password,id FROM `secrets`;'
|
|
return query
|
|
|
|
cursor.execute(generate_query())
|
|
secrets = cursor.fetchall()
|
|
|
|
if not len(secrets) > 0:
|
|
print 'No secrets for ' + url + ' expanding search.'
|
|
url = get_domain(url)
|
|
print 'Trying ' + url + '.'
|
|
cursor.execute(generate_query())
|
|
secrets = cursor.fetchall()
|
|
|
|
return secrets
|
|
|
|
|
|
def get_domain(base_url):
|
|
with closing(urlopen('https://mxr.mozilla.org/mozilla/source/netwerk/dns/src/effective_tld_names.dat?raw=1')) as tldFile:
|
|
tlds = [line.strip() for line in tldFile if line[0] not in "/\n"]
|
|
|
|
urlElements = base_url.split('.')
|
|
|
|
for i in range(-len(urlElements),0):
|
|
lastIElements = urlElements[i:]
|
|
|
|
candidate = ".".join(lastIElements)
|
|
wildcardCandidate = ".".join(["*"]+lastIElements[1:])
|
|
exceptionCandidate = "!"+candidate
|
|
|
|
if (exceptionCandidate in tlds):
|
|
return ".".join(urlElements[i:])
|
|
if (candidate in tlds or wildcardCandidate in tlds):
|
|
return ".".join(urlElements[i-1:])
|
|
|
|
return base_url
|
|
|
|
|
|
def mkpass(size=10):
|
|
validChars = string.ascii_letters + string.digits
|
|
validChars = validChars.strip("oO01l")
|
|
|
|
return string.join([random.choice(validChars) for x in range(size)],"")
|
|
|
|
def mkshort(size=4):
|
|
validChars = string.ascii_letters + string.digits
|
|
validChars = validChars.strip("oO01l")
|
|
|
|
return string.join([random.choice(validChars) for x in range(size)],"")
|
|
|
|
|
|
def get_generated(domain):
|
|
get = 'SELECT password FROM secrets_gen WHERE base_url LIKE "%'+get_domain(domain)+'%" LIMIT 1'
|
|
create = 'INSERT INTO secrets_gen (base_url, password) VALUES ("'+get_domain(domain)+'","'+mkpass()+'")'
|
|
|
|
cursor.execute(get)
|
|
gen = cursor.fetchone()
|
|
|
|
if not gen:
|
|
cursor.execute(create)
|
|
cursor.execute(get)
|
|
gen = cursor.fetchone()
|
|
|
|
return str(gen[0])
|
|
|
|
|
|
def sanitize_path(path):
|
|
return path.lstrip('./')
|
|
|
|
|
|
def render_file(name,public=False):
|
|
|
|
path = os.path.join(conf['repo'], name)
|
|
filename, extension = os.path.splitext(name)
|
|
filename = os.path.basename(name)
|
|
|
|
if isdir(path) and lower(extension) in conf['ext_bundles']:
|
|
|
|
d = datetime.now()
|
|
|
|
basedir = re.sub(filename+extension, '', path)
|
|
rootdir = filename+extension
|
|
|
|
z = shutil.make_archive('/tmp/' + unquote(filename) + '_' + \
|
|
d.strftime("%Y%M%d%H%M%S"), "zip", basedir, rootdir )
|
|
|
|
return static_file(os.path.basename(z), root='/tmp')
|
|
|
|
if lower(extension) in conf['ext_render']:
|
|
try:
|
|
img = Image.open(path)
|
|
width, height = img.size
|
|
|
|
if width > 1024 or height > 1024:
|
|
if height > width:
|
|
h = 1024
|
|
w = round(1024 * (float(width)/float(height)))
|
|
else:
|
|
if height < width:
|
|
h = round(1024 * (float(height)/float(width)))
|
|
w = 1024
|
|
else:
|
|
h = 1024
|
|
w = 1024
|
|
else:
|
|
h = height
|
|
w = width
|
|
|
|
content = '<img height="'+str(h)+'" width="'+str(w)+'" src="/raw/'+sanitize_path(name)+'" />'
|
|
|
|
except:
|
|
try:
|
|
o = open(path,'r')
|
|
content = markdown(o.read())
|
|
o.close()
|
|
|
|
|
|
content += '<p><a href="/edit/'+sanitize_path(name)+'">Edit</a> - '
|
|
content += '<a href="/raw/'+sanitize_path(name)+'">Raw</a></p>'
|
|
|
|
except:
|
|
content = "<p>This cannot be rendered.</p>"
|
|
|
|
|
|
if sanitize_path(os.path.dirname(name)):
|
|
content += '<p>Back to <a href="/repo/'+sanitize_path(os.path.dirname(name))\
|
|
+'">'+os.path.dirname(name)+'</a></p>'
|
|
|
|
return template('templates/repo', content = content, \
|
|
title=filename)
|
|
|
|
else:
|
|
|
|
return static_file(unquote(name), root=conf['repo'])
|
|
|
|
|
|
|
|
|
|
# Return the static assets.
|
|
|
|
@route('/static/<name:path>')
|
|
def static(name=''):
|
|
return static_file(name, root='./static/')
|
|
|
|
|
|
|
|
# Traverse the repository
|
|
|
|
@route('/repo')
|
|
@route('/repo/')
|
|
@route('/repo/<name:path>')
|
|
def public(name=''):
|
|
|
|
repo = Repo(conf['repo'])
|
|
repo.git.pull()
|
|
tree = []
|
|
|
|
filename, extension = os.path.splitext(name)
|
|
filename = os.path.basename(filename)
|
|
|
|
|
|
path = os.path.join(conf['repo'], sanitize_path(name))
|
|
|
|
|
|
if os.path.exists(path):
|
|
if isdir(path) and not lower(extension) in conf['ext_bundles']:
|
|
tree.append('<ul>')
|
|
print "This is a regular dir: " + path
|
|
|
|
if not name == '':
|
|
n = name.rstrip('/')
|
|
l = split(n, '/')
|
|
tree.append('<li>')
|
|
if len(l) > 1:
|
|
tree.append('<a href="/repo/'+'/'.join(l[0:-1])+'">..</a>')
|
|
else:
|
|
tree.append('<a href="/repo/">..</a>')
|
|
tree.append('</li>')
|
|
|
|
dirs = []
|
|
files = []
|
|
|
|
for f in sorted(os.listdir(path)):
|
|
if not f.startswith('.') and not f.startswith('_'):
|
|
if isdir(os.path.join(path,f)):
|
|
dirs.append('<li>')
|
|
dirs.append('<a href="/repo/'+os.path.join(sanitize_path(name),f)+'">'+f+'</a>')
|
|
dirs.append('<a href="/move/'+os.path.join(sanitize_path(name),f)+'">(move)</a>')
|
|
dirs.append('<a href="/delete/'+os.path.join(sanitize_path(name),f)+'">(delete)</a>')
|
|
dirs.append('</li>')
|
|
else:
|
|
files.append('<li>')
|
|
files.append('<a href="/repo/'+os.path.join(sanitize_path(name),f)+'">'+f+'</a>')
|
|
False,e = os.path.splitext(f)
|
|
if e in conf['ext_edit']:
|
|
files.append('<a href="/edit/'+os.path.join(sanitize_path(name),f)+'">(edit)</a>')
|
|
files.append('<a href="/move/'+os.path.join(sanitize_path(name),f)+'">(move)</a>')
|
|
files.append('<a href="/delete/'+os.path.join(sanitize_path(name),f)+'">(delete)</a>')
|
|
files.append('</li>')
|
|
|
|
for d in dirs: tree.append(d)
|
|
for f in files: tree.append(f)
|
|
|
|
tree.append('</ul>')
|
|
|
|
tree.append('<p><a href="/upload/'+sanitize_path(name)+'">Upload</a> ')
|
|
tree.append('<a href="/new/'+sanitize_path(name)+'">New File</a> ')
|
|
tree.append('<a href="/mkdir/'+sanitize_path(name)+'">New Dir</a></p>')
|
|
|
|
return template('templates/repo', content="\n".join(tree), title="Files in "+sanitize_path(name))
|
|
|
|
else:
|
|
return render_file(name)
|
|
|
|
else:
|
|
|
|
return 'File does not exist.'
|
|
|
|
|
|
# Raw access to files.
|
|
|
|
@route('/raw/<path:path>')
|
|
def raw(path=False):
|
|
try:
|
|
return static_file(unquote(path),root=conf['repo'])
|
|
except:
|
|
return 'No such file'
|
|
|
|
|
|
|
|
# Uploading files.
|
|
|
|
@route('/upload/<path:path>', method="GET")
|
|
@route('/upload/', method="GET")
|
|
@route('/upload', method="GET")
|
|
def upload(path=''):
|
|
|
|
path = sanitize_path(path)
|
|
|
|
body = []
|
|
|
|
body.append('<style type="text/css">\
|
|
td.r { text-align: left; }\
|
|
td.c { text-align: center; }\
|
|
td.l { text-align: right; }\
|
|
</style>')
|
|
|
|
body.append('<h1>Upload a new file</h1>')
|
|
body.append('<form style="width:500px;" method="post" action="/upload" enctype="multipart/form-data">')
|
|
body.append('<table>')
|
|
body.append('<tr><td class="l"><label for="uploaded">Upload:</label></td>')
|
|
body.append('<td class="r"><input type="file" name="uploaded" /></td></tr>')
|
|
body.append('<tr><td class="l"><label for="path">Destination:</label></td>')
|
|
body.append('<td class="r"><input type="text" name="path" style="width:250px" ')
|
|
if not path == '':
|
|
body.append('value="'+path+'" ')
|
|
body.append('/></td></tr>')
|
|
body.append('<tr><td class="l"><label for="message">Commit Message</label></td>')
|
|
body.append('<td class="r"><textarea name="message" cols="50" rows="7"></textarea></td></tr>')
|
|
body.append('<tr><td class="c"><input type="submit" name="submit"></td></tr>')
|
|
body.append('</table>')
|
|
body.append('</form>')
|
|
|
|
|
|
return template('templates/repo', content='\n'.join(body), \
|
|
title='Add')
|
|
|
|
|
|
@route('/upload', method="POST")
|
|
def do_upload():
|
|
repo = Repo(conf['repo'])
|
|
repo.git.pull()
|
|
|
|
path = request.forms.path
|
|
|
|
path = sanitize_path(path)
|
|
|
|
message = request.forms.message
|
|
|
|
u = request.files.uploaded
|
|
|
|
filename = u.filename
|
|
|
|
new_file = os.path.join(conf['repo'],path,filename)
|
|
|
|
if not os.path.exists(os.path.join(conf['repo'],path)):
|
|
os.mkdir(os.path.join(conf['repo'],path))
|
|
|
|
overwritten = False
|
|
if os.path.exists(new_file):
|
|
overwritten = True
|
|
|
|
w = open(new_file,'wb')
|
|
w.write(u.file.read())
|
|
w.close()
|
|
|
|
content = ['<p><a href="/repo/'+path+'/'+filename+'">' + filename + '</a> uploaded to\
|
|
<a href="/repo/'+path+'">/' + path + '</a>']
|
|
|
|
if overwritten:
|
|
content.append(' (original overwritten).</p>')
|
|
else:
|
|
content.append('.</p>')
|
|
|
|
if not overwritten or (overwritten and not repo.git.diff(new_file) == ""):
|
|
repo.git.add(new_file)
|
|
content.append("<p>Git: ")
|
|
commit_result = repo.git.commit(new_file,m=message)
|
|
repo.git.push()
|
|
content.append(commit_result)
|
|
content.append('</p>')
|
|
else:
|
|
content.append('<p>Git: file is not different.</p>')
|
|
|
|
content.append('<p><a href="/upload">Upload another.</a></p>')
|
|
|
|
return template('templates/repo', content='\n'.join(content), title='"'+filename+'" uploaded.')
|
|
|
|
|
|
|
|
# Deleting files.
|
|
|
|
@route('/delete', method="GET")
|
|
@route('/delete/<path:path>', method="GET")
|
|
def delete(path = ''):
|
|
body = []
|
|
|
|
path = sanitize_path(path)
|
|
|
|
body.append('<style type="text/css">\
|
|
td.r { text-align: left; }\
|
|
td.c { text-align: center; }\
|
|
td.l { text-align: right; }\
|
|
</style>')
|
|
|
|
body.append('<h1>Delete a file</h1>')
|
|
body.append('<form style="width:500px;" method="post" action="/delete" enctype="multipart/form-data">')
|
|
body.append('<table>')
|
|
body.append('<tr><td class="l"><label for="path">File to be deleted:</label></td>')
|
|
body.append('<td class="r"><input type="text" name="path" style="width:250px" ')
|
|
|
|
if path: body.append('value="'+path+'" ')
|
|
|
|
body.append('/></td></tr>')
|
|
body.append('<tr><td class="l"><label for="message">Commit Message</label></td>')
|
|
body.append('<td class="r"><textarea name="message" cols="50" rows="7"></textarea></td></tr>')
|
|
body.append('<tr><td><label for="delete">Do you really want to delete?</label></td>')
|
|
body.append('<td class="c"><input type="submit" name="delete" value="Yes."></td></tr>')
|
|
body.append('</table>')
|
|
body.append('</form>')
|
|
|
|
return template('templates/repo', content='\n'.join(body), title='Delete')
|
|
|
|
|
|
@route('/delete', method='POST')
|
|
def delete():
|
|
body = []
|
|
repo = Repo(conf['repo'])
|
|
path = request.forms.path
|
|
path = sanitize_path(path)
|
|
directory,filename = os.path.split(path)
|
|
directory = '/'+directory
|
|
message = request.forms.message
|
|
result = False
|
|
|
|
repo.git.pull()
|
|
|
|
if os.path.exists(os.path.join(conf['repo'],path)):
|
|
try:
|
|
repo.git.rm(path, r=True)
|
|
result = repo.git.commit(path, m=message)
|
|
repo.git.push()
|
|
except:
|
|
if not isdir(os.path.join(conf['repo'],path)):
|
|
os.remove(os.path.join(conf['repo'],path))
|
|
|
|
body.append('<p>' + path + ' deleted from <a href="/repo'+directory+'">'+directory+'</a>.</p>')
|
|
|
|
if result: body.append('<p>Git: '+result+'</p>')
|
|
|
|
else:
|
|
body.append('<p>'+path+' does not exist.</p>')
|
|
|
|
|
|
return template('templates/repo', content='\n'.join(body), title=path+' deleted.')
|
|
|
|
|
|
|
|
# And if we want to edit a file?
|
|
|
|
@route('/edit/<path:path>', method='GET')
|
|
@route('/edit', method="GET")
|
|
def edit(path=''):
|
|
|
|
if not path and request.query.path:
|
|
path = request.query.path
|
|
|
|
path = sanitize_path(path)
|
|
|
|
body = []
|
|
if path:
|
|
full = os.path.join(conf['repo'],path)
|
|
False, ext = os.path.splitext(path)
|
|
|
|
if os.path.exists(full) and not isdir(full) and ext in conf['ext_edit']:
|
|
body.append('<style type="text/css">\
|
|
td.r { text-align: left; vertical-align:top;}\
|
|
td.c { text-align: center; }\
|
|
td.l { text-align: right; vertical-align:top;}\
|
|
</style>')
|
|
|
|
body.append('<h1>Editing '+ path +'</h1>')
|
|
body.append('<form style="width:500px;" method="post" action="/edit" enctype="multipart/form-data">')
|
|
body.append('<input type="hidden" name="path" value="'+path+'" />')
|
|
body.append('<table>')
|
|
body.append('<tr><td class="l"><label for="content">Content:</label></td>')
|
|
body.append('<td class="c" style="width:100%"><textarea name="content" cols="80" rows="80">')
|
|
|
|
with open(full,'r') as f: body.append(f.read())
|
|
|
|
body.append('</textarea></td></tr>')
|
|
body.append('<tr><td class="l"><label for="message">Commit Message</label></td>')
|
|
body.append('<td class="r"><textarea name="message" cols="50" rows="7"></textarea></td></tr>')
|
|
body.append('<tr><td class="c"><input type="submit" name="submit"></td></tr>')
|
|
body.append('</table>')
|
|
body.append('</form>')
|
|
else:
|
|
body.append('<p>Path does not exist or is not editable.')
|
|
else:
|
|
body.append('<h1>Edit a file</h1>')
|
|
body.append('<form style="width:500px;" method="get" action="/edit">')
|
|
body.append('<table>')
|
|
body.append('<tr><td><label for="path">File:</label></td>')
|
|
body.append('<td><input type="text" name="path" style="width:250px;" /></td></tr>')
|
|
body.append('<tr><td><input type="submit" /></td></tr>')
|
|
body.append('</table>')
|
|
body.append('</form>')
|
|
|
|
return template('templates/repo', content='\n'.join(body), \
|
|
title='New')
|
|
|
|
|
|
@route('/edit', method='POST')
|
|
def edit():
|
|
|
|
repo = Repo(conf['repo'])
|
|
path = request.forms.path
|
|
content = request.forms.content
|
|
message = request.forms.message
|
|
full_path = os.path.join(conf['repo'],path)
|
|
|
|
repo.git.pull()
|
|
|
|
body = []
|
|
|
|
f = open(full_path, 'w')
|
|
f.write(content)
|
|
f.close()
|
|
|
|
|
|
if not repo.git.diff(path) == '':
|
|
|
|
commit = repo.git.commit(path,m=message)
|
|
|
|
repo.git.push()
|
|
|
|
body.append('<p><a href="/repo/'+path+'">' + path + '</a> edited.</p>')
|
|
body.append('<p>Git: ' + commit + '</p>')
|
|
|
|
else:
|
|
body.append('<p>' + path + ' not changed.</p>')
|
|
|
|
return template('templates/repo', content='\n'.join(body),\
|
|
title=path+' edited.')
|
|
|
|
|
|
|
|
|
|
# Let's add some functionality to make new files.
|
|
|
|
@route('/new', method='GET')
|
|
@route('/new/<path:path>', method='GET')
|
|
def new(path = ''):
|
|
|
|
path = sanitize_path(path)
|
|
|
|
body = []
|
|
|
|
body.append('<style type="text/css">\
|
|
td.r { text-align: left; vertical-align:top;}\
|
|
td.c { text-align: center; }\
|
|
td.l { text-align: right; vertical-align:top;}\
|
|
</style>')
|
|
|
|
body.append('<h1>Create a new file</h1>')
|
|
body.append('<form style="width:500px;" method="post" action="/new" enctype="multipart/form-data">')
|
|
body.append('<table>')
|
|
body.append('<tr><td class="l"><label for="name">Filename:</label></td>')
|
|
body.append('<td class="r"><input type="text" name="name" style="width:250px"/></td></tr>')
|
|
body.append('<tr><td class="l"><label for="path">Destination:</label></td>')
|
|
body.append('<td class="r"><input type="text" name="path" style="width:250px"')
|
|
if path: body.append('value="'+path+'" ')
|
|
body.append('/></td></tr>')
|
|
body.append('<tr><td class="l"><label for="content">Content:</label></td>')
|
|
body.append('<td class="c" style="width:100%"><textarea name="content" cols="80" rows="80"></textarea></td></tr>')
|
|
body.append('<tr><td class="l"><label for="message">Commit Message</label></td>')
|
|
body.append('<td class="r"><textarea name="message" cols="50" rows="7"></textarea></td></tr>')
|
|
body.append('<tr><td class="c"><input type="submit" name="submit"></td></tr>')
|
|
body.append('</table>')
|
|
body.append('</form>')
|
|
|
|
|
|
return template('templates/repo', content='\n'.join(body), \
|
|
title='New')
|
|
|
|
@route('/new', method="POST")
|
|
def new():
|
|
filename = request.forms.name
|
|
directory = sanitize_path(request.forms.path)
|
|
content = request.forms.content
|
|
message = request.forms.message
|
|
full_path = os.path.join(conf['repo'], directory, filename)
|
|
|
|
w = open(full_path, 'w')
|
|
w.write(content)
|
|
w.close()
|
|
|
|
repo = Repo(conf['repo'])
|
|
|
|
repo.git.pull()
|
|
|
|
commit = False
|
|
|
|
overwritten = False
|
|
if os.path.exists(os.path.join(directory,filename)):
|
|
overwritten = True
|
|
diff = repo.git.diff(os.path.join(directory,filename))
|
|
|
|
if not overwritten or (overwritten and not diff == ''):
|
|
repo.git.add(os.path.join(directory, filename))
|
|
commit = repo.git.commit(os.path.join(directory, filename),m=message)
|
|
|
|
repo.git.push()
|
|
|
|
body = []
|
|
body.append('<p>'+filename+' added to <a href="/repo/'+directory+'">'+(directory if not directory == '' else '/')+'</a></p>')
|
|
if commit:
|
|
body.append('<p>Git: '+commit+'</p>')
|
|
|
|
return template('templates/repo', content='\n'.join(body), \
|
|
title=filename + ' created')
|
|
|
|
|
|
|
|
|
|
# Let's add in some functionality to move files.
|
|
|
|
@route('/move/<path:path>', method="GET")
|
|
@route('/move', method="GET")
|
|
def rename(path = ''):
|
|
body = []
|
|
|
|
path = sanitize_path(path)
|
|
|
|
body.append('<style type="text/css">\
|
|
td.r { text-align: left; vertical-align:top;}\
|
|
td.c { text-align: center; }\
|
|
td.l { text-align: right; vertical-align:top;}\
|
|
</style>')
|
|
|
|
body.append('<h1>Move</h1>')
|
|
body.append('<form style="width:500px;" method="post" action="/move" enctype="multipart/form-data">')
|
|
body.append('<table>')
|
|
body.append('<tr><td class="l"><label for="name">Current:</label></td>')
|
|
body.append('<td class="r"><input type="text" name="current" style="width:250px"')
|
|
if path: body.append(' value="'+path+'" ')
|
|
body.append('/></td></tr>')
|
|
body.append('<tr><td class="l"><label for="path">Destination:</label></td>')
|
|
body.append('<td class="r"><input type="text" name="destination" style="width:250px"/></td></tr>')
|
|
body.append('<tr><td class="l"><label for="message">Commit Message</label></td>')
|
|
body.append('<td class="r"><textarea name="message" cols="50" rows="7"></textarea></td></tr>')
|
|
body.append('<tr><td class="c"><input type="submit" name="submit"></td></tr>')
|
|
body.append('</table>')
|
|
body.append('</form>')
|
|
|
|
|
|
return template('templates/repo', content='\n'.join(body),\
|
|
title='move')
|
|
|
|
@route('/move', method="POST")
|
|
def rename():
|
|
current = os.path.join(conf['repo'],sanitize_path(request.forms.current))
|
|
new = os.path.join(conf['repo'],sanitize_path(request.forms.destination))
|
|
message = request.forms.message
|
|
|
|
body = []
|
|
|
|
if current and new:
|
|
if os.path.exists(current):
|
|
if not os.path.exists(new):
|
|
repo = Repo(conf['repo'])
|
|
|
|
repo.git.pull()
|
|
|
|
repo.git.mv(current,new)
|
|
if not message: message = datetime.now().isoformat()
|
|
commit = repo.git.commit(current,new,m=message)
|
|
|
|
repo.git.push()
|
|
|
|
body.append('<p>'+request.forms.current+' moved to '\
|
|
+request.forms.destination+'.</p>')
|
|
body.append('<p>Git: '+commit+'</p>')
|
|
|
|
else:
|
|
body.append('<p>'+request.forms.destination+' already exists.</p>')
|
|
else:
|
|
body.append('<p>'+request.forms.current+' does not exist.</p>')
|
|
else:
|
|
body.append('<p>Must have both a current and new name.</p>')
|
|
|
|
return template('templates/repo', content='\n'.join(body),\
|
|
title=request.forms.current+' moved to '+request.forms.destination)
|
|
|
|
|
|
|
|
|
|
|
|
# What if we want to make a new directory?
|
|
|
|
@route('/mkdir/<path:path>', method="GET")
|
|
@route('/mkdir', method="GET")
|
|
def mkdir(path=''):
|
|
body = []
|
|
path = sanitize_path(path)
|
|
|
|
body.append('<style type="text/css">\
|
|
td.r { text-align: left; vertical-align:top;}\
|
|
td.c { text-align: center; }\
|
|
td.l { text-align: right; vertical-align:top;}\
|
|
</style>')
|
|
|
|
body.append('<h1>Create Directory</h1>')
|
|
body.append('<form style="width:500px;" method="post" action="/mkdir" enctype="multipart/form-data">')
|
|
body.append('<table>')
|
|
body.append('<tr><td class="l"><label for="name">Name:</label></td>')
|
|
body.append('<td class="r"><input type="text" name="path" style="width:250px"')
|
|
if path: body.append(' value="'+path+'" ')
|
|
body.append('/></td></tr>')
|
|
body.append('<tr><td class="c"><input type="submit" name="submit"></td></tr>')
|
|
body.append('</table>')
|
|
body.append('</form>')
|
|
|
|
|
|
return template('templates/repo', content='\n'.join(body),\
|
|
title='Create Directory')
|
|
|
|
@route('/mkdir', method="POST")
|
|
def mkdir():
|
|
body = []
|
|
path = request.forms.path
|
|
path = sanitize_path(path)
|
|
|
|
if not os.path.exists(os.path.join(conf['repo'],path)):
|
|
os.mkdir(os.path.join(conf['repo'],path))
|
|
|
|
if isdir(os.path.join(conf['repo'],path)):
|
|
body.append('<p><a href="/repo/'+path+'">' + path + '</a> created.</p>')
|
|
else:
|
|
body.append('<p>Directory could not be created</p>')
|
|
else:
|
|
body.append('<p>Path exists.</p>')
|
|
|
|
|
|
return template('templates/repo', content='\n'.join(body),\
|
|
title='Create Directory')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Let's build in the url shortening functionality.
|
|
|
|
@get('/short/<short>')
|
|
def short(short = ''):
|
|
body = []
|
|
if short:
|
|
query = 'SELECT url,public FROM short WHERE `key` = "'+short+'" LIMIT 1;'
|
|
|
|
cursor.execute(query)
|
|
url = cursor.fetchone()
|
|
|
|
if url:
|
|
redirect(url[0])
|
|
|
|
|
|
@get('/short/')
|
|
@get('/short')
|
|
def mkshort(short = ''):
|
|
body = []
|
|
|
|
body.append("<h3>Create Shortened URL.</h3>")
|
|
body.append('<form method="POST" action="/short">')
|
|
body.append('<input type="submit">')
|
|
body.append('</form>')
|
|
|
|
return template('templates/public', content='\n'.join(body),\
|
|
title='Create Shortened URL' + short)
|
|
|
|
|
|
# Let's make a place to store my secrets
|
|
# A big list of secrets, need a special password'
|
|
@post('/secrets/list')
|
|
@get('/secrets/list')
|
|
@get('/secrets/list/')
|
|
def secret_list(path = ''):
|
|
|
|
body = []
|
|
|
|
if request.forms.password == "allyourbasearebelongtous":
|
|
secrets = get_secrets()
|
|
|
|
for s in secrets:
|
|
body.append(s[0]+': '+s[1]+' | '+s[2])
|
|
body.append('<a href="/secrets/trash/'+str(s[3])+'">(x)</a>')
|
|
body.append('<br/>')
|
|
|
|
else:
|
|
body.append('<form method="post" action="/secrets/list" />')
|
|
body.append('<p>Are you sure?</p>')
|
|
body.append('<table>')
|
|
body.append('<tr><td>Password:</td>')
|
|
body.append('<td><input type="password" name="password" /></td></tr>')
|
|
body.append('<td><td><input type="submit" /></td></tr>')
|
|
body.append('</table>')
|
|
body.append('</form>')
|
|
|
|
return template('templates/secret', content = '\n'.join(body), title = 'Secrets List')
|
|
|
|
|
|
# Show the secrets associated with a specific site.
|
|
@get('/secrets/show/<url>')
|
|
@get('/secrets/show/')
|
|
@get('/secrets/show')
|
|
def secret_lookup(url = False):
|
|
|
|
body = []
|
|
|
|
if url:
|
|
secrets = get_secrets(url)
|
|
for s in secrets:
|
|
body.append(s[0]+': '+s[1]+' | '+s[2])
|
|
body.append('<a href="/secrets/trash/'+str(s[3])+'">(x)</a>')
|
|
body.append('<br/>')
|
|
|
|
else:
|
|
body.append('Must provide a url.')
|
|
|
|
return template('templates/secret', content = '\n'.join(body), title = 'Secrets for ' + url)
|
|
|
|
|
|
# A form for trashing secrets.
|
|
@get('/secrets/trash/<key>')
|
|
@get('/secrets/trash/')
|
|
@get('/secrets/trash')
|
|
def secret_trash(key=False):
|
|
body = []
|
|
|
|
body.append('<form method="post" action="/secrets/trash/" >')
|
|
body.append('<p>Trash a secret</p>')
|
|
body.append('<table>')
|
|
body.append('<tr><td><label for="id">Secret id</label></td>')
|
|
body.append('<td><input name="id" ')
|
|
if key: body.append('value="'+key+'" ')
|
|
body.append('/></td></tr>')
|
|
body.append('<tr><td><input type="submit" /></td></tr>')
|
|
body.append('</table>')
|
|
|
|
return template('templates/secret', content = '\n'.join(body), title = 'Trash Secret')
|
|
|
|
|
|
|
|
# Actually trashing secrets.
|
|
@post('/secrets/trash')
|
|
@post('/secrets/trash/')
|
|
def secret_trash():
|
|
#query = 'SELECT base_url,username,password,id FROM `secrets` WHERE base_url LIKE "%' + url + '";'
|
|
#cursor.execute(query)
|
|
#secrets = cursor.fetchall()
|
|
original = 'SELECT id FROM `secrets` WHERE id = "' + str(request.forms.id) + '" LIMIT 1'
|
|
copy = 'INSERT INTO `secrets_trash` SELECT * FROM `secrets` WHERE id = "' + str(request.forms.id) + '"'
|
|
check = 'SELECT * FROM `secrets_trash` INNER JOIN `secrets` ON (secrets_trash.base_url = secrets.base_url AND secrets_trash.username = secrets.username AND secrets_trash.password = secrets.password)'
|
|
delete = 'DELETE FROM `secrets` WHERE id = "' + str(request.forms.id) + '" LIMIT 1'
|
|
|
|
body = []
|
|
|
|
if cursor.execute(original):
|
|
body.append('<p>Record exists.</p>')
|
|
cursor.execute(copy)
|
|
body.append('<p>Record copied.</p>')
|
|
if cursor.execute(check):
|
|
body.append('<p>Duplicate records exist.</p>')
|
|
cursor.execute(delete)
|
|
body.append('<p>Original record deleted.</p>')
|
|
if not cursor.execute(original):
|
|
body.append('<p>Original record does not exist.</p>')
|
|
body.append('<p>Record ' + str(request.forms.id) + ' trashed.</p>')
|
|
|
|
else:
|
|
body.append('<p>No such record.</p>')
|
|
|
|
return template('templates/secret', content = '\n'.join(body), title = 'Secret ' + str(request.forms.id) + ' trashed.')
|
|
|
|
|
|
# Create a new secret.
|
|
@get('/secrets/create/<url>')
|
|
@get('/secrets/create/')
|
|
@get('/secrets/create')
|
|
def secrets_create(url = False):
|
|
body = []
|
|
|
|
body.append('<h3>Create Secret</h3>')
|
|
body.append('<form method="POST" action="/secrets/create">')
|
|
body.append('<table>')
|
|
body.append('<tr><td><label for="url">URL:</label></td>')
|
|
body.append('<td><input name="url" ')
|
|
if url: body.append('value="'+url+'" ')
|
|
body.append('/></td></tr>')
|
|
body.append('<tr><td><label for="username">Username:</label></td>')
|
|
body.append('<td><input name="username" /></td></tr>')
|
|
body.append('<tr><td><label for="password">Password:</label></td>')
|
|
body.append('<td><input type="password" name="password" ')
|
|
if url: body.append('value="'+get_generated(url)+'" ')
|
|
body.append('/></td></tr>')
|
|
body.append('<tr><td><input type="submit" /></td></tr>')
|
|
body.append('</table>')
|
|
body.append('</form>')
|
|
|
|
return template('templates/secret', content='\n'.join(body), title = 'Create Secret')
|
|
|
|
|
|
# Create a new secret
|
|
@post('/secrets/create')
|
|
def create_secret():
|
|
body = []
|
|
query = 'INSERT INTO secrets (base_url, username, password) VALUES (' +\
|
|
'"'+request.forms.url+'", '+\
|
|
'"'+request.forms.username+'", '+\
|
|
'"'+request.forms.password+'")'
|
|
|
|
print query
|
|
|
|
if cursor.execute(query):
|
|
body.append('<p>Secret created.</p>')
|
|
body.append('<p>View secrets for <a href="/secrets/show/'+\
|
|
request.forms.url+'">'+request.forms.url+'</a>.</p>')
|
|
else:
|
|
body.append('Secret could not be created.')
|
|
|
|
return template('templates/secret', content='\n'.join(body), title = 'Create Secret')
|
|
|
|
|
|
|
|
@get('/secrets/overlay/<url>')
|
|
def secret_overlay(url):
|
|
body = []
|
|
body.append('<p>Secrets for: '+url+'</p>')
|
|
|
|
secrets = get_secrets(url)
|
|
for s in secrets:
|
|
body.append(s[0] + ': ' + s[1] + ' | ' + s[2] + '<br/>')
|
|
|
|
gen = get_generated(url)
|
|
|
|
body.append('<p>Generated: ' + gen + '</p>')
|
|
|
|
body.append('<form method="POST" action="/secrets/create" target="_blank">')
|
|
body.append('<table>')
|
|
body.append('<tr><td>URL:</td><td><input name="base_url" value="'+url+'" /></td></tr>')
|
|
body.append('<tr><td>U:</td><td><input name="username" /></td></tr>')
|
|
body.append('<tr><td>P:</td><td><input name="password" type="password" value="'+gen+'" /></td></tr>')
|
|
body.append('<tr><td><input type="submit" /></td></tr>')
|
|
body.append('</table>')
|
|
body.append('</form>')
|
|
|
|
return template('templates/overlay', content='\n'.join(body), title = url + ' overlay')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# An API will be needed for bookmarklets and whatnot.
|
|
@route('/api')
|
|
def api():
|
|
return 'Someday there will be an API here.'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Do something with the home page.
|
|
@route('/')
|
|
def index():
|
|
redirect('/repo')
|
|
|
|
|
|
|
|
application = bottle.default_app()
|
|
|
|
if __name__ == "__main__":
|
|
bottle.debug(True)
|
|
conf['repo'] = os.path.expanduser('~/dev/repo')
|
|
run(host='0.0.0.0', port=8000, reloader=True)
|