1    package geekblog.filters;
2    
3    
4    import java.io.*;
5    import java.lang.*;
6    import java.security.*;
7    import java.text.*;
8    import java.util.*;
9    import java.util.prefs.*;
10   import javax.servlet.*;
11   import javax.servlet.http.*;
12   import geekblog.*;
13   import org.apache.commons.fileupload.*;
14   
15   
16   /**
17    * Filter to handle all "action" (a.k.a. Controller) processing in front of
18    * index.jsp.
19    */
20   public class ActionFilter
21     implements Filter
22   {
23     private FilterConfig config;
24     private ServletContext application;
25     private DataManager dm;
26     private Preferences blogPrefs;
27   
28     
29     public void init(FilterConfig cfg)
30     {
31       config = cfg;
32       application = config.getServletContext();
33     }
34     public void destroy()
35     {
36     }
37   
38   
39     public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
40       throws ServletException, IOException
41     {
42       ServletContext application = config.getServletContext();
43       HttpServletRequest request = (HttpServletRequest)req;
44       HttpServletResponse response = (HttpServletResponse)resp;
45   
46       if (dm == null)
47         dm = (DataManager)application.getAttribute(DataManager.KEY);
48   
49       if (blogPrefs == null)
50       {
51         String ctx = request.getContextPath();
52         blogPrefs = Preferences.systemRoot().node("net/sourceforge/geekblog" + ctx);
53       }
54       
55       if (FileUpload.isMultipartContent(request))
56       {
57         application.log("Is multipart-formdata");
58         request = new MultipartHttpServletRequest(request, application.getRealPath("/WEB-INF"));
59       }
60       else
61       {
62         application.log("Nope, no multipart-formdata here, no siree....");
63       }
64   
65       // Do any processing that needs to be done
66       //
67       String action = request.getParameter("action");
68       if (action != null)
69       {
70         if (action.equals("login"))
71           process_login(request, response);
72         else if (action.equals("save"))
73           process_save(request, response);
74         else if (action.equals("addlink"))
75           process_addlink(request, response);
76         else if (action.equals("addblogroll"))
77           process_addblogroll(request, response);
78         else if (action.equals("search"))
79           process_search(request, response);
80         else if (action.equals("savepage"))
81           process_savepage(request, response);
82       }
83   
84       Collection entries = findBlogEntries(request, response);
85   
86       // TODO: Verify this logic--how *exactly* are we supposed to handle
87       // this? I'm not entirely sure what the algorithm's supposed to look like. --TKN
88       //
89       if (request.getDateHeader("If-Modified-Since") != -1)
90       {
91         BlogEntry mostRecentEntry = (BlogEntry)entries.iterator().next();
92         if (mostRecentEntry != null)
93         {
94           Date ts = mostRecentEntry.getTimestamp();
95           Date ims = new Date(request.getDateHeader("If-Modified-Since"));
96   
97           if (ts.getTime() > ims.getTime())
98           {
99             response.setDateHeader("Last-Modified", ts.getTime());
100          }
101          else
102          {
103            // ???
104          }
105        }
106      }
107  
108      chain.doFilter(request, response);
109    }
110  
111    private void process_login(HttpServletRequest request, HttpServletResponse response)
112    {
113      String userid = request.getParameter("userid");
114      String password = request.getParameter("password");
115  
116      if (userid.equals(blogPrefs.get("userid", null)) && 
117          password.equals(blogPrefs.get("password", null)))
118      {
119        HttpSession session = request.getSession(true);
120        session.setAttribute("userid", userid);
121      }
122    }
123  
124    private void process_save(HttpServletRequest req, HttpServletResponse response)
125    {
126      MultipartHttpServletRequest request = (MultipartHttpServletRequest)req;
127  
128      if (request.getSession(false) == null)
129      {
130        // Do nothing
131      }
132      else
133      {
134        // There were no files; proceed normally
135        //
136        String id = request.getParameter("entryID");
137        String tt = request.getParameter("title");
138        String tx = request.getParameter("text");
139        String ar = request.getParameter("article");
140  
141        // Save off the file someplace
142        //
143        int suffix = 0;
144        while (true)
145        {
146          FileItem fileItem = request.getFileParameter("file_" + suffix);
147          String fileDest = request.getParameter("filedest_" + suffix);
148  
149          if (fileItem == null || fileItem.getName().equals(""))
150          {
151            break;
152          }
153          else
154          {
155            // Save off file to destination
156            //
157            File sourceFile = fileItem.getStoreLocation();
158            File destFile = new File(application.getRealPath("/"), fileDest);
159            File destDir = new File(destFile.getParent());
160            if (!destDir.exists())
161            {
162              destDir.mkdirs();
163            }
164  
165            try
166            {
167              FileInputStream fis = new FileInputStream(sourceFile);
168              FileOutputStream fos = new FileOutputStream(destFile);
169              BufferedInputStream bis = new BufferedInputStream(fis);
170              byte[] buffer = new byte[1024];
171              int ct = 0;
172              while ((ct = bis.read(buffer, 0, buffer.length)) != -1)
173                fos.write(buffer, 0, ct);
174              bis.close();
175              fis.close();
176              fos.close();
177            }
178            catch (IOException IOEx)
179            {
180              throw new RuntimeException("Error in writing " + sourceFile + " to " + destFile, IOEx);
181            }
182  
183            suffix++;
184          }
185        }
186  
187        BlogEntry entry;
188        if (id.equals("0"))
189          entry = new BlogEntry(tt, tx);
190        else
191        {
192          entry = dm.getEntry(Long.parseLong(id));
193          entry.setTitle(tt);
194          entry.setText(tx);
195        }
196  
197        dm.postEntry(entry);
198  
199        if (ar != null)
200        {
201          dm.markAsArticle(entry);
202        }
203      }
204    }
205  
206    private void process_addlink(HttpServletRequest request, HttpServletResponse response)
207      throws IOException
208    {
209      if (request.getSession(false) == null)
210      {
211        // Do nothing
212      }
213      else
214      {
215        String linkName = request.getParameter("linktitle");
216        String linkURL = request.getParameter("linkurl");
217    
218        FileWriter fw = new FileWriter(application.getRealPath("/WEB-INF/links.jsp"), true);
219        PrintWriter pw = new PrintWriter(fw);
220    
221        pw.println("<a href=\"" + linkURL + "\">" + linkName + "</a><br />");
222    
223        pw.close();
224        fw.close();
225      }
226    }
227  
228    private void process_addblogroll(HttpServletRequest request, HttpServletResponse response)
229      throws IOException
230    {
231      if (request.getSession(false) == null)
232      {
233        // Do nothing
234      }
235      else
236      {
237        String linkName = request.getParameter("blogrolltitle");
238        String linkURL = request.getParameter("blogrollurl");
239        String linkRSSURL = request.getParameter("blogrollrssurl");
240    
241        FileWriter fw = new FileWriter(application.getRealPath("/WEB-INF/blogroll.jsp"), true);
242        PrintWriter pw = new PrintWriter(fw);
243    
244        pw.println("<a href=\"" + linkURL + "\">" + linkName + "</a> (<a href=\"" + linkRSSURL + "\">RSS</a>)<br />");
245    
246        pw.close();
247        fw.close();
248      }
249    }
250  
251    private void process_search(HttpServletRequest request, HttpServletResponse response)
252    {
253      String searchText = request.getParameter("search");
254  
255      request.setAttribute("geekblog.entries", dm.findEntries(searchText));
256    }
257  
258    private void process_savepage(HttpServletRequest request, HttpServletResponse response)
259      throws IOException
260    {
261      String fileContents = request.getParameter("pagecontent");
262      String filename = request.getParameter("filename");
263  
264      FileWriter fw = new FileWriter(application.getRealPath(filename));
265      fw.write(fileContents, 0, fileContents.length());
266  
267      fw.close();
268    }
269  
270    private Collection findBlogEntries(HttpServletRequest request, HttpServletResponse response)
271    {
272      GregorianCalendar workingDate = new GregorianCalendar();
273      Collection entries = null;
274  
275      String action = request.getParameter("action");
276      if (action != null && action.equals("search"))
277      {
278        // Entries were already found, workingDate is already correct, just no-op
279        // 
280      }
281      else
282      {
283        // We need to look up the entries for the current date, or the date
284        // passed in via query param
285        //
286        String date = request.getParameter("date");
287        String month = request.getParameter("month");
288        String all = request.getParameter("all");
289        if (date != null)
290        {
291          try
292          {
293            workingDate.setTime(new SimpleDateFormat("yyyyMMdd").parse(date));
294            entries = dm.getEntriesForDate(workingDate.getTime());
295          }
296          catch (ParseException parseEx)
297          {
298            // Fall through to final check, below
299          }
300        }
301        else if (month != null)
302        {
303          try
304          {
305            workingDate.setTime(new SimpleDateFormat("yyyyMM").parse(month));
306            entries = dm.getEntriesForMonth(workingDate.getTime());
307          }
308          catch (ParseException parseEx)
309          {
310            // Fall through to final check, below
311          }
312        }
313        else if (all != null)
314          entries = dm.getAllEntries();
315  
316        // TODO: change this to read number of entries from blogPrefs "weblog.recententries"
317        //
318        int recentEntries = blogPrefs.getInt("weblog.recententries", 15);
319        if (entries == null)
320          entries = dm.getLastNEntries(recentEntries);
321      }
322  
323      request.setAttribute("geekblog.entries", entries);
324      request.setAttribute("workingDate", workingDate);
325  
326      return entries;
327    }
328  }
329  
330  
331  /**
332   * Why is there no HttpServletRequestWrapper? I want to silently replace the
333   * HttpServletRequest with a Wrapper that provides the exact same interface, yet
334   * wraps around multipart-formdata. Doing this lets me support both "normal" and
335   * multipart-formdata without having to write anything different in the JSPs or
336   * servlets.
337   */
338  class MultipartHttpServletRequest extends ServletRequestWrapper
339    implements HttpServletRequest
340  {
341    private Map fileMap = new HashMap();
342    private Map parameterMap = new HashMap();
343    private HttpServletRequest request;
344  
345  
346    /**
347     * Wrap (Decorate, in GOF terms) a HttpServletRequest, adding functionality
348     * to consume a multipart-formdata request and serve it back via the
349     * standard HttpServletRequest methods. We add a few methods to be used in
350     * the event that (request instanceof MultipartHttpServletRequest) == true
351     * from within the JSP/servlet.
352     */
353    public MultipartHttpServletRequest(HttpServletRequest r, String repositoryPath)
354    {
355      super(r);
356      
357      request = r;
358  
359      Map originalParamMap = r.getParameterMap();
360      for (Iterator iter = originalParamMap.keySet().iterator(); iter.hasNext(); )
361      {
362        Object key = iter.next();
363        parameterMap.put(key, originalParamMap.get(key));
364      }
365  
366      FileUpload fu = new FileUpload();
367  
368      fu.setSizeMax(5000000);
369      fu.setSizeThreshold(4096);
370      fu.setRepositoryPath(repositoryPath);
371  
372      try
373      {
374        List fileItems = fu.parseRequest(request);
375        for (Iterator iter = fileItems.iterator(); iter.hasNext(); )
376        {
377          FileItem current = (FileItem)iter.next();
378  
379          if (current.isFormField())
380          {
381            parameterMap.put(current.getFieldName(), current.getString());
382          }
383          else
384          {
385            parameterMap.put(current.getFieldName(), current);
386            fileMap.put(current.getName(), current);
387          }
388        }
389      }
390      catch (FileUploadException fuEx)
391      {
392        throw new RuntimeException("Error in parsing multipart-formdata: " + fuEx);
393      }
394    }
395  
396  
397    /**
398     *
399     */
400    public Iterator getFiles()
401    {
402      return fileMap.values().iterator();
403    }
404    /**
405     *
406     */
407    public Iterator getFileNames()
408    {
409      return fileMap.keySet().iterator();
410    }
411    /**
412     *
413     */
414    public byte[] getFile(String name)
415    {
416      Object o = fileMap.get(name);
417      FileItem fi = (FileItem)o;
418      return fi.get();
419    }
420  
421  
422    // ================================================================
423    //                                         ServletRequest methods
424    // ================================================================
425    /**
426     *
427     */
428    public String getParameter(String paramName)
429    {
430      String retval = null;
431      if ((retval = request.getParameter(paramName)) == null)
432        retval = (String)parameterMap.get(paramName);
433      
434      return retval;
435    }
436    /**
437     *
438     */
439    public FileItem getFileParameter(String paramName)
440    {
441      return (FileItem)parameterMap.get(paramName);
442    }
443    /**
444     *
445     */
446    public Enumeration getParameterNames()
447    {
448      final Enumeration enum = request.getParameterNames();
449      final Iterator iter = parameterMap.keySet().iterator();
450      return new Enumeration()
451        {
452          public boolean hasMoreElements() 
453          {
454            return (enum.hasMoreElements() || iter.hasNext());
455          }
456          public Object nextElement() 
457          {
458            if (enum.hasMoreElements())
459            {
460              return enum.nextElement();
461            }
462            else if (iter.hasNext())
463            {
464              return iter.next();
465            }
466            return null;
467          }
468        };
469    }
470    /**
471     *
472     */
473    public String[] getParameterValues(String paramName)
474    {
475      throw new UnsupportedOperationException("Sorry; can't do this");
476    }
477    /**
478     *
479     */
480    public Map getParameterMap()
481    {
482      throw new UnsupportedOperationException("Sorry; can't do this");
483    }
484  
485  
486    // ================================================================
487    //                                     HttpServletRequest methods
488    // ================================================================
489    public String getAuthType()
490    {
491      return request.getAuthType();
492    }
493    public Cookie getCookies()[]
494    {
495      return request.getCookies();
496    }
497    public long getDateHeader(String headerName)
498    {
499      return request.getDateHeader(headerName);
500    }
501    public String getHeader(String headerName)
502    {
503      return request.getHeader(headerName);
504    }
505    public Enumeration getHeaders(String headerNames)
506    {
507      return request.getHeaders(headerNames);
508    }
509    public Enumeration getHeaderNames()
510    {
511      return request.getHeaderNames();
512    }
513    public int getIntHeader(String headerName)
514    {
515      return request.getIntHeader(headerName);
516    }
517    public String getMethod()
518    {
519      return request.getMethod();
520    }
521    public String getPathInfo()
522    {
523      return request.getPathInfo();
524    }
525    public String getPathTranslated()
526    {
527      return request.getPathTranslated();
528    }
529    public String getContextPath()
530    {
531      return request.getContextPath();
532    }
533    public String getQueryString()
534    {
535      return request.getQueryString();
536    }
537    public String getRemoteUser()
538    {
539      return request.getRemoteUser();
540    }
541    public boolean isUserInRole(String role)
542    {
543      return request.isUserInRole(role);
544    }
545    public Principal getUserPrincipal()
546    {
547      return request.getUserPrincipal();
548    }
549    public String getRequestedSessionId()
550    {
551      return request.getRequestedSessionId();
552    }
553    public String getRequestURI()
554    {
555      return request.getRequestURI();
556    }
557    public StringBuffer getRequestURL()
558    {
559      return request.getRequestURL();
560    }
561    public String getServletPath()
562    {
563      return request.getServletPath();
564    }
565    public HttpSession getSession(boolean force)
566    {
567      return request.getSession(force);
568    }
569    public HttpSession getSession()
570    {
571      return request.getSession();
572    }
573    public boolean isRequestedSessionIdValid()
574    {
575      return request.isRequestedSessionIdValid();
576    }
577    public boolean isRequestedSessionIdFromCookie()
578    {
579      return request.isRequestedSessionIdFromCookie();
580    }
581    public boolean isRequestedSessionIdFromURL()
582    {
583      return request.isRequestedSessionIdFromURL();
584    }
585    public boolean isRequestedSessionIdFromUrl()
586    {
587      return request.isRequestedSessionIdFromUrl();
588    }
589  }
590