summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrabhu Ramachandran2011-11-12 23:46:12 +0530
committerPrabhu Ramachandran2011-11-12 23:46:12 +0530
commitb9c42580676c0b130d3de38305a5ef18cb5e441a (patch)
tree354a20f9db8e76f621f51bed71208237d9fa2dae
parentfb31dcc7693395c9856fb19c3e867fbfa2e9b4f8 (diff)
downloadonline_test-b9c42580676c0b130d3de38305a5ef18cb5e441a.tar.gz
online_test-b9c42580676c0b130d3de38305a5ef18cb5e441a.tar.bz2
online_test-b9c42580676c0b130d3de38305a5ef18cb5e441a.zip
ENH/BUG: Python server bug and user directory
The Python server was not setting the effective gid. There was also a bug in that traceback was not imported. Added option so that the python server chdirs to a user specific directory in order that a user can save files which could be used as part of the test.
-rw-r--r--exam/views.py26
-rw-r--r--output/README.txt4
-rwxr-xr-xpython_server.py5
3 files changed, 29 insertions, 6 deletions
diff --git a/exam/views.py b/exam/views.py
index ed33c91..1cf2480 100644
--- a/exam/views.py
+++ b/exam/views.py
@@ -1,10 +1,9 @@
import random
-import sys
-import traceback
import string
+import os
+import stat
+from os.path import dirname, pardir, abspath, join, exists
-from django.db import IntegrityError
-from django.contrib.auth.models import User
from django.contrib.auth import login, logout, authenticate
from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.template import RequestContext
@@ -12,11 +11,18 @@ from exam.models import Question, Quiz, Profile, Answer
from exam.forms import UserRegisterForm, UserLoginForm
from exam.xmlrpc_clients import python_server
+# The directory where user data can be saved.
+OUTPUT_DIR = abspath(join(dirname(__file__), pardir, 'output'))
+
def gen_key(no_of_chars):
"""Generate a random key of the number of characters."""
allowed_chars = string.digits+string.uppercase
return ''.join([random.choice(allowed_chars) for i in range(no_of_chars)])
+def get_user_dir(user):
+ """Return the output directory for the user."""
+ return join(OUTPUT_DIR, str(user.username))
+
def index(request):
"""The start page.
"""
@@ -95,6 +101,15 @@ def start(request):
ip = request.META['REMOTE_ADDR']
key = gen_key(10)
new_quiz = Quiz(user=user, user_ip=ip, key=key)
+
+ # Make user directory.
+ user_dir = get_user_dir(user)
+ if not exists(user_dir):
+ os.mkdir(user_dir)
+ # Make it rwx by others.
+ os.chmod(user_dir, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH \
+ | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR \
+ | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP)
questions = [ str(_.id) for _ in Question.objects.all() ]
random.shuffle(questions)
@@ -131,7 +146,8 @@ def check(request, q_id):
# Otherwise we were asked to check. We obtain the results via XML-RPC
# with the code executed safely in a separate process (the python_server.py)
# running as nobody.
- success, err_msg = python_server.run_code(answer, question.test)
+ user_dir = get_user_dir(user)
+ success, err_msg = python_server.run_code(answer, question.test, user_dir)
# Add the answer submitted.
new_answer = Answer(question=question, answer=answer.strip())
diff --git a/output/README.txt b/output/README.txt
new file mode 100644
index 0000000..3163ed4
--- /dev/null
+++ b/output/README.txt
@@ -0,0 +1,4 @@
+This directory contains files generated/saved by users as per their
+username. The test executor will chdir into this user directory for each
+user when they run the test. Do not delete this directory and ensure that
+it is writeable by all. \ No newline at end of file
diff --git a/python_server.py b/python_server.py
index debd73d..1670f90 100755
--- a/python_server.py
+++ b/python_server.py
@@ -4,13 +4,16 @@ and returns the output. It *should* be run as root and will run as the user
'nobody' so as to minimize any damange by errant code.
"""
import sys
+import traceback
from SimpleXMLRPCServer import SimpleXMLRPCServer
import pwd
import os
+from os.path import isdir
# Set the effective uid
nobody = pwd.getpwnam('nobody')
+os.setegid(nobody.pw_gid)
os.seteuid(nobody.pw_uid)
@@ -26,7 +29,7 @@ def run_code(answer, test_code, in_dir=None):
A tuple: (success, error message).
"""
- if in_dir is not None:
+ if in_dir is not None and isdir(in_dir):
os.chdir(in_dir)
success = False