You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2006/05/02 00:23:34 UTC
svn commit: r398712 [18/32] - in /incubator/roller/trunk/src/org/apache: ./
roller/ roller/business/ roller/business/hibernate/
roller/business/referrers/ roller/business/runnable/
roller/business/search/ roller/business/search/operations/ roller/busin...
Added: incubator/roller/trunk/src/org/apache/roller/presentation/search/SearchResultsPageModel.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/search/SearchResultsPageModel.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/search/SearchResultsPageModel.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/search/SearchResultsPageModel.java Mon May 1 15:23:02 2006
@@ -0,0 +1,346 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License. For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+/*
+ * SearchResultsPageModel.java
+ *
+ * Created on September 23, 2005, 11:27 AM
+ */
+
+package org.apache.roller.presentation.search;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.collections.comparators.ReverseComparator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.search.Hits;
+import org.apache.roller.RollerException;
+import org.apache.roller.business.search.FieldConstants;
+import org.apache.roller.business.search.operations.SearchOperation;
+import org.apache.roller.model.IndexManager;
+import org.apache.roller.model.Roller;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.model.UserManager;
+import org.apache.roller.model.WeblogManager;
+import org.apache.roller.pojos.WeblogEntryComparator;
+import org.apache.roller.pojos.WeblogEntryData;
+import org.apache.roller.pojos.WeblogEntryWrapperComparator;
+import org.apache.roller.pojos.WebsiteData;
+import org.apache.roller.pojos.wrapper.WeblogEntryDataWrapper;
+import org.apache.roller.presentation.RollerRequest;
+import org.apache.roller.util.DateUtil;
+import org.apache.roller.util.StringUtils;
+
+
+
+/**
+ * Encapsulate seach result in page model so it can be used from Velocity or JSP.
+ * @author Min (original code)
+ * @author Dave Johnson (encapsulation)
+ */
+public class SearchResultsPageModel {
+
+ private String term = "";
+ private Integer hits = new Integer(0);
+ private Integer offset = new Integer(0);
+ private Integer limit = new Integer(0);
+ private TreeMap results = new TreeMap();
+ private Set categories = new TreeSet();
+ private boolean websiteSpecificSearch = false;
+ private String errorMessage = null;
+ private boolean useWrappers = false;
+
+ /* How many results to display */
+ private static int LIMIT = 10;
+
+ /* Where to start fetching results */
+ private static int OFFSET = 0;
+
+ private static Log mLogger =
+ LogFactory.getFactory().getInstance(SearchResultsPageModel.class);
+ private static ResourceBundle bundle =
+ ResourceBundle.getBundle("ApplicationResources");
+
+ public SearchResultsPageModel(HttpServletRequest request, boolean wrappers) {
+ useWrappers = wrappers;
+ try {
+ RollerRequest rreq = RollerRequest.getRollerRequest(request);
+ setWebsiteSpecificSearch(checkForWebsite(request));
+
+ SearchOperation search =
+ new SearchOperation(RollerFactory.getRoller().getIndexManager());
+ search.setTerm(request.getParameter("q"));
+ setTerm(request.getParameter("q"));
+
+ WebsiteData website = null;
+ if (isWebsiteSpecificSearch()) {
+ website = rreq.getWebsite();
+ search.setWebsiteHandle(rreq.getWebsite().getHandle());
+ }
+
+ if (StringUtils.isNotEmpty(request.getParameter("c"))) {
+ search.setCategory(request.getParameter("c"));
+ }
+
+ // execute search
+ executeSearch(RollerFactory.getRoller(), search);
+
+ if (search.getResultsCount() == -1) {
+ // this means there has been a parsing (or IO) error
+ setErrorMessage(bundle.getString("error.searchProblem"));
+ } else {
+ // Convert the Hits into WeblogEntryData instances.
+ Hits hits = search.getResults();
+ setResults(convertHitsToEntries(rreq, website, hits));
+ setOffset((Integer)request.getAttribute("offset"));
+ setLimit((Integer)request.getAttribute("limit"));
+ if (request.getAttribute("categories") != null) {
+ Set cats = (Set)request.getAttribute("categories");
+ if (cats.size() > 0) {
+ setCategories(cats);
+ }
+ }
+ }
+ setHits(new Integer(search.getResultsCount()));
+
+ } catch (IOException ex) {
+ mLogger.error("ERROR: initializing search page model");
+ } catch (RollerException ex) {
+ mLogger.error("ERROR: initializing search page model");
+ }
+ }
+
+ private void executeSearch(Roller roller, SearchOperation search)
+ throws RollerException {
+ IndexManager indexMgr = roller.getIndexManager();
+ indexMgr.executeIndexOperationNow(search);
+ if (mLogger.isDebugEnabled()) {
+ mLogger.debug("numresults = " + search.getResultsCount());
+ }
+ }
+
+ /** Look in PathInfo so req.getRemoteUser() doesn't interfere. */
+ private boolean checkForWebsite(HttpServletRequest request) {
+ if (StringUtils.isNotEmpty(
+ request.getParameter(RollerRequest.WEBLOG_KEY))) {
+ return true;
+ }
+ String pathInfoStr = request.getPathInfo();
+ pathInfoStr = (pathInfoStr!=null) ? pathInfoStr : "";
+
+ String[] pathInfo = StringUtils.split(pathInfoStr,"/");
+ if ( pathInfo.length > 0 ) {
+ return true; // is a user page
+ }
+ return false;
+ }
+
+ /**
+ * Iterate over Hits and build sets of WeblogEntryData
+ * objects, placed into Date buckets (in reverse order).
+ * @param rreq
+ * @param website
+ * @param hits
+ * @throws RollerException
+ * @throws IOException
+ */
+ private TreeMap convertHitsToEntries(
+ RollerRequest rreq, WebsiteData website, Hits hits)
+ throws RollerException, IOException {
+ // determine offset (starting point)
+ int ioffset = useOffset(rreq.getRequest());
+ if (ioffset >= hits.length()) ioffset = OFFSET;
+ rreq.getRequest().setAttribute("offset", new Integer(ioffset));
+
+ // determine limit (number of results to display)
+ int ilimit = useLimit(rreq.getRequest());
+ rreq.getRequest().setAttribute("limit", new Integer(ilimit));
+ if (ioffset + ilimit > hits.length()) ilimit = hits.length()-ioffset;
+
+ boolean websiteSpecificSearch = checkForWebsite(rreq.getRequest());
+ TreeMap searchResults = new TreeMap(new ReverseComparator());
+ TreeSet categories = new TreeSet();
+ Roller roller = RollerFactory.getRoller();
+ UserManager userMgr = roller.getUserManager();
+ WeblogManager weblogMgr =roller.getWeblogManager();
+ WeblogEntryData entry;
+ Document doc = null;
+ String handle = null;
+ for (int i = ioffset; i < ioffset+ilimit; i++) {
+ entry = null; // reset for each iteration
+
+ doc = hits.doc(i);
+ handle = doc.getField(FieldConstants.WEBSITE_HANDLE).stringValue();
+
+ if (websiteSpecificSearch && website != null) {
+ // "wrong user" results have been reported
+ if (handle.equals(rreq.getWebsite().getHandle())) {
+ // get real entry for display on user's site
+ entry = weblogMgr.getWeblogEntry(
+ doc.getField(FieldConstants.ID).stringValue() );
+ }
+ } else {
+ // if user is not enabled, website will be null
+ //entry = buildSearchEntry(website, doc);
+ entry = weblogMgr.getWeblogEntry(
+ doc.getField(FieldConstants.ID).stringValue() );
+ if (doc.getField(FieldConstants.CATEGORY) != null) {
+ categories.add(
+ doc.getField(FieldConstants.CATEGORY).stringValue());
+ }
+ }
+
+ // maybe null if search result returned inactive user
+ // or entry's user is not the requested user.
+ if (entry != null && useWrappers) {
+ addEntryWrapperToSearchResults(searchResults, WeblogEntryDataWrapper.wrap(entry));
+ }
+ else if (entry != null && !useWrappers) {
+ addEntryToSearchResults(searchResults, entry);
+ }
+ }
+ rreq.getRequest().setAttribute("categories", categories);
+ return searchResults;
+ }
+
+ private void addEntryToSearchResults(
+ TreeMap searchResults, WeblogEntryData entry) {
+ // convert entry's each date to midnight (00m 00h 00s)
+ Date midnight = DateUtil.getStartOfDay( entry.getPubTime() );
+
+ // ensure we do not get duplicates from Lucene by
+ // using a Set Collection. Entries sorted by pubTime.
+ TreeSet set = (TreeSet) searchResults.get(midnight);
+ if (set == null) {
+ // date is not mapped yet, so we need a new Set
+ set = new TreeSet( new WeblogEntryComparator() );
+ searchResults.put(midnight, set);
+ }
+ set.add(entry);
+ }
+
+ private void addEntryWrapperToSearchResults(
+ TreeMap searchResults, WeblogEntryDataWrapper entry) {
+ // convert entry's each date to midnight (00m 00h 00s)
+ Date midnight = DateUtil.getStartOfDay( entry.getPubTime() );
+
+ // ensure we do not get duplicates from Lucene by
+ // using a Set Collection. Entries sorted by pubTime.
+ TreeSet set = (TreeSet) searchResults.get(midnight);
+ if (set == null) {
+ // date is not mapped yet, so we need a new Set
+ set = new TreeSet( new WeblogEntryWrapperComparator() );
+ searchResults.put(midnight, set);
+ }
+ set.add(entry);
+ }
+
+ private int useOffset(HttpServletRequest request) {
+ int offset = OFFSET;
+ if (request.getParameter("o") != null) {
+ try {
+ offset = Integer.valueOf(request.getParameter("o")).intValue();
+ } catch (NumberFormatException e) {
+ // Not a valid Integer
+ }
+ }
+ return offset;
+ }
+
+ private int useLimit(HttpServletRequest request) {
+ int limit = LIMIT;
+ if (request.getParameter("n") != null) {
+ try {
+ limit = Integer.valueOf(request.getParameter("n")).intValue();
+ } catch (NumberFormatException e) {
+ // Not a valid Integer
+ }
+ }
+ return limit;
+ }
+
+ public String getTerm() {
+ return term;
+ }
+
+ public void setTerm(String term) {
+ this.term = term;
+ }
+
+ public Integer getHits() {
+ return hits;
+ }
+
+ public void setHits(Integer hits) {
+ this.hits = hits;
+ }
+
+ public Integer getOffset() {
+ return offset;
+ }
+
+ public void setOffset(Integer offset) {
+ this.offset = offset;
+ }
+
+ public Integer getLimit() {
+ return limit;
+ }
+
+ public void setLimit(Integer limit) {
+ this.limit = limit;
+ }
+
+ public TreeMap getResults() {
+ return results;
+ }
+
+ public void setResults(TreeMap results) {
+ this.results = results;
+ }
+
+ public Set getCategories() {
+ return categories;
+ }
+
+ public void setCategories(Set categories) {
+ this.categories = categories;
+ }
+
+ public boolean isWebsiteSpecificSearch() {
+ return websiteSpecificSearch;
+ }
+
+ public void setWebsiteSpecificSearch(boolean websiteSpecificSearch) {
+ this.websiteSpecificSearch = websiteSpecificSearch;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+}
\ No newline at end of file
Added: incubator/roller/trunk/src/org/apache/roller/presentation/search/SearchServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/search/SearchServlet.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/search/SearchServlet.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/search/SearchServlet.java Mon May 1 15:23:02 2006
@@ -0,0 +1,78 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License. For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.roller.presentation.search;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.velocity.Template;
+import org.apache.velocity.context.Context;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.roller.RollerException;
+import org.apache.roller.config.RollerConfig;
+import org.apache.roller.presentation.RollerRequest;
+import org.apache.roller.presentation.velocity.ContextLoader;
+import org.apache.roller.presentation.velocity.PageServlet;
+
+/**
+ * This servlet retrieves (and displays) search results.
+ *
+ * @web.servlet name="SearchServlet" load-on-startup="5"
+ * @web.servlet-init-param name="properties" value="/WEB-INF/velocity.properties"
+ * @web.servlet-mapping url-pattern="/search/*"
+ */
+public class SearchServlet extends PageServlet {
+
+ static final long serialVersionUID = -2150090108300585670L;
+
+ private static Log mLogger = LogFactory.getLog(SearchServlet.class);
+
+ private boolean searchEnabled = true;
+
+
+ public void init(ServletConfig config) throws ServletException {
+
+ super.init(config);
+
+ // lookup if search is enabled
+ this.searchEnabled = RollerConfig.getBooleanProperty("search.enabled");
+ }
+
+ /**
+ * Prepare the requested page for execution by setting content type
+ * and populating velocity context.
+ */
+ protected Template prepareForPageExecution(
+ Context ctx,
+ RollerRequest rreq,
+ HttpServletResponse response,
+ org.apache.roller.pojos.Template page)
+ throws ResourceNotFoundException, RollerException {
+
+ // search model executes search, makes results available to page
+ SearchResultsPageModel model =
+ new SearchResultsPageModel(rreq.getRequest(), true);
+ ctx.put("searchResults", model);
+ return super.prepareForPageExecution(ctx, rreq, response, page);
+ }
+}
+
+
Added: incubator/roller/trunk/src/org/apache/roller/presentation/servlets/CommentAuthenticatorServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/servlets/CommentAuthenticatorServlet.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/servlets/CommentAuthenticatorServlet.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/servlets/CommentAuthenticatorServlet.java Mon May 1 15:23:02 2006
@@ -0,0 +1,97 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License. For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+/*
+ * CommentAuthenticatorServlet.java
+ *
+ * Created on January 5, 2006, 12:37 PM
+ */
+
+package org.apache.roller.presentation.servlets;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.config.RollerConfig;
+import org.apache.roller.presentation.velocity.CommentAuthenticator;
+import org.apache.roller.presentation.velocity.DefaultCommentAuthenticator;
+
+
+/**
+ * The CommentAuthenticatorServlet is used for generating the html used for
+ * comment authentication. This is done outside of the normal rendering process
+ * so that we can cache full pages and still set the comment authentication
+ * section dynamically.
+ *
+ * @web.servlet name="CommentAuthenticatorServlet"
+ * @web.servlet-mapping url-pattern="/CommentAuthenticatorServlet"
+ */
+public class CommentAuthenticatorServlet extends HttpServlet {
+
+ private static Log mLogger =
+ LogFactory.getLog(CommentAuthenticatorServlet.class);
+
+ private CommentAuthenticator authenticator = null;
+
+
+ /**
+ * Handle incoming http GET requests.
+ *
+ * We only handle get requests.
+ */
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException {
+
+ PrintWriter out = response.getWriter();
+
+ response.setContentType("text/html");
+ out.println(this.authenticator.getHtml(null, request, response));
+ }
+
+
+ /**
+ * Initialization.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+
+ // lookup the authenticator we are going to use and instantiate it
+ try {
+ String name = RollerConfig.getProperty("comment.authenticator.classname");
+
+ Class clazz = Class.forName(name);
+ this.authenticator = (CommentAuthenticator) clazz.newInstance();
+
+ } catch(Exception e) {
+ mLogger.error(e);
+ this.authenticator = new DefaultCommentAuthenticator();
+ }
+
+ }
+
+ /**
+ * Destruction.
+ */
+ public void destroy() {}
+
+}
Added: incubator/roller/trunk/src/org/apache/roller/presentation/servlets/CommentServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/servlets/CommentServlet.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/servlets/CommentServlet.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/servlets/CommentServlet.java Mon May 1 15:23:02 2006
@@ -0,0 +1,558 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License. For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.roller.presentation.servlets;
+
+import java.io.IOException;
+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.ServletConfig;
+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.apache.roller.RollerException;
+import org.apache.roller.config.RollerConfig;
+import org.apache.roller.config.RollerRuntimeConfig;
+import org.apache.roller.model.IndexManager;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.model.WeblogManager;
+import org.apache.roller.pojos.CommentData;
+import org.apache.roller.pojos.UserData;
+import org.apache.roller.pojos.WeblogEntryData;
+import org.apache.roller.pojos.WebsiteData;
+import org.apache.roller.presentation.RollerContext;
+import org.apache.roller.presentation.RollerRequest;
+import org.apache.roller.presentation.RollerSession;
+import org.apache.roller.presentation.velocity.CommentAuthenticator;
+import org.apache.roller.presentation.weblog.formbeans.CommentFormEx;
+import org.apache.roller.util.SpamChecker;
+import org.apache.roller.util.MailUtil;
+import org.apache.roller.util.StringUtils;
+import org.apache.roller.presentation.cache.CacheManager;
+import org.apache.roller.presentation.velocity.DefaultCommentAuthenticator;
+import org.apache.roller.util.Utilities;
+
+/**
+ * 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 Log mLogger = LogFactory.getLog(CommentServlet.class);
+
+ private static final String EMAIL_ADDR_REGEXP = "^.*@.*[.].{2,}$";
+
+ private ResourceBundle bundle =
+ ResourceBundle.getBundle("ApplicationResources");
+
+ private CommentAuthenticator authenticator = null;
+
+
+ /**
+ * Initialization.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+
+ // lookup the authenticator we are going to use and instantiate it
+ try {
+ String name = RollerConfig.getProperty("comment.authenticator.classname");
+
+ Class clazz = Class.forName(name);
+ this.authenticator = (CommentAuthenticator) clazz.newInstance();
+
+ } catch(Exception e) {
+ mLogger.error(e);
+ this.authenticator = new DefaultCommentAuthenticator();
+ }
+
+ }
+
+
+ /**
+ * 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;
+
+ // parse request and validate
+ RollerRequest rreq = RollerRequest.getRollerRequest(request);
+ HttpSession session = request.getSession();
+
+ // make sure we know the entry this comment is going to
+ WeblogEntryData entry = rreq.getWeblogEntry();
+ if (entry == null || entry.getId() == null) {
+ session.setAttribute(RollerSession.ERROR_MESSAGE, "Cannot post comment to null entry");
+ RequestDispatcher dispatcher =
+ request.getRequestDispatcher(entry_permalink);
+ dispatcher.forward(request, response);
+ return;
+ }
+
+ try {
+ // 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";
+
+ // If comment contains blacklisted text, warn commenter
+ SpamChecker checker = new SpamChecker();
+ if (checker.checkComment(comment)) {
+ error = bundle.getString("commentServlet.previewMarkedAsSpam");
+ mLogger.debug("Comment marked as spam");
+ }
+ request.setAttribute("previewComments", "dummy");
+ mLogger.debug("Comment is a preview");
+
+ } else {
+ if (this.authenticator.authenticate(comment, request)) {
+ mLogger.debug("Comment passed authentication");
+
+ // If comment contains blacklisted text, mark as spam
+ SpamChecker checker = new SpamChecker();
+ if (checker.checkComment(comment)) {
+ comment.setSpam(Boolean.TRUE);
+ error = bundle.getString("commentServlet.commentMarkedAsSpam");
+ mLogger.debug("Comment marked as spam");
+ }
+
+ // If comment moderation is on, set comment as pending
+ if (website.getCommentModerationRequired()) {
+ comment.setPending(Boolean.TRUE);
+ comment.setApproved(Boolean.FALSE);
+ message = bundle.getString("commentServlet.submittedToModerator");
+ } else {
+ comment.setPending(Boolean.FALSE);
+ comment.setApproved(Boolean.TRUE);
+ }
+
+ mgr.saveComment(comment);
+ RollerFactory.getRoller().flush();
+ reindexEntry(entry);
+
+ // Clear all caches associated with comment
+ CacheManager.invalidate(comment);
+
+ // Send email notifications
+ RollerContext rc = RollerContext.getRollerContext();
+ String rootURL = rc.getAbsoluteContextUrl(request);
+ if (rootURL == null || rootURL.trim().length()==0) {
+ rootURL = RequestUtils.serverURL(request) + request.getContextPath();
+ }
+ sendEmailNotification(comment, rootURL);
+
+ } else {
+ error = bundle.getString("error.commentAuthFailed");
+ mLogger.debug("Comment failed authentication");
+ }
+ }
+ } 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);
+ if (message != null)
+ session.setAttribute(RollerSession.STATUS_MESSAGE, message);
+
+ if(error == 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);
+ }
+ }
+
+ /**
+ * Send email notification of comment.
+ *
+ * TODO: Make the addressing options configurable on a per-website basis.
+ */
+ public static void sendEmailNotification(CommentData cd, String rootURL) {
+
+ // Send commment notifications in locale of server
+ ResourceBundle resources = ResourceBundle.getBundle("ApplicationResources");
+
+ WeblogEntryData entry = cd.getWeblogEntry();
+ 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();
+ // get only approved, non spam comments
+ comments = entry.getComments(true, true);
+ } 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((escapeHtml) ? Utilities.escapeHTML(cd.getContent())
+ : Utilities.transformToHTMLSubset(Utilities.escapeHTML(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 />");
+
+ // Build link back to comment
+ StringBuffer commentURL = new StringBuffer(rootURL);
+ commentURL.append(entry.getPermaLink());
+ commentURL.append("#comments");
+
+ 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/commentManagement.do?method=query&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
+ }
+
+ /**
+ * Send message to author of approved comment
+ *
+ * TODO: Make the addressing options configurable on a per-website basis.
+ */
+ public static void sendEmailApprovalNotification(CommentData cd, String rootURL) {
+
+ // Send commment notifications in locale of server
+ ResourceBundle resources = ResourceBundle.getBundle("ApplicationResources");
+
+ WeblogEntryData entry = cd.getWeblogEntry();
+ WebsiteData site = entry.getWebsite();
+ UserData user = entry.getCreator();
+
+ // Only send email if email notificaiton is enabled
+ boolean notify = RollerRuntimeConfig.getBooleanProperty("users.comments.emailnotify");
+ if (notify && site.getEmailComments().booleanValue()) {
+ mLogger.debug("Comment notification enabled ... preparing email");
+
+
+
+ //------------------------------------------
+ // --- 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();
+
+ //------------------------------------------
+ // --- Form the message to be sent -
+
+ String subject = resources.getString("email.comment.commentApproved");
+
+ StringBuffer msg = new StringBuffer();
+ msg.append(resources.getString("email.comment.commentApproved"));
+
+ // Build link back to comment
+ StringBuffer commentURL = new StringBuffer(rootURL);
+ commentURL.append(entry.getPermaLink());
+ commentURL.append("#comments");
+ msg.append(commentURL.toString());
+
+ //------------------------------------------
+ // --- Send message to author of approved comment
+ try {
+ javax.naming.Context ctx = (javax.naming.Context)
+ new InitialContext().lookup("java:comp/env");
+ Session session = (Session)ctx.lookup("mail/Session");
+ String[] cc = null;
+ String[] bcc = null;
+ sendMessage(session, from,
+ new String[] {cd.getEmail()},
+ null, // cc
+ null, // bcc
+ subject, msg.toString(), false);
+ } 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.
+ */
+ static 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/trunk/src/org/apache/roller/presentation/servlets/ResourceServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/servlets/ResourceServlet.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/servlets/ResourceServlet.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/servlets/ResourceServlet.java Mon May 1 15:23:02 2006
@@ -0,0 +1,151 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License. For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.roller.presentation.servlets;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLDecoder;
+import java.util.Date;
+import javax.servlet.ServletConfig;
+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.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.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.getLog(ResourceServlet.class);
+
+ private String upload_dir = null;
+ private ServletContext context = null;
+
+
+ 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); }
+
+ }
+
+
+ /**
+ * Handles requests for user uploaded resources.
+ */
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ String context = request.getContextPath();
+ String servlet = request.getServletPath();
+ String reqURI = request.getRequestURI();
+
+ // URL decoding
+
+ // Fix for ROL-1065: even though a + should mean space in a URL, folks
+ // who upload files with plus signs expect them to work without
+ // escaping. This is essentially what other systems do (e.g. JIRA) to
+ // enable this.
+ reqURI = reqURI.replaceAll("\\+", "%2B");
+
+ // now we really decode the URL
+ reqURI = URLDecoder.decode(reqURI, "UTF-8");
+
+ // 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() || resource.isDirectory()) {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND);
+ return;
+ }
+
+ // make sure someone isn't trying to sneek outside the uploads dir
+ File uploadDir = new File(this.upload_dir);
+ if(!resource.getCanonicalPath().startsWith(uploadDir.getCanonicalPath())) {
+ 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();
+ }
+
+
+ public void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ doGet(request, response);
+ }
+
+}
Added: incubator/roller/trunk/src/org/apache/roller/presentation/servlets/TrackbackServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/servlets/TrackbackServlet.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/servlets/TrackbackServlet.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/servlets/TrackbackServlet.java Mon May 1 15:23:02 2006
@@ -0,0 +1,259 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License. For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+/*
+ * Created on Apr 13, 2003
+ */
+package org.apache.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.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.util.RequestUtils;
+import org.apache.roller.config.RollerRuntimeConfig;
+import org.apache.roller.pojos.CommentData;
+import org.apache.roller.util.SpamChecker;
+
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.model.WeblogManager;
+import org.apache.roller.pojos.WeblogEntryData;
+import org.apache.roller.pojos.WebsiteData;
+import org.apache.roller.presentation.RollerContext;
+import org.apache.roller.presentation.RollerRequest;
+import org.apache.roller.presentation.cache.CacheManager;
+import org.apache.roller.util.LinkbackExtractor;
+
+
+/**
+ * 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 {
+
+ private static Log logger =
+ LogFactory.getFactory().getInstance(TrackbackServlet.class);
+
+ /** 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 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 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;
+ boolean verified = true;
+ 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();
+ WebsiteData website = entry.getWebsite();
+ boolean siteAllows = website.getAllowComments().booleanValue();
+
+ if (entry!=null && siteAllows && entry.getCommentsStillAllowed()) {
+
+ // 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()));
+
+ // If comment contains blacklisted text, mark as spam
+ SpamChecker checker = new SpamChecker();
+ if (checker.checkTrackback(comment)) {
+ comment.setSpam(Boolean.TRUE);
+ logger.debug("Trackback blacklisted: "+comment.getUrl());
+ error = "REJECTED: trackback contains spam words";
+ }
+ // Else, if trackback verification is on...
+ else if (RollerRuntimeConfig.getBooleanProperty(
+ "site.trackbackVerification.enabled")) {
+
+ // ...ensure trackbacker actually links to us
+ RollerContext rctx= RollerContext.getRollerContext();
+ String absurl = rctx.getAbsoluteContextUrl();
+ LinkbackExtractor linkback = new LinkbackExtractor(
+ comment.getUrl(), absurl + entry.getPermaLink());
+ if (linkback.getExcerpt() == null) {
+ comment.setPending(Boolean.TRUE);
+ comment.setApproved(Boolean.FALSE);
+ verified = false;
+ // if we can't verify trackback, then reject it
+ error = "REJECTED: trackback failed verification";
+ logger.debug("Trackback failed verification: "+comment.getUrl());
+ }
+ }
+
+ if (error == null) {
+ // If comment moderation is on, set comment as pending
+ if (verified && website.getCommentModerationRequired()) {
+ comment.setPending(Boolean.TRUE);
+ comment.setApproved(Boolean.FALSE);
+ } else if (verified) {
+ comment.setPending(Boolean.FALSE);
+ comment.setApproved(Boolean.TRUE);
+ }
+
+ // save, commit, send response
+ WeblogManager mgr = RollerFactory.getRoller().getWeblogManager();
+ mgr.saveComment(comment);
+ RollerFactory.getRoller().flush();
+
+ // Clear all caches associated with comment
+ CacheManager.invalidate(comment);
+
+ // Send email notifications
+ RollerContext rc = RollerContext.getRollerContext();
+ String rootURL = rc.getAbsoluteContextUrl(req);
+ if (rootURL == null || rootURL.trim().length()==0) {
+ rootURL = RequestUtils.serverURL(req) + req.getContextPath();
+ }
+ CommentServlet.sendEmailNotification(comment, rootURL);
+
+ pw.println("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>");
+ pw.println("<response>");
+ pw.println("<error>0</error>");
+ if (comment.getPending().booleanValue()) {
+ pw.println("<message>Trackback sumitted to moderation</message>");
+ } else {
+ pw.println("<message>Trackback accepted</message>");
+ }
+ 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
Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/DateTag.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/DateTag.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/DateTag.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/DateTag.java Mon May 1 15:23:02 2006
@@ -0,0 +1,142 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License. For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.roller.presentation.tags;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.Globals;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.util.RequestUtils;
+
+/**
+ * Struts-based date field tag that wraps Matt Kruze's JavaScript data chooser.
+ * @jsp.tag name="Date"
+ */
+public class DateTag extends TagSupport {
+ static final long serialVersionUID = 1485100916981692535L;
+
+ // Unique key prefix keeps us from colliding with other tags and user data
+ public static final String KEY_PREFIX = "ZZZ_DATETAG_ZZZ";
+
+ private String property = null;
+ private String dateFormat = null;
+ private Boolean readOnly = Boolean.FALSE;
+ private String formName = null;
+
+ private static Log mLogger =
+ LogFactory.getFactory().getInstance(DateTag.class);
+
+ /**
+ * Renders date field by calling a JSP page.
+ */
+ public int doStartTag() throws JspException {
+
+ // Get form name
+ ActionMapping mapping =
+ (ActionMapping) pageContext.getRequest().getAttribute(
+ Globals.MAPPING_KEY);
+ if (formName == null) {
+ formName = mapping.getName();
+ }
+
+ // Get value of form field
+ Object value =
+ RequestUtils.lookup(pageContext, formName, property, null);
+ if (value == null)
+ value = "";
+
+ // put variables into request scope for view page
+ pageContext.getRequest().setAttribute(
+ KEY_PREFIX + "_formName",
+ formName);
+ pageContext.getRequest().setAttribute(
+ KEY_PREFIX + "_property",
+ property);
+ pageContext.getRequest().setAttribute(
+ KEY_PREFIX + "_dateFormat",
+ dateFormat);
+ pageContext.getRequest().setAttribute(
+ KEY_PREFIX + "_readOnly",
+ readOnly);
+ pageContext.getRequest().setAttribute(KEY_PREFIX + "_value", value);
+
+ // dispatch to view page
+ try {
+ pageContext.include("/tags/date.jsp");
+ } catch (Exception e) {
+ // can't handle this here
+ throw new JspException("ERROR including date.jsp");
+ }
+
+ // Don't evaluate content of tag, just continue processing this page
+ return (SKIP_BODY);
+ }
+
+ /**
+ * Date format string to be used.
+ *
+ * @jsp.attribute required="true" rtexprvalue="true" type="java.lang.String"
+ */
+ public String getDateFormat() {
+ return dateFormat;
+ }
+
+ public void setDateFormat(String dateFormat) {
+ this.dateFormat = dateFormat;
+ }
+
+ /**
+ * Name of form property represented.
+ * @jsp.attribute required="true" rtexprvalue="true" type="java.lang.String"
+ */
+ public String getProperty() {
+ return property;
+ }
+
+ public void setProperty(String property) {
+ this.property = property;
+ }
+
+ /**
+ * True if field should be readOnly.
+ * @jsp.attribute required="false" rtexprvalue="true" type="java.lang.Boolean"
+ */
+ public Boolean getReadOnly() {
+ return readOnly;
+ }
+
+ public void setReadOnly(Boolean readOnly) {
+ this.readOnly = readOnly;
+ }
+
+ /**
+ * Form name, only needed when more than one form on page.
+ * @jsp.attribute required="false" rtexprvalue="true" type="java.lang.String"
+ */
+ public String getFormName() {
+ return formName;
+ }
+
+ public void setFormName(String formName) {
+ this.formName = formName;
+ }
+
+}
Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/HybridTag.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/HybridTag.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/HybridTag.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/HybridTag.java Mon May 1 15:23:02 2006
@@ -0,0 +1,96 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License. For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+/*
+ * HybridTag.java
+ *
+ * Created on February 10, 2002, 11:12 PM
+ */
+
+package org.apache.roller.presentation.tags;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.TagSupport;
+
+/**
+ * JSP tag designed to be used from JSP page or from Velocity page.
+ * Tag must be a standalone tag, design precludes contents.
+ * @author David M Johnson
+ */
+public abstract class HybridTag extends TagSupport
+{
+ private static Log mLogger =
+ LogFactory.getFactory().getInstance(HybridTag.class);
+
+ public HybridTag()
+ {
+ }
+
+ public String toString()
+ {
+ String ret = null;
+ try
+ {
+ StringWriter sw = new StringWriter();
+ doStartTag( new PrintWriter( sw, true ));
+ // See, design precludes contents
+ doEndTag( new PrintWriter( sw, true ));
+ ret = sw.toString();
+ }
+ catch (Exception e)
+ {
+ ret = "Exception in tag";
+ mLogger.error(ret,e);
+ }
+ return ret;
+ }
+
+ public String emit()
+ {
+ return toString();
+ }
+
+ public int doStartTag() throws JspException
+ {
+ return doStartTag( new PrintWriter( pageContext.getOut(), true) );
+ }
+
+
+ public int doEndTag() throws JspException
+ {
+ return doEndTag( new PrintWriter( pageContext.getOut(), true) );
+ }
+
+ /** Default processing of the end tag returning SKIP_BODY. */
+ public int doStartTag( PrintWriter pw ) throws JspException
+ {
+ return SKIP_BODY;
+ }
+
+ /** Default processing of the end tag returning EVAL_PAGE. */
+ public int doEndTag( PrintWriter pw ) throws JspException
+ {
+ return EVAL_PAGE;
+ }
+
+}
Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/LinkParamTag.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/LinkParamTag.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/LinkParamTag.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/LinkParamTag.java Mon May 1 15:23:02 2006
@@ -0,0 +1,192 @@
+/*
+ * $Header: /cvs/roller/roller/src/org/roller/presentation/tags/LinkParamTag.java,v 1.2 2004/08/18 03:19:34 lavandowska Exp $
+ * $Revision: 1.2 $
+ * $Date: 2004/08/18 03:19:34 $
+ *
+ * ====================================================================
+ */
+
+
+package org.apache.roller.presentation.tags;
+
+import org.apache.log4j.Category;
+import org.apache.struts.util.RequestUtils;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.BodyContent;
+import javax.servlet.jsp.tagext.BodyTagSupport;
+
+/**
+ * Implements a custom tag to add parameter to a href request.<br/>
+ * This tag is intended to be nested in a <code>hm:link</code> tag.
+ *
+ * Title: BSquare
+ * Description: Bsquare Projects
+ * Copyright: Copyright (c) 2001
+ * Company: HubMethods
+ * @author Eric Fesler
+ * @version 1.0
+ */
+
+public class LinkParamTag extends BodyTagSupport {
+ // ----------------------------------------------------- Logging
+ static Category cat = Category.getInstance(LinkParamTag.class);
+
+ // ----------------------------------------------------- Instance variables
+ /**
+ * The name of the request parameter
+ */
+ private String id = null;
+
+ /**
+ * The value of the request parameter
+ */
+ private String value = null;
+
+ /**
+ * The source bean
+ */
+ private String name = null;
+
+ /**
+ * The source bean property
+ */
+ private String property = null;
+
+ /**
+ * The scope of the source bean
+ */
+ private String scope = null;
+
+
+ // ----------------------------------------------------- Properties
+
+ /**
+ * Sets the request parameter tag name
+ *
+ * @param name the request parameter tag name
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Returns the request parameter name
+ *
+ * @return the request parameter name
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the request parameter value
+ *
+ * @param value the request parameter value
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns the request parameter value
+ *
+ * @return the request parameter value
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the source bean name
+ * @param sourceBean the source bean name
+ */
+ public void setName ( String sourceBean) {
+ this.name = sourceBean;
+ }
+
+ /**
+ * Returns the source bean name
+ * @return the source bean name
+ */
+ public String getName () {
+ return this.name;
+ }
+
+ /**
+ * Sets the source bean property
+ * @param sourceProperty the source property
+ */
+ public void setProperty(String sourceProperty) {
+ this.property = sourceProperty;
+ }
+
+ /**
+ * Returns the source bean property
+ * @return the source property
+ */
+ public String getProperty() {
+ return property;
+ }
+
+ /**
+ * Set the source bean scope.
+ * @param sourceScope the source bean scope
+ */
+ public void setScope(String sourceScope) {
+ this.scope = sourceScope;
+ }
+
+ /**
+ * Returns the source bean scope
+ * @return the source bean scope
+ */
+ public String getScope() {
+ return this.scope;
+ }
+
+
+ // ------------------------------------------------------ Public Methods
+ /**
+ * Add the parameter and its value to the link tag
+ */
+ public int doEndTag() throws JspException {
+ // parent tag must be a LinkTag, gives access to methods in parent
+ LinkTag myparent = (LinkTag)javax.servlet.jsp.tagext.TagSupport.findAncestorWithClass(this, LinkTag.class);
+
+ if (myparent == null)
+ throw new JspException("linkparam tag not nested within link tag");
+ else {
+ BodyContent bodyContent = getBodyContent();
+ if (bodyContent != null && !bodyContent.getString().equals("")) {
+ setValue(bodyContent.getString());
+ }
+ else if (getValue() == null) setValue("null");
+// throw new JspException("Unable to assign a value to the parameter: '" + getId() + "'");
+ myparent.addRequestParameter(getId(), getValue());
+ }
+ return SKIP_BODY;
+ }
+
+ /**
+ * Process the start tag
+ */
+ public int doStartTag() throws javax.servlet.jsp.JspException {
+
+ // Look up the requested property value
+ if (name != null) {
+ Object beanValue =
+ RequestUtils.lookup(pageContext, name, property, scope);
+ if (cat.isDebugEnabled()) cat.debug("Value is : '" + beanValue + "'");
+ if (beanValue == null)
+ return (EVAL_BODY_TAG);
+
+ // set the property as value
+ setValue(beanValue.toString());
+ }
+
+ // Continue processing this page
+ return (EVAL_BODY_TAG);
+
+ }
+}