tons more work on secrets... should be nearly fully functioning, still no API.

This commit is contained in:
Andrew Davidson 2012-05-17 21:07:05 -07:00
parent ee63abc16c
commit f6a2e30ce0
5 changed files with 325 additions and 22 deletions

251
brain.py
View file

@ -1,7 +1,7 @@
import os, sys
from git import *
import bottle
from bottle import default_app, route, run, request, template, static_file, redirect
from bottle import default_app, get, post, route, run, request, template, static_file, redirect
from os.path import isdir
from string import lower, split
from urllib import unquote
@ -11,6 +11,13 @@ import re
import Image
from markdown2 import markdown
import MySQLdb
from contextlib import closing
from urllib import urlopen
from urlparse import urlparse
from contextlib import closing
import string
import random
try:
conn = MySQLdb.connect( host = "localhost",
@ -29,6 +36,65 @@ 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):
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`;'
cursor.execute(query)
secrets = cursor.fetchall()
if not len(secrets) > 0:
url = get_domain(url)
cursor.execute(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 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('./')
@ -673,35 +739,182 @@ def short(short = ''):
# Let's make a place to store my secrets
@route('/secrets/<path>')
@route('/secrets/')
@route('/secrets')
def secrets(path = ''):
if path and not path == "list":
query = 'SELECT username,password FROM `secrets` WHERE base_url LIKE "%' + path + '";'
# A big list of secrets, need a special password'
@post('/secrets/list')
@get('/secrets/list')
@get('/secrets/list/')
def secret_list(path = ''):
cursor.execute(query)
secrets = cursor.fetchall()
body = []
body = []
if request.forms.password == "allyourbasearebelongtous":
secrets = get_secrets()
for s in secrets:
body.append(s[0]+' | '+ s[1]+'<br/>')
body.append(s[0]+': '+s[1]+' | '+s[2])
body.append('<a href="/secrets/trash/'+str(s[3])+'">(x)</a>')
body.append('<br/>')
return template('templates/secret', content = '\n'.join(body), title = 'Secrets')
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>')
if path == "list":
query = 'SELECT base_url,username,password FROM `secrets`;'
return template('templates/secret', content = '\n'.join(body), title = 'Secrets List')
cursor.execute(query)
secrets = cursor.fetchall()
body = []
# 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]+'<br/>')
body.append(s[0]+': '+s[1]+' | '+s[2])
body.append('<a href="/secrets/trash/'+str(s[3])+'">(x)</a>')
body.append('<br/>')
return template('templates/secret', content = '\n'.join(body), title = 'Secrets')
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')

View file

@ -1,4 +1,4 @@
body {
body, table {
background-color: #CCC;
color: #3c3c3c;
font-family: Helvetica;

77
static/overlay.js Normal file
View file

@ -0,0 +1,77 @@
(function() {
function cleanHouse() {
elements = document.querySelectorAll('.myS');
for (i=0; i<elements.length; i++) {
elements[i].parentNode.removeChild(elements[i]);
}
}
cleanHouse();
s=document.createElement('style');
s.id='myS-style';
s.type='text/css';
s.className+='myS';
s.innerHTML='\
.myS{\
font-family:Georgia;\
color:#3C3C3C;\
text-align:center;\
text-size:14px;\
}\
.myS iframe {\
border: none;\
}\
.myS p {\
color:#3C3C3C;\
padding:10px;\
}\
.myS a {\
text-decoration:none;\
color:#3C3C3C;\
}\
.myS a:hover{\
text-decoration:underline;\
}\
.myS a.close:hover {\
border:1px solid #F00;\
text-decoration:none;\
color:#F00;\
}\
';
document.body.appendChild(s);
o=document.createElement('div');
o.id='myS-overlay';
o.className+='myS';
o.style.position='fixed';
o.style.left=o.style.right=o.style.top=o.style.bottom='0%';
o.style.zIndex='1337';
o.style.backgroundColor='rgba(0,0,0,0.7)';
document.body.appendChild(o);
i=document.createElement('div');
i.id='myS-inner';
i.className+='myS';
i.style.position='relative';
i.style.margin='0em auto';
i.style.marginTop='20px';
i.style.backgroundColor='rgba(255,255,255,1)';
o.appendChild(i);
f=document.createElement('iframe');
f.id='myS-iframe';
f.className+='myS';
f.width=320;
f.height=320;
f.style.overflow='auto';
f.src='https://amdavidson.net/secrets/overlay/'+document.domain;
i.appendChild(f);
e=document.createElement('p');
e.className+='myS';
e.onclick=function(){cleanHouse();};
e.innerHTML='<a style="font-size:10pt;" class="myS close">Close</a>';
i.appendChild(e);
})();

15
templates/overlay.tpl Normal file
View file

@ -0,0 +1,15 @@
<html>
<head>
<title>{{title or 'myStuff'}}</title>
<link rel="shortcut icon" href="/static/favicon.ico" />
<link rel="stylesheet" type="text/css" href="/static/brain.css" />
<style type="text/css">
body, table {
background: #FFF !important;
}
</style>
</head>
<body>
{{!content}}
</body>
</html>

View file

@ -1,5 +1,3 @@
{{!content}}
<p>Back to <a href="/repo">Repo</a></p>
%rebase templates/layout title=title