Parent Directory
|
Revision Log
making functions.createsqlite only create table if it doesn't exist yet
"""Generic functions used by PySignup. @copyright: 2008 by Nathaniel Herman @license: GNU GPLv3, see COPYING for more 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 <http://www.gnu.org/licenses/>. ### import string, random, sys, cgi, re import smtplib import cPickle as pickle from configobj import ConfigObj # if its py2.5 or higher, import hashlib, else import md5 # this isn't going to work if it starts using sha1, etc. so a different method # will have to be used if sys.version_info >= (2, 5, 0): import hashlib as md5 else: import md5 def save(file, data): """Appends given data to a given file. If it cannot write to the file, returns None, otherwise, returns True.""" try: f = open(file, 'a') except IOError: return f.write(data) f.close() return True def write(file, data): """Overwrites a given file with the given data. If it cannot write to the file, returns None, otherwise returns True.""" try: f = open(file, 'w') except IOError: return f.write(data) f.close() return True def read(file): """Attempts to open given file and return its contents. If the file doesn't exist, returns False""" try: f = open(file, 'r') contents = f.read() f.close() except IOError: contents = False return contents def checkboolean(string): """Returns the boolean value of a given string if it were evaluated.""" truvalues = ("on", "1", "true", "yes") falvalues = ("off", "0", "false", "no") if string.lower() in truvalues: return True elif string.lower() in falvalues: return False elif not string: # if the string is blank, return false return False else: # they could've put anything thats not specifically true or false # so we'll assume true return True def createhtaccess(config): """Creates a .htaccess file if it doesn't already exist.""" createhtaccess = config["required"]["createhtaccess"] datafile = config["file"]["data-file"] sessionfile = config["file"]["session-file"] sqlitedb = config['sqlite']['sqlitedb'] # if they don't want to make a .htaccess file, just exit if not checkboolean(createhtaccess): return # Don't do anything if .htaccess already exists try: f = open(".htaccess", "r") if f.read(): return except IOError: pass # now make sure .htaccess is writable by the web server try: f = open(".htaccess", "w") htaccess = """\ DirectoryIndex index.py <FilesMatch ^(.*settings.conf.*|%s|%s|%s)$> deny from all </FilesMatch> RedirectMatch 403 /backups(/|$)""" % (datafile, sessionfile, sqlitedb) f.write(htaccess) except IOError: print "<p><b>Unable to write to .htaccess file!</b></p>" print "<p><b>Check permissions.</b></p>" def _makesalt(length): """Returns a random salt of given length.""" chars = string.letters + string.digits salt = random.sample(chars, length) return ''.join(salt) def _md5hash(password, usesalt=False, saltlength=5): """Returns the md5 hash of a given string. usesalt determines whether it should use a salt with the string, and saltlength is the length of the salt if usesalt is true. If usesalt is true, the password hash, followed by the salt will be returned.""" # initialize hash hash = md5.md5() if usesalt: salt = _makesalt(saltlength) hash.update(salt) hash.update(password) return hash.hexdigest(), salt else: hash.update(password) return hash.hexdigest() def makehash(password, saltlength=5): """Returns a hash of the given password. Currently only makes md5 hashes.""" # this allows the use of different hashing techniques in the future, # by using a different letter for the type (i.e. sha1, etc.) type = 'A' hash, salt = _md5hash(password, True, saltlength) return '%s:%s:%s' % (type, salt, hash) def checkhash(hash, password): """Checks the given password against the given hash. Returns True if they match, False if they don't.""" try: # seperate hash by each ":" type, salt, realhash = hash.split(':') # the hash is somehow invalid except: print "Invalid hash" return # this way we could add a "B" type hash, etc. which might use sha1 for # encryption as an example if type == 'A': checkhash = md5.md5() checkhash.update(salt) checkhash.update(password) return realhash == checkhash.hexdigest() else: print "Invalid hash" return def makesessionid(): """Returns a random, 20 character session id.""" # a salt is basically a bunch of random characters, which will work fine # for a session id as well id = _makesalt(20) return id def redirect(url): """Redirects browser to the given url.""" print 'Status: 302 Moved' print 'Location: %s' % url print def loadtheme(themename): """Returns the HTML to load the given theme name.""" # none of the skins use JavaScript yet, but it still includes main.js # and user.js for future skin-specific JavaScript html = """ <link rel="stylesheet" type="text/css" href="skins/%(theme)s/main.css" /> <script type="text/javascript" src="skins/%(theme)s/main.js"></script> <link rel="stylesheet" type="text/css" href="skins/%(theme)s/user.css" /> <script type="text/javascript" src="skins/%(theme)s/user.js"></script> """ % {'theme': cgi.escape(themename)} return html def escapebackslash(str): """Returns given string with all backslashes escaped. re.escape will do this as well, however re.escape also escapes all other non-alphanumeric characters.""" newstr = '' for char in str: if char == '\\': char = '\\' + char newstr += char return newstr def stripquotes(s): """Strips opening and closing quotes from given string.""" if s[0] == s[-1] and s[0] == '"': s = s[1:-1] return s def parselist(str): """Parses a comma seperated string into a Python list.""" try: # looks for anything in quotes not followed by a comma nolistreg = re.match(r'(".*?")\s*(?!,)', str.strip()).group(1) except AttributeError: nolistreg = None if ',' not in str: return stripquotes(str) elif '"' not in str: return [item.strip() for item in str.split(',')] elif nolistreg == str.strip(): return stripquotes(nolistreg) # listregex.findall will then return a list of each comma seperated entry listregex = re.compile(r''' ( (?:".*?")| # double quotes (?:[^",\#].*?) # unquoted ) (?:\s*,\s*|\s*$) # comma or the end of the string ''', re.VERBOSE) list = listregex.findall(str.strip()) list = [stripquotes(item) for item in list] return list def parsedict(str): """Parses the given dictionary-like string into a list of tuples. The given string should look something like: "key1: value1, key2: value2" Returns the result, which will be [('key1', 'value1'), ('key2', 'value2')]""" keys = [] values = [] # disabled in favor of a regex """ if '"' in str: pos = 0 list = [] quoted = False while 1: try: char = str[pos] except IndexError: list.append(str) break if char == '"': if quoted: quoted = False else: quoted = True # basically removes the current " mark from str str = str[:pos] + str[pos + 1:] continue elif char == ',' and not quoted: list.append(str[:pos]) str = str[pos + 1:] pos = 0 continue pos += 1 else: # if str doesn't contain any " marks, just split it by comma list = str.split(',') """ # the first dictregex group will match everything on the left side of a # colon, i.e. "foo" in "foo: bar", and the second group will match # everything on the right side until a comma or the end of the string. dictregex = re.compile(r''' ( (?:".*?")| # double quotes (?:[^":\#].*?) # unquoted ) (?:\s*:\s*) # colon ( (?:".*?")| # quotes (?:[^",\#].*?) # no quotes ) (?:\s*,\s*|\s*$) # comma or end of string ''', re.VERBOSE) dict = dictregex.findall(str) return dict for entry in list: entrylist = dictregex.findall(entry) print entrylist key = entrylist[0].strip() value = entrylist[1].strip() keys.append(key) values.append(value) return zip(keys, values) def mail(server, fromaddr, toaddr, subject, msg, user='', passwd=''): '''Sends an email using smtplib and the given information.''' smtp = smtplib.SMTP(server) if user: smtp.login(user, passwd) body = "To: %s\nFrom: %s\nSubject: %s\n\n%s" % (toaddr, fromaddr, subject, msg) smtp.sendmail(fromaddr, parselist(toaddr), body) def createsqlite(conn, datafields=False): '''Creates the required tables at the given SQLite database connection. conn should be a connection to an SQLite database i.e. conn = sqlite.connect('filename') datafields should be a tuple of all the datafields. If datafields is passed, the signup table will be created, otherwise, the sessions table will be created.''' c = conn.cursor() if not datafields: c.execute('create table if not exists sessions (sessionid text)') c.close() conn.commit() return columns = '%s text, ' * len(datafields) statement = 'create table if not exists signup (status text, %s passwd \ text)' % columns statement %= datafields c.execute(statement) c.close() conn.commit()
| Report a bug | ViewVC Help |
| Powered by ViewVC 1.0.5 |