You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by ag...@apache.org on 2005/10/12 21:06:11 UTC

svn commit: r315003 - in /incubator/roller/branches/roller_2.0: sandbox/atomprotocol/src/org/roller/presentation/atomapi/ sandbox/atomprotocol/src/org/roller/presentation/atomapi04/ src/org/roller/presentation/ src/org/roller/presentation/servlets/ src...

Author: agilliland
Date: Wed Oct 12 12:06:05 2005
New Revision: 315003

URL: http://svn.apache.org/viewcvs?rev=315003&view=rev
Log:
just moving a few standalone servlets into a single location.


Added:
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/CommentServlet.java
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/LoginServlet.java
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/ResourceServlet.java
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/TrackbackServlet.java
Removed:
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/CommentServlet.java
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/LoginServlet.java
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/ResourceServlet.java
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/weblog/TrackbackServlet.java
Modified:
    incubator/roller/branches/roller_2.0/sandbox/atomprotocol/src/org/roller/presentation/atomapi/RollerAtomHandler.java
    incubator/roller/branches/roller_2.0/sandbox/atomprotocol/src/org/roller/presentation/atomapi04/RollerAtomHandler.java

Modified: incubator/roller/branches/roller_2.0/sandbox/atomprotocol/src/org/roller/presentation/atomapi/RollerAtomHandler.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/sandbox/atomprotocol/src/org/roller/presentation/atomapi/RollerAtomHandler.java?rev=315003&r1=315002&r2=315003&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.0/sandbox/atomprotocol/src/org/roller/presentation/atomapi/RollerAtomHandler.java (original)
+++ incubator/roller/branches/roller_2.0/sandbox/atomprotocol/src/org/roller/presentation/atomapi/RollerAtomHandler.java Wed Oct 12 12:06:05 2005
@@ -40,7 +40,7 @@
 import org.roller.pojos.WeblogCategoryData;
 import org.roller.pojos.WeblogEntryData;
 import org.roller.pojos.WebsiteData;
-import org.roller.presentation.LoginServlet;
+import org.roller.presentation.servlets.LoginServlet;
 import org.roller.presentation.RollerContext;
 import org.roller.util.RollerMessages;
 import org.roller.util.Utilities;

Modified: incubator/roller/branches/roller_2.0/sandbox/atomprotocol/src/org/roller/presentation/atomapi04/RollerAtomHandler.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/sandbox/atomprotocol/src/org/roller/presentation/atomapi04/RollerAtomHandler.java?rev=315003&r1=315002&r2=315003&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.0/sandbox/atomprotocol/src/org/roller/presentation/atomapi04/RollerAtomHandler.java (original)
+++ incubator/roller/branches/roller_2.0/sandbox/atomprotocol/src/org/roller/presentation/atomapi04/RollerAtomHandler.java Wed Oct 12 12:06:05 2005
@@ -39,7 +39,7 @@
 import org.roller.pojos.WeblogCategoryData;
 import org.roller.pojos.WeblogEntryData;
 import org.roller.pojos.WebsiteData;
-import org.roller.presentation.LoginServlet;
+import org.roller.presentation.servlets.LoginServlet;
 import org.roller.presentation.RollerContext;
 import org.roller.util.RollerMessages;
 import org.roller.util.Utilities;

Added: incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/CommentServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/CommentServlet.java?rev=315003&view=auto
==============================================================================
--- incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/CommentServlet.java (added)
+++ incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/CommentServlet.java Wed Oct 12 12:06:05 2005
@@ -0,0 +1,457 @@
+package org.roller.presentation.servlets;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.naming.InitialContext;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.util.RequestUtils;
+import org.roller.RollerException;
+import org.roller.config.RollerConfig;
+import org.roller.config.RollerRuntimeConfig;
+import org.roller.model.IndexManager;
+import org.roller.model.RollerFactory;
+import org.roller.model.WeblogManager;
+import org.roller.pojos.CommentData;
+import org.roller.pojos.UserData;
+import org.roller.pojos.WeblogEntryData;
+import org.roller.pojos.WebsiteData;
+import org.roller.presentation.pagecache.PageCacheFilter;
+import org.roller.presentation.velocity.CommentAuthenticator;
+import org.roller.presentation.weblog.formbeans.CommentFormEx;
+import org.roller.util.CommentSpamChecker;
+import org.roller.util.MailUtil;
+import org.roller.util.StringUtils;
+import org.roller.presentation.*;
+
+
+/**
+ * The CommentServlet handles all incoming weblog entry comment posts.
+ * 
+ * We validate each incoming comment based on various comment settings and
+ * if all checks are passed then the comment is saved.
+ * 
+ * Incoming comments are tested against the MT Blacklist. If they are found
+ * to be spam, then they are marked as spam and hidden from view.
+ *
+ * If email notification is turned on, each new comment will result in an
+ * email sent to the blog owner and all who have commented on the same post.
+ * 
+ * @author Allen Gilliland
+ *
+ * @web.servlet name="CommentServlet"
+ * @web.servlet-mapping url-pattern="/comment/*"
+ */
+public class CommentServlet extends HttpServlet {
+    
+    private static final String EMAIL_ADDR_REGEXP = "^.*@.*[.].{2,}$";
+    
+    private static final String COMMENT_SPAM_MSG =
+            "Your comment has been recognized as "
+            + "<a href='http://www.jayallen.org/projects/mt-blacklist/'>"
+            + "Comment Spam</a> and rejected.";
+    
+    private transient ResourceBundle bundle =
+            ResourceBundle.getBundle("ApplicationResources");
+    
+    private static Log mLogger = 
+            LogFactory.getFactory().getInstance(CommentServlet.class);
+    
+    
+    /**
+     * Handle incoming http GET requests.
+     *
+     * The CommentServlet is not meant to handle GET requests, so we just
+     * redirect these request to the root of the webapp.
+     */
+    public void doGet(HttpServletRequest request, HttpServletResponse response)
+        throws IOException, ServletException {
+        
+        // we should never get any GET requests, but just in case
+        response.sendRedirect(request.getContextPath());
+    }
+    
+    
+    /**
+     * Service incoming POST requests.
+     *
+     * Here we handle incoming comment postings.  We will collect the data,
+     * validate it, and save it.
+     */
+    public void doPost(HttpServletRequest request, HttpServletResponse response)
+        throws IOException, ServletException {
+        
+        boolean preview = false;
+        String error = null;
+        String message = null;
+        String entry_permalink = request.getContextPath();
+        
+        String method = request.getParameter("method");
+        if(method == null)
+            method = "post";
+        else if (method.equals("preview"))
+            preview = true;
+        
+        RollerRequest rreq = RollerRequest.getRollerRequest(request);
+        HttpSession session = request.getSession();
+        try {
+            // Get weblog entry object
+            WeblogEntryData entry = rreq.getWeblogEntry();
+            if (entry == null || entry.getId() == null) {
+                throw new RollerException("Unable to find WeblogEntry for "+ 
+                        request.getParameter(RollerRequest.WEBLOGENTRYID_KEY));
+            }
+            
+            // we know what our weblog entry is, so setup our permalink url
+            entry_permalink = entry.getPermaLink();
+            
+            mLogger.debug("Doing comment posting for entry = "+entry_permalink);
+            
+            // check if we even allow comments
+            if(!RollerRuntimeConfig.getBooleanProperty("users.comments.enabled"))
+                throw new Exception("Comments are disabled for this site.");
+            
+            if (!entry.getWebsite().getAllowComments().booleanValue() ||
+                    !entry.getCommentsStillAllowed())
+                throw new Exception("Comments not allowed on this entry");
+            
+            WebsiteData website = entry.getWebsite();
+            
+            // Construct our Comment object from the submitted data
+            WeblogManager mgr = RollerFactory.getRoller().getWeblogManager();
+            CommentFormEx cf = new CommentFormEx();
+            CommentData comment = new CommentData();
+            RequestUtils.populate(cf, request);
+            cf.copyTo(comment, request.getLocale());
+            
+            comment.setWeblogEntry(entry);
+            comment.setRemoteHost(request.getRemoteHost());
+            comment.setPostTime(new java.sql.Timestamp(System.currentTimeMillis()));
+            
+            cf.setWeblogEntry(entry);
+            cf.setPostTime(new java.sql.Timestamp(System.currentTimeMillis()));
+            
+            request.setAttribute("commentForm", cf);
+            request.setAttribute("blogEntry", entry);
+            
+            if(preview) {
+                message = "This is a comment preview only";
+                request.setAttribute("previewComments", "dummy");
+                
+                mLogger.debug("Comment is a preview");
+                
+            } else if(!commentSpam(comment)) {
+                
+                // this is a real comment posting.
+                // lets authenticate it then save
+                CommentAuthenticator commentAuth = 
+                        RollerContext.getCommentAuthenticator();
+                if (commentAuth.authenticate(comment, request)) {
+                    
+                    mLogger.debug("Comment is valid ... saving it");
+                    
+                    comment.save();
+                    RollerFactory.getRoller().commit();
+                    reindexEntry(entry);
+                    
+                    // Refresh user's entries in page cache
+                    PageCacheFilter.removeFromCache(request, website);
+                    
+                    // Send email notifications
+                    sendEmailNotification(request, rreq, entry, comment);
+                    
+                } else {
+                    error = bundle.getString("error.commentAuthFailed");
+                    mLogger.debug("Comment failed authentication");
+                }
+                
+            } else {
+                error = COMMENT_SPAM_MSG;
+                mLogger.debug("Comment marked as spam");
+            }
+            
+        } catch (RollerException re) {
+            mLogger.error("ERROR posting comment", re);
+            error = re.getMessage();
+        } catch (Exception e) {
+            error = e.getMessage();
+        }
+        
+        // the work has been done, now send the user back to the entry page
+        if(error != null)
+            session.setAttribute(RollerSession.ERROR_MESSAGE, error);
+        else if(message != null)
+            session.setAttribute(RollerSession.STATUS_MESSAGE, message);
+        
+        if(error == null && message == null && !preview) {
+            entry_permalink = request.getContextPath()+entry_permalink;
+            
+            mLogger.debug("comment complete, redirecting to "+entry_permalink);
+            response.sendRedirect(entry_permalink);
+        } else {
+            mLogger.debug("more work needed, forwarding to "+entry_permalink);
+            RequestDispatcher dispatcher = 
+                request.getRequestDispatcher(entry_permalink);
+            dispatcher.forward(request, response);
+        }
+    }
+    
+    
+    /**
+     * Re-index the WeblogEntry so that the new comment gets indexed.
+     */
+    private void reindexEntry(WeblogEntryData entry) 
+        throws RollerException {
+        
+        IndexManager manager = RollerFactory.getRoller().getIndexManager();
+        
+        // remove entry before (re)adding it, or in case it isn't Published
+        manager.removeEntryIndexOperation(entry);
+        
+        // if published, index the entry
+        if (entry.isPublished()) {
+            manager.addEntryIndexOperation(entry);
+        }
+    }
+    
+
+    /**
+     * Test CommentData to see if it is spam.
+     */
+    private boolean commentSpam(CommentData cd) {
+        
+        CommentSpamChecker checker = new CommentSpamChecker();
+        checker.testComment(cd);
+        if (cd.getSpam().booleanValue())
+            return true;
+        
+        return false;
+    }
+    
+    
+    /**
+     * Send email notification of comment.
+     *
+     * TODO: Make the addressing options configurable on a per-website basis.
+     */
+    private void sendEmailNotification(HttpServletRequest request,
+                        RollerRequest rreq,
+                        WeblogEntryData entry,
+                        CommentData cd) 
+            throws MalformedURLException {
+        
+        RollerContext rc = RollerContext.getRollerContext(request);
+        ResourceBundle resources = ResourceBundle.getBundle(
+                "ApplicationResources",LanguageUtil.getViewLocale(request));
+
+        WebsiteData site = entry.getWebsite();
+        UserData user = entry.getCreator();
+        
+        // Send e-mail to owner and subscribed users (if enabled)
+        boolean notify = RollerRuntimeConfig.getBooleanProperty("users.comments.emailnotify");
+        if (notify && site.getEmailComments().booleanValue()) {
+            mLogger.debug("Comment notification enabled ... preparing email");
+            
+            // Determine message and addressing options from init parameters
+            boolean separateMessages =
+                    RollerConfig.getBooleanProperty("comment.notification.separateOwnerMessage");
+            boolean hideCommenterAddrs =
+                    RollerConfig.getBooleanProperty("comment.notification.hideCommenterAddresses");
+            
+            //------------------------------------------
+            // --- Determine the "from" address
+            // --- Use either the site configured from address or the user's address
+            
+            String from =
+                    (StringUtils.isEmpty(site.getEmailFromAddress()))
+                    ? user.getEmailAddress()
+                    : site.getEmailFromAddress();
+            
+            //------------------------------------------
+            // --- Build list of email addresses to send notification to
+            
+            List comments = null;
+            try {
+                WeblogManager wMgr = RollerFactory.getRoller().getWeblogManager();
+                comments = wMgr.getComments(entry.getId());
+            } catch(RollerException re) {
+                // should never happen
+                comments = new ArrayList();
+            }
+            
+            // Get all the subscribers to this comment thread
+            Set subscribers = new TreeSet();
+            for (Iterator it = comments.iterator(); it.hasNext();) {
+                CommentData comment = (CommentData) it.next();
+                if (!StringUtils.isEmpty(comment.getEmail())) {
+                    // If user has commented twice,
+                    // count the most recent notify setting
+                    if (comment.getNotify().booleanValue()) {
+                        // only add those with valid email
+                        if (comment.getEmail().matches(EMAIL_ADDR_REGEXP)) {
+                            subscribers.add(comment.getEmail());
+                        }
+                    } else {
+                        // remove user who doesn't want to be notified
+                        subscribers.remove(comment.getEmail());
+                    }
+                }
+            }
+            
+            // Form array of commenter addrs
+            String[] commenterAddrs = (String[])subscribers.toArray(new String[0]);
+            
+            //------------------------------------------
+            // --- Form the messages to be sent -
+            // For simplicity we always build separate owner and commenter messages even if sending a single one
+            
+            // Determine with mime type to use for e-mail
+            StringBuffer msg = new StringBuffer();
+            StringBuffer ownermsg = new StringBuffer();
+            boolean escapeHtml = RollerRuntimeConfig.getBooleanProperty("users.comments.escapehtml");
+            
+            if (!escapeHtml) {
+                msg.append("<html><body style=\"background: white; ");
+                msg.append(" color: black; font-size: 12px\">");
+            }
+            
+            if (!StringUtils.isEmpty(cd.getName())) {
+                msg.append(cd.getName() + " "
+                        + resources.getString("email.comment.wrote")+": ");
+            } else {
+                msg.append(resources.getString("email.comment.anonymous")+": ");
+            }
+            
+            msg.append((escapeHtml) ? "\n\n" : "<br /><br />");
+            msg.append(cd.getContent());
+            msg.append((escapeHtml) ? "\n\n----\n"
+                    : "<br /><br /><hr /><span style=\"font-size: 11px\">");
+            msg.append(resources.getString("email.comment.respond") + ": ");
+            msg.append((escapeHtml) ? "\n" : "<br />");
+            
+            String rootURL = rc.getAbsoluteContextUrl(request);
+            if (rootURL == null || rootURL.trim().length()==0) {
+                rootURL = RequestUtils.serverURL(request) + request.getContextPath();
+            }
+            
+            // Build link back to comment
+            
+            StringBuffer commentURL = new StringBuffer(rootURL);
+            commentURL.append("/comments/");
+            commentURL.append(user.getUserName());
+            
+            org.roller.pojos.Template page = rreq.getPage();
+            if (page == null) {
+                commentURL.append("?entry=");
+            } else {
+                commentURL.append("/").append(page.getLink()).append("/");
+            }
+            
+            commentURL.append(entry.getAnchor());
+            
+            if (escapeHtml) {
+                msg.append(commentURL.toString());
+            } else {
+                msg.append("<a href=\""+commentURL+"\">"+commentURL+"</a></span>");
+            }
+            
+            ownermsg.append(msg);
+            
+            // add link to weblog edit page so user can login to manage comments
+            ownermsg.append((escapeHtml) ? "\n\n----\n" :
+                "<br /><br /><hr /><span style=\"font-size: 11px\">");
+            ownermsg.append("Link to comment management page:");
+            ownermsg.append((escapeHtml) ? "\n" : "<br />");
+            
+            StringBuffer deleteURL = new StringBuffer(rootURL);
+            deleteURL.append("/editor/weblog.do?method=edit&entryid="+entry.getId());
+            
+            if (escapeHtml) {
+                ownermsg.append(deleteURL.toString());
+            } else {
+                ownermsg.append(
+                        "<a href=\"" + deleteURL + "\">" + deleteURL + "</a></span>");
+                msg.append("</Body></html>");
+                ownermsg.append("</Body></html>");
+            }
+            
+            String subject = null;
+            if ((subscribers.size() > 1) ||
+                    (StringUtils.equals(cd.getEmail(), user.getEmailAddress()))) {
+                subject= "RE: "+resources.getString("email.comment.title")+": ";
+            } else {
+                subject = resources.getString("email.comment.title") + ": ";
+            }
+            subject += entry.getTitle();
+            
+            //------------------------------------------
+            // --- Send message to email recipients
+            try {
+                javax.naming.Context ctx = (javax.naming.Context)
+                new InitialContext().lookup("java:comp/env");
+                Session session = (Session)ctx.lookup("mail/Session");
+                boolean isHtml = !escapeHtml;
+                if (separateMessages) {
+                    // Send separate messages to owner and commenters
+                    sendMessage(session, from,
+                            new String[]{user.getEmailAddress()}, null, null, subject, ownermsg.toString(), isHtml);
+                            if (commenterAddrs.length > 0) {
+                                // If hiding commenter addrs, they go in Bcc: otherwise in the To: of the second message
+                                String[] to = hideCommenterAddrs ? null : commenterAddrs;
+                                String[] bcc = hideCommenterAddrs ? commenterAddrs : null;
+                                sendMessage(session, from, to, null, bcc, subject, msg.toString(), isHtml);
+                                
+                            }
+                } else {
+                    // Single message.  User in To: header, commenters in either cc or bcc depending on hiding option
+                    String[] cc = hideCommenterAddrs ? null : commenterAddrs;
+                    String[] bcc = hideCommenterAddrs ? commenterAddrs : null;
+                    sendMessage(session, from, new String[]{user.getEmailAddress()}, cc, bcc, subject,
+                            ownermsg.toString(), isHtml);
+                }
+            } catch (javax.naming.NamingException ne) {
+                mLogger.error("Unable to lookup mail session.  Check configuration.  NamingException: " + ne.getMessage());
+            } catch (Exception e) {
+                mLogger.warn("Exception sending comment mail: " + e.getMessage());
+                // This will log the stack trace if debug is enabled
+                if (mLogger.isDebugEnabled()) {
+                    mLogger.debug(e);
+                }
+            }
+            
+            mLogger.debug("Done sending email message");
+            
+        } // if email enabled
+    }
+    
+    
+    /*
+     * This is somewhat ridiculous, but avoids duplicating a bunch of logic 
+     * in the already messy sendEmailNotification.
+     */
+    private void sendMessage(Session session, String from, String[] to, String[] cc, String[] bcc, String subject,
+            String msg, boolean isHtml) throws MessagingException {
+        if (isHtml)
+            MailUtil.sendHTMLMessage(session, from, to, cc, bcc, subject, msg);
+        else
+            MailUtil.sendTextMessage(session, from, to, cc, bcc, subject, msg);
+    }
+    
+}
+

Added: incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/LoginServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/LoginServlet.java?rev=315003&view=auto
==============================================================================
--- incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/LoginServlet.java (added)
+++ incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/LoginServlet.java Wed Oct 12 12:06:05 2005
@@ -0,0 +1,226 @@
+package org.roller.presentation.servlets;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.presentation.util.SslUtil;
+import org.roller.util.Utilities;
+
+import java.io.IOException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.roller.config.RollerConfig;
+import org.roller.presentation.*;
+
+
+
+/**
+ * Implementation of <strong>HttpServlet</strong> that is used
+ * to get a username and password and mEncrypt the password
+ * before sending to container-managed authentication.
+ *
+ * <p><a href="LoginServlet.java.html"><i>View Source</i></a></p>
+ *
+ * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
+ * @version $Revision: 1.19 $ $Date: 2005/06/07 18:30:18 $
+ *
+ * @web.servlet
+ *     display-name="Login Servlet"
+ *     load-on-startup="3"
+ *     name="login"
+ *
+ * @web.servlet-init-param
+ *     name="authURL"
+ *     value="/j_security_check"
+ *
+ * @web.servlet-mapping
+ *     url-pattern="/auth/*"
+ */
+public class LoginServlet extends HttpServlet
+{
+    static final long serialVersionUID = 8054268881470797053L;
+    
+    protected static String mAuthURL = "/j_security_check";
+    protected static String mAlgorithm = "SHA";
+    protected static Boolean mEncrypt = Boolean.FALSE;
+    
+    private boolean secureLogin = false;
+    private String loginHttpsPort = SslUtil.STD_HTTPS_PORT;
+    
+    //=========================================================================
+    // Private Member Variables
+    //=========================================================================
+    private static Log mLogger = LogFactory.getLog(LoginServlet.class);
+
+    // --------------------------------------------------------- Public Methods
+
+    /**
+     * Validates the Init and Context parameters, configures authentication URL
+     *
+     * @throws ServletException if the init parameters are invalid or any
+     * other problems occur during initialisation
+     */
+    public void init() throws ServletException
+    {
+        // Get the container authentication URL for FORM-based Authentication
+        // J2EE spec says should be j_security_check
+        if (getInitParameter("authURL") != null) 
+        {
+        	    mAuthURL = getInitParameter("authURL");
+        }
+        
+        String secureLogin = RollerConfig.getProperty("securelogin.enabled");
+        if(secureLogin != null && "true".equalsIgnoreCase(secureLogin))
+            this.secureLogin = true;
+        
+        String secureLoginPort = RollerConfig.getProperty("securelogin.https.port");
+        if(secureLoginPort != null)
+            this.loginHttpsPort = secureLoginPort;
+        
+        mLogger.info("secure login enabled: "+this.secureLogin);
+        mLogger.info("secure login port: "+this.loginHttpsPort);
+    }
+
+    /**
+     * Route the user to the execute method
+     *
+     * @param request The HTTP request we are processing
+     * @param response The HTTP response we are creating
+     *
+     * @exception IOException if an input/output error occurs
+     * @exception ServletException if a servlet exception occurs
+     */
+    public void doGet(HttpServletRequest request, HttpServletResponse response)
+               throws IOException, ServletException
+    {
+        execute(request, response);
+    }
+
+    /**
+     * Route the user to the execute method
+     *
+     * @param request The HTTP request we are processing
+     * @param response The HTTP response we are creating
+     *
+     * @exception IOException if an input/output error occurs
+     * @exception ServletException if a servlet exception occurs
+     */
+    public void doPost(HttpServletRequest request, HttpServletResponse response)
+                throws IOException, ServletException
+    {
+        execute(request, response);
+    }
+
+    /**
+     * Process the specified HTTP request, and create the corresponding HTTP
+     * response (or forward to another web component that will create it).
+     *
+     * @param request The HTTP request we are processing
+     * @param response The HTTP response we are creating
+     *
+     * @exception IOException if an input/output error occurs
+     * @exception ServletException if a servlet exception occurs
+     */
+    public void execute(HttpServletRequest request, 
+                        HttpServletResponse response) throws IOException, 
+                                                             ServletException
+    {
+        // if user is already authenticated, it means they probably bookmarked
+        // or typed in the URL to login.jsp directly, route them to the main
+        // menu if this is the case
+        if (request.getRemoteUser() != null) {
+            if (mLogger.isDebugEnabled()) {
+                mLogger.debug("User '" + request.getRemoteUser() +
+                          "' already logged in, routing to main");
+            }
+            response.sendRedirect(request.getContextPath() + "/main.do");
+            return;
+        }
+        
+        // Extract attributes we will need
+        String username = request.getParameter("j_username");
+        String password = request.getParameter("j_password");
+        
+        String encryptedPassword = getEncryptedPassword(request, username, password);
+
+        String req = null;
+        String contextUrl = null;
+        if (this.secureLogin)
+        {
+            // Secure login and app server may not know it, so we must build URL 
+            StringBuffer sb = new StringBuffer("");
+            sb.append("https://");
+            if (this.loginHttpsPort.equals(SslUtil.STD_HTTPS_PORT)) 
+            {
+                sb.append(request.getServerName());
+            }
+            else 
+            {
+                sb.append(request.getServerName() + ":" + this.loginHttpsPort);
+            }
+            sb.append(request.getContextPath());
+            contextUrl = sb.toString();
+        }
+        else 
+        {
+            contextUrl = request.getContextPath();
+        }
+        // TODO: is there a way we can do this without having password in the URL?
+        req = contextUrl + mAuthURL 
+            + "?j_username=" + username 
+            + "&j_password=" + encryptedPassword 
+            + "&j_uri=" + request.getParameter("j_uri");
+
+        if (mLogger.isDebugEnabled())
+        {
+            mLogger.debug("Authenticating user '" + username + "'");
+        }
+
+        response.sendRedirect(response.encodeRedirectURL(req));
+    }
+
+    /**
+     * Encode the user's password (if necessary) before redirecting to
+     * the Container Managed Security servlet.
+     * 
+     * @param request
+     * @param username
+     * @param password
+     * @return
+     */
+    public static String getEncryptedPassword(
+                       HttpServletRequest request, String username, String password)
+    {
+        // This determines if the password should be encrypted programmatically
+        mEncrypt = new Boolean(RollerConfig.getProperty("passwds.encryption.enabled"));
+        mAlgorithm = RollerConfig.getProperty("passwds.encryption.algorithm");
+
+        if (mLogger.isDebugEnabled())
+        {
+            mLogger.debug("Authentication URL: " + mAuthURL);
+            mLogger.debug("Programmatic encryption of password? " + mEncrypt);
+            mLogger.debug("Encryption algorithm: " + mAlgorithm);
+        }
+
+        if (request.getParameter("rememberMe") != null) {
+            request.getSession().setAttribute(RollerRequest.LOGIN_COOKIE, "true");
+        }
+        String encryptedPassword = "";
+        if (mEncrypt.booleanValue() && (request.getAttribute("encrypt") == null))
+        {
+            if (mLogger.isDebugEnabled())
+            {
+                mLogger.debug("Encrypting password for user '" + username + "'");
+            }
+            encryptedPassword = Utilities.encodePassword(password, mAlgorithm);
+        }
+        else
+        {
+            encryptedPassword = password;
+        }
+        return encryptedPassword;
+    }
+}
\ No newline at end of file

Added: incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/ResourceServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/ResourceServlet.java?rev=315003&view=auto
==============================================================================
--- incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/ResourceServlet.java (added)
+++ incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/ResourceServlet.java Wed Oct 12 12:06:05 2005
@@ -0,0 +1,136 @@
+package org.roller.presentation.servlets;
+
+import java.io.*;
+import java.util.Date;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.roller.model.RollerFactory;
+
+
+/**
+ * Resources servlet.  Acts as a gateway to files uploaded by users.
+ *
+ * Since we keep uploaded resources in a location outside of the webapp
+ * context we need a way to serve them up.  This servlet assumes that 
+ * resources are stored on a filesystem in the "uploads.dir" directory.
+ *
+ * @author Allen Gilliland
+ *
+ * @web.servlet name="ResourcesServlet"
+ * @web.servlet-mapping url-pattern="/resources/*"
+ */
+public class ResourceServlet extends HttpServlet
+{   
+    private static Log mLogger =
+            LogFactory.getFactory().getInstance(ResourceServlet.class);
+    
+    private String upload_dir = null;
+    private ServletContext context = null;
+    
+    
+    /** Initializes the servlet.*/
+    public void init(ServletConfig config) throws ServletException {
+        super.init(config);
+        
+        this.context = config.getServletContext();
+
+        try {
+            this.upload_dir = RollerFactory.getRoller().getFileManager().getUploadDir();
+            mLogger.debug("upload dir is ["+this.upload_dir+"]");
+        } catch(Exception e) { mLogger.warn(e); }
+
+    }
+    
+    /** Destroys the servlet.
+     */
+    public void destroy() {
+        
+    }
+    
+    
+    /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
+     * @param request servlet request
+     * @param response servlet response
+     */
+    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
+    throws ServletException, IOException {
+        
+        String context = request.getContextPath();
+        String servlet = request.getServletPath();
+        String reqURI = request.getRequestURI();
+        
+        // calculate the path of the requested resource
+        // we expect ... /<context>/<servlet>/path/to/resource
+        String reqResource = reqURI.substring(servlet.length() + context.length());
+        
+        // now we can formulate the *real* path to the resource on the filesystem
+        String resource_path = this.upload_dir + reqResource;
+        File resource = new File(resource_path);
+
+        mLogger.debug("Resource requested ["+reqURI+"]");
+        mLogger.debug("Real path is ["+resource.getAbsolutePath()+"]");
+        
+        // do a quick check to make sure the resource exits, otherwise 404
+        if(!resource.exists() || !resource.canRead()) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+        
+        // does the client already have this file?  if so, then 304
+        Date ifModDate = new Date(request.getDateHeader("If-Modified-Since"));
+        Date lastMod = new Date(resource.lastModified());
+        if(lastMod.compareTo(ifModDate) <= 0) {
+            mLogger.debug("Resource unmodified ... sending 304");
+            response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+            return;
+        }
+        
+        // looks like we'll be serving up the file ... lets set some headers
+        // set last-modified date so we can do if-modified-since checks
+        // set the content type based on whatever is in our web.xml mime defs
+        response.addDateHeader("Last-Modified", (new Date()).getTime());
+        response.setContentType(this.context.getMimeType(resource.getAbsolutePath()));
+        
+        // ok, lets serve up the file
+        byte[] buf = new byte[8192];
+        int length = 0;
+        OutputStream out = response.getOutputStream();
+        InputStream resource_file = new FileInputStream(resource);
+        while((length = resource_file.read(buf)) > 0)
+            out.write(buf, 0, length);
+        
+        // cleanup
+        out.close();
+        resource_file.close();
+    }
+    
+    
+    /** Handles the HTTP <code>GET</code> method.
+     * @param request servlet request
+     * @param response servlet response
+     */
+    protected void doGet(HttpServletRequest request, HttpServletResponse response)
+    throws ServletException, IOException {
+        processRequest(request, response);
+    }
+    
+    /** Handles the HTTP <code>POST</code> method.
+     * @param request servlet request
+     * @param response servlet response
+     */
+    protected void doPost(HttpServletRequest request, HttpServletResponse response)
+    throws ServletException, IOException {
+        processRequest(request, response);
+    }
+    
+    /** Returns a short description of the servlet.
+     */
+    public String getServletInfo() {
+        return "ResourceServlet ... serving you since 2005 ;)";
+    }
+    
+}

Added: incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/TrackbackServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/TrackbackServlet.java?rev=315003&view=auto
==============================================================================
--- incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/TrackbackServlet.java (added)
+++ incubator/roller/branches/roller_2.0/src/org/roller/presentation/servlets/TrackbackServlet.java Wed Oct 12 12:06:05 2005
@@ -0,0 +1,184 @@
+/*
+ * Created on Apr 13, 2003
+ */
+package org.roller.presentation.servlets;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.sql.Timestamp;
+import java.util.Date;
+import org.roller.config.RollerRuntimeConfig;
+import org.roller.pojos.CommentData;
+import org.roller.util.CommentSpamChecker;
+
+import org.roller.model.RollerFactory;
+import org.roller.pojos.WeblogEntryData;
+import org.roller.presentation.RollerRequest;
+
+
+/**
+ * Roller's Trackback server implementation. POSTing to this Servlet will add a
+ * Trackback to a Weblog Entrty. For more info on Trackback, read the spec:
+ * <a href="http://www.movabletype.org/docs/mttrackback.html>MT Trackback</a>.
+ *
+ * @web.servlet name="TrackbackServlet"
+ * @web.servlet-mapping url-pattern="/trackback/*"
+ *
+ * @author David M Johnson
+ */
+public class TrackbackServlet extends HttpServlet {
+    /** Request parameter to indicate a trackback "tb" */
+    //private static final String TRACKBACK_PARAM = "tb";
+    
+    /** Request parameter for the trackback "title" */
+    private static final String TRACKBACK_TITLE_PARAM = "title";
+    
+    /** Request parameter for the trackback "excerpt" */
+    private static final String TRACKBACK_EXCERPT_PARAM = "excerpt";
+    
+    /** Request parameter for the trackback "url" */
+    private static final String TRACKBACK_URL_PARAM = "url";
+    
+    /** Request parameter for the trackback "blog_name" */
+    private static final String TRACKBACK_BLOG_NAME_PARAM = "blog_name";
+    
+    /** Key under which the trackback return code will be placed
+     * (example: on the request for the JSPDispatcher) */
+    public static final String BLOJSOM_TRACKBACK_RETURN_CODE =
+            "BLOJSOM_TRACKBACK_RETURN_CODE";
+    
+    /** Key under which the trackback error message will be placed
+     * (example: on the request for the JSPDispatcher) */
+    public static final String BLOJSOM_TRACKBACK_MESSAGE =
+            "BLOJSOM_TRACKBACK_MESSAGE";
+    
+    /** Trackback success page */
+    //private static final String TRACKBACK_SUCCESS_PAGE = "trackback-success";
+    
+    /** Trackback failure page */
+    //private static final String TRACKBACK_FAILURE_PAGE = "trackback-failure";
+    
+    /**
+     * Constructor.
+     */
+    public TrackbackServlet() {
+        super();
+    }
+    
+    /**
+     * POSTing to this Servlet will add a Trackback to a Weblog Entrty.
+     */
+    protected void doGet(HttpServletRequest req, HttpServletResponse res)
+    throws ServletException, IOException {
+        doPost(req,res);
+    }
+    
+    /**
+     * POSTing to this Servlet will add a Trackback to a Weblog Entrty.
+     */
+    protected void doPost(HttpServletRequest req, HttpServletResponse res)
+        throws ServletException, IOException {
+        
+        try {
+            // insure that incoming data is parsed as UTF-8
+            req.setCharacterEncoding("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new ServletException("Can't set incoming encoding to UTF-8");
+        }
+        
+        String url = req.getParameter(TRACKBACK_URL_PARAM);
+        String title = req.getParameter(TRACKBACK_TITLE_PARAM);
+        String excerpt = req.getParameter(TRACKBACK_EXCERPT_PARAM);
+        String blogName = req.getParameter(TRACKBACK_BLOG_NAME_PARAM);
+        
+        if ((title == null) || "".equals(title)) {
+            title = url;
+        }
+        
+        if (excerpt == null) {
+            excerpt = "";
+        } else {
+            if (excerpt.length() >= 255) {
+                excerpt = excerpt.substring(0, 252);
+                excerpt += "...";
+            }
+        }
+        
+        String error = null;
+        PrintWriter pw = new PrintWriter(res.getOutputStream());
+        try {
+            if(!RollerRuntimeConfig.getBooleanProperty("users.trackbacks.enabled")) {
+                error = "Trackbacks are disabled for this site";
+            } else if ( title==null || url==null || 
+                    excerpt==null || blogName==null ) {
+                error = "title, url, excerpt, and blog_name not specified.";
+            } else {
+                RollerRequest rreq = RollerRequest.getRollerRequest(req);
+                WeblogEntryData entry = rreq.getWeblogEntry();
+                
+                if (entry!=null && entry.getCommentsStillAllowed()) {
+                    String modTitle = blogName + ": "  + title;
+                    if (modTitle.length() >= 250) {
+                        modTitle = modTitle.substring(0, 257);
+                        modTitle += "...";
+                    }
+                    
+                    // Track trackbacks as comments
+                    CommentData comment = new CommentData();
+                    comment.setContent("[Trackback] "+excerpt);
+                    comment.setName(blogName);
+                    comment.setUrl(url);
+                    comment.setWeblogEntry(entry);
+                    comment.setNotify(Boolean.FALSE);
+                    comment.setPostTime(new Timestamp(new Date().getTime()));
+                    
+                    // check if this is spam
+                    CommentSpamChecker checker = new CommentSpamChecker();
+                    checker.testComment(comment);
+                    if (comment.getSpam().booleanValue()) {
+                        error = "Trackback spam!";
+                        
+                    } else {
+                        // save, commit, send response
+                        comment.save();
+                        RollerFactory.getRoller().commit();
+                        
+                        pw.println("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>");
+                        pw.println("<response>");
+                        pw.println("<error>0</error>");
+                        pw.println("</response>");
+                        pw.flush();
+                    }
+                } else if (entry!=null) {
+                    error = "Comments and Trackbacks are disabled for the entry you specified.";
+                } else {
+                    error = "Entry not specified.";
+                }
+            }
+            
+        } catch (Exception e) {
+            error = e.getMessage();
+            if ( error == null ) {
+                error = e.getClass().getName();
+            }
+        }
+        
+        if ( error!= null ) {
+            pw.println("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>");
+            pw.println("<response>");
+            pw.println("<error>1</error>");
+            pw.println("<message>ERROR: "+error+"</message>");
+            pw.println("</response>");
+            pw.flush();
+        }
+        res.flushBuffer();
+        
+        // TODO : FindBugs thinks 'pw' should close
+    }
+}
\ No newline at end of file