#!/usr/bin/python
### ^ change above to reflect the file path to python, if it's not
# /usr/bin/python (i.e. on a windows box)
"""Web interface for changing settings.conf.
Allows you to change all of the variables in settings.conf.
@copyright: 2008 Nathaniel Herman
@license: GNU GPLv3, see COPYING for full details
"""
###
# Copyright (C) 2008 Nathaniel Herman
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
Permission denied!
' def setcookie(expires=''): """Creates a session ID cookie. Cookie will expire after the given expiry time in seconds. The value of the session ID is returned.""" sitename = cgi.escape(config['required']['sitename']) # creates a 20 character long string of random letters, numbers sessionid = functions.makesessionid() # cookie name will be sitename_sessionid, with sitename having all cookie # illegal characters taken out cookiename = '%s_sessionid' % stripillegal(sitename) cookie[cookiename] = sessionid cookie[cookiename]['expires'] = expires return sessionid def getcookie(): """Returns a session ID cookie from the viewer. If they don't have a cookie, returns None.""" sitename = cgi.escape(config['required']['sitename']) cookiename = '%s_sessionid' % stripillegal(sitename) try: viewer_cookie = os.environ['HTTP_COOKIE'] except KeyError: # no cookie return # if they have a cookie, get the sessionid value and return it if viewer_cookie: cookie.load(viewer_cookie) try: sessionid = cookie[cookiename].value return sessionid # they have a cookie from the site, but none called "sitename_sessionid" except KeyError: return # no cookie, so return none else: return class FileSto: '''Class for using raw files to store data (sessionids, etc).''' def __init__(self, datafile='', sessionfile=''): self.datafile = datafile self.sessionfile = sessionfile def clear(self): """Clears data file, and makes a backup at datafile.timestamp.""" curdata = functions.read(self.datafile) # datafile doesn't exist or is empty if not curdata: return bakdatafile = 'backups/%s.%s' % (self.datafile, time.time()) didbak = functions.write(bakdatafile, curdata) if not didbak: chtml.interfacemsg = '''Could not backup data file! Check permissions of the backups directory.
''' # if it can't back up the data, make sure it doesn't clear it either return didclear = functions.write(self.datafile, "") if not didclear: chtml.interfacemsg = '''Could not clear data file! Check permissions.
''' def startsession(self): """Starts a session for a user.""" # expires in a week expires = 60 * 60 * 24 * 7 sessionid = setcookie(expires) # we hash the sessionid, so that even if someone can read the file, # they won't actually know the sessionid towrite = '%s\n' % functions.makehash(sessionid, 0) didwrite = functions.save(self.sessionfile, towrite) if not didwrite: chtml.interfacemsg = 'Error: cannot write to '
chtml.interfacemsg += 'session file! Check permissions.'
def hassession(self):
"""Checks if the viewer has a valid session.
First gets the viewer's sessionid cookie, if there is one, then checks
to see if their sessionid is valid. Returns True if they have a valid
session, and None if not."""
sessionid = getcookie()
if not sessionid:
return
valid_ids = functions.read(self.sessionfile)
if not valid_ids:
# functions.read returns False if the file doesn't exist, which will
# break the regex search
valid_ids = ''
# regex for the md5 hash of the given sid, with a newline after it
sidreg = re.compile('%s\n' % functions.makehash(sessionid, 0))
# check if the viewer's session id is in the session file
if sidreg.search(valid_ids):
return True
else:
return
class Sqlite:
'''Class for using an SQLite database to store data (sessionids, etc.)'''
def __init__(self, dbfile):
try:
import pysqlite2.dbapi2 as sqlite
self.sqlite = sqlite
except ImportError:
chtml.html = 'Content-type: text/html\n\n'
chtml.html += 'PySQLite 2 is not installed!\n
\n'
chtml.html += 'You can download it here'
chtml.display()
sys.exit()
self.dbfile = dbfile
try:
self.conn = sqlite.connect(self.dbfile)
except sqlite.OperationalError:
chtml.html = 'Content-type: text/html\n\n'
chtml.html += 'Could not read the SQLite DB. Check permissions.'
chtml.display()
sys.exit()
def clear(self):
'''Clears signup data table, and backs up the database.'''
curdata = functions.read(self.dbfile)
if not curdata:
return
bakdb = 'backups/%s.%s' % (self.dbfile, time.time())
didbak = functions.write(bakdb, curdata)
if not didbak:
chtml.interfacemsg = '''
Could not backup SQLite DB! Check permissions of the backups directory.
''' # if it can't back up the data, make sure it doesn't clear it either return c = self.conn.cursor() try: c.execute('drop table if exists signup') except self.sqlite.OperationalError: chtml.interfacemsg = '''Could not clear SQLite DB! Check permissions.
''' return c.close() self.conn.commit() def startsession(self): '''Starts session for a user.''' # open dbfile in append mode to make sure it can write to the db try: open(self.dbfile, 'a') except IOError: chtml.interfacemsg = 'Cannot write to SQLite' chtml.interfacemsg += ' database! Check permissions.
' return c = self.conn.cursor() # expires in a week expires = 60 * 60 * 24 * 7 sessionid = setcookie(expires) # we hash the sessionid, so that even if someone can read the db, # they won't actually know the sessionid sesshash = functions.makehash(sessionid, 0) try: c.execute('insert into sessions values (?)', (sesshash,)) # the sessions table doesn't exist, so create it and then rerun query except self.sqlite.OperationalError: functions.createsqlite(self.conn) c.execute('insert into sessions values (?)', (sesshash,)) c.close() self.conn.commit() def hassession(self): '''Checks db to see if viewer has a valid session. First gets the viewer's sessionid cookie, if there is one, then checks to see if their sessionid is valid. Returns True if they have a valid session, and None if not.''' sessionid = getcookie() if not sessionid: return c = self.conn.cursor() sesshash = functions.makehash(sessionid, 0) try: c.execute('select * from sessions where sessionid=?', (sesshash,)) except self.sqlite.OperationalError: # sessions table doesn't exist, so obviously aren't logged in yet return if c.fetchall(): return True else: return def changepass(): """Trys to change the admin password. First, makes sure form value "oldpass" is correct, then makes sure "newpass" and "confirmpass" match, and if so changes the password in settings.conf.""" redtext = '%s' oldpass = form['oldpass'].value curpass = config['required']['passhash'] if not functions.checkhash(curpass, oldpass): return redtext % "Old password was not right!" if "newpass" not in form or "confirmpass" not in form: return redtext % "You must specify a new password and confirm it!" newpass = form['newpass'].value confirmpass = form['confirmpass'].value if newpass != confirmpass: return redtext % "New password was not confirmed" changeto = functions.makehash(newpass, 4) config['required']['passhash'] = changeto try: config.write() except IOError: return redtext % "Can't write to settings.conf! Check permissions." return "Password changed successfully" def loginmain(): """Main function for change.py login interface.""" error = '' # check if they already have a session correct = DB.hassession() if "action" in form: if form["action"].value == "login": if "passwd" in form: password = form["passwd"].value hash = config['required']['passhash'] correct = functions.checkhash(hash, password) # if the password's right, create a session if correct: DB.startsession() # if the password is "pysignup" take them to the change # password page if password == 'pysignup': print cookie functions.redirect('?action=changepass') return # if pass is wrong, tell them it's wrong and reload else: error = 'Incorrect password!' error += '' elif form["action"].value == "changepass": msg = '' # if they at least put something for oldpass in the form, try to # change their pass if "oldpass" in form: msg = changepass() chtml.loadpass(msg) chtml.display() return # so the other forms aren't shown if not correct: # if the password isn't correct, (re)display the login form chtml.loadlogin(error) chtml.display() return correct def interfacemain(): """Main function for change.py's admin interface.""" if "action" in form: if form['action'].value == 'Change': getnchange() elif form['action'].value == 'Change and clear signup data': getnchange() DB.clear() chtml.loadinterface() chtml.display() chtml = Html() if stometh.lower() == 'sqlite': DB = Sqlite(sqlitedb) else: DB = FileSto(datafile, sessionfile) def main(): """Main function for change.py.""" # if the password is correct if loginmain(): chtml.html += "%s\n" % cookie interfacemain() if __name__ == '__main__': main()