server.modules = ( "mod_rewrite", "mod_alias", "mod_access", "mod_auth", "mod_proxy_core", "mod_proxy_backend_fastcgi", "mod_redirect", "mod_magnet", "mod_accesslog" )
server.errorlog = "/var/log/lighttpd/error_log"
-$HTTP["useragent"] !~ "^check_http" {
- accesslog.filename = "/var/log/lighttpd/access_log"
-}
+#$HTTP["useragent"] !~ "^check_http" {
+# accesslog.filename = "/var/log/lighttpd/access_log"
+#}
etag.use-inode = "disable"
index-file.names = ( "index.php", "index.html" )
url.access-deny = ( "~", ".inc", ".svn", "CVS" )
server.port = 80
server.pid-file = "/var/run/lighttpd.pid"
server.username = "lighttpd"
-server.groupname = "lighttpd"
+server.groupname = "apache"
$PHYSICAL["existing-path"] =~ "\.php$" {
proxy-core.balancer = "round-robin"
ssl.verifyclient.username = "SSL_CLIENT_S_DN_emailAddress"
$SERVER["socket"] == "0.0.0.0:443" {
+ server.document-root = "/srv/www/root/"
ssl.engine = "enable"
ssl.pemfile = "/etc/lighttpd/sql.mit.edu.pem"
ssl.ca-file = "/etc/lighttpd/mitCAclient.pem"
ssl.verifyclient.enforce = "disable"
ssl.verifyclient.depth = 2
- $HTTP["url"] =~ "^/api(/|$)" {
- $HTTP["useragent"] =~ "AppleWebKit" {
- url.access-deny = ("")
- }
- auth.backend = "gssapi"
- auth.backend.gssapi.principal = "HTTP/sql.mit.edu"
- auth.backend.gssapi.keytab = "/etc/lighttpd/krb5.keytab"
- auth.require = ( "/" => ( "method" => "gssapi", "realm" => "ATHENA.MIT.EDU", "require" => "valid-user"))
- magnet.attract-raw-url-to = ( "/srv/www/api.lua" )
+ url.redirect += ( "^/$" => "/manage/" )
+ $HTTP["url"] =~ "^/manage(/|$)" {
+ proxy-core.balancer = "round-robin"
+ proxy-core.protocol = "fastcgi"
+ proxy-core.backends = ( "unix:/srv/var/run/interface.sock" )
+ proxy-core.max-pool-size = 4
+ proxy-core.rewrite-request = (
+ "_pathinfo" => ( "^/manage(/.*)" => "$1" ),
+ "_scriptname" => ( "^(/manage/)" => "$1" )
+ )
}
}
-import mitsql
-config = mitsql.config.interface
-
-from MySQLdb import Connection as _connect
-from MySQLdb.cursors import DictCursor as _cursor
-
-def _connect(*argv, **kw):
- return _connect(config.db_host, config.db_user, config.db_pass, config.db_name, cursorclass=_Cursor)
+import templates
+
+from cherrypy.process.plugins import DropPrivileges
+class DropSock(DropPrivileges):
+ def start(self):
+ if cherrypy.server.socket_file:
+ import os
+ os.chown(cherrypy.server.socket_file, self.uid, self.gid)
+ DropPrivileges.start(self)
+ start.priority = 78
+import cherrypy
+DropSock(cherrypy.engine, uid='lighttpd', gid='apache').subscribe()
from handler import Root as _root
root = _root()
-
-from cheetah import load
-load(mitsql._base + '/www/templates')
-
-import cherrypy
-cherrypy.tree.mount(root, '/')
-cherrypy.config.update({'error_page.404': root.error._404,
- 'error_page.500': root.error._500,
- 'tools.staticdir.on': True,
- 'tools.staticdir.dir': mitsql._base + '/www/root'})
-
-def map_uri():
- print root.default()
- #from cherrypy.lib.httpauth import parseAuthorization
- #if not cherrypy.request.login:
- # authorization = cherrypy.request.headers.get('Authorization', None)
- # if authorization:
- # cherrypy.request.login = parseAuthorization(authorization)
-
-#cherrypy.tools.map_uri = cherrypy.Tool('on_start_resource', map_uri)
-#cherrypy.tools.map_uri = cherrypy.Tool('before_request_body', map_uri)
+++ /dev/null
-import qwobl
-import os, sys, types, time
-import threading
-from pyinotify import WatchManager, Notifier, EventsCodes
-from Cheetah.Template import Template as _Template
-import logging
-
-class Template(object):
- def __init__(self, name='templates', ns={}, path=[]):
- self._name, self._ns, self._path = name, ns, len(path) and path+[name] or [name]
- if len(self._path) > 1:
- assert self._template()
-
- def _template(self):
- return sys.modules['.'.join(self._path)]
-
- def __getattr__(self, name):
- return Template(name, self._ns, self._path)
-
- def __call__(self, **kw):
- namespaces = self._ns.copy()
- namespaces.update(kw)
- return getattr(self._template(),
- self._name)(namespaces=namespaces).respond()
-
-class Loader(object):
- _mask = EventsCodes.ALL_FLAGS['IN_CREATE'] \
- | EventsCodes.ALL_FLAGS['IN_MODIFY'] \
- | EventsCodes.ALL_FLAGS['IN_DELETE'] \
- | EventsCodes.ALL_FLAGS['IN_ATTRIB']
- _watch_manager = None
- _notifier = None
- _thread = None
-
- _loaded = False
- _files = {}
- _modules = {}
-
- def __init__(self, global_namespace={}):
- self._event_init()
- self._assert_module('templates')
- self._globals = global_namespace
- self._thread = threading.Thread(target=self.loop)
- self._thread.setDaemon(True)
- self._thread.start()
-
- def _tree_walk(self, tree, path, func):
- path = list(path)
- if len(path) > 1:
- x = path.pop(0)
- if not x in tree:
- tree[x] = {}
- return self._tree_walk(tree[x], path, func)
- elif callable(func):
- return func(tree, path[0])
-
- def _tree_add(self, tree, path, value):
- def _add(tree, key):
- tree[key] = value
- return value
- print self._tree_walk(tree, path, _add)
-
- def _assert_module(self, name, path=None):
- if not name in self._modules:
- self._modules[name] = types.ModuleType(name)
- if path:
- self._modules[name].__path__ = path
- sys.modules[name] = self._modules[name]
-
- def _get_template_path(self, path_name, template_file):
- r = template_file.startswith(path_name) \
- and template_file[len(path_name)+1:].split(os.path.sep) or []
- if r[-1].endswith('.tmpl'):
- r[-1] = r[-1][:-5]
- return tuple(r)
-
- def _compile(self, template_path):
- template = _Template.compile(file=self._files[template_path],
- returnAClass=False,
- moduleName='.'.join(['templates']+list(template_path)),
- className=template_path[-1],
- useCache=False,
- compilerSettings={'useStackFrames':False})
- return template
-
- def add(self, path_name, template_file):
- template_path = self._get_template_path(path_name, template_file)
- template_name = '.'.join(['templates']+list(template_path))
- template_pkg = '.'.join(['templates']+list(template_path[:-1]))
- template_py = os.path.join(os.path.dirname(template_file), '%s.py' % template_path[-1])
- self._assert_module(template_pkg, [os.path.dirname(template_file)])
- self._files[template_path] = template_file
- code = self._compile(template_path)
- f_code = file(template_py, 'w')
- f_code.write(code)
- f_code.close()
- if template_name in sys.modules:
- reload(sys.modules[template_name])
-
- def remove(self, template_file):
- #print 'removing', template_file
- pass
-
- def _walk_path(self, path_name):
- def _walk_load(args, dname, fnames):
- for fname in fnames:
- if fname.endswith('.tmpl'):
- template_file = os.path.join(dname, fname)
- self.add(path_name, template_file)
- return _walk_load
-
- def load(self, path_name):
- os.path.walk(path_name, self._walk_path(path_name), None)
- for path, filename in self._files.items():
- logging.debug('TEMPLATE LOAD [%s] %s', path, filename)
- __import__('.'.join(['templates']+list(path)))
- self._event_add_watch(path_name)
-
- def _path_event_handler(self, path_name):
- def _event_handler(event):
- logging.debug('TEMPLATE EVENT: %s', repr(event.__dict__.items()))
- if event.name.endswith('.tmpl') and not event.name.startswith('.'):
- if event.maskname == 'IN_DELETE':
- self.remove(event.pathname)
- else:
- time.sleep(0.5)
- self.add(path_name, event.pathname)
- return _event_handler
-
- def _event_init(self):
- self._watch_manager = WatchManager()
- self._notifier = Notifier(self._watch_manager)
-
- def _event_add_watch(self, path_name):
- r = self._watch_manager.add_watch(path_name,
- self._mask,
- self._path_event_handler(path_name),
- rec=True,
- auto_add=True)
-
- def loop(self):
- while True:
- try:
- self._notifier.process_events()
- if self._notifier.check_events():
- self._notifier.read_events()
- except KeyboardInterrupt:
- self._notifier.stop()
- break
-
-_loader = Loader()
-load = _loader.load
-templates = Template()
-
-__all__ = ['load', 'templates']
-
-if __name__ == '__main__':
- t = Loader('/home/joe/templates')
--- /dev/null
+import MySQLdb as _my, pgsql as _pg
+
+class Database(object): pass
+
+class MySQL(Database):
+ def list(self, username):
+ cxn = _my.connect('127.0.0.1', 'root', '', 'mysql')
+ cur = cxn.cursor()
+ cur.execute('SELECT Db FROM db WHERE User=%s AND Host="%%"', username)
+ return dict([(x[0],{'sz_tot':0,'sz_max':100}) for x in cur.fetchall()])
+
+mysql = MySQL()
+
+class PgSQL(Database):
+ def list(self, username):
+ cxn = _pg.connect(user='postgres')
+ cur = cxn.execute('SELECT datname FROM pg_database INNER JOIN pg_user ON pg_user.usesysid=pg_database.datdba WHERE pg_user.usename=$1', username)
+ return dict([(x[0],{'sz_tot':0,'sz_max':100}) for x in cur.fetchall()])
+
+pgsql = PgSQL()
+++ /dev/null
-def db_list_entry(name, size_tot, size_max):
- return '%s: %s/%s' % (name, size_tot, size_max)
\ No newline at end of file
import mitsql
-from cheetah import templates
+
import cherrypy
+mako = cherrypy.tools.mako
from pprint import pformat
-def _500(*argv, **kw):
- s_exc = cherrypy._cperror.format_exc()
- mitsql.logging.error(s_exc)
- return templates.common.shell(title='%s (CherryPy %s)' % (kw.get('status'), kw.get('version')),
- content=('<p>%s</p>' + (2*'<div><pre>%s</pre></div>'))
- % (kw.get('message'), kw.get('traceback'),
- _phtml(dict(filter(lambda x: not x[0][:2] == '__',
- cherrypy.request.__dict__.items())))))
+#def _500(*argv, **kw):
+# s_exc = cherrypy._cperror.format_exc()
+# mitsql.logging.error(s_exc)
+# return templates.common.shell(title='%s (CherryPy %s)' % (kw.get('status'), kw.get('version')),
+# content=('<p>%s</p>' + (2*'<div><pre>%s</pre></div>'))
+# % (kw.get('message'), kw.get('traceback'),
+# _phtml(dict(filter(lambda x: not x[0][:2] == '__',
+# cherrypy.request.__dict__.items())))))
+
+def _before_request_body():
+ if not cherrypy.request.login is None:
+ if cherrypy.request.login.endswith('@MIT.EDU'):
+ cherrypy.request.login = cherrypy.request.login[:-8]
+ else:
+ cherrypy.request.login = None
+
+from databases import mysql, pgsql
class Root(object):
- class Error(object):
- @cherrypy.expose
- def _404(*argv, **kw):
- return templates.common._404()
- def _500(*argv, **kw):
- return _500(*argv, **kw)
- error = Error()
+ _cp_config = {
+ 'hooks.before_request_body': _before_request_body,
+ 'tools.mako.collection_size': 500,
+ 'tools.mako.directories': mitsql._base+'/www/templates',
+ }
+ #class Error(object):
+ # def _404(*argv, **kw):
+ # return templates.common._404()
+ # def _500(*argv, **kw):
+ # return _500(*argv, **kw)
+ #error = Error()
- class DB(object):
- def list(*argv, **kw):
- r = {'db_list': [],
- 'size_tot': '1M',
- 'size_max': '100M',
- 'user': {
- 'db_prefix': 'presbrey+'
- }}
- return templates.main.db_list(**r)
- list.exposed = True
- db = DB()
-
+ @cherrypy.expose
def test(self, *argv, **kw):
cherrypy.response.headers['Content-type'] = 'text/plain'
return pformat(dict(filter(lambda x: not x[0][:2] == '__', cherrypy.request.__dict__.items())))
- test.exposed = True
+ @cherrypy.expose
+ @mako(filename='index')
def index(self, *argv, **kw):
- return templates.main.index()
- index.exposed = True
+ return {
+ 'title': 'SQL Service',
+ 'login': cherrypy.request.login,
+ }
+ @cherrypy.expose
+ @mako(filename='passwd')
def passwd(self, *argv, **kw):
- return templates.main.passwd()
- passwd.exposed = True
\ No newline at end of file
+ return {
+ 'title': 'Change Passwords',
+ 'login': cherrypy.request.login,
+ }
+
+ @cherrypy.expose
+ @mako(filename='contact')
+ def contact(self, *argv, **kw):
+ return {
+ 'title': 'Contact',
+ }
+
+ @cherrypy.expose
+ @mako(filename='database')
+ def database(self, *argv, **kw):
+ return {
+ 'title': 'Databases',
+ 'login': cherrypy.request.login,
+ 'mysql': mysql.list(cherrypy.request.login),
+ 'pgsql': pgsql.list(cherrypy.request.login),
+ }
+
+#Root._cp_config['error_page.404'] = Root.error._404
+#Root._cp_config['error_page.500'] = Root.error._500
--- /dev/null
+import cherrypy
+from mako.lookup import TemplateLookup
+
+class MakoHandler(cherrypy.dispatch.LateParamPageHandler):
+ """Callable which sets response.body."""
+
+ def __init__(self, template, next_handler):
+ self.template = template
+ self.next_handler = next_handler
+
+ def __call__(self):
+ env = globals().copy()
+ env.update(self.next_handler())
+ return self.template.render(**env)
+
+class MakoLoader(object):
+
+ def __init__(self):
+ self.lookups = {}
+
+ def __call__(self, filename, directories, module_directory=None,
+ collection_size=-1):
+ # Find the appropriate template lookup.
+ key = (tuple(directories), module_directory)
+ try:
+ lookup = self.lookups[key]
+ except KeyError:
+ lookup = TemplateLookup(directories=directories,
+ module_directory=module_directory,
+ collection_size=collection_size,
+ )
+ self.lookups[key] = lookup
+ cherrypy.request.lookup = lookup
+
+ # Replace the current handler.
+ cherrypy.request.template = t = lookup.get_template(filename)
+ cherrypy.request.handler = MakoHandler(t, cherrypy.request.handler)
+
+cherrypy.tools.mako = cherrypy.Tool('on_start_resource', MakoLoader())
--- /dev/null
+#!/bin/bash
+
+cherryd -c /srv/www/etc/interface.conf -p /srv/var/run/interface.pid -f -i mitsql.interface "$@"
+++ /dev/null
-[global]
-server.socket_host: "0.0.0.0"
-server.socket_port: 8336
-tools.encode.on: True
-tools.encode.encoding: 'utf-8'
-#tools.map_uri.on: True
-#tools.header_auth.on: True
-#request.show_tracebacks: True
--- /dev/null
+[global]
+server.socket_file: mitsql._base + '/var/run/interface.sock'
+tools.encode.on: True
+tools.encode.encoding: 'utf-8'
+tools.trailing_slash.on: False
+tree.root.manage: cherrypy.Application(mitsql.interface.root, '/manage')
+++ /dev/null
-[global]
-tree.root: mitsql.interface.root
-server.socket_file: '/tmp/mitsql.sock'
-
-tools.encode.on: True
-tools.encode.encoding: 'utf-8'
-#tools.map_uri.on: True
-#autoreload.on: False
-#checker.on: False
-#engine.SIGHUP: None
-#engine.SIGTERM: None
}
#farouter {
background: #ffffff;
- width: 80%;
+ width: 760px;
border: 1px solid #3A291F;
margin: 10px auto 10px auto;
text-align: left; /* IE 5.5 hack part II */
#outer div#masthead { margin: 1em; }
#outer div#content_wide { margin: 1em; }
#content { float: left; width: 490px; }
-#content_wide { padding: 0 35px 0 35px; }
+#content_wide { padding: 1em 2em; }
#content_home { float: left; width: 490px; padding-top: 0px; }
#menu { float: right; width: 175px; margin-right: 10px; border-left: 1px dashed #2050A0; }
#nav { padding-left: 10px; }
-#extends templates.common.shell
+<%include file="header"/>
-#def title: Page Not Found
-
-#block content
<p>We're sorry! The page you requested does not exist. Please return to our <a href="/">homepage</a> or <a href="/contact">contact us</a>.</p>
-#end block content
+
+<%include file="footer"/>
-#extends templates.common.shell
+<%include file="header"/>
-#def title: Page Error
-
-#block content
<p>We're sorry! The requested you made caused an internal error we weren't expecting. The support team has been notified.</p>
<p>Please return to our <a href="/">homepage</a>, go back and try again, or <a href="/contact">contact us</a>.</p>
-#end block content
+
+<%include file="footer"/>
+++ /dev/null
-#extends skeleton
+++ /dev/null
-#from mitsql import config
-#import cherrypy, time
-#set global x_agent = cherrypy.request.headers.get('X-Agent', 'Mozilla')
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- #set page_title = $title.split('|')[0]
- <title>$page_title</title>
- <link rel="stylesheet" type="text/css" href="/assets/css/style.css?$time.time" />
- <link rel="icon" type="image/png" href="/assets/images/favicon.ico" />
- <script type="text/javascript" src="/assets/js/prototype.js"></script>
- #block head_append
- #end block head_append
-</head>
-<body>
-<div id="farouter">
- <div id="outer">
- <div id="masthead">
- <h1 id="title">$title</h1>
- <h1 id="sitename"><a href="http://sql.mit.edu/" target="_top">sql.mit.edu</a></h1>
- <h2 id="tagline">MIT SIPB MySQL Service for Athena<br />
- email: sql@mit.edu</h2>
- </div>
- <div id="hmenu">
- <div id="hnav">
- <ul id="navlist">
-<div style="float:left;">
-<li><a href="/db/list">Manage DBs</a></li>
-<li><a href="do/setup">Account</a></li>
-<li><a href="do/admin/main">Admin</a></li>
-<li><a href="do/logout">Logout</a></li>
-<li><a href="do/signup">Sign up</a></li>
-<li><a href="https://scripts.mit.edu/~sql/phpMyAdmin/" target="_blank">phpMyAdmin</a></li>
-</div>
-<div style="text-align: right;">
-Login via:
- <li><a href="do/login?ssl=0">SQL Password</a></li>
- <li class="menu_last"><a href="do/login?ssl=1">MIT Certificate</a></li>
-</div>
- </ul>
- </div>
- </div>
- <div id="main">
- <div id="content_wide">
- #block body
- #end block body
- </div><!-- end#content -->
- </div><!-- end#main -->
-
- <!-- footer -->
- <div id="foot"> </div><!-- end#foot -->
- <div id="clearer"> </div><!-- end#clearer -->
- <div id="footer">
- <p id="credit" style="text-align: right;">
- <strong><em>sql.mit.edu v2.0</em></strong>
- </p>
- </div><!-- end#footer -->
- </div><!-- end#outer -->
-</div><!-- end#farouter -->
-</body>
-</html>
-#extends templates.common.shell
-
-#def title: Contact
-
-#block body
-<h3>Contact/Help</h3>
+<%include file="header"/>
<p>We welcome all questions, comments, and suggestions.</p>
<p>Please direct inquiries to <strong>sql@mit.edu</strong></p>
-#end block body
\ No newline at end of file
+<%include file="footer"/>
--- /dev/null
+<%include file="header"/>
+
+<table width="100%">
+% if mysql is UNDEFINED:
+<tr><td width="100%"><em>You have no MySQL databases. Add one below.</em></td></tr>
+% else:
+ % for name, data in sorted(mysql.items()):
+<tr><td width="100%">
+${name}
+</td><td>
+<p>drop</p>
+</td></tr>
+ % endfor
+% endif
+<tr><td colspan=2>
+<hr />
+</td></tr><tr><td colspan=2>
+<!--echo display.db_list_entry('TOTAL', $sz_tot, $sz_max)-->
+</td></tr>
+</table>
+
+<form method="post" action="create">
+<p align="right">
+ <span style="width: 150px; font-style: italic;">
+ <label for="p1">new database:</label>
+ </span> ${login}+<input type="text" name="db_name" />
+ <input type=submit value="create" />
+</p>
+</form>
+
+<%include file="footer"/>
--- /dev/null
+ </div><!-- end#content -->
+ </div><!-- end#main -->
+
+ <!-- footer -->
+ <div id="foot"> </div><!-- end#foot -->
+ <div id="clearer"> </div><!-- end#clearer -->
+ <div id="footer">
+ <p id="credit" style="text-align: right;">
+ <strong><em>sql.mit.edu v2.0</em></strong>
+ </p>
+ </div><!-- end#footer -->
+ </div><!-- end#outer -->
+</div><!-- end#farouter -->
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>${title}</title>
+ <link rel="stylesheet" type="text/css" href="/css/style.css" />
+ <link rel="icon" type="image/png" href="/images/favicon.ico" />
+ <script type="text/javascript" src="/js/jquery.min.js"></script>
+ <script type="text/javascript" src="/js/jquery.ui.min.js"></script>
+</head>
+<body>
+<div id="farouter">
+ <div id="outer">
+ <div id="masthead">
+ <h1 id="title">${title}</h1>
+ <h1 id="sitename"><a href="http://sql.mit.edu/" target="_top">sql.mit.edu</a></h1>
+ <h2 id="tagline">MIT SIPB MySQL Service for Athena<br />email: sql@mit.edu</h2>
+ </div>
+ <div id="hmenu">
+ <div id="hnav">
+ <ul id="navlist">
+
+<div style="float:left;">
+<li><a href="database">Databases</a></li>
+<li><a href="account">Account</a></li>
+<li><a href="admin">Admin</a></li>
+<li><a href="logout">Logout</a></li>
+</div>
+<div style="text-align: right;">
+%if login is UNDEFINED:
+<li><a href="login">Login</a></li>
+%else:
+Logged in: <strong>${login}</strong>
+%endif
+</div>
+
+ </ul>
+ </div>
+ </div>
+ <div id="main">
+ <div id="content_wide">
-#extends templates.common.shell
+<%include file="header"/>
-#def title: MySQL Services
-
-#block body
<p>
This service provides <a target="_blank" href="http://dev.mysql.com/doc">MySQL</a> databases to <a target="_blank" href="http://ca.mit.edu/">MIT certificate</a> holders.
-You must choose a MySQL password (which should be different from your Athena account password) when you <a href="do/signup">sign up</a>, and
+You must choose a MySQL password (which should be different from your Athena account password) when you <a href="signup">sign up</a>, and
then use this interface to create and drop databases. All subsequent SQL commands can be issued from any host, client, and/or script of your choice;
simply connect to the MySQL server at <b>sql.mit.edu</b> using your username and your new MySQL password.
You may find it convenient to run scripts using the <a target="_blank" href="http://scripts.mit.edu/web">web script service</a> or
<div style="text-align:center; font-style: italic;">
<!-- /afs/athena.mit.edu/contrib/sql/stat/questions -->
</div>
-#end block body
\ No newline at end of file
+
+<%include file="footer"/>
+++ /dev/null
-#extends templates.common.shell
-#from mitsql.interface import display
-
-#def title: Manage Databases
-
-#block body
-
-<table width="100%">
-#if len($db_list) == 0:
-<tr><td width="100%"><em>You have no databases. Add one below.</em></td></tr>
-#else:
-#for name, data in $db_list:
-<tr><td width="100%">
-#echo display.db_list_entry($name, $data.size_tot, $data.size_max)
-</td><td>
-<p>drop</p>
-</td></tr>
-#end for
-#end if
-<tr><td colspan=2>
-<hr />
-</td></tr><tr><td colspan=2>
-#echo display.db_list_entry('TOTAL', $size_tot, $size_max)
-</td></tr>
-</table>
-
-<form method="post" action="create">
-<p align="right">
- <span style="width: 150px; font-style: italic;">
- <label for="p1">new database:</label>
- </span> $user.db_prefix<input type="text" name="db_name" />
- <input type=submit value="create">
-</p>
-</form>
-
-<h3>Manage Data</h3>
-<p>One interface we recommend for managing SQL data is <a href="https://scripts.mit.edu/~sql/phpMyAdmin/" target="_blank">phpMyAdmin</a>. Feel free to use it after you've created your databases.</p>
-
-#end block body
\ No newline at end of file
-#extends templates.common.shell
+<%include file="header"/>
-#def title: Change Password
-
-#block body
<p>Your MySQL password should be different from your Athena account password.</p>
<form method="post">
from any Athena prompt.
</div>
-#end block body
\ No newline at end of file
+<%include file="footer"/>
-#extends templates.common.shell
+<%include file="header"/>
-#def title: Change Password
-
-#block body
<p>Your MySQL password should be different from your Athena account password.</p>
<form method="post">
</form>
<hr />
<p>Note: you need to also <a href="http://scripts.mit.edu/faq/59">update your .my.cnf file on Athena</a> if you want to use SIPB <a href="http://scripts.mit.edu/start/">scripts auto-installers</a> or access the MySQL service from the command-line.</p>
-#end block body
\ No newline at end of file
+
+<%include file="footer"/>