Creating a Multiple Choice Quiz System, Part 2

 in
Designing our CGI quiz to be more robust and to include error checking.
Creating the Quiz File

So far, we have dealt with ways in which the QuizQuestions object can handle syntax errors within the quiz file. But many syntax errors are created simply by mistake or by users unfamiliar with the defined file format.

One solution is to provide users with tools for creating quiz files with fewer errors. Given the amount of time we spend writing CGI programs and HTML forms, it makes sense to create a short program that takes the contents of an HTML form and saves it to disk.

An example of one such form is shown in Listing 4. Upon submission, the form's contents are handed to create-quizfile.pl, which then creates a properly formatted quiz file.

In order to implement this feature, we need to add two new methods to QuizQuestions. One, addQuestion, takes a six-element list and adds it to questions, the instance variable containing fields from the quiz file. The second method, saveFile, does the opposite of loadFile, taking the current questions and saving them.

Here is one possible implementation of addQuestion:

sub addQuestion
{
    # Get ourselves
    my $self = shift;
    # Get our arguments
    my ($question, $a1, $a2, $a3, $a4,
                    $correct) = @_;
    # Turn our arguments into a string
    my $new_question = join("      ", @_);
    # Get our instance variable
    my @questions = @{$self->{"questions"}};
    # Add the new question
    push (@questions, $new_question);
    # Reset the instance variable
    $self->{"questions"} = \@questions;
    # Return successfully (= 0)
    return 0;
}

This version of addQuestion is fairly simple, if not very robust. For instance, it doesn't check to make sure the correct answer is one of A, B, C or D. But it does let us add new questions to the QuizQuestions object. Notice that addQuestion both retrieves and sets values for the instance variable questions.

If we were interested in extending our quiz on Emacs, we could use addQuestion in the following way:

my $error = $questions->loadFile;
&log_and_die($error) if $error;
$questions->addQuestion(
"What term describes the cursor's current location?",
  "mark", "point", "cursor", "mouse", "B");

Immediately after executing this code, $questions contains one more question. However, this question is lost upon the program's exit, because we have not yet saved the new question to the quiz file. In order to save the questions to a quiz file, define saveFile like this:

sub saveFile
{
    # Get ourselves
    my $self = shift;
    # Open the questions file for writing
    open (QUESTIONS, ">$questionDir" .
                    $self->{"quizname"}) ||
        return "Could not open " .
                    $self->{"quizname"} . " for writing";
    # Loop through the questions
    my @questions = @{$self->{"questions"}};
    my $question;
    for each $question (@questions)
    {
        print QUESTIONS $question, "\n";
    }
    close(QUESTIONS);
    return 0;
}
This code iterates through the questions, and writes them to the quiz file. Since we are writing all of the questions to disk rather than appending them, we use the > when opening the file, thereby overwriting any data that existed previously.

Since saveFile saves only the contents of the questions instance variable, it effectively obliterates comments and white space in the file. Of course, anyone creating the quiz file using a program is unlikely to look at the comments. Nonetheless, a more refined version of saveFile and the QuizQuestions object might let users add comments and white space to the file, as well as questions. (Obviously, the HTML form would also have to allow for this.)

Our version of saveFile uses the same system for reporting errors as loadFile--by returning a string, while the lack of an error is indicated by returning 0. This lets us use the following code:

$error = $questions->saveFile;
&log_and_die($error) if $error;

Now that you have seen the skeleton for create-quizfile.pl, you should have a good understanding of the program shown in Listing 5. This version of create-quizfile.pl is fairly straightforward. It checks to see if the user entered a question; if there is text for a question, it takes the remaining parameters from the HTML form submitted.

Now is a good time to remember that CGI programs that write user-defined strings to your file system are potentially dangerous, and thus must be placed in locations that are restricted to authorized users, either by using your HTTP server's built-in protection or by placing such programs behind a firewall. No matter how unlikely this may seem, a user may eventually discover that you have a program named create-quizfile.pl, and create quizzes on your system, possibly overwriting your creations.

This month, we made our quiz engine friendlier for non-programmers by checking the integrity of the quiz file and by allowing users to create quiz files using HTML forms. What happens when users want to edit quiz files? For now, they are stuck modifying the file on disk, which again opens Pandora's box of potential syntax problems. While we can discover these problems with our simple error-checking code, it might be a good idea to create a program that can edit quiz files as well as create them. Next month, we will modify create-quizfile.pl to do just that, making our quiz system easier for everyone to handle.

Reuven M. Lerner is an Internet and Web consultant living in Haifa, Israel, who has been using the Web since early 1993. In his spare time, he cooks, reads and volunteers with educational projects in his community. He can be reached via e-mail at reuven@netvision.net.il.

______________________

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix