From 90cd412923fedeac8f5a4abb9b17ba787990cc53 Mon Sep 17 00:00:00 2001
From: Hostmaster of the Day <root@localhost>
Date: Fri, 1 Apr 2011 02:30:27 +0200
Subject: commited uncommited changes

---
 gen_password.py                    |   6 -
 index.py                           | 587 +++++++++++++++++++------------------
 templates/base.html                |   2 +-
 templates/delete_reminder_mail.txt |  19 ++
 templates/deleted_project_mail.txt |   4 +-
 templates/new_project.html         |  12 +-
 templates/new_project_mail.txt     |   4 +-
 templates/register.html            |   4 +-
 8 files changed, 332 insertions(+), 306 deletions(-)
 delete mode 100644 gen_password.py
 create mode 100644 templates/delete_reminder_mail.txt

diff --git a/gen_password.py b/gen_password.py
deleted file mode 100644
index 19b7781..0000000
--- a/gen_password.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import base64, cracklib, sha, string, os
-
-# generate a htpasswd compatible sha1 digest in base64 encoding
-# see: http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
-def generate_sha_base64(password):
-	print "{SHA}" + base64.encodestring(sha.new(password).digest()).rstrip('\n')
diff --git a/index.py b/index.py
index 781cc43..8922e3a 100644
--- a/index.py
+++ b/index.py
@@ -23,110 +23,111 @@ import base64, cracklib, sha, string, os, re
 
 # render mail template and send it using local sendmail binary
 def sendmail(to_addr, template, c):
-	c['from_addr'] = "dev@spline.de"
-	c['to_addr'] = to_addr
+    c['from_addr'] = "dev@spline.de"
+    c['to_addr'] = to_addr
 
-	msg = render_to_string(template + "_mail.txt", c)
+    msg = render_to_string(template + "_mail.txt", c)
 
-	# open sendmail process for writing
-	p = os.popen("/usr/sbin/sendmail -t", 'w')
-	p.write(msg)
+    # open sendmail process for writing
+    p = os.popen("/usr/sbin/sendmail -t", 'w')
+    p.write(msg.encode('utf8'))
 
-	# close will return exit status
-	# TODO: log error to some file
-	if p.close():
-		return False
+    # close will return exit status
+    # TODO: log error to some file
+    if p.close():
+        return False
 
-	return True
+    return True
 
 
 # cleanup database connection after every request
 def closedb(req):
-	req.cursor.close()
-	req.dbc.close()
+    req.cursor.close()
+    req.dbc.close()
 
 
 # start a new session and context and register the session dictionary in our
 # global template context
 def session_start(req, anonymous):
-	try:
-		req.dbc = MySQLdb.connect(host="localhost", user="apache", passwd="password", db="trac")
-	except:
-		redirect(req, "db_error")
+    try:
+        req.dbc = MySQLdb.connect(host="localhost", user="apache", passwd="password", db="trac")
+    except:
+        redirect(req, "db_error")
 
-	req.cursor = req.dbc.cursor()
-	req.register_cleanup(closedb, req)
+    req.cursor = req.dbc.cursor()
+    req.register_cleanup(closedb, req)
 
-	s = Session.Session(req)
+    s = Session.Session(req)
 
-	if not 'login' in s:
-		s['login'] = None
+    if not 'login' in s:
+        s['login'] = None
 
-	s.save()
+    s.save()
 
-	req.c = Context()
-	req.c['session'] = s
+    req.c = Context()
+    req.c['session'] = s
 
-	# None means everyone can acccess this URL
-	# True/False means only anonymous/authenticated users can access this URL
-	if anonymous != None:
-		if (anonymous and s['login']) or (not anonymous and not s['login']):
-			redirect(req, "index")
+    # None means everyone can acccess this URL
+    # True/False means only anonymous/authenticated users can access this URL
+    if anonymous != None:
+        if (anonymous and s['login']) or (not anonymous and not s['login']):
+            redirect(req, "index")
 
-	return (req.c, s, req.cursor)
+    return (req.c, s, req.cursor)
 
 
 # generate a htpasswd compatible sha1 digest in base64 encoding
 # see: http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
 def generate_sha_base64(password):
-	return "{SHA}" + base64.encodestring(sha.new(password).digest()).rstrip('\n')
+    return "{SHA}" + base64.encodestring(sha.new(password).digest()).rstrip('\n')
 
 
 # this function calls /var/www/localhost/scripts/bin/generate_users to create
 # project specific htpasswd files
+# start via http://dev.spline.de/account/genusers
 def generate_users_file(cursor):
-	cursor.execute("SELECT project_name FROM project WHERE project_name != 'ALL'")
-	projects = cursor.fetchall()
+    cursor.execute("SELECT project_name FROM project WHERE project_name != 'ALL'")
+    projects = cursor.fetchall()
 
-	for project in projects:
-		cursor.execute("SELECT DISTINCT login, password FROM project_members WHERE password IS NOT NULL AND (project_name = %s OR project_name = 'ALL')", (project[0],))
-		users = cursor.fetchall()
-		htpasswd = open("/var/www/localhost/users/" + project[0], "w")
+    for project in projects:
+        cursor.execute("SELECT DISTINCT login, password FROM project_members WHERE password IS NOT NULL AND (project_name = %s OR project_name = 'ALL')", (project[0],))
+        users = cursor.fetchall()
+        htpasswd = open("/var/www/localhost/users/" + project[0], "w")
 
-		for user in users:
-			htpasswd.write("%s:%s\n" % (user[0], user[1]))
+        for user in users:
+            htpasswd.write("%s:%s\n" % (user[0], user[1]))
 
-		htpasswd.close()
+        htpasswd.close()
 
 # generate a new random password, save it to the database and send it to the user
 # WARNING: this function will do an implicit commit/rollback to the database!
 def set_random_password(req, user_id, length):
-	req.c['new_password'] = ''.join([choice(string.letters) for i in range(length)])
+    req.c['new_password'] = ''.join([choice(string.letters) for i in range(length)])
 
-	pw_hash = generate_sha_base64(req.c['new_password'])
-	req.cursor.execute("UPDATE user SET password = %s WHERE id = %s", (pw_hash, user_id))
+    pw_hash = generate_sha_base64(req.c['new_password'])
+    req.cursor.execute("UPDATE user SET password = %s WHERE id = %s", (pw_hash, user_id))
 
-	req.cursor.execute("SELECT email FROM user WHERE id = %s", (user_id,))
-	result = req.cursor.fetchone()
-	email = result[0]
+    req.cursor.execute("SELECT email FROM user WHERE id = %s", (user_id,))
+    result = req.cursor.fetchone()
+    email = result[0]
 
-	req.cursor.execute("SELECT login FROM user WHERE id = %s AND password IS NOT NULL", (user_id,))
-	result = req.cursor.fetchone()
+    req.cursor.execute("SELECT login FROM user WHERE id = %s AND password IS NOT NULL", (user_id,))
+    result = req.cursor.fetchone()
 
-	if not result:
-		template = 'registration'
-	else:
-		req.c['login'] = result[0]
-		template = 'password'
+    if not result:
+        template = 'registration'
+    else:
+        req.c['login'] = result[0]
+        template = 'password'
 
-	if not sendmail(email, template, req.c):
-		req.dbc.rollback()
-		return "failed to send temporary password. sorry."
+    if not sendmail(email, template, req.c):
+        req.dbc.rollback()
+        return "failed to send temporary password. sorry."
 
-	# otherwise commit to database and confirm
-	req.dbc.commit()
-	generate_users_file(req.cursor)
-	return None
+    # otherwise commit to database and confirm
+    req.dbc.commit()
+    generate_users_file(req.cursor)
+    return None
 
 
 # Ditch nonsense email addresses.
@@ -166,47 +167,47 @@ def invalid(emailaddress, domains = GENERIC_DOMAINS):
 
 
 def validate_and_register(req, login, email):
-	# check for invalid entries
+    # check for invalid entries
 
-	# empty login
-	if login == "":
-		return "please enter a username"
+    # empty login
+    if login == "":
+        return "please enter a username"
 
-	if not re.match("^[a-z._]{3,25}$", login):
-		return "your login is either too long, too short, or contains other characters than [a-z] including . and _"
+    if not re.match("^[a-z._]{3,25}$", login):
+        return "your login is either too long, too short, or contains other characters than [a-z] including . and _"
 
-	# no fu-berlin.de address
-	if not email.endswith('.fu-berlin.de'):
-		return "you did not give a &nbsp;*.fu-berlin.de address"
+    # no fu-berlin.de address
+    if not email.endswith('fu-berlin.de'):
+        return "you did not give a &nbsp;*.fu-berlin.de address"
 
-	# regex checker for valid email
-	if invalid(email):
-		return "please enter a valid email address"
+    # regex checker for valid email
+    if invalid(email):
+        return "please enter a valid email address"
 
-	req.cursor.execute("SELECT login FROM user WHERE login = %s", (login, ))
-	if req.cursor.fetchone():
-		return "username already taken, please choose another one"
+    req.cursor.execute("SELECT login FROM user WHERE login = %s", (login, ))
+    if req.cursor.fetchone():
+        return "username already taken, please choose another one"
 
-	req.cursor.execute("SELECT login FROM user WHERE email = %s", (email, ))
-	if req.cursor.fetchone():
-		return 'you already have an account! <a href="password">forgot your password?</a>'
+    req.cursor.execute("SELECT login FROM user WHERE email = %s", (email, ))
+    if req.cursor.fetchone():
+        return 'you already have an account! <a href="password">forgot your password?</a>'
 
-	# entries are valid - generate activation code and prepare insert statements
-	hash = ''.join([choice(string.letters) for i in range(10)])
-	req.cursor.execute("INSERT INTO user (login, email, date_added) VALUES (%s, %s, NOW())", (login, email))
-	req.cursor.execute("INSERT INTO activation (hash, user_id) VALUES (%s, LAST_INSERT_ID())", (hash, ))
+    # entries are valid - generate activation code and prepare insert statements
+    hash = ''.join([choice(string.letters) for i in range(10)])
+    req.cursor.execute("INSERT INTO user (login, email, date_added) VALUES (%s, %s, NOW())", (login, email))
+    req.cursor.execute("INSERT INTO activation (hash, user_id) VALUES (%s, LAST_INSERT_ID())", (hash, ))
 
-	# send confirmation email to applicant
-	req.c['activation_link'] = "https://dev.spline.de/account/activate?hash=" + hash
+    # send confirmation email to applicant
+    req.c['activation_link'] = "https://dev.spline.de/account/activate?hash=" + hash
 
-	# in case of an error, rollback
-	if not sendmail(email, 'activation', req.c):
-		req.dbc.rollback()
-		return "failed to send confirmation link."
+    # in case of an error, rollback
+    if not sendmail(email, 'activation', req.c):
+        req.dbc.rollback()
+        return "failed to send confirmation link."
 
-	# otherwise commit to database
-	req.dbc.commit()
-	return None
+    # otherwise commit to database
+    req.dbc.commit()
+    return None
 
 
 ###############################
@@ -215,299 +216,303 @@ def validate_and_register(req, login, email):
 
 # req = request
 def index(req):
-	(c, s, cursor) = session_start(req, None)
-	return render_to_string("index.html", c)
+    (c, s, cursor) = session_start(req, None)
+    return render_to_string("index.html", c)
 
 
 def activate(req, **formdata):
-	(c, s, cursor) = session_start(req, True)
+    (c, s, cursor) = session_start(req, True)
 
-	# check whether a (correct) hashcode is given in the url
-	if "hash" in formdata and ('activated' not in s or not s['activated']):
-		cursor.execute("SELECT user_id FROM activation WHERE hash = %s", (formdata['hash'],))
-		result = cursor.fetchone()
+    # check whether a (correct) hashcode is given in the url
+    if "hash" in formdata and ('activated' not in s or not s['activated']):
+        cursor.execute("SELECT user_id FROM activation WHERE hash = %s", (formdata['hash'],))
+        result = cursor.fetchone()
 
-		if not result:
-			c['error_msg'] = "invalid activation code"
-		else:
-			user_id = result[0]
-			cursor.execute("DELETE FROM activation WHERE user_id = %s", (user_id,))
-			cursor.execute("UPDATE user SET activated = 1 WHERE id = %s", (user_id,))
+        if not result:
+            c['error_msg'] = "invalid activation code"
+        else:
+            user_id = result[0]
+            cursor.execute("DELETE FROM activation WHERE user_id = %s", (user_id,))
+            cursor.execute("UPDATE user SET activated = 1 WHERE id = %s", (user_id,))
 
-			# send email containing a temporary password
-			c['error_msg'] = set_random_password(req, user_id, 8)
+            # send email containing a temporary password
+            c['error_msg'] = set_random_password(req, user_id, 8)
 
-			if not c['error_msg']:
-				s['activated'] = True
-				s.save()
-				c['info_msg'] = "your account has been activated. you will receive an email with a temporary password."
+            if not c['error_msg']:
+                s['activated'] = True
+                s.save()
+                c['info_msg'] = "your account has been activated. you will receive an email with a temporary password."
 
-	return render_to_string("index.html", c)
+    return render_to_string("index.html", c)
 
 
 def login(req, **formdata):
-	(c, s, cursor) = session_start(req, True)
+    (c, s, cursor) = session_start(req, True)
 
-	if req.method == "POST":
-		pw_hash = generate_sha_base64(formdata['password'])
-		cursor.execute("SELECT * FROM user WHERE login = %s AND password = %s AND activated = 1", (formdata['login'], pw_hash))
+    if req.method == "POST":
+        pw_hash = generate_sha_base64(formdata['password'])
+        cursor.execute("SELECT * FROM user WHERE login = %s AND password = %s AND activated = 1", (formdata['login'], pw_hash))
 
-		if not cursor.fetchone():
-			c['error_msg'] = "Login failed. Sorry."
-			return render_to_string("index.html", c)
-		else:
-			s['login'] = formdata['login']
-			s.save()
+        if not cursor.fetchone():
+            c['error_msg'] = "Login failed. Sorry."
+            return render_to_string("index.html", c)
+        else:
+            s['login'] = formdata['login']
+            s.save()
 
-	redirect(req, 'index')
+    redirect(req, 'index')
 
 
 def logout(req):
-	(c, s, cursor) = session_start(req, False)
-	s['login'] = None
-	s.save()
-	redirect(req, 'index')
+    (c, s, cursor) = session_start(req, False)
+    s['login'] = None
+    s.save()
+    redirect(req, 'index')
 
 
 def register(req, **formdata):
-	(c, s, cursor) = session_start(req, True)
+    (c, s, cursor) = session_start(req, True)
 
-	if req.method == "POST":
-		c['error_msg'] = validate_and_register(req, formdata['login'], formdata['email'])
-		if not c['error_msg']:
-			c['info_msg'] = "we have sent an email to " + formdata['email'] + " with your confirmation link"
-			return render_to_string("index.html", c)
+    if req.method == "POST":
+        c['error_msg'] = validate_and_register(req, formdata['login'], formdata['email'])
+        if not c['error_msg']:
+            c['info_msg'] = "we have sent an email to " + formdata['email'] + " with your confirmation link"
+            return render_to_string("index.html", c)
 
-	return render_to_string("register.html", c)
+    return render_to_string("register.html", c)
 
 
 def password(req, **formdata):
-	(c, s, cursor) = session_start(req, True)
+    (c, s, cursor) = session_start(req, True)
 
-	if req.method == 'POST':
-		cursor.execute("SELECT id FROM user WHERE email = %s", (formdata['email'],))
-		result = cursor.fetchone()
+    if req.method == 'POST':
+        cursor.execute("SELECT id FROM user WHERE email = %s", (formdata['email'],))
+        result = cursor.fetchone()
 
-		if not result:
-			c['error_msg'] = "unknown email address"
-		else:
-			c['error_msg'] = set_random_password(req, result[0], 8)
+        if not result:
+            c['error_msg'] = "unknown email address"
+        else:
+            c['error_msg'] = set_random_password(req, result[0], 8)
 
-		if not c['error_msg']:
-			c['info_msg'] = "a new temporary password has been sent to your email address"
-			return render_to_string("index.html", c)
+        if not c['error_msg']:
+            c['info_msg'] = "a new temporary password has been sent to your email address"
+            return render_to_string("index.html", c)
 
-	return render_to_string("password.html", c)
+    return render_to_string("password.html", c)
 
 
 def profile(req, **formdata):
-	(c, s, cursor) = session_start(req, False)
+    (c, s, cursor) = session_start(req, False)
 
-	if req.method == 'POST':
-		old_pw_hash = generate_sha_base64(formdata['old_pw'])
-		cursor.execute("SELECT * FROM user WHERE password = %s AND login = %s", (old_pw_hash,s['login']))
+    if req.method == 'POST':
+        old_pw_hash = generate_sha_base64(formdata['old_pw'])
+        cursor.execute("SELECT * FROM user WHERE password = %s AND login = %s", (old_pw_hash,s['login']))
 
-		new_pw_bad = cracklib.FascistCheck(formdata['new_pw1'])
+        if not cursor.fetchone():
+            c['error_msg'] = "old pasword did not match"
 
-		if not cursor.fetchone():
-			c['error_msg'] = "old pasword did not match"
+        elif formdata['new_pw1'] != formdata['new_pw2']:
+            c['error_msg'] = "new passwords did not match"
 
-		elif formdata['new_pw1'] != formdata['new_pw2']:
-			c['error_msg'] = "new passwords did not match"
+        else:
+            try:
+                cracklib.FascistCheck(formdata['new_pw1'])
 
-		elif new_pw_bad:
-			c['error_msg'] = "cannot accept new password: " + new_pw_bad
+                new_pw_hash = generate_sha_base64(formdata['new_pw1'])
+                cursor.execute("UPDATE user SET password = %s WHERE login = %s", (new_pw_hash, s['login']))
+                req.dbc.commit()
+                generate_users_file(req.cursor)
+                c['info_msg'] = "new password has been set"
 
-		else:
-			new_pw_hash = generate_sha_base64(formdata['new_pw1'])
-			cursor.execute("UPDATE user SET password = %s WHERE login = %s", (new_pw_hash, s['login']))
-			req.dbc.commit()
-			generate_users_file(req.cursor)
+                return render_to_string("index.html", c)
+            except ValueError, ex:
+                c['error_msg'] = "cannot accept new password: " + ex.message
 
-			c['info_msg'] = "new password has been set"
-			return render_to_string("index.html", c)
 
-	cursor.execute("SELECT email FROM user WHERE login = %s", (s['login'],))
-	result = cursor.fetchone()
-	c['email'] = result[0]
+    cursor.execute("SELECT email FROM user WHERE login = %s", (s['login'],))
+    result = cursor.fetchone()
+    c['email'] = result[0]
 
-	return render_to_string("profile.html", c)
+    return render_to_string("profile.html", c)
 
 
 def projects(req, **formdata):
-	(c, s, cursor) = session_start(req, False)
-
-	if "action" in formdata and "proj_name" in formdata:
-		if formdata['action'] == "leave":
-			cursor.execute("select count(*) from member where project_id = (select id from project where project_name = %s)")
-			result = cursor.fetchone()
-			if result[0] == 1:
-				c['error_msg'] = "you cannot leave this project! you're its only member! maybe you want to delete it?"
-			else:
-				cursor.execute("delete from member where user_id = (select id from user where login = %s) "
-					+ "and project_id = (select id from project where project_name = %s)", (s['login'], formdata['proj_name']))
-				req.dbc.commit()
-				generate_users_file(req.cursor)
-				c['info_msg'] = "you left project " + formdata['proj_name']
-
-		elif formdata['action'] == "delete":
-			# check whether the person is member of the project he or she wants to delete
-			cursor.execute("select * from member where user_id = (select id from user where login = %s) "
-				+ "and project_id = (select id from project where project_name = %s)", (s['login'], formdata['proj_name']))
-			if cursor.fetchone() != None:
-				cursor.execute("update project set deleted = 1 where project_name = %s", (formdata['proj_name'],))
-				req.dbc.commit()
-				c['info_msg'] = "you deleted project " + formdata['proj_name']
-				c['proj_name'] = formdata['proj_name']
-				sendmail("dev@spline.de", "deleted_project", c)
-
-	cursor.execute("select project_name from project p join member m on m.project_id = p.id join user u on u.id = m.user_id where p.deleted <> 1 and u.login = %s", (s['login'],))
-	c['projects'] = cursor.fetchall()
-
-	return render_to_string("projects.html", c)
+    (c, s, cursor) = session_start(req, False)
+
+    if "action" in formdata and "proj_name" in formdata:
+        if formdata['action'] == "leave":
+            cursor.execute("select count(*) from member where project_id = (select id from project where project_name = %s)", (formdata['proj_name'],))
+            result = cursor.fetchone()
+            if result[0] == 1:
+                c['error_msg'] = "you cannot leave this project! you're its only member! maybe you want to delete it?"
+            else:
+                cursor.execute("delete from member where user_id = (select id from user where login = %s) "
+                    + "and project_id = (select id from project where project_name = %s)", (s['login'], formdata['proj_name']))
+                req.dbc.commit()
+                generate_users_file(req.cursor)
+                c['info_msg'] = "you left project " + formdata['proj_name']
+
+        elif formdata['action'] == "delete":
+            # check whether the person is member of the project he or she wants to delete
+            cursor.execute("select * from member where user_id = (select id from user where login = %s) "
+                + "and project_id = (select id from project where project_name = %s)", (s['login'], formdata['proj_name']))
+            if cursor.fetchone() != None:
+                cursor.execute("update project set deleted = 1 where project_name = %s", (formdata['proj_name'],))
+                req.dbc.commit()
+                c['info_msg'] = "you deleted project " + formdata['proj_name']
+                c['proj_name'] = formdata['proj_name']
+                sendmail("dev@spline.de", "deleted_project", c)
+
+    cursor.execute("select project_name from project p join member m on m.project_id = p.id join user u on u.id = m.user_id where p.deleted <> 1 and u.login = %s", (s['login'],))
+    c['projects'] = cursor.fetchall()
+
+    return render_to_string("projects.html", c)
 
 
 def imprint(req):
-	(c, s, cursor) = session_start(req, None)
-	return render_to_string("imprint.html", c)
+    (c, s, cursor) = session_start(req, None)
+    return render_to_string("imprint.html", c)
 
 def contact(req):
-	(c, s, cursor) = session_start(req, None)
-	return render_to_string("contact.html", c)
+    (c, s, cursor) = session_start(req, None)
+    return render_to_string("contact.html", c)
 
 def new_project(req, **formdata):
-	(c, s, cursor) = session_start(req, False)
+    (c, s, cursor) = session_start(req, False)
 
-	if req.method == "POST":
-		c['name'] = formdata['project_name']
-		c['desc'] = formdata['project_desc']
-		c['priv'] = formdata['priv']
+    umlauts = False
+    if req.method == "POST":
+        c['name'] = formdata['project_name']
+        c['desc'] = formdata['project_desc']
+        c['priv'] = formdata['priv']
 
-		cursor.execute("SELECT email FROM user WHERE login = %s", (s['login'],))
-		c['email'] = cursor.fetchone()[0]
+        cursor.execute("SELECT email FROM user WHERE login = %s", (s['login'],))
+        c['email'] = cursor.fetchone()[0]
 
-		cursor.execute("SELECT id FROM project WHERE project_name = %s", (c['name'], ))
-		if cursor.fetchone():
-			c['error_msg'] = "project %s already exists." % c['name']
-		elif len(c['name']) < 3:
-			c['error_msg'] = "project name must be at least 3 chars long"
-		elif len(c['desc']) < 0:
-			c['error_msg'] = "project description may not be empty"
-		else:
-			# send message to dev.spline.de
-			sendmail("dev@spline.de", "new_project", c)
+        cursor.execute("SELECT id FROM project WHERE project_name = %s", (c['name'], ))
+        if cursor.fetchone():
+            c['error_msg'] = "project %s already exists." % c['name']
+        elif len(c['name']) < 3:
+            c['error_msg'] = "project name must be at least 3 chars long"
+        elif len(c['desc']) < 0:
+            c['error_msg'] = "project description may not be empty"
+        elif c['name'] == "test":
+            c['error_msg'] = "NO TEST PROJECTS"
+        else:
+            # send message to dev.spline.de
+            sendmail("dev@spline.de", "new_project", c)
 
-			# confirm to user
-			c['info_msg'] = "your application has been sent to the dev.spline.de team. you'll receive a message shortly"
-			return render_to_string("index.html", c)
+            # confirm to user
+            c['info_msg'] = "your application has been sent to the dev.spline.de team. you'll receive a message shortly"
+            return render_to_string("index.html", c)
 
-	return render_to_string("new_project.html", c)
+    return render_to_string("new_project.html", c)
 
 
 def members(req, **formdata):
-	(c, s, cursor) = session_start(req, False)
+    (c, s, cursor) = session_start(req, False)
 
-	if not "proj_name" in formdata:
-		redirect(req,"index")
+    if not "proj_name" in formdata:
+        redirect(req,"index")
 
-	proj = formdata['proj_name']
+    proj = formdata['proj_name']
 
-	cursor.execute("select id from project where project_name = %s", (proj,))
-	result = cursor.fetchone()
+    cursor.execute("select id from project where project_name = %s", (proj,))
+    result = cursor.fetchone()
 
-	if not result:
-		c['error_msg'] = "project '%s' does not exist" % proj
-		return render_to_string("index.html", c)
+    if not result:
+        c['error_msg'] = "project '%s' does not exist" % proj
+        return render_to_string("index.html", c)
 
-	project_id = result[0]
+    project_id = result[0]
 
-	# if he/she wants to add/delete members, the logged in user must be a member of the project, too
-	cursor.execute("select * from member where user_id = (select id from user where login = %s) "
-		+ "and project_id = %s", (s['login'], project_id))
+    # if he/she wants to add/delete members, the logged in user must be a member of the project, too
+    cursor.execute("select * from member where user_id = (select id from user where login = %s) "
+        + "and project_id = %s", (s['login'], project_id))
 
-	if cursor.fetchone() == None:
-		c['error_msg'] = "you are not a member of project '%s'" % proj
+    if cursor.fetchone() == None:
+        c['error_msg'] = "you are not a member of project '%s'" % proj
 
-	elif "login" in formdata and "action" in formdata:
-		who = formdata['login']
-		what = formdata['action']
+    elif "login" in formdata and "action" in formdata:
+        who = formdata['login']
+        what = formdata['action']
 
-		cursor.execute("select id from user where login = %s", (who, ))
-		result = cursor.fetchone()
+        cursor.execute("select id from user where login = %s", (who, ))
+        result = cursor.fetchone()
 
-		if result:
-			user_id = result[0]
+        if result:
+            user_id = result[0]
 
-			if what == "delete":
-				cursor.execute("delete from member where user_id = %s and project_id = %s", (user_id, project_id))
-				req.dbc.commit()
-				generate_users_file(req.cursor)
-				c['info_msg'] = "you deleted " + who + " from project " + proj
+            if what == "delete":
+                cursor.execute("delete from member where user_id = %s and project_id = %s", (user_id, project_id))
+                req.dbc.commit()
+                generate_users_file(req.cursor)
+                c['info_msg'] = "you deleted " + who + " from project " + proj
 
-			elif what == "add":
-				cursor.execute("select * from member where user_id = %s and project_id = %s", (user_id, project_id));
-				if cursor.fetchone() == None:
-					cursor.execute("insert into member (user_id, project_id) values (%s, %s)", (user_id, project_id))
-					req.dbc.commit()
-					generate_users_file(req.cursor)
-					c['info_msg'] = "you added " + who + " to project " + proj
-				else:
-					c['error_msg'] = who + " is already a member of project " + proj
+            elif what == "add":
+                cursor.execute("select * from member where user_id = %s and project_id = %s", (user_id, project_id));
+                if cursor.fetchone() == None:
+                    cursor.execute("insert into member (user_id, project_id) values (%s, %s)", (user_id, project_id))
+                    req.dbc.commit()
+                    generate_users_file(req.cursor)
+                    c['info_msg'] = "you added " + who + " to project " + proj
+                else:
+                    c['error_msg'] = who + " is already a member of project " + proj
 
-		else:
-			c['error_msg'] = "invalid user name"
+        else:
+            c['error_msg'] = "invalid user name"
 
-	cursor.execute("select login from user u join member m on u.id = m.user_id "
-			+ "where m.project_id = (select id from project where project_name = %s)", (proj,))
-	c['members'] = cursor.fetchall()
-	c['proj'] = proj
+    cursor.execute("select login from user u join member m on u.id = m.user_id "
+            + "where m.project_id = (select id from project where project_name = %s)", (proj,))
+    c['members'] = cursor.fetchall()
+    c['proj'] = proj
 
-	return render_to_string("members.html", c)
+    return render_to_string("members.html", c)
 
 
 def del_profile(req):
-	(c, s, cursor) = session_start(req, False)
+    (c, s, cursor) = session_start(req, False)
 
-	cursor.execute("delete from user where login = %s", (s['login'], ))
-	req.dbc.commit()
-	generate_users_file(req.cursor)
+    cursor.execute("delete from user where login = %s", (s['login'], ))
+    req.dbc.commit()
+    generate_users_file(req.cursor)
 
-	s['login'] = None
-	s.save()
+    s['login'] = None
+    s.save()
 
-	c['info_msg'] = "your profile has been deleted successfully"
+    c['info_msg'] = "your profile has been deleted successfully"
 
-	return render_to_string("index.html", c)
+    return render_to_string("index.html", c)
 
 
 def list_projects(req):
-	(c, s, cursor) = session_start(req, None)
+    (c, s, cursor) = session_start(req, None)
 
-	cursor.execute("SELECT project_name FROM project WHERE private = 0 AND project_name != 'ALL' ORDER BY project_name")
-	result = cursor.fetchall()
+    cursor.execute("SELECT project_name FROM project WHERE private = 0 AND project_name != 'ALL' ORDER BY project_name")
+    result = cursor.fetchall()
 
-	c['public_projects'] = []
+    c['public_projects'] = []
 
-	for project in result:
-		ini = trac.config.Configuration('/var/lib/trac/' + project[0] + '/conf/trac.ini')
-		c['public_projects'].append((project[0], ini.get('project', 'name'), ini.get('project','descr')))
+    for project in result:
+        ini = trac.config.Configuration('/var/lib/trac/' + project[0] + '/conf/trac.ini')
+        c['public_projects'].append((project[0], ini.get('project', 'name'), ini.get('project','descr')))
 
-	cursor.execute("SELECT project_name FROM project WHERE private = 1 AND project_name != 'ALL' ORDER BY project_name")
-	result = cursor.fetchall()
+    cursor.execute("SELECT project_name FROM project WHERE private = 1 AND project_name != 'ALL' ORDER BY project_name")
+    result = cursor.fetchall()
 
-	c['private_projects'] = []
+    c['private_projects'] = []
 
-	for project in result:
-		ini = trac.config.Configuration('/var/lib/trac/' + project[0] + '/conf/trac.ini')
-		c['private_projects'].append((project[0], ini.get('project', 'name'), ini.get('project','descr')))
+    for project in result:
+        ini = trac.config.Configuration('/var/lib/trac/' + project[0] + '/conf/trac.ini')
+        c['private_projects'].append((project[0], ini.get('project', 'name'), ini.get('project','descr')))
 
-	return render_to_string("list_projects.html", c)
+    return render_to_string("list_projects.html", c)
 
 
 def genusers(req):
-	(c, s, cursor) = session_start(req, None)
-	generate_users_file(cursor)
-	return "OK"
+    (c, s, cursor) = session_start(req, None)
+    generate_users_file(cursor)
+    return "OK"
 
 # this is returned whenever a db error occurs
 def db_error(req):
diff --git a/templates/base.html b/templates/base.html
index 6e04fea..200a316 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -58,7 +58,7 @@
               <p><a href="password">I forgot my password</a></p>
             </div>
             <div id="register" class="navbox">
-              <p>Don't have a dev.spline.de account?<br/><br/>
+              <p>You don't have a dev.spline.de account?<br/><br/>
               <a href="register">Create an account now</a></p>
             </div>
             {% endif %}
diff --git a/templates/delete_reminder_mail.txt b/templates/delete_reminder_mail.txt
new file mode 100644
index 0000000..44e76b6
--- /dev/null
+++ b/templates/delete_reminder_mail.txt
@@ -0,0 +1,19 @@
+From: {{ from_addr }}
+Subject: dev reminder
+To: {{ to_addr }}
+
+Hi {{ name }},
+
+you are member of one or more dev.spline.de project(s):
+{{ projects }}
+if any of your projects is no longer needed we ask you to delete it.
+you will be supplied with a full backup of your project, so no data will be
+lost in case you may need it later.
+
+!you should not delete projects that other people might still be using!
+
+to delete projects, log in to https://dev.spline.de and click on 'my projects'.
+next to each project name you will find a link to delete the project.
+
+Yours,
+	dev.spline.de
diff --git a/templates/deleted_project_mail.txt b/templates/deleted_project_mail.txt
index c75aa54..cdb9a3a 100644
--- a/templates/deleted_project_mail.txt
+++ b/templates/deleted_project_mail.txt
@@ -4,8 +4,8 @@ To: {{ to_addr }}
 
 Hi dev.spline.de team,
 
-{{ session.login }} requested the deletion of project {{ proj_name }}.
-Please take care of it ASAP.
+{{ session.login }} requested the deletion of project {{ proj_name }}
+Please take care of it soon (but at your convenience, of course!).
 
 Yours,
 	dev.spline.de
diff --git a/templates/new_project.html b/templates/new_project.html
index f89ad0a..0efc2bd 100644
--- a/templates/new_project.html
+++ b/templates/new_project.html
@@ -12,13 +12,19 @@
 			<label for="name">project name</label>
 			<input id="name" type="text" name="project_name" value="your project's name" onfocus="clearInput('name')"/>
 			</li>
+      <li><p style="margin-bottom:-10px;"><strong>How should I name my project?</strong></p><br/>
+      We would be grateful if you could give your project an unambiguous name. For example, calling your
+      project <em class="black">mafi3</em> would definitely NOT be unambiguous, but <em class="black">loginname_ss2010_mafi3</em> would be well chosen.<br/>
+      We also do prefer lower-case letters, no white space and no dots in the project name. And there will be NO projects called <em class="black">test</em>.
+      If you were just about to write 'test', forget it! No! There will be no test projects!
+      </li>
 			<li>
 			<label for="desc">project description</label>
 			<textarea id="desc" style="width: 70%;" type="text" name="project_desc" onfocus="clearInput('desc')" rows="10" maxlength="500">describe your project here</textarea>
 			</li>
 			<li>
 			<fieldset>
-				<legend>i want my project to be <em>*</em></legend>
+        <legend>i want my project to be <strong><em>*</em></strong></legend>
 					<label><input type="radio" name="priv" value="open" checked="checked" /> open</label>
 					<label><input type="radio" name="priv" value="private" /> private</label>
 			</fieldset>
@@ -29,7 +35,7 @@
 </form>
 <hr style="margin: 20px 0 10px; width: 40%; color: #C9DCA6;" />
 <p style="width: 85%; font-size:11px; color:dark-gray; text-align:justify;">
-<em>*</em> it is recommended that your project is <em>open</em>. this means read-access for everyone (<em>open source!</em>).<br/>
-a <em>private</em> project will grant read- and write-access only to its members.
+<strong><em>*</em> It is recommended that your project is <em>open</em>. this means read- (but not write-) access for everyone (<em>open source!</em>).
+  A <em>private</em> project will grant read- and write-access only to its members.</strong>
 </p>
 {% endblock %}
diff --git a/templates/new_project_mail.txt b/templates/new_project_mail.txt
index 3a056c4..e9ea91d 100644
--- a/templates/new_project_mail.txt
+++ b/templates/new_project_mail.txt
@@ -2,10 +2,12 @@ From: {{ from_addr }}
 Reply-To: {{ email }}
 Subject: new project application from {{ session.login }} !
 To: {{ to_addr }}
+Content-Type: text/plain; charset="utf8"
+Content-Transfer-Encoding: 8bit
 
 hello dev.spline.de,
 
-{{ session.login }} has applied for a new project called {{ name }}.
+{{ session.login }} has applied for a new project called {{ name }}
 
 the description is:
 {{ desc }}
diff --git a/templates/register.html b/templates/register.html
index 1b579f3..f197ab0 100644
--- a/templates/register.html
+++ b/templates/register.html
@@ -17,7 +17,7 @@
 				</li>
 				<li>
 				<label for="email">E-Mail</label>
-				<input id="email_input" type="text" name="email" value="you@*.fu-berlin.de" onfocus="clearInput('email_input')"/>
+				<input id="email_input" type="text" name="email" value="you@*fu-berlin.de" onfocus="clearInput('email_input')"/>
 				</li>
 			</ol>
 		</fieldset>
@@ -27,7 +27,7 @@
 
 	<div class="c33r">
 		<div class="infobox">
-			<h1>I do not have a &nbsp;*.fu-berlin.de email address!</h1>
+			<h1>I do not have a &nbsp;*fu-berlin.de email address!</h1>
 			<p>
 			In this case write an email to <a href="mailto:dev@spline.de">dev@spline.de</a> and
 			give a good reason why you need a dev.spline.de account.
-- 
cgit v1.2.3