TDDI48 Project, Part 5: Extensions to the Message Forum

Written by Jonas Kvarnström. Please report any bugs, inconsistencies or vague requirements as soon as possible. Please include the course code "TDDI48" in the subject!

Below you can choose between a number of extensions to the message forum system. We would also like to encourage you to invent your own extensions, in case there are other aspects of web programming that you would like to explore. If you do invent your own extensions, please send the examiner a mail with a resonably detailed description of the extension for approval – in English, and sufficiently detailed for future inclusion in this list of extensions – and we will discuss how many "extension points" should be assigned. For example, you could make extensions using JavaScript, or maybe use AJAX to allow users to quickly preview the contents of a message topic when hovering over a topic title or to view information about the author of a message when hovering over the author's name. These are only examples, and we are sure that you can come up with other variations.

The main criteria used for determining your final grade are related to code quality and usability, where higher grades naturally require a higher quality throughout your project. This is also affected by the number of people in the group, where groups of 3 must achieve considerably higher quality to achieve any given grade.

However, as a secondary tool we also require a greater number of extensions to be implemented for higher grades, according to the table below. Note that because parts 1 and 2 of the project would correspond to at least 50 points on this scale, the difference in total workload is in fact quite small: One person requires 5 extension points for a total of 55 points for grade 3, while three persons require 12 extension points (more than twice as much work in this part of the project) for a total of 62 points (only 12 percent more work for the complete project).

We repeat, once again: Extension points are only a secondary criterion used to determine grades. If your project is lacking in usability or code quality, your grade will not be higher than the overall project quality allows. Spending all your time trying to achieve enough extension points for grade 5 may be a bad idea if your overall project quality is at level 3!

Group sizeGrade 3Grade 4Grade 5
1 (alone)at least 5 pointsat least 9 pointsat least 15 points
2at least 7 pointsat least 12 pointsat least 21 points
3at least 12 pointsat least 21 pointsat least 30 points

Some of these extensions are specified in much less detail than the previous exercises. The idea is that you should have some more freedom in exactly how you implement them and what aspects you choose to concentrate on. Please don't abuse this freedom by trying to do as little as possible while still not exactly breaking the rules. Spend a reasonable amount of effort on each extension. If in doubt, consider what you would expect from this application if you were using it, not developing it.

Many of these extensions are new. We have tried to make sure they contain sufficient and correct information, but there may be omissions or plain mistakes that are only detected when a large number of students start implementing them. If so, we will attempt to update this web page as quickly as possible. Please ask a lab assistant if something is unclear, and report any problems to jonkv@ida.liu.se as soon as possible! Please include the course code "TDDI48" in the subject.

Recent changes and updates

No changes since the first version for 2007.

[+/-] Extension 1: Message Trees (2p)

In the basic implementation of the forum, messages within a single topic are always shown in date order. This means replies end up far from original messages and that there is no easy way of skipping a particular subtree.

Extend the message system to support message trees, where replies are linked to their original messages.

The database will have to be extended, so that for each message you store not only a message ID and topic ID but also the ID of the parent message. Message roots (the messages that start a new topic) can for example be indicated by having a parent ID of -1. Use the ALTER TABLE SQL command to add columns to a table. If you don't know anything about ALTER TABLE, use Google to find some information!

When someone starts a new topic, the parent ID of the initial message should be set to -1. All other messages within that topic should be created as replies (comments) to some existing message within the topic. This means there has to be a reply link or button for each message, rather than just one for the entire topic.

The message viewer must be extended to show messages in a nested tree format, where a reply is shown indented below its original. See the IntelliJ Forums for an example. One way of achieving this is using a separate table for each message, where the leftmost column is empty and has a width proportional to the nesting depth. A better method would be using a DIV tag where you specify an explicit left margin using a style attribute.

Here's an example of an indented paragraph.

And another one, nested another level.

SCALABILITY: You should still only show a limited number of messages per page.

[+/-] Extension 2: Administrative Interface (2p)

In the basic version of the project, you are permitted to make all the functionality of the web forum available to any use who is logged in. This is naturally not a good idea in a real web forum. In this extension, you should implement separate access levels for administrators and common users.

You should be able to make any user an administrator by setting a special flag on his account. Naturally only an administrator should be able to make someone else an administrator!

You probably already have a number of servlets and JSP documents that should only be available to administrators. Decide for yourselves which ones should be protected.

The administrator should also be able to delete messages from the forum.

If you have implemented message trees, deleting leaves is "harmless" but you should be careful about allowing anyone to delete "inner" messages. You should warn the user that he is about to delete an inner message and ask him to confirm; if he agrees, you should make sure the children of the deleted message are instead made children of the parent of the deleted message, so that they are not suddenly "disconnected" from the message tree. Alternatively, you could simply remove the message text without actually deleting the message.

PROBLEM: The method described above does not work if you delete the root post (the original post in the message tree). Decide for yourselves how to solve this.

ROBUSTNESS: If you need to perform more than one database operation to delete a message and re-link its old children, you should use transactions to ensure that all or none of the operations are performed.

[+/-] Extension 3: Print Layout (1-2p)

Message boards often have a separate print layout, where sidebars and banners are removed, as well as any limitations on message width. This is intended to make printouts to flow better when printed. A print layout often also avoids the use of icons, which are not as pretty on paper as they are on screen, and background colors, which waste ink or toner.

Implement a print layout for your message forum. This should not involve changes to the HTML code generated by the forum; it should only involve using different CSS definitions (one hint may be the use of "display: none" to hide certain elements and the use of "width: auto" to override previously specified fixed widths for other elements).

The implementation can involve reloading a topic with additional query parameters that indicate that a separate layout should be used (1p), or you may investigate the use of JavaScript to add and remove style sheets from the current page, thereby implementing a quick toggle between standard and print layout (2p).

Note: Though we have mentioned the use of "@media print" in CSS, which specifies a separate look for printing which is different from how your document looks on screen, this is not yet supported by a sufficient number of browsers.

[+/-] Extension 4: Statistics (1-2p)

Add statistics for each user: Keep track of the number of times a user has logged in, the number of messages he has written, and so on. Display this information in the list of users.

Display the number of messages a user has written in each message (as in this example).

Add "user level" icons like in the second example, where new users get one star (or other icon) and the number of stars increases depending on the number of messages. Make the required number of messages configurable using webapp initialization parameters in web.xml.

Also add a way of displaying statistics for the entire system: Total number of topics, threads, messages, users, and so on.

The number of extension points depends on the quality of the implementation.

[+/-] Extension 5: Choose thread icon (1p)

When a user starts a new topic, let him choose between a number of standard "built-in" icons to identify the topic. For example, a small question mark to indicate a question, a few smiley faces to indicate good or bad news, and so on. There should be a "neutral" default icon.

[+/-] Extension 6: Upload user icon (1p)

Let each user specify an icon to be shown beside each of his messages, as in this example. This icon should be uploaded to the system using a form and the file upload input tag.

There should be a size limit, both in pixels and in kilobytes.

[+/-] Extension 7: Editing existing messages (1p)

Make it possible for users to edit existing messages. The system should keep track of how many times a message has been edited as well as the last time the message was edited. This should be displayed at the bottom of each edited message. (Don't add a text to the message in the message database -- generate "Edited 2 times ..." or something similar when the message is actually shown.)

If you add administrative access, ordinary users should only be able to edit their own messages but the administrator should be able to edit any message.

[+/-] Extension 8: Moving existing messages (2p)

Make it possible to move an existing message, or a set of messages. It should be possible to move them to another topic in the same forum or another topic in another forum (to be used in case these messages were off topic but should be preserved in a new topic).

Make sure the user interface is reasonably easy to use. For example, there may be many forums and topics, and we don't want to have to type the destination manually.

[+/-] Extension 9: Notification for new messages (2p)

In forums related to specific software, there is often an announcement topic where a single new message is posted every time there is a new version. In such cases it may be useful to let the forum notify you each time a new message is posted in this topic.

Make it possible to register and unregister your interest in specific topics. When a new message is posted to a topic, send a message to all users registered for that topic.

USABILITY: If a user has subscribed to a particular topic, then this should be shown when that topic is displayed – but you must also make sure there is a single web page where you can see a list of all topics you have subscribed to, so that you don't have to visit every single topic in the entire forum just to find those you are subscribed to. On this page you should be able to unsubscribe from topics as well as jump directly to one of the topics.

DATA STRUCTURES: One possible data structure would be a simple table containing two fields: userID / topicID. Make sure both columns are indexed, so that you can efficiently find all topics a particular user is interested in as well as all users that are interested in a particular topic.

Sending a mail message

The core class libraries have no built-in support for sending e-mail. However, there is an optional package called JavaMail providing support for mail clients as well as mail servers written in Java. This extension (version 1.3) has been installed on the lab computers.

The main documentation for JavaMail 1.2 is available as a PDF document here (1.3 is a minor update and there is no new version of the PDF file). Appendix B of that document contains some simple examples; the last example shows how to send a message. Read that example carefully and write your own mail sender class (se.liu.ida.youremail.tddi48.project.server.MailSender) with a static method that sends a message from a sender to a single recipient. Then use this class from the threaded server.

You can also browse the API documentation here.

As usual, don't hardcode the name of the mail server. Make it a servlet or webapp initialization parameter.

You may be able to send mail messages using the portofix.ida.liu.se and/or mail.student.liu.se SMTP servers.

[+/-] Extension 10: Mailing Registered Users (2p)

Add the capability for an administrator to send a message to registered users.

Create a servlet or JSP page that dynamically generates an HTML-form-based user interface. The form should contain a subject text field and a message text area. It should also contain a dynamically generated multi-select choice box or a table of checkboxes, where all registered users are listed and can be checked or unchecked by the administrator who is using the servlet.

The submit button should submit the form to another servlet which then sends mails to all users that were marked as recipients in the form.

You should first send an HTML header back to the user; then, you should send the mail to one user at a time, each time writing an additional line of information back to the caller for each user, reporting whether the mail was sent successfully or not and showing how many percent have been handled so far. (This should hopefully make the browser show each line of text incrementally as the mails are being sent, providing a simple status log display. Whether this works may differ between different browsers.)

Finally, it might be a good idea to include a link back to some other page on your web site, such as the main guest book page.

Make sure that ordinary users are not allowed to send mail!

Sending a mail message

The core class libraries have no built-in support for sending e-mail. However, there is an optional package called JavaMail providing support for mail clients as well as mail servers written in Java. This extension (version 1.3) has been installed on the lab computers.

The main documentation for JavaMail 1.2 is available as a PDF document here (1.3 is a minor update and there is no new version of the PDF file). Appendix B of that document contains some simple examples; the last example shows how to send a message. Read that example carefully and write your own mail sender class (se.liu.ida.youremail.tddi48.project.server.MailSender) with a static method that sends a message from a sender to a single recipient. Then use this class from the threaded server.

You can also browse the API documentation here.

As usual, don't hardcode the name of the mail server. Make it a servlet or webapp initialization parameter.

You may be able to send mail messages using the portofix.ida.liu.se and/or mail.student.liu.se SMTP servers.

[+/-] Extension 11: Message Formatting (2p)

Add support for formatted messages.

Although you do not want to support arbitrary HTML tags in messages (who knows what users would do with that?), many message forum systems allow you to use a set of pre-defined pseudo-HTML tags, such as:

A list of all pseudo-HTML tags supported by YaBB can be seen here. Implement the hr, url, img, b, i, u, s, and color tags.

You will have to make sure that these tags are closed — that any start tag is eventually followed by an end tag, with proper nesting. You could for example scan the message from beginning to end, keeping a stack of unclosed tags, popping tags when appropriate. We won't give you a complete algorithm here, so you might have to think about it for a while to get something that's guaranteed to work.

Then, you should also add a list of graphical smileys (emoticons) and automatically translate certain character combinations into graphical smileys (using the IMG tag). You can use the icons and codes from the list of YaBB emoticons.

[+/-] Extension 12: Auto-login using cookies (2p)

Although users only have to log in once every session, the session disappears after turning off the web browser (or after a short timeout when the user is inactive), and then the user has to log in again.

Many sites make it possible to log in "automatically", by setting a semi-permanent cookie in the user's web browser that verifies that a person using this web browser has previously logged in to this web site. This is naturally not a good idea for high-security web sites such as Internet banks, but it usually provides sufficient security for a simple message forum.

Implement this type of automatic login in your system.

The user/password form should have a checkbox turning this feature on or off, so that users who want a higher level of security can leave the checkbox off. If the user enters his name and password, turns on auto-login, and then submits the form, the system should first check that the name and password is valid, just like it did before.

If it was valid, then you should generate a long random number (using a cryptographically secure random generator, SecureRandom) consisting of at least 128 bits of data, possibly more. This number is now the user's magic login cookie. You must store it in the user database, and you must set a couple of cookies in your response: One cookie specifying the user name, and one specifying the random number.

If the user returns the next day, the HTTPSession is gone, so he would ordinarily have had to log in again. But now the browser will automatically send the user name and the random key along with any request. Instead of immediately complaining that the user is not logged in, just validate the name/key against the database, and if it is correct, let the user log in automatically.

Make sure that the user can log off in some way, disabling the auto-login feature. This should clear the random number stored in the database.

Why a random number? Why not simply store his password as a cookie? Because storing a random number in the browser's relatively unsafe cookie database is not as dangerous as storing the password. After all, the random number is only valid for this site, and only until the user manually logs off. The password is likely to be valid for a longer time, and users may use the same password, or a similar one, for other sites too.

[+/-] Extension 13: What's new? (3p)

Trying to keep track of which messages you have already read may be quite tedious. Let the system do it!

In this exercise, you will have to think about the data structures you want to use. When you hand in your code you should also motivate why you stored the necessary information in this particular format! Since the message and user database may grow quite large, you must particularly consider the potential size of the data structures. Perhaps there should be a way to remove old data, for topics that have not been visited in a long time?

For each topic (not only each forum!), you will have to keep track of whether the user has ever visited that topic or not, and if so, when.

When you list all topics within a forum, you should show in some manner whether there are new messages in a specific topic. This could be shown as a "new messages" icon beside the topic title, for example.

When you display messages within a topic, you should mark those messages that are new since the last time the user visited this topic.

The "last read" timestamp for a counter should only be updated when the user actually visits the topic and views the messages in that topic, not when the topic title is displayed in a topic list.

[+/-] Extension 14: Search (2p)

Add the ability to search for messages.

The search form should allow you to constrain your search using a number of criteria, including the author, date (within a given range or "last x days"), subject, and message body. For simplicity, you may want to restrict yourself to conjunctive (AND) queries, where any field that is actually filled in gives another constraint on the search. Implementing nested AND/OR search ((x AND y) or (x AND z AND w)) gives 1p extra.

Think about how to present search results. Should you present them in a certain order? Should the result be paged and/or limited to a certain maximum number of results?

If you have implemented any form of forum access limitations or private messages, consider this in your search; users should search through exactly those messages they can see in the forum, no more and no less.

[+/-] Extension 15: Private messages (2p)

Add the ability to write private messages to users.

Internally, this might for example be handled by giving each user a private forum that only this user can read. Sending a private message to the user can't involve entering the forum as it does for ordinary posts, of course; you would need a separate "send private message" function for that.

What happens with the messages you send to another user? You might want to be able to see them and re-read them later, but you can't do that by accessing the private forum of the user to which the message was sent. One option would be to automatically add the message to both users' private forums. If you do this, you need some way of knowing to whom you sent the message, so you might have to add a "to:" field to the message database -- a field which is empty/null for standard forum messages.

Changing the use of a structure you have already used extensively may lead to complications. For example, suppose you add the same message, with the same message ID, to two forums -- your own private forum and that of another user. What happens if the other user deletes the message from his personal mailbox? Before, you might have simply deleted the topic entry AND the message itself. Now, that might leave a dangling pointer from your own personal mailbox... so you'd have to check whether the message is completely unlinked before actually deleting it. Other similar consistency issues might arise, such as what would happen if you edit a private message after sending it. Consider these issues carefully.

Private messages might be more important than others. Maybe the user should be notified on the front page if he has unread private messages?

[+/-] Extension 16: Access Groups (2p)

Add support for forums with restricted access.

Since it is far too tedious to configure individual users' access to individual forums, a two-step approach is required. First, it should be possible for the main site administrator to configure groups of members, where each group has one or more group administrators who can add and remove group members. Second, each forum should be associated with a set of groups (not just a single group!) that has read access and a set of groups that have write access.

Usually, many forums should be accessible by any user. This could be handled using a special hack for such forums, but it would perhaps be more elegant to add a separate group containing all users and automatically adding each user to that group during account creation. This group could then be used for forums that should be accessible by anyone.

Note that if a search function is implemented, it must respect these access privileges!

[+/-] Extension 17: Polls / voting (2p)

Many forums support polls, a special kind of post where you can vote by choosing among a number of predetermined alternatives. Implement this for your forum. It should be possible to add an arbitrary number of alternatives to a poll.

Decide whether you would like anonymous users to be able to vote or whether you keep track of exactly which members have voted. Another approach is to log which IP numbers have voted; this lets you limit the number of people who vote multiple times, but does not deal with the case where many people are using a browser from the same IP number or the case where a dial-up user gets a new IP number each time.

Decide whether you should be able to see the results without voting; usually this is not possible, though it requires keeping track of users in some way.

The poll creator or the site administrator should be able to lock the poll.

For 1p extra credit, make it possible to modify polls afterwards (intended for spelling mistakes, etc., or adding missing items); also add an ability to lock the poll automatically after n days/hours.

[+/-] Extension 18: RDF Feed (advanced)

Extend the message forum to provide an RDF feed. Only do this if you already know what you're doing! Determine exactly what you want to do and send a small specification to the course leader. The number of points given for the extension will depend on the complexity of the extension.

[+/-] Extension 19: NNTP Feed (advanced)

Extend the message forum to provide an NNTP feed. Only do this if you already know what you're doing! Determine exactly what you want to do and send a small specification to the course leader. The number of points given for the extension will depend on the complexity of the extension.



Jonas Kvarnström

Valid HTML 4.01!   [Check links]