You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by aj...@apache.org on 2009/03/07 00:31:05 UTC

svn commit: r751135 [2/3] - in /incubator/jspwiki/trunk: ./ src/WebContent/ src/WebContent/WEB-INF/ src/WebContent/WEB-INF/classes/ src/WebContent/WEB-INF/classes/templates/ src/WebContent/scripts/ src/WebContent/templates/default/ src/WebContent/templ...

Modified: incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/templates/default_zh_CN.properties
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/templates/default_zh_CN.properties?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/templates/default_zh_CN.properties (original)
+++ incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/templates/default_zh_CN.properties Fri Mar  6 23:31:03 2009
@@ -43,10 +43,6 @@
 diff.goback=\u8fd4\u56de {0} \u6216 {1}
 diff.versionhistory={0} \u9875\u9762\u4fe1\u606f
 diff.nodiff=\u6ca1\u6709\u5dee\u5f02\u3002
-# EditContent.jsp
-
-edit.locked=\u7528\u6237 <strong>{0}</strong> \u5df2\u5f00\u59cb\u7f16\u8f91\u8be5\u9875\u9762\uff0c\u4f46\u8fd8\u672a\u4fdd\u5b58\u3002\u6211\u4e0d\u4f1a\u963b\u6b62\u60a8\u7f16\u8f91\u8be5\u9875\u9762\uff0c\u4f46\u662f\u8981\u77e5\u9053\u5176\u4ed6\u4eba\u53ef\u80fd\u4f1a\u5f88\u70e6\u3002\u7b49\u5f85\u9501\u5b9a\u8fc7\u671f\u6216\u522b\u4eba\u505c\u6b62\u7f16\u8f91\uff0c\u8fd9\u6837\u4f1a\u6bd4\u8f83\u793c\u8c8c\u3002\u9501\u5b9a\u4f1a\u5728 {1} \u5206\u949f\u540e\u8fc7\u671f\u3002
-edit.restoring=\u5c06\u6062\u590d\u7248\u672c {0}\u3002\u5355\u51fb\u201c\u4fdd\u5b58\u201d\u6765\u8fdb\u884c\u6062\u590d\u3002\u4e5f\u53ef\u4ee5\u5728\u6062\u590d\u9875\u9762\u524d\u8fdb\u884c\u7f16\u8f91\u3002
 edit.tab.attachments=\u9644\u4ef6
 edit.tab.help=\u5e2e\u52a9
 edit.tab.edit=\u7f16\u8f91
@@ -98,8 +94,8 @@
 
 group.tab=\u67e5\u770b\u7ec4
 #replaced by grp.deletegroup.confirm
-#group.areyousure=Are you sure you want to permanently delete group &quot;{0}&quot;? \ 
-#    Users might not be able to access pages whose ACLS contain this group. \\n\\n \ 
+#group.areyousure=Are you sure you want to permanently delete group &quot;{0}&quot;? \
+#    Users might not be able to access pages whose ACLS contain this group. \\n\\n \
 #    If you click OK, the group will be removed immediately.
 group.doesnotexist=\u8be5\u7ec4\u4e0d\u5b58\u5728\u3002
 group.createsuggestion=\u4e3a\u4ec0\u4e48\u4e0d {0}
@@ -376,18 +372,10 @@
 # 0 : Application Name
 # 1 : Page name
 view.title.view={0}\uff1a{1}
-# The built-in editors also have their localized strings in this file.
-
-editor.plain.name=\u60a8\u7684\u540d\u79f0(<span class='accesskey'>N</span>)
-editor.plain.remember=\u662f\u5426\u8bb0\u4f4f\u6211\u7684\u4fe1\u606f\uff1f
 editor.plain.email=\u4e3b\u9875\u6216\u7535\u5b50\u90ae\u4ef6(<span class='accesskey'>M</span>)
-editor.plain.save.submit=\u4fdd\u5b58
 editor.plain.save.title=\u4fdd\u5b58 [ s ]
-editor.plain.preview.submit=\u9884\u89c8
 editor.plain.preview.title=\u9884\u89c8 [ v ]
-editor.plain.cancel.submit=\u53d6\u6d88
 editor.plain.cancel.title=\u53d6\u6d88\u7f16\u8f91\u3002\u60a8\u6240\u505a\u7684\u66f4\u6539\u5c06\u4e22\u5931\u3002[ q ]
-editor.plain.changenote=\u66f4\u6539\u6ce8\u91ca
 editor.commentsignature=\u6ce8\u91ca\u7b7e\u540d
 editor.plain.toolbar=\u5de5\u5177\u680f
 editor.plain.find=\u67e5\u627e
@@ -407,9 +395,6 @@
 editor.plain.smartpairs.title=\u81ea\u52a8\u8f93\u5165\u6210\u5bf9\u7684\u7b26\u53f7 () [] {} &lt;&gt; &quot;&quot; &#39;&#39;
 editor.plain.tabcompletion=Tab \u5b8c\u6210\uff08\u5173\u952e\u5b57 + Tab\uff09
 editor.plain.tabcompletion.title=\u5c06\u5173\u952e\u5b57\u81ea\u52a8\u6269\u5c55\u4e3a Wiki \u6807\u8bb0
-#editor.plain.editassist=Edit Assist
-#editor.plain.editassist.title=Toggle Edit Assist buttons
-editor.plain.sneakpreview=\u62a2\u5148\u9884\u89c8
 editor.plain.sneakpreview.title=\u62a2\u5148\u9884\u89c8\u3002\u5728\u6587\u672c\u6846\u5916\u9762\u70b9\u51fb\u53ef\u4ee5\u5237\u65b0\u62a2\u5148\u9884\u89c8\u533a\u57df\u3002
 editor.plain.tbLink.title=\u94fe\u63a5 - \u63d2\u5165 Wiki \u94fe\u63a5
 editor.plain.tbH1.title=h1 - \u63d2\u5165\u6807\u9898\u6837\u5f0f1

Modified: incubator/jspwiki/trunk/src/WebContent/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/WEB-INF/web.xml?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/WEB-INF/web.xml (original)
+++ incubator/jspwiki/trunk/src/WebContent/WEB-INF/web.xml Fri Mar  6 23:31:03 2009
@@ -96,13 +96,6 @@
       This is new in 2.4.  This defines a servlet filter which filters all requests. 
    -->
 
-   <!--
-   <filter>
-      <filter-name>WikiJSPFilter</filter-name>
-      <filter-class>org.apache.wiki.ui.WikiJSPFilter</filter-class>
-   </filter>
-   -->
-
    <filter-mapping>
        <filter-name>WikiServletFilter</filter-name>
        <url-pattern>/attach/*</url-pattern>
@@ -147,17 +140,6 @@
    </filter-mapping>
 
    <!--
-   <filter-mapping>
-       <filter-name>WikiJSPFilter</filter-name>
-       <url-pattern>/wiki/*</url-pattern>
-   </filter-mapping>
-   <filter-mapping>
-       <filter-name>WikiJSPFilter</filter-name>
-       <url-pattern>*.jsp</url-pattern>
-   </filter-mapping>
-   -->
-
-   <!--
        HttpSessionListener used for managing WikiSessions.
      -->
    <listener>

Modified: incubator/jspwiki/trunk/src/WebContent/Wiki.jsp
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/Wiki.jsp?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/Wiki.jsp (original)
+++ incubator/jspwiki/trunk/src/WebContent/Wiki.jsp Fri Mar  6 23:31:03 2009
@@ -1,8 +1,15 @@
 <%@ taglib uri="http://jakarta.apache.org/jspwiki.tld" prefix="wiki" %>
 <%@ taglib uri="http://stripes.sourceforge.net/stripes.tld" prefix="s" %>
 <s:useActionBean beanclass="org.apache.wiki.action.ViewActionBean" event="view" executeResolution="true" id="wikiActionBean" />
-<s:layout-render name="/templates/default/ViewLayout.jsp">
+<s:layout-render name="/templates/default/DefaultLayout.jsp">
 
+  <%-- If wiki page is current, allow search engines to spider it --%>
+  <wiki:CheckVersion mode="latest">
+    <s:layout-component name="head.meta.robots">
+      <meta name="robots" content="index,follow" />
+    </s:layout-component>
+  </wiki:CheckVersion>
+    
   <s:layout-component name="content">
     <wiki:NoSuchPage>
       <fmt:message key="common.nopage">

Modified: incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-edit.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-edit.js?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-edit.js (original)
+++ incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-edit.js Fri Mar  6 23:31:03 2009
@@ -496,7 +496,7 @@
 				var ta = this.textarea,
 					isOn = checkbox.checked;
 
-				$('sneakpreview').empty();
+				$('livepreview').empty();
 				ta.removeEvents('preview');
 				Wiki.prefs.set('autopreview',isOn);
 
@@ -506,7 +506,7 @@
     },
 
 	refreshPreview: function(){
-    	var	preview = $('sneakpreview');
+    	var	preview = $('livepreview');
 
 		$('previewSpin').show();
 		new Ajax( Wiki.TemplateUrl + "/AJAXPreview.jsp?page="+Wiki.PageName, { 

Modified: incubator/jspwiki/trunk/src/WebContent/templates/default/AttachmentTab.jsp
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/templates/default/AttachmentTab.jsp?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/templates/default/AttachmentTab.jsp (original)
+++ incubator/jspwiki/trunk/src/WebContent/templates/default/AttachmentTab.jsp Fri Mar  6 23:31:03 2009
@@ -27,7 +27,7 @@
     <div id="addattachment">
       <h3><fmt:message key="attach.add" /></h3>
       <wiki:Permission permission="upload">
-        <s:form beanclass="org.apache.wiki.action.ViewActionBean" class="wikiform" id="uploadform" acceptcharset="UTF-8">
+        <s:form beanclass="org.apache.wiki.action.UploadActionBean" class="wikiform" id="uploadform" acceptcharset="UTF-8">
           <s:param name="progressid" value="<%=progressId%>" />
           <s:param name="page" value="${wikiActionBean.page.name}" />
           <table>
@@ -35,8 +35,13 @@
             <td colspan="2"><div class="formhelp"><fmt:message key="attach.add.info" /></div></td>
           </tr>
           <tr>
+            <td span="2"><s:errors field="newAttachments" /></td>
+          </tr>
+          <tr>
             <td><s:label for="attachfile0" name="attach.add.selectfile" /></td>
-            <td><s:file name="newAttachments[0]" id="attachfile0" /></td>
+            <td><s:file name="newAttachments[0]" id="attachfile0" /><br/>
+              <s:file name="newAttachments[1]" id="attachfile1" /><br/>
+              <s:file name="newAttachments[2]" id="attachfile2" /></td>
           </tr>
           <tr>
             <td><s:label for="attachnote" name="attach.add.changenote" /></td>
@@ -53,7 +58,6 @@
       
           </table>
         </s:form>
-        <wiki:Messages div="error" />
       </wiki:Permission>
       <wiki:Permission permission="!upload">
         <div class="formhelp"><fmt:message key="attach.add.permission" /></div>

Copied: incubator/jspwiki/trunk/src/WebContent/templates/default/DefaultLayout.jsp (from r746887, incubator/jspwiki/trunk/src/WebContent/templates/default/ViewLayout.jsp)
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/templates/default/DefaultLayout.jsp?p2=incubator/jspwiki/trunk/src/WebContent/templates/default/DefaultLayout.jsp&p1=incubator/jspwiki/trunk/src/WebContent/templates/default/ViewLayout.jsp&r1=746887&r2=751135&rev=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/templates/default/ViewLayout.jsp (original)
+++ incubator/jspwiki/trunk/src/WebContent/templates/default/DefaultLayout.jsp Fri Mar  6 23:31:03 2009
@@ -1,29 +1,144 @@
 <%@ taglib uri="http://jakarta.apache.org/jspwiki.tld" prefix="wiki" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
 <%@ taglib uri="http://stripes.sourceforge.net/stripes.tld" prefix="s" %>
+<%@ page import="org.apache.wiki.WikiContext" %>
+<%@ page import="org.apache.wiki.action.WikiContextFactory" %>
+<%--
+     This file contains the default layout used by all JSPWiki 3 pages.
+     The default layout contains the HTML doctype declaration, header,
+     and page layout. It can be customized in the following ways:
+     
+     1) Top-level JSPs can define default components, as defined by
+        Stripes <s:layout-component name="foo"> elements. Named components
+        that can be overridden include:
+        
+          head.title          : The HTML page title, which will be rendered
+                                in the <title> element. Default=wiki: pagename
+          stylesheet          : Link tags to external stylesheets. Default=blank
+          inlinecss           : Inline stylesheets. Default=blank
+          script              : JavaScript <script> elements. Default=blank
+          jslocalizedstrings  : Localized scripts for JavaScript
+                                functions. Default=blank
+          jsfunction          : JavaScript functions. Default=blank
+          head.meta.robots    : Search engine options. Default=noindex,nofollow
+          content             : The page contents. Default=blank
+          
+     2) DefaultLayout injects additional JSPs that are meant to be
+        customized. These include:
+          
+          commonheader.jsp    : A "local header" that can contain company logos
+                                or other markup. Default=blank
+
+--%>
 <s:layout-definition>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>
+    <%--
+
+         Title: by default, use the "view page" title
+    --%>
+    <s:layout-component name="head.title">
       <fmt:message key="view.title.view">
         <fmt:param><wiki:Variable var="ApplicationName" /></fmt:param>
         <fmt:param><wiki:PageName/></fmt:param>
       </fmt:message>
+    </s:layout-component>
     </title>
-    <wiki:Include page="commonheader.jsp" />
-    <wiki:CheckVersion mode="notlatest">
-      <meta name="robots" content="noindex,nofollow" />
-    </wiki:CheckVersion>
-    <wiki:CheckRequestContext context="diff|info">
-      <meta name="robots" content="noindex,nofollow" />
-    </wiki:CheckRequestContext>
-    <wiki:CheckRequestContext context="!view">
-      <meta name="robots" content="noindex,follow" />
+    <%--
+
+         CSS stylesheets
+    --%>
+    <link rel="stylesheet" media="screen, projection, print" type="text/css" href="<wiki:Link format='url' templatefile='jspwiki.css' />" />
+    <%-- put this at the top, to avoid double load when not yet cached --%>
+    <link rel="stylesheet" type="text/css" media="print" href="<wiki:Link format='url' templatefile='jspwiki_print.css' />" />
+    <link rel="alternate stylesheet" type="text/css" href="<wiki:Link format='url' templatefile='jspwiki_print.css' />" title="Print friendly" />
+    <link rel="alternate stylesheet" type="text/css" href="<wiki:Link format='url' templatefile='jspwiki.css' />" title="Standard" />
+    <s:layout-component name="stylesheet" />
+    <s:layout-component name="inlinecss" />
+    <%--
+
+         Links to favicon and common pages
+    --%>
+    <link rel="search" href="<wiki:LinkTo format='url' page='FindPage' />" title='Search ${wikiEngine.applicationName}' />
+    <link rel="help" href="<wiki:LinkTo format='url' page='TextFormattingRules' />" title="Help" />
+    <link rel="start" href="<wiki:LinkTo format='url' page='${wikiEngine.frontPage}' />" title="Front page" />
+    <link rel="shortcut icon" type="image/x-icon" href="<wiki:Link format='url' jsp='images/favicon.ico' />" />
+    <%-- ie6 needs next line --%>
+    <link rel="icon" type="image/x-icon" href="<wiki:Link format='url' jsp='images/favicon.ico' />" />
+    <%--
+
+         Support for the universal edit button
+         (www.universaleditbutton.org)
+    --%>
+    <wiki:CheckRequestContext context='view|info|diff|upload'>
+    <wiki:Permission permission="edit">
+    <wiki:PageType type="page">
+    <link rel="alternate" type="application/x-wiki" href="<wiki:EditLink format='url' />" title="<fmt:message key='actions.edit.title' />" />
+    </wiki:PageType>
+    </wiki:Permission>
     </wiki:CheckRequestContext>
+    <%--
+
+         Skins: extra stylesheets, extra javascript
+    --%>
+    <c:if test='${(!empty prefs.Skin) && (prefs.Skin!="PlainVanilla") }'>
+    <link rel="stylesheet" type="text/css" media="screen, projection, print" href="<wiki:Link format='url' templatefile='skins/${prefs.Skin}/skin.css' />" />
+    <script type="text/javascript" src="<wiki:Link format='url' templatefile='skins/${prefs.Skin}/skin.js' />"></script>
+    </c:if>
+    <%--
+
+         JavaScript
+    --%>
+    <script type="text/javascript" src="<wiki:Link format='url' jsp='scripts/mootools.js' />"></script>
+    <script type="text/javascript" src="<wiki:Link format='url' jsp='scripts/prettify.js' />"></script>
+    <script type="text/javascript" src="<wiki:Link format='url' jsp='scripts/jspwiki-common.js' />"></script>
+    <script type="text/javascript" src="<wiki:Link format='url' jsp='scripts/jspwiki-commonstyles.js' />"></script>
+    <s:layout-component name="script" />
+    <%--
+
+         JavaScript: localized strings and functions
+    --%>
+    <script type="text/javascript">//<![CDATA[
+    /* Localized javascript strings: LocalizedStrings[] */
+    <s:layout-component name="jslocalizedstrings" />
+    <s:layout-component name="jsfunction" />
+    //]]></script>
+    <%--
+
+         Meta tags
+    --%>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <meta name="wikiContext" content='${wikiContext.requestContext}' />
+    <meta name="wikiBaseUrl" content='<wiki:BaseURL/>' />
+    <meta name="wikiPageUrl" content='<wiki:Link format="url" page="#$%" />' />
+    <meta name="wikiEditUrl" content='<wiki:EditLink format="url" />' />
+    <meta name="wikiJsonUrl" content='<%=  WikiContextFactory.findContext(pageContext).getURL( WikiContext.NONE, "JSON-RPC" ) %>' /><%--unusual pagename--%>
+    <meta name="wikiPageName" content='<wiki:Variable var="pagename" />' /><%--pagename without blanks--%>
+    <meta name="wikiUserName" content='<wiki:UserName/>' />
+    <meta name="wikiTemplateUrl" content='<wiki:Link format="url" templatefile="" />' />
+    <meta name="wikiApplicationName" content='${wikiEngine.applicationName}' />
+    <%--
+
+         Search engines: by default, page is not indexed or followed
+    --%>
+    <s:layout-component name="head.meta.robots">
+    <meta name="robots" content="noindex,nofollow" />
+    </s:layout-component>
+    <%--
+
+         RSS Feed discovery
+    --%>
+    <wiki:FeedDiscovery/>
+
+    <wiki:Include page="localheader.jsp" />
+
+    
   </head>
 
-  <body class="view">
+  <body class="${wikiContext.requestContext}">
 
     <div id="wikibody" class="${prefs.Orientation}">
      

Modified: incubator/jspwiki/trunk/src/WebContent/templates/default/EditContent.jsp
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/templates/default/EditContent.jsp?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/templates/default/EditContent.jsp (original)
+++ incubator/jspwiki/trunk/src/WebContent/templates/default/EditContent.jsp Fri Mar  6 23:31:03 2009
@@ -1,7 +1,8 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
 <%@ taglib uri="http://jakarta.apache.org/jspwiki.tld" prefix="wiki" %>
+<%@ taglib uri="http://stripes.sourceforge.net/stripes.tld" prefix="s" %>
 <%@ page import="org.apache.wiki.*" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <%@ page import="javax.servlet.jsp.jstl.fmt.*" %>
 <%@ page import="org.apache.wiki.action.WikiContextFactory" %>
 <%
@@ -11,51 +12,28 @@
   if( attCount != 0 ) attTitle += " (" + attCount + ")";
 %>
   
-<wiki:TabbedSection defaultTab="editcontent">  
+<wiki:TabbedSection defaultTab="editcontent">
+
   <wiki:Tab id="editcontent" titleKey="edit.tab.edit" accesskey="e">
-  <wiki:CheckLock mode="locked" id="lock">
-    <div class="error">
-      <fmt:message key="edit.locked">
-        <fmt:param><c:out value="${lock.locker}" /></fmt:param>
-        <fmt:param><c:out value="${lock.timeLeft}" /></fmt:param>
-      </fmt:message>
-    </div>
-  </wiki:CheckLock>
-  
-  <wiki:CheckVersion mode="notlatest">
-    <div class="warning">
-      <fmt:message key="edit.restoring">
-        <fmt:param><wiki:PageVersion/></fmt:param>
-      </fmt:message>
-    </div>
-  </wiki:CheckVersion>
-    
-  <wiki:Editor/>
-    
-</wiki:Tab>
+    <s:errors />
+    <s:messages />
+    <wiki:Editor/>
+  </wiki:Tab>
   
   <wiki:PageExists>  
-
-  <wiki:Tab id="attach" title="<%= attTitle %>" accesskey="a">
-    <wiki:Include page="AttachmentTab.jsp" />
-  </wiki:Tab>
-
-  <wiki:Tab id="info" titleKey="info.tab"
-           url="<%=c.getURL(WikiContext.INFO, c.getPage().getName())%>"
-           accesskey="i" >
-  </wiki:Tab>
-
+    <wiki:Tab id="attach" title="<%= attTitle %>" accesskey="a" url="Attachments.jsp?page=${wikiActionBean.page.name}" />
+    <wiki:Tab id="info" titleKey="info.tab" url="PageInfo.jsp?page=${wikiActionBean.page.name}" accesskey="i" />
   </wiki:PageExists>  
-    
+
   <wiki:Tab id="edithelp" titleKey="edit.tab.help" accesskey="h">
-  <wiki:InsertPage page="EditPageHelp" />
-  <wiki:NoSuchPage page="EditPageHelp">
-    <div class="error">
-      <fmt:message key="comment.edithelpmissing">
-        <fmt:param><wiki:EditLink page="EditPageHelp">EditPageHelp</wiki:EditLink></fmt:param>
-      </fmt:message>
-    </div>
-  </wiki:NoSuchPage>  
+    <wiki:InsertPage page="EditPageHelp" />
+    <wiki:NoSuchPage page="EditPageHelp">
+      <div class="error">
+        <fmt:message key="comment.edithelpmissing">
+          <fmt:param><wiki:EditLink page="EditPageHelp">EditPageHelp</wiki:EditLink></fmt:param>
+        </fmt:message>
+      </div>
+    </wiki:NoSuchPage>  
   </wiki:Tab>
 
 </wiki:TabbedSection>
\ No newline at end of file

Modified: incubator/jspwiki/trunk/src/WebContent/templates/default/PreviewContent.jsp
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/templates/default/PreviewContent.jsp?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/templates/default/PreviewContent.jsp (original)
+++ incubator/jspwiki/trunk/src/WebContent/templates/default/PreviewContent.jsp Fri Mar  6 23:31:03 2009
@@ -1,24 +1,51 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
 <%@ taglib uri="http://jakarta.apache.org/jspwiki.tld" prefix="wiki" %>
+<%@ taglib uri="http://stripes.sourceforge.net/stripes.tld" prefix="s" %>
+<%@ page import="org.apache.wiki.filters.SpamFilter" %>
 <%@ page import="org.apache.wiki.ui.EditorManager" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
 <%@ page import="javax.servlet.jsp.jstl.fmt.*" %>
 
-<%-- Inserts page content for preview. --%>
 <wiki:TabbedSection>
-<wiki:Tab id="previewcontent" titleKey="preview.tab">
-
-  <div class="information">
-    <fmt:message key="preview.info" />
-    <wiki:Editor/>
-  </div>
-
-  <div class="previewcontent">
-    <wiki:Translate><%=EditorManager.getEditedText(pageContext)%></wiki:Translate>
-  </div>
-
-  <div class="information">
-    <fmt:message key="preview.info" />
-  </div>
+  <wiki:Tab id="previewcontent" titleKey="preview.tab">
+  
+    <div class="information">
+      <fmt:message key="preview.info" />
+    </div>
+    <s:errors />
+    <s:messages />
 
-</wiki:Tab>
+    <s:form beanclass="org.apache.wiki.action.EditActionBean" method="post" acceptcharset="UTF-8" 
+      class="wikiform" id="editform" enctype="application/x-www-form-urlencoded">
+    
+      <p>
+        <%-- Edit.jsp & Comment.jsp rely on these being found.  So be careful, if you make changes. --%>
+        <s:hidden name="author" />
+        <s:hidden name="changenote" />
+        <s:hidden name="link" />
+        <s:hidden name="page" value="${wikiActionBean.page.name}" />
+        <s:hidden name="remember" />
+        <s:hidden name="text" />
+        <s:hidden name="<%=SpamFilter.getHashFieldName(request)%>"><c:out value="${lastchange}" /></s:hidden>
+      </p>
+      <div id="submitbuttons">
+        <c:set var="editTitle"><fmt:message key="editor.preview.edit.title"/></c:set>
+        <s:submit name="edit" accesskey="e" title="${editTitle}"><fmt:message key="editor.preview.edit.submit" /></s:submit>
+        <c:set var="saveTitle"><fmt:message key='editor.preview.save.title'/></c:set>
+        <s:submit name="save" accesskey="s" title="${saveTitle}" />
+        <c:set var="cancelTitle"><fmt:message key='editor.preview.cancel.title'/></c:set>
+        <s:submit name="cancel" accesskey="q" title="${cancelTitle}" />
+      </div>
+      
+    </s:form>
+  
+    <div class="previewcontent">
+      <wiki:Translate>${wikiActionBean.text}</wiki:Translate>
+    </div>
+  
+    <div class="information">
+      <fmt:message key="preview.info" />
+    </div>
+  
+  </wiki:Tab>
 </wiki:TabbedSection>
\ No newline at end of file

Modified: incubator/jspwiki/trunk/src/WebContent/templates/default/editors/plain.jsp
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/templates/default/editors/plain.jsp?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/templates/default/editors/plain.jsp (original)
+++ incubator/jspwiki/trunk/src/WebContent/templates/default/editors/plain.jsp Fri Mar  6 23:31:03 2009
@@ -1,220 +1,163 @@
-<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
-<%@ taglib uri="http://jakarta.apache.org/jspwiki.tld" prefix="wiki" %>
-<%@ page import="org.apache.wiki.*" %>
-<%@ page import="org.apache.wiki.auth.*" %>
-<%@ page import="org.apache.wiki.auth.permissions.*" %>
-<%@ page import="org.apache.wiki.tags.*" %>
-<%@ page import="org.apache.wiki.filters.SpamFilter" %>
-<%@ page import="org.apache.wiki.ui.*" %>
-<%@ page import="org.apache.wiki.rpc.*" %>
-<%@ page import="org.apache.wiki.rpc.json.*" %>
-<%@ page import="org.apache.wiki.api.WikiPage" %>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-<%@ taglib uri="http://stripes.sourceforge.net/stripes.tld" prefix="stripes" %>
-<%@ page import="org.apache.wiki.action.WikiContextFactory" %>
+<%@ taglib uri="http://jakarta.apache.org/jspwiki.tld" prefix="wiki" %>
+<%@ taglib uri="http://stripes.sourceforge.net/stripes.tld" prefix="s" %>
+<%@ page import="org.apache.wiki.filters.SpamFilter" %>
 <%@ page import="org.apache.wiki.util.TextUtil" %>
 <%--
         This is a plain editor for JSPWiki.
 --%>
-<% 
-   WikiContext context = WikiContextFactory.findContext( pageContext ); 
-   WikiEngine engine = context.getEngine();
-   
-   String contextPath = request.getContextPath();
-
-   TemplateManager.addResourceRequest( context, "script",  contextPath + "/scripts/jspwiki-edit.js" );
-   TemplateManager.addResourceRequest( context, "script",  contextPath + "/scripts/posteditor.js" );
-   String usertext = EditorManager.getEditedText( pageContext );
-%>
-<wiki:CheckRequestContext context="edit">
-<wiki:NoSuchPage> <%-- this is a new page, check if we're cloning --%>
-<%
-  String clone = request.getParameter( "clone" ); 
-  if( clone != null )
-  {
-    WikiPage p = engine.getPage( clone );
-    if( p != null )
-    {
-        AuthorizationManager mgr = engine.getAuthorizationManager();
-        PagePermission pp = new PagePermission( p, PagePermission.VIEW_ACTION );
-
-        try
-        {            
-          if( mgr.checkPermission( context.getWikiSession(), pp ) )
-          {
-            usertext = engine.getPureText( p );
-          }
-        }
-        catch( Exception e ) {  /*log.error( "Accessing clone page "+clone, e );*/ }
-    }
-  }
-%>
-</wiki:NoSuchPage>
-<%
-  if( usertext == null )
-  {
-    usertext = engine.getPureText( context.getPage() );
-  }
-%>
-</wiki:CheckRequestContext>
-<% if( usertext == null ) usertext = "";  %>
-
-
 <div style="width:100%"> <%-- Required for IE6 on Windows --%>
-
-<form action="<wiki:CheckRequestContext 
-     context='edit'><wiki:EditLink format='url'/></wiki:CheckRequestContext><wiki:CheckRequestContext 
-     context='comment'><wiki:CommentLink format='url'/></wiki:CheckRequestContext>" 
-       class="wikiform"
-          id="editform" 
-    onsubmit="return Wiki.submitOnce(this);"
-      method="post" accept-charset="<wiki:ContentEncoding/>"
-     enctype="application/x-www-form-urlencoded" >
-
-  <%-- Edit.jsp relies on these being found.  So be careful, if you make changes. --%>
-  <p id="submitbuttons">
-  <input name="page" type="hidden" value="<wiki:Variable var='pagename' />" />
-  <input name="action" type="hidden" value="save" />
-  <%=SpamFilter.insertInputFields( pageContext )%>
-  <input name="<%=SpamFilter.getHashFieldName(request)%>" type="hidden" value="<c:out value='${lastchange}' />" />
-  <input type="submit" name="ok" value="<fmt:message key='editor.plain.save.submit'/>" 
-    accesskey="s"
-        title="<fmt:message key='editor.plain.save.title'/>" />
-  <input type="submit" name="preview" value="<fmt:message key='editor.plain.preview.submit'/>" 
-    accesskey="v"
-        title="<fmt:message key='editor.plain.preview.title'/>" />
-  <input type="submit" name="cancel" value="<fmt:message key='editor.plain.cancel.submit'/>" 
-    accesskey="q" 
-        title="<fmt:message key='editor.plain.cancel.title'/>" />
-  </p>
-    <%-- This following field is only for the SpamFilter to catch bots which are just randomly filling all fields and submitting.
-       Normal user should never see this field, nor type anything in it. --%>
-  <div style="display:none;">Authentication code: <input type="text" name="<%=SpamFilter.getBotFieldName()%>" id="<%=SpamFilter.getBotFieldName()%>" value="" /></div>
-  <table>
-<%--FIXME
-    <wiki:Permission permission="rename">
-    <tr>
-    <td><label for="renameto"><fmt:message key='editor.renameto'/></label></td>
-    <td><input type="text" name="renameto" value="<wiki:Variable var='pagename' />" size="40" />
-    &nbsp;&nbsp;
-    <input type="checkbox" name="references" checked="checked" />
-    <fmt:message key="info.updatereferrers"/>
-    FIXME</td>
-    </tr>
-    </wiki:Permission>
---%>  
-    <tr>
-    <td><label for="changenote"><fmt:message key='editor.plain.changenote' /></label></td>
-    <td><input type="text" name="changenote" id="changenote" size="80" maxlength="80" value="<c:out value='${changenote}' />" /></td>
-    </tr>
-  </table>
   
-  <div id="tools">
+  <s:form beanclass="org.apache.wiki.action.EditActionBean" class="wikiform"
+    id="editform" method="post" acceptcharset="UTF-8" enctype="application/x-www-form-urlencoded" >
+    
+    <%-- Edit.jsp relies on these being found.  So be careful, if you make changes. --%>
+    <p id="submitbuttons">
+      <s:hidden name="page"><wiki:Variable var='pagename' /></s:hidden>
+      <s:hidden name="<%=SpamFilter.getHashFieldName(request)%>"><c:out value="${lastchange}" /></s:hidden>
+      <%=SpamFilter.insertInputFields( pageContext )%>
+      <c:set var="saveTitle" scope="page"><fmt:message key="editor.plain.save.title" /></c:set>
+      <wiki:CheckRequestContext context='edit'>
+        <s:submit name="save" accesskey="s" title="${saveTitle}" />
+      </wiki:CheckRequestContext>
+      <wiki:CheckRequestContext context='comment'>
+        <s:submit name="comment" accesskey="s" title="${saveTitle}"><fmt:message key="editor.plain.save.submit"/></s:submit> 
+      </wiki:CheckRequestContext>
+    
+      <c:set var="previewTitle" scope="page"><fmt:message key="editor.plain.preview.title" /></c:set>
+      <s:submit name="preview" accesskey="v" title="${previewTitle}" />
+    
+      <c:set var="cancelTitle" scope="page"><fmt:message key="editor.plain.cancel.title" /></c:set>
+      <s:submit name="cancel" accesskey="q" title="${cancelTitle}" />
+    </p>
+    
+    <%-- This following field is only for the SpamFilter to catch bots which are just
+         randomly filling all fields and submitting. Normal user should never see this field,
+         nor type anything in it. --%>
+    <div style="display:none;">Authentication code: <input type="text" name="<%=SpamFilter.getBotFieldName()%>" id="<%=SpamFilter.getBotFieldName()%>" value="" /></div>
+    
+    <%-- Fields for changenote, renaming etc. --%>
+    <table>
+      <tr>
+        <td>
+          <s:label for="changenote" name="changenote" />
+        </td>
+        <td>
+          <s:text name="changenote" id="changenote" size="80" maxlength="80" />
+        </td>
+      </tr>
+    </table>
+    
+    <%-- Toolbar --%>
+    <div id="tools">
       <h4><fmt:message key='editor.plain.toolbar' /></h4>
       <div id="toolbuttons">
-      <span>
-	  <a href="#" class="tool" rel="" id="tbLink" title="<fmt:message key='editor.plain.tbLink.title' />">link</a>
-	  <a href="#" class="tool" rel="break" id="tbH1" title="<fmt:message key='editor.plain.tbH1.title' />">h1</a>
-	  <a href="#" class="tool" rel="break" id="tbH2" title="<fmt:message key='editor.plain.tbH2.title' />">h2</a>
-	  <a href="#" class="tool" rel="break" id="tbH3" title="<fmt:message key='editor.plain.tbH3.title' />">h3</a>
-      </span>
-      <span>
-	  <a href="#" class="tool" rel="" id="tbB" title="<fmt:message key='editor.plain.tbB.title' />">bold</a>
-	  <a href="#" class="tool" rel="" id="tbI" title="<fmt:message key='editor.plain.tbI.title' />">italic</a>
-	  <a href="#" class="tool" rel="" id="tbMONO" title="<fmt:message key='editor.plain.tbMONO.title' />">mono</a>
-	  <a href="#" class="tool" rel="" id="tbSUP" title="<fmt:message key='editor.plain.tbSUP.title' />">sup</a>
-	  <a href="#" class="tool" rel="" id="tbSUB" title="<fmt:message key='editor.plain.tbSUB.title' />">sub</a>
-	  <a href="#" class="tool" rel="" id="tbSTRIKE" title="<fmt:message key='editor.plain.tbSTRIKE.title' />">strike</a>
-      </span>
-      <span>
-	  <a href="#" class="tool" rel="" id="tbBR" title="<fmt:message key='editor.plain.tbBR.title' />">br</a>
-	  <a href="#" class="tool" rel="break" id="tbHR" title="<fmt:message key='editor.plain.tbHR.title' />">hr</a>
-	  <a href="#" class="tool" rel="break" id="tbPRE" title="<fmt:message key='editor.plain.tbPRE.title' />">pre</a>
-	  <a href="#" class="tool" rel="break" id="tbCODE" title="<fmt:message key='editor.plain.tbCODE.title' />">code</a>
-	  <a href="#" class="tool" rel="break" id="tbDL" title="<fmt:message key='editor.plain.tbDL.title' />">dl</a>
-      </span>
-      <span>
-	  <a href="#" class="tool" rel="break" id="tbTOC" title="<fmt:message key='editor.plain.tbTOC.title' />">toc</a>
-	  <a href="#" class="tool" rel="break" id="tbTAB" title="<fmt:message key='editor.plain.tbTAB.title' />">tab</a>
-	  <a href="#" class="tool" rel="break" id="tbTABLE" title="<fmt:message key='editor.plain.tbTABLE.title' />">table</a>
-	  <a href="#" class="tool" rel="" id="tbIMG" title="<fmt:message key='editor.plain.tbIMG.title' />">img</a>
-	  <a href="#" class="tool" rel="break" id="tbQUOTE" title="<fmt:message key='editor.plain.tbQUOTE.title' />">quote</a>
-	  <a href="#" class="tool" rel="break" id="tbSIGN" title="<fmt:message key='editor.plain.tbSIGN.title' />">sign</a>
-      </span>
-      <span>
-      <a href="#" class="tool" rel="break" id="tbUNDO" title="<fmt:message key='editor.plain.undo.title' />"><fmt:message key='editor.plain.undo.submit' /></a>
-      </span>
-      <span>
-	  <a href="#" class="tool" rel="break" id="tbREDO" title="<fmt:message key='editor.plain.redo.title' />"><fmt:message key='editor.plain.redo.submit' /></a>
-      </span>
-	  </div>
-
-	  <div id="toolextra" class="clearbox" style="display:none;">
-      <span>
-      <input type="checkbox" name="tabcompletion" id="tabcompletion" <%=TextUtil.isPositive((String)session.getAttribute("tabcompletion")) ? "checked='checked'" : ""%> />
-      <label for="tabcompletion" title="<fmt:message key='editor.plain.tabcompletion.title' />"><fmt:message key="editor.plain.tabcompletion" /></label>
-      </span>
-      <span>
-      <input type="checkbox" name="smartpairs" id="smartpairs" <%=TextUtil.isPositive((String)session.getAttribute("smartpairs")) ? "checked='checked'" : ""%> />
-      <label for="smartpairs" title="<fmt:message key='editor.plain.smartpairs.title' />"><fmt:message key="editor.plain.smartpairs" /></label>	  
-      </span>
-	  </div>
-
-	  <div id="searchbar">
-  		<span>
-        <label for="tbFIND"><fmt:message key="editor.plain.find" /></label>
-  		<input type="text" name="tbFIND" id="tbFIND" size="16" />
-		<label for="tbREPLACE"><fmt:message key="editor.plain.replace" /></label>
-		<input type="text" name="tbREPLACE" id="tbREPLACE" size="16" />
-        <input type="button" name="doreplace" id="doreplace" value="<fmt:message key='editor.plain.find.submit' />" />
-        </span>
-  		<span>
-  		<input type="checkbox" name="tbMatchCASE" id="tbMatchCASE" />
-  		<label for="tbMatchCASE"><fmt:message key="editor.plain.matchcase" /></label>
-  		</span>
-  		<span>
-  		<input type="checkbox" name="tbREGEXP" id="tbREGEXP" />
-  		<label for="tbREGEXP"><fmt:message key="editor.plain.regexp" /></label>
-  		</span>
-  		<span>
-  		<input type="checkbox" name="tbGLOBAL" id="tbGLOBAL" checked="checked" />
-  		<label for="tbGLOBAL"><fmt:message key="editor.plain.global" /></label>
-  		</span>
-	  </div>
-	  <div class="clearbox"></div>
-  </div>
-
-  <div>
-  <textarea id="editorarea" name="<%=EditorManager.REQ_EDITEDTEXT%>" 
-         class="editor" 
-          rows="20" cols="80"><%=TextUtil.replaceEntities(usertext)%></textarea>
-  <div class="clearbox" ></div>
-  </div>
-
-  <wiki:CheckRequestContext context="comment">
-    <fieldset>
-	<legend><fmt:message key="editor.commentsignature" /></legend>
-    <p>
-    <label for="authorname" accesskey="n"><fmt:message key="editor.plain.name" /></label>
-    <input type="text" name="author" id="authorname" value="<c:out value='${sessionScope.author}' />" />
-    <input type="checkbox" name="remember" id="rememberme" <%=TextUtil.isPositive((String)session.getAttribute("remember")) ? "checked='checked'" : ""%> />
-    <label for="rememberme"><fmt:message key="editor.plain.remember" /></label>
-    </p>
-    <p>
-    <label for="link" accesskey="m"><fmt:message key="editor.plain.email" /></label>
-    <input type="text" name="link" id="link" size="24" value="<c:out value='${sessionScope.link}' />" />
-    </p>
-    </fieldset>
-  </wiki:CheckRequestContext>
-
-</form>
-
-<div id="sneakpreviewheader">
-  <input type="checkbox" name="autopreview" id="autopreview" <%=TextUtil.isPositive((String)session.getAttribute("autopreview")) ? "checked='checked'" : ""%> />
-  <label for="autopreview" title="<fmt:message key='editor.plain.sneakpreview.title' />"><fmt:message key="editor.plain.sneakpreview" /></label>	  
-  <span id="previewSpin" class="spin" style="position:absolute;display:none;"></span>
-</div>
-<div id="sneakpreview"></div>
+        <span>
+      	  <a href="#" class="tool" rel="" id="tbLink" title="<fmt:message key='editor.plain.tbLink.title' />">link</a>
+      	  <a href="#" class="tool" rel="break" id="tbH1" title="<fmt:message key='editor.plain.tbH1.title' />">h1</a>
+      	  <a href="#" class="tool" rel="break" id="tbH2" title="<fmt:message key='editor.plain.tbH2.title' />">h2</a>
+      	  <a href="#" class="tool" rel="break" id="tbH3" title="<fmt:message key='editor.plain.tbH3.title' />">h3</a>
+        </span>
+        <span>
+      	  <a href="#" class="tool" rel="" id="tbB" title="<fmt:message key='editor.plain.tbB.title' />">bold</a>
+      	  <a href="#" class="tool" rel="" id="tbI" title="<fmt:message key='editor.plain.tbI.title' />">italic</a>
+      	  <a href="#" class="tool" rel="" id="tbMONO" title="<fmt:message key='editor.plain.tbMONO.title' />">mono</a>
+      	  <a href="#" class="tool" rel="" id="tbSUP" title="<fmt:message key='editor.plain.tbSUP.title' />">sup</a>
+      	  <a href="#" class="tool" rel="" id="tbSUB" title="<fmt:message key='editor.plain.tbSUB.title' />">sub</a>
+      	  <a href="#" class="tool" rel="" id="tbSTRIKE" title="<fmt:message key='editor.plain.tbSTRIKE.title' />">strike</a>
+        </span>
+        <span>
+      	  <a href="#" class="tool" rel="" id="tbBR" title="<fmt:message key='editor.plain.tbBR.title' />">br</a>
+      	  <a href="#" class="tool" rel="break" id="tbHR" title="<fmt:message key='editor.plain.tbHR.title' />">hr</a>
+      	  <a href="#" class="tool" rel="break" id="tbPRE" title="<fmt:message key='editor.plain.tbPRE.title' />">pre</a>
+      	  <a href="#" class="tool" rel="break" id="tbCODE" title="<fmt:message key='editor.plain.tbCODE.title' />">code</a>
+      	  <a href="#" class="tool" rel="break" id="tbDL" title="<fmt:message key='editor.plain.tbDL.title' />">dl</a>
+        </span>
+        <span>
+      	  <a href="#" class="tool" rel="break" id="tbTOC" title="<fmt:message key='editor.plain.tbTOC.title' />">toc</a>
+      	  <a href="#" class="tool" rel="break" id="tbTAB" title="<fmt:message key='editor.plain.tbTAB.title' />">tab</a>
+      	  <a href="#" class="tool" rel="break" id="tbTABLE" title="<fmt:message key='editor.plain.tbTABLE.title' />">table</a>
+      	  <a href="#" class="tool" rel="" id="tbIMG" title="<fmt:message key='editor.plain.tbIMG.title' />">img</a>
+      	  <a href="#" class="tool" rel="break" id="tbQUOTE" title="<fmt:message key='editor.plain.tbQUOTE.title' />">quote</a>
+      	  <a href="#" class="tool" rel="break" id="tbSIGN" title="<fmt:message key='editor.plain.tbSIGN.title' />">sign</a>
+        </span>
+        <span>
+          <a href="#" class="tool" rel="break" id="tbUNDO" title="<fmt:message key='editor.plain.undo.title' />"><fmt:message key='editor.plain.undo.submit' /></a>
+        </span>
+        <span>
+      	  <a href="#" class="tool" rel="break" id="tbREDO" title="<fmt:message key='editor.plain.redo.title' />"><fmt:message key='editor.plain.redo.submit' /></a>
+        </span>
+  	  </div>
+  
+      <%-- Toolbar extras --%>
+  	  <div id="toolextra" class="clearbox" style="display:none;">
+        <span>
+          <input type="checkbox" name="tabcompletion" id="tabcompletion" <%=TextUtil.isPositive((String)session.getAttribute("tabcompletion")) ? "checked='checked'" : ""%> />
+          <label for="tabcompletion" title="<fmt:message key='editor.plain.tabcompletion.title' />"><fmt:message key="editor.plain.tabcompletion" /></label>
+        </span>
+        <span>
+          <input type="checkbox" name="smartpairs" id="smartpairs" <%=TextUtil.isPositive((String)session.getAttribute("smartpairs")) ? "checked='checked'" : ""%> />
+          <label for="smartpairs" title="<fmt:message key='editor.plain.smartpairs.title' />"><fmt:message key="editor.plain.smartpairs" /></label>	  
+        </span>
+  	  </div>
+  
+      <%-- Search bar --%>
+  	  <div id="searchbar">
+    		<span>
+          <label for="tbFIND"><fmt:message key="editor.plain.find" /></label>
+          <input type="text" name="tbFIND" id="tbFIND" size="16" />
+          <label for="tbREPLACE"><fmt:message key="editor.plain.replace" /></label>
+          <input type="text" name="tbREPLACE" id="tbREPLACE" size="16" />
+          <input type="button" name="doreplace" id="doreplace" value="<fmt:message key='editor.plain.find.submit' />" />
+        </span>
+    		<span>
+          <input type="checkbox" name="tbMatchCASE" id="tbMatchCASE" />
+          <label for="tbMatchCASE"><fmt:message key="editor.plain.matchcase" /></label>
+    		</span>
+    		<span>
+          <input type="checkbox" name="tbREGEXP" id="tbREGEXP" />
+          <label for="tbREGEXP"><fmt:message key="editor.plain.regexp" /></label>
+    		</span>
+    		<span>
+          <input type="checkbox" name="tbGLOBAL" id="tbGLOBAL" checked="checked" />
+          <label for="tbGLOBAL"><fmt:message key="editor.plain.global" /></label>
+    		</span>
+  	  </div>
+  	  <div class="clearbox"></div>
+    </div>
+  
+    <%-- You knew this would be here somewhere. Yes, it's the textarea where the user
+         actually edits stuff. --%>
+    <div>
+      <s:textarea id="editorarea" name="text" class="editor" rows="20" cols="80" />
+      <div class="clearbox" ></div>
+    </div>
+  
+    <wiki:CheckRequestContext context="comment">
+      <fieldset>
+      	<legend><fmt:message key="editor.commentsignature" /></legend>
+        <p>
+          <s:label for="author" accesskey="n" name="author" />
+          <s:text id="author" name="author" />
+          <s:checkbox id="remember" name="remember" />
+          <s:label for="remember" name="remember" />
+        </p>
+        <p>
+          <s:label for="link" accesskey="m" name="editor.plain.email" />
+          <s:text id="link" name="link" size="24" />
+        </p>
+      </fieldset>
+    </wiki:CheckRequestContext>
+  
+    <div id="livepreviewheader">
+      <s:checkbox id="livePreview" name="livePreview" />
+      <c:set var="livePreviewTitle" scope="page"><fmt:message key="editor.plain.livepreview.title"/></c:set>
+      <s:label for="livePreview" title="${livePreviewTitle}" name="livePreview" />	  
+      <span id="previewSpin" class="spin" style="position:absolute;display:none;"></span>
+    </div>
+    <div id="livepreview"></div>
 
+  </s:form>
+  
 </div>
\ No newline at end of file

Modified: incubator/jspwiki/trunk/src/WebContent/templates/default/jspwiki.css
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/templates/default/jspwiki.css?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/templates/default/jspwiki.css (original)
+++ incubator/jspwiki/trunk/src/WebContent/templates/default/jspwiki.css Fri Mar  6 23:31:03 2009
@@ -1177,14 +1177,14 @@
 
 
 /* +++ 475 PreviewContent - "This is a preview" comment +++ */
-#sneakpreviewheader {
+#livepreviewheader {
 	clear:both;
 	font-size:110%;
 	background-color:#ddd;
 	padding:0.5em;
 	margin:0.5em 0;
 }  
-#sneakpreview {
+#livepreview {
 }  
 #previewcontent {
 }  

Modified: incubator/jspwiki/trunk/src/WebContent/templates/default/skins/OrderedList/skin.css
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/templates/default/skins/OrderedList/skin.css?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/templates/default/skins/OrderedList/skin.css (original)
+++ incubator/jspwiki/trunk/src/WebContent/templates/default/skins/OrderedList/skin.css Fri Mar  6 23:31:03 2009
@@ -350,10 +350,10 @@
 }
 
 /* +++ 475 PageContent.jsp +++ */
-#sneakpreviewheader {
+#livepreviewheader {
 	background-color:#3f464a;
 } 
-#sneakpreview {
+#livepreview {
 	background:transparent !important;
 }
 /* +++ 475 PreviewContent - "This is a preview" comment +++ */

Modified: incubator/jspwiki/trunk/src/WebContent/templates/default/skins/Smart/skin.css
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/templates/default/skins/Smart/skin.css?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/templates/default/skins/Smart/skin.css (original)
+++ incubator/jspwiki/trunk/src/WebContent/templates/default/skins/Smart/skin.css Fri Mar  6 23:31:03 2009
@@ -275,7 +275,7 @@
 	color:white;
 	padding:0.5em 0.25em;
 }
-#sneakpreviewheader {
+#livepreviewheader {
 	background-color:#fff7c0;
 }  
 

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/action/AbstractPageActionBean.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/action/AbstractPageActionBean.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/action/AbstractPageActionBean.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/action/AbstractPageActionBean.java Fri Mar  6 23:31:03 2009
@@ -30,10 +30,9 @@
  * process {@link org.apache.wiki.api.WikiPage} objects bound to the
  * <code>page</code> request parameter. In particular, this subclass contains
  * special processing logic that ensures that, the <code>page</code>
- * properties of this object and its related
- * {@link org.apache.wiki.WikiContext} are set to the same value. When
- * {@link #setPage(WikiPage)} is called by, for example, the Stripes controller,
- * the underlying
+ * properties of this object and its related {@link org.apache.wiki.WikiContext}
+ * are set to the same value. When {@link #setPage(WikiPage)} is called by, for
+ * example, the Stripes controller, the underlying
  * {@link org.apache.wiki.ui.stripes.WikiActionBeanContext#setPage(WikiPage)}
  * method is called also.
  */
@@ -55,10 +54,14 @@
      * Sets the WikiPage property for this ActionBean, and also sets the
      * WikiActionBeanContext's page property to the same value by calling
      * {@link org.apache.wiki.ui.stripes.WikiActionBeanContext#setPage(WikiPage)}.
+     * Note that because of the {@link Validate} annotation, the
+     * <code>page</code> field will be required by any executing event handler
+     * method. To change this property, subclasses should override this method
+     * and supply a <code>Validate( required = false )</code> annotation.
      * 
      * @param page the wiki page.
      */
-    @Validate( required = false )
+    @Validate( required = true )
     public void setPage( WikiPage page )
     {
         m_page = page;

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/action/DeleteActionBean.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/action/DeleteActionBean.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/action/DeleteActionBean.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/action/DeleteActionBean.java Fri Mar  6 23:31:03 2009
@@ -108,15 +108,6 @@
     }
 
     /**
-     * {@inheritDoc}
-     */
-    @Validate( required = true )
-    public void setPage( WikiPage page )
-    {
-        super.setPage( page );
-    }
-    
-    /**
      * Sets the version to delete. If not set, all versions of the page or
      * attachment will be deleted.
      * 

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/action/EditActionBean.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/action/EditActionBean.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/action/EditActionBean.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/action/EditActionBean.java Fri Mar  6 23:31:03 2009
@@ -21,26 +21,88 @@
 
 package org.apache.wiki.action;
 
+import java.io.IOException;
+import java.security.Principal;
+import java.util.List;
+
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
-import org.apache.wiki.WikiContext;
+import net.sourceforge.stripes.action.*;
+import net.sourceforge.stripes.controller.LifecycleStage;
+import net.sourceforge.stripes.validation.LocalizableError;
+import net.sourceforge.stripes.validation.Validate;
+import net.sourceforge.stripes.validation.ValidationErrors;
+
+import org.apache.wiki.*;
+import org.apache.wiki.api.WikiException;
+import org.apache.wiki.api.WikiPage;
 import org.apache.wiki.auth.permissions.PagePermission;
+import org.apache.wiki.filters.RedirectException;
 import org.apache.wiki.filters.SpamFilter;
-import org.apache.wiki.ui.EditorManager;
+import org.apache.wiki.htmltowiki.HtmlStringToWikiTranslator;
+import org.apache.wiki.log.Logger;
+import org.apache.wiki.log.LoggerFactory;
 import org.apache.wiki.ui.stripes.HandlerPermission;
+import org.apache.wiki.ui.stripes.WikiActionBeanContext;
 import org.apache.wiki.ui.stripes.WikiRequestContext;
-
-import net.sourceforge.stripes.action.*;
-
+import org.apache.wiki.workflow.DecisionRequiredException;
+import org.jdom.JDOMException;
 
 @HttpCache( allow = false )
-@UrlBinding( "/Edit.jsp" )
 public class EditActionBean extends AbstractPageActionBean
 {
-    @HandlesEvent("comment")
-    @HandlerPermission(permissionClass=PagePermission.class, target="${page.qualifiedName}", actions=PagePermission.COMMENT_ACTION)
-    @WikiRequestContext("comment")
+    private static final Logger log = LoggerFactory.getLogger( EditActionBean.class );
+
+    private String m_author = null;
+
+    private String m_spamhash = null;
+
+    private String m_text = null;
+
+    private String m_changeNote = null;
+
+    private boolean m_append = false;
+
+    private boolean m_captcha = false;
+
+    private boolean m_remember = true;
+
+    private String m_htmlPageText = null;
+
+    private boolean m_livePreview = false;
+
+    private String m_link = null;
+
+    /**
+     * Event handler method that cancels any locks the user possesses for the current wiki page,
+     * and redirects the user to the {@link ViewActionBean} "view" handler.
+     * @return the redirect
+     */
+    @DontValidate
+    @HandlesEvent( "cancel" )
+    @HandlerPermission( permissionClass = PagePermission.class, target = "${page.qualifiedName}", actions = PagePermission.EDIT_ACTION )
+    @WikiRequestContext( "cancel" )
+    public Resolution cancel()
+    {
+        String pagereq = m_page.getName();
+        log.debug( "Cancelled editing " + pagereq );
+        
+        // Cancel page lock
+        HttpSession session = getContext().getRequest().getSession();
+        WikiEngine engine = getContext().getEngine();
+        PageLock lock = (PageLock) session.getAttribute( "lock-" + pagereq );
+        if( lock != null )
+        {
+            engine.getPageManager().unlockPage( lock );
+            session.removeAttribute( "lock-" + pagereq );
+        }
+        return new RedirectResolution( ViewActionBean.class ).addParameter( "page", pagereq );
+    }
+
+    @HandlesEvent( "comment" )
+    @HandlerPermission( permissionClass = PagePermission.class, target = "${page.qualifiedName}", actions = PagePermission.COMMENT_ACTION )
+    @WikiRequestContext( "comment" )
     public Resolution comment()
     {
         return null;
@@ -61,17 +123,176 @@
     }
 
     @DefaultHandler
+    @DontValidate
     @HandlesEvent( "edit" )
     @HandlerPermission( permissionClass = PagePermission.class, target = "${page.qualifiedName}", actions = PagePermission.EDIT_ACTION )
     @WikiRequestContext( "edit" )
     public Resolution edit()
     {
-        return null;
+        WikiActionBeanContext wikiContext = getContext();
+        HttpServletRequest request = wikiContext.getRequest();
+        HttpSession session = request.getSession();
+        Principal user = wikiContext.getCurrentUser();
+        String pagereq = m_page.getName();
+
+        log.info( "Editing page " + pagereq + ". User=" + user.getName() + ", host=" + request.getRemoteAddr() );
+
+        // If page is locked, make sure we tell the user
+        List<Message> messages = wikiContext.getMessages();
+        WikiEngine engine = wikiContext.getEngine();
+        PageManager mgr = engine.getPageManager();
+        PageLock lock = mgr.getCurrentLock( m_page );
+        if( lock != null )
+        {
+            messages.add( new LocalizableMessage( "edit.locked", lock.getLocker(), lock.getTimeLeft() ) );
+        }
+        
+        // If user is not editing the latest one, tell user also
+        ValidationErrors errors = getContext().getValidationErrors();
+        WikiPage latest = engine.getPage( m_page.getName() );
+        if( latest.getVersion() != m_page.getVersion() )
+        {
+            errors.addGlobalError( new LocalizableError( "edit.restoring", m_page.getVersion() ) );
+        }
+
+        // Attempt to lock the page.
+        lock = mgr.lockPage( m_page, user.getName() );
+        if( lock != null )
+        {
+            session.setAttribute( "lock-" + pagereq, lock );
+        }
+
+        // Load the page text
+        m_text = engine.getPureText( m_page );
+
+        return new ForwardResolution( "/Edit.jsp" );
+    }
+
+    /**
+     * Returns whether the edited text should be appended to the page.
+     * 
+     * @return <code>true</code> if text should be appended;
+     *         <code>false</code> otherwise (the default).
+     */
+    public boolean getAppend()
+    {
+        return m_append;
+    }
+
+    /**
+     * Returns the author.
+     * 
+     * @return the author
+     */
+    public String getAuthor()
+    {
+        return m_author;
+    }
+
+    /**
+     * Returns whether a CAPTCHA is being used for editing.
+     * 
+     * @return <code>true</code> if a CAPTCHA is in use; <code>false</code>
+     *         otherwise.
+     */
+    public boolean getCaptcha()
+    {
+        return m_captcha;
+    }
+
+    /*
+     * Returns the changenote for this upload.
+     */
+    public String getChangenote()
+    {
+        return m_changeNote;
+    }
+
+    /**
+     * Returns the HTML page text.
+     * 
+     * @return the HTML page text
+     */
+    public String getHtmlPageText()
+    {
+        return m_htmlPageText;
+    }
+
+    /**
+     * Returns the link.
+     * 
+     * @return the link
+     */
+    public String getLink()
+    {
+        return m_link;
+    }
+
+    /**
+     * Returns <code>true</code> if the "live preview" feature is turned on;
+     * <code>false</code> otherwise
+     * 
+     * @return the "live preview" setting
+     */
+    public boolean getLivePreview()
+    {
+        return m_livePreview;
+    }
+
+    /**
+     * Returns the flag indicating whether the author name should be remembered.
+     * 
+     * @return the remember-me flag
+     */
+    public boolean getRemember()
+    {
+        return m_remember;
     }
 
     /**
-     * Event that extracts the current state of the edited page from the HTTP
-     * session and redirects the user to the previewer JSP.
+     * Returns the edited text.
+     * 
+     * @return the text
+     */
+    public String getText()
+    {
+        return m_text;
+    }
+
+    /**
+     * Initializes default values. Also looks up the correct spam hash field, as determined by
+     * {@link SpamFilter#getHashFieldName(HttpServletRequest)}.
+
+     */
+    @After( stages = LifecycleStage.BindingAndValidation )
+    public void initDefaultValues()
+    {
+        HttpServletRequest request = getContext().getRequest();
+
+        // Look up and set spam hash field name for this particular edit
+        String hashParam = SpamFilter.getHashFieldName( request );
+        m_spamhash = request.getParameter( hashParam );
+        if( m_spamhash != null )
+        {
+            m_spamhash = m_spamhash.trim();
+        }
+        
+        // Set author: prefer authenticated/asserted principals first
+        WikiSession wikiSession = getContext().getWikiSession();
+        if( wikiSession.isAsserted() || wikiSession.isAuthenticated() )
+        {
+            m_author = wikiSession.getUserPrincipal().getName();
+        }
+
+        // Otherwise, if author not bound, check session
+        else if( m_author == null )
+        {
+            m_author = wikiSession.getUserPrincipal().getName();
+        }
+    }
+
+    /**
+     * Event that the user to the preview display JSP.
      * 
      * @return a forward resolution back to the preview page.
      */
@@ -80,15 +301,202 @@
     @WikiRequestContext( "preview" )
     public Resolution preview()
     {
-        WikiContext context = getContext();
-        HttpServletRequest request = context.getHttpRequest();
+        log.debug( "Previewing " + m_page.getName() );
+        return new ForwardResolution( "/Preview.jsp" );
+    }
+
+    @HandlesEvent( "save" )
+    @HandlerPermission( permissionClass = PagePermission.class, target = "${page.qualifiedName}", actions = PagePermission.EDIT_ACTION )
+    @WikiRequestContext( "save" )
+    public Resolution save() throws WikiException
+    {
+        WikiSession wikiSession = getContext().getWikiSession();
+        HttpServletRequest request = getContext().getHttpRequest();
         HttpSession session = request.getSession();
+        WikiContext wikiContext = getContext();
+        WikiEngine engine = getContext().getEngine();
+        String pagereq = m_page.getName();
+
+        log.info( "Saving page " + m_page.getName() + ". UserPrincipal=" + wikiSession.getUserPrincipal().getName() + ", Author="
+                  + m_author + ", Host=" + getContext().getRequest().getRemoteAddr() );
+
+        // Check for session expiration
+        Resolution r = SpamFilter.checkHash( this );
+        if( r != null )
+        {
+            return r;
+        }
+
+        // FIXME: I am not entirely sure if the JSP page is the
+        // best place to check for concurrent changes. It certainly
+        // is the best place to show errors, though.
+        String h = SpamFilter.getSpamHash( m_page, request );
+
+        // Someone changed the page while we were editing it!
+        if( !h.equals( m_spamhash ) )
+        {
+            log.info( "Page changed, warning user." );
+            return new RedirectResolution( PageModifiedActionBean.class, "conflict" ).addParameter( "page", pagereq );
+        }
+
+        //
+        // We expire ALL locks at this moment, simply because someone has
+        // already broken it.
+        //
+        PageLock lock = engine.getPageManager().getCurrentLock( m_page );
+        engine.getPageManager().unlockPage( lock );
+        session.removeAttribute( "lock-" + pagereq );
+
+        // Set author information and other metadata
+        WikiPage modifiedPage = (WikiPage) wikiContext.getPage().clone();
+        modifiedPage.setAuthor( m_author );
+
+        // If this is an append, add it to the page.
+        // If a full edit, replace the previous contents.
+        try
+        {
+            wikiContext.setPage( modifiedPage );
+
+            if( m_captcha )
+            {
+                wikiContext.setVariable( "captcha", Boolean.TRUE );
+                session.removeAttribute( "captcha" );
+            }
+
+            if( m_append )
+            {
+                StringBuffer pageText = new StringBuffer( engine.getText( pagereq ) );
+                pageText.append( m_text );
+                engine.saveText( wikiContext, pageText.toString() );
+            }
+            else
+            {
+                engine.saveText( wikiContext, m_text );
+            }
+        }
+        catch( DecisionRequiredException ex )
+        {
+            return new RedirectResolution( ViewActionBean.class, "view" ).addParameter( "page", "ApprovalRequiredForPageChanges" );
+        }
+        catch( RedirectException ex )
+        {
+            // Should work, but doesn't
+            wikiContext.getWikiSession().addMessage( ex.getMessage() ); // FIXME:
+            session.setAttribute( "message", ex.getMessage() );
+            session.setAttribute( SpamFilter.getHashFieldName( request ), m_spamhash );
+            return new RedirectResolution( ex.getRedirect() ).flash( this );
+        }
 
-        request.setAttribute( EditorManager.ATTR_EDITEDTEXT, session.getAttribute( EditorManager.REQ_EDITEDTEXT ) );
+        return new RedirectResolution( ViewActionBean.class, "view" ).addParameter( "page", pagereq );
+    }
 
-        String lastchange = SpamFilter.getSpamHash( context.getPage(), request );
-        request.setAttribute( "lastchange", lastchange );
+    /**
+     * Sets a flag indicating that new page text should be appended to the old
+     * text.
+     * 
+     * @param <code>true</code> if text should be appended; <code>false</code>
+     *            otherwise (the default).
+     */
+    @Validate( required = false )
+    public void setAppend( boolean append )
+    {
+        m_append = append;
+    }
 
-        return new ForwardResolution( "/Preview.jsp" );
+    /**
+     * Sets the author.
+     * 
+     * @param author the author
+     */
+    @Validate( required = false )
+    public void setAuthor( String author )
+    {
+        m_author = author;
     }
+
+    /**
+     * Sets a flag indicating that CAPTCHA should be used for editing.
+     * 
+     * @param captcha <code>true</code> if a CAPTCHA is in use;
+     *            <code>false</code> otherwise.
+     */
+    @Validate( required = false )
+    public void setCaptcha( boolean captcha )
+    {
+        m_captcha = captcha;
+    }
+
+    /**
+     * Sets the changenote for this upload; usually a short comment.
+     * 
+     * @param changenote the change note
+     */
+    @Validate( required = false )
+    public void setChangenote( String changenote )
+    {
+        m_changeNote = changenote;
+    }
+
+    /**
+     * Sets the HTML page text, which will be translated into wiki text by
+     * {@link HtmlStringToWikiTranslator}. Calling this method causes
+     * {@link #setText(String)} to be called, with the translated text supplied.
+     * 
+     * @param the HTML to translate
+     * @throws JDOMException if the HTML cannot be translated
+     * @throws IOException if the HtmlStringToWikiTranslator cannot translated
+     *             the text
+     */
+    @Validate( required = false )
+    public void setHtmlPageText( String html ) throws IOException, JDOMException
+    {
+        m_htmlPageText = html;
+        m_text = new HtmlStringToWikiTranslator().translate( html, getContext() );
+    }
+
+    /**
+     * Sets the link.
+     * 
+     * @param link the link
+     */
+    @Validate( required = false )
+    public void setLink( String link )
+    {
+        m_link = link;
+    }
+
+    /**
+     * Returns <code>true</code> if the "live preview" feature is turned on;
+     * <code>false</code> otherwise
+     * 
+     * @param livePreview the "live preview" setting
+     */
+    @Validate( required = false )
+    public void setLivePreview( boolean livePreview )
+    {
+        m_livePreview = livePreview;
+    }
+
+    /**
+     * Sets the flag indicating that the author name should be remembered.
+     * 
+     * @param remember the remember-me flag
+     */
+    @Validate( required = false )
+    public void setRemember( boolean remember )
+    {
+        m_remember = remember;
+    }
+
+    /**
+     * Sets the edited text.
+     * 
+     * @param text the text
+     */
+    @Validate( required = true )
+    public void setText( String text )
+    {
+        m_text = text;
+    }
+
 }

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/action/RenameActionBean.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/action/RenameActionBean.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/action/RenameActionBean.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/action/RenameActionBean.java Fri Mar  6 23:31:03 2009
@@ -23,21 +23,23 @@
 
 import javax.servlet.http.HttpServletRequest;
 
+import net.sourceforge.stripes.action.HandlesEvent;
+import net.sourceforge.stripes.action.RedirectResolution;
+import net.sourceforge.stripes.action.Resolution;
+import net.sourceforge.stripes.action.UrlBinding;
+import net.sourceforge.stripes.validation.LocalizableError;
+import net.sourceforge.stripes.validation.Validate;
+import net.sourceforge.stripes.validation.ValidationErrors;
+import net.sourceforge.stripes.validation.ValidationMethod;
+
 import org.apache.wiki.WikiEngine;
 import org.apache.wiki.api.WikiException;
-import org.apache.wiki.api.WikiPage;
 import org.apache.wiki.auth.permissions.PagePermission;
 import org.apache.wiki.log.Logger;
 import org.apache.wiki.log.LoggerFactory;
 import org.apache.wiki.ui.stripes.HandlerPermission;
 import org.apache.wiki.ui.stripes.WikiRequestContext;
 
-import net.sourceforge.stripes.action.HandlesEvent;
-import net.sourceforge.stripes.action.RedirectResolution;
-import net.sourceforge.stripes.action.Resolution;
-import net.sourceforge.stripes.action.UrlBinding;
-import net.sourceforge.stripes.validation.*;
-
 
 /**
  * <p>
@@ -138,16 +140,6 @@
     }
 
     /**
-     * Sets the page.
-     * @param page the wiki page.
-     */
-    @Validate( required = true )
-    public void setPage( WikiPage page )
-    {
-        super.setPage( page );
-    }
-    
-    /**
      * Sets the new name for the page, which will be set when the
      * {@link #rename()} handler is executed.
      * 

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/action/UploadActionBean.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/action/UploadActionBean.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/action/UploadActionBean.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/action/UploadActionBean.java Fri Mar  6 23:31:03 2009
@@ -21,26 +21,52 @@
 
 package org.apache.wiki.action;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.Principal;
 import java.util.List;
 
+import net.sourceforge.stripes.action.FileBean;
+import net.sourceforge.stripes.action.HandlesEvent;
+import net.sourceforge.stripes.action.RedirectResolution;
+import net.sourceforge.stripes.action.Resolution;
+import net.sourceforge.stripes.validation.LocalizableError;
+import net.sourceforge.stripes.validation.Validate;
+import net.sourceforge.stripes.validation.ValidationErrors;
+import net.sourceforge.stripes.validation.ValidationMethod;
+
+import org.apache.wiki.WikiContext;
+import org.apache.wiki.WikiEngine;
+import org.apache.wiki.api.WikiException;
+import org.apache.wiki.api.WikiPage;
+import org.apache.wiki.attachment.Attachment;
+import org.apache.wiki.attachment.AttachmentManager;
 import org.apache.wiki.auth.permissions.PagePermission;
+import org.apache.wiki.content.WikiName;
+import org.apache.wiki.i18n.InternationalizationManager;
 import org.apache.wiki.log.Logger;
 import org.apache.wiki.log.LoggerFactory;
+import org.apache.wiki.providers.ProviderException;
 import org.apache.wiki.ui.stripes.HandlerPermission;
 import org.apache.wiki.ui.stripes.WikiRequestContext;
 
-import net.sourceforge.stripes.action.FileBean;
-import net.sourceforge.stripes.action.HandlesEvent;
-import net.sourceforge.stripes.action.Resolution;
-import net.sourceforge.stripes.action.UrlBinding;
-
-@UrlBinding( "/Upload.jsp" )
-public class UploadActionBean extends AbstractActionBean
+public class UploadActionBean extends AbstractPageActionBean
 {
-    private Logger log = LoggerFactory.getLogger( UploadActionBean.class );
+    private static final Logger log = LoggerFactory.getLogger( UploadActionBean.class );
 
     private List<FileBean> m_newAttachments;
 
+    private String m_changeNote = null;
+
+    /**
+     * Returns the new attachments uploaded by the user.
+     * @return the new files to attach
+     */
+    public List<FileBean> getNewAttachments()
+    {
+        return m_newAttachments;
+    }
+    
     /**
      * Sets the set of new attachments that should be saved when the
      * {@link #upload()} event is executed.
@@ -53,17 +79,157 @@
     }
 
     /**
+     * Sets the changenote for this upload; usually a short comment.
+     * 
+     * @param changenote the change note
+     */
+    @Validate( required = false )
+    public void setChangenote( String changenote )
+    {
+        m_changeNote = changenote;
+    }
+
+    /*
+     * Returns the changenote for this upload.
+     */
+    public String getChangenote()
+    {
+        return m_changeNote;
+    }
+
+    /**
      * Handler method that uploads a new attachment to the ViewActionBean.
      * 
-     * @return {@link Resolution}
+     * @return
      */
     @HandlesEvent( "upload" )
-    @HandlerPermission( permissionClass = PagePermission.class, target = "${page.qualifiedName}", actions = PagePermission.VIEW_ACTION )
+    @HandlerPermission( permissionClass = PagePermission.class, target = "${page.qualifiedName}", actions = PagePermission.UPLOAD_ACTION )
     @WikiRequestContext( "upload" )
-    public Resolution upload()
+    public Resolution upload() throws Exception
+    {
+        for( FileBean attachment : m_newAttachments )
+        {
+            if ( attachment != null )
+            {
+                executeUpload( attachment );
+                log.debug( "Executed upload; " + m_newAttachments.size() + " attachments found." );
+            }
+        }
+
+        return new RedirectResolution( ViewActionBean.class, "attachments" ).addParameter( "page", m_page.getName() );
+    }
+    
+    @ValidationMethod
+    public void validateFileType( ValidationErrors errors )
     {
-        log.debug( "Executed upload; " + m_newAttachments.size() + " attachments found." );
-        return null;
+        AttachmentManager mgr = getContext().getEngine().getAttachmentManager();
+        for ( FileBean attachment : m_newAttachments )
+        {
+            if ( attachment != null )
+            {
+                // Clean the file name before validating
+                String filename = attachment.getFileName();
+                try
+                {
+                    filename = AttachmentManager.cleanFileName( filename );
+                }
+                catch( WikiException e )
+                {
+                    // Error message returns the i18n key name
+                    errors.add( "newAttachments", new LocalizableError( e.getMessage(), filename ) );
+                }
+                
+                if ( !mgr.isFileTypeAllowed( filename ) )
+                {
+                    errors.add( "newAttachments", new LocalizableError( "attach.bad.filetype", filename ) );
+                }
+            }
+        }
+    }
+
+    /**
+     * Uploads a single FileBean to the AttachmentManager. This method assumes
+     * that the user has permissions to do so; handler method callers should use
+     * the {@link HandlerPermission} annotation to force permission checks.
+     * 
+     * @param filebean the FileBean containing the file to be uploaded
+     * @return <code>true</code> if upload results in the creation of a new
+     *         page; <code>false</code> otherwise
+     * @throws IOException If there is a problem in the upload.
+     * @throws ProviderException If there is a problem in the backend.
+     */
+    private boolean executeUpload( FileBean filebean ) throws Exception
+    {
+        boolean created = false;
+        WikiContext context = getContext();
+        WikiEngine engine = context.getEngine();
+        AttachmentManager mgr = engine.getAttachmentManager();
+        
+        // Get the file name, size etc from the FileBean
+        InputStream data = filebean.getInputStream();
+        String filename = filebean.getFileName();
+        int contentLength = (int)filebean.getSize();
+        
+        // Cleanse the file name
+        filename = AttachmentManager.cleanFileName( filename );
+        log.debug( "file=" + filename );
+
+        // Get the name of the user uploading the file
+        Principal user = context.getCurrentUser();
+
+        //
+        // Check whether we already have this kind of a page.
+        // If the "page" parameter already defines an attachment
+        // name for an update, then we just use that file.
+        // Otherwise we create a new attachment, and use the
+        // filename given. Incidentally, this will also mean
+        // that if the user uploads a file with the exact
+        // same name than some other previous attachment,
+        // then that attachment gains a new version.
+        //
+
+        Attachment att = mgr.getAttachmentInfo( context.getPage().getName() );
+
+        if( att == null )
+        {
+            String contentType = "application/octet-stream"; // FIXME: This is not a good guess
+            WikiName path = context.getPage().getQualifiedName().resolve(filename);
+            att = engine.getContentManager().addPage( path, contentType );
+            created = true;
+        }
+        att.setSize( contentLength );
+
+        if( user != null )
+        {
+            att.setAuthor( user.getName() );
+        }
+
+        if( m_changeNote != null && m_changeNote.length() > 0 )
+        {
+            att.setAttribute( WikiPage.CHANGENOTE, m_changeNote );
+        }
+
+        try
+        {
+            engine.getAttachmentManager().storeAttachment( att, data );
+        }
+        catch( ProviderException pe )
+        {
+            // this is a kludge, the exception that is caught here contains
+            // the i18n key
+            // here we have the context available, so we can
+            // internationalize it properly :
+            throw new ProviderException( context.getBundle( InternationalizationManager.CORE_BUNDLE )
+                .getString( pe.getMessage() ) );
+        }
+        
+        // Close the stream and delete the filebean, since we're done with it
+        data.close();
+        filebean.delete();
+
+        log.info( "User " + user + " uploaded attachment to " + m_page.getName() + " called " + filename + ", size " + att.getSize() );
+
+        return created;
     }
 
 }

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/action/ViewActionBean.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/action/ViewActionBean.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/action/ViewActionBean.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/action/ViewActionBean.java Fri Mar  6 23:31:03 2009
@@ -23,6 +23,7 @@
 
 import net.sourceforge.stripes.action.*;
 import net.sourceforge.stripes.controller.LifecycleStage;
+import net.sourceforge.stripes.validation.Validate;
 import net.sourceforge.stripes.validation.ValidationError;
 import net.sourceforge.stripes.validation.ValidationErrors;
 
@@ -192,6 +193,17 @@
     }
 
     /**
+     * {@inheritDoc}. This method overrides the superclass method
+     * by disabling validation of the <code>page</code> field.
+     */
+    @Override
+    @Validate( required = false )
+    public void setPage( WikiPage page )
+    {
+        super.setPage( page );
+    }
+    
+    /**
      * Sets the name to rename the page to
      * 
      * @param renameTo the page name to use

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/Attachment.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/Attachment.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/Attachment.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/Attachment.java Fri Mar  6 23:31:03 2009
@@ -20,8 +20,6 @@
  */
 package org.apache.wiki.attachment;
 
-import java.io.InputStream;
-
 import org.apache.wiki.api.WikiPage;
 
 /**

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/AttachmentManager.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/AttachmentManager.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/AttachmentManager.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/AttachmentManager.java Fri Mar  6 23:31:03 2009
@@ -40,6 +40,7 @@
 import org.apache.wiki.log.Logger;
 import org.apache.wiki.log.LoggerFactory;
 import org.apache.wiki.providers.ProviderException;
+import org.apache.wiki.util.TextUtil;
 
 import com.opensymphony.oscache.base.Cache;
 import com.opensymphony.oscache.base.NeedsRefreshException;
@@ -80,6 +81,16 @@
     private WikiEngine             m_engine;
 
     /**
+     *  List of attachment types which are allowed.
+     */
+    private String[] m_allowedPatterns;
+
+    /**
+     *  List of attachment types which are forbidden.
+     */
+    private String[] m_forbiddenPatterns;
+    
+    /**
      *  Creates a new AttachmentManager.  Note that creation will never fail,
      *  but it's quite likely that attachments do not function.
      *  <p>
@@ -96,6 +107,7 @@
     public AttachmentManager( WikiEngine engine, Properties props )
     {
         m_engine = engine;
+        initFileRestrictions();
     }
 
     /**
@@ -376,7 +388,7 @@
      *          disabled.
      *  @throws ProviderException If the provider fails for some reason.
      */
-    public List getVersionHistory( String attachmentName )
+    public List<WikiPage> getVersionHistory( String attachmentName )
         throws ProviderException
     {
         return m_engine.getContentManager().getVersionHistory( WikiName.valueOf(attachmentName) );
@@ -407,14 +419,14 @@
     }
 
     /**
-     *  Validates the filename and makes sure it is legal.  It trims and splits
-     *  and replaces bad characters.
+     *  Cleans an attachment filename by trimming and replacing bad characters.
+     *  If a file path is supplied, only the trailing file name will be returned.
      *  
-     *  @param filename
+     *  @param filename the filename to cleanse
      *  @return A validated name with annoying characters replaced.
      *  @throws WikiException If the filename is not legal (e.g. empty)
      */
-    static String validateFileName( String filename )
+    public static String cleanFileName( String filename )
         throws WikiException
     {
         if( filename == null || filename.trim().length() == 0 )
@@ -457,4 +469,69 @@
     
         return filename;
     }
+
+    /**
+     * Determines whether a supplied attachment is allowed to be
+     * uploaded, based on the file name. The list of files types allowed for uploading
+     * are contained in <code>jspwiki.properties</code> property
+     * {@link #PROP_ALLOWEDEXTENSIONS}. The list of denied file types are
+     * contained in {@link #PROP_FORDBIDDENEXTENSIONS}. If an extension is
+     * included in both lists, the forbidden list wins.
+     * @param name the proposed file name
+     * @return <code>true</code> if a supplied attachment file name is
+     * allowed to be uploaded; <code>false</code> otherwise.
+     */
+    public boolean isFileTypeAllowed( String name )
+    {
+        if( name == null || name.length() == 0 ) return false;
+
+        name = name.toLowerCase();
+
+        for( int i = 0; i < m_forbiddenPatterns.length; i++ )
+        {
+            if( name.endsWith(m_forbiddenPatterns[i]) && m_forbiddenPatterns[i].length() > 0 )
+                return false;
+        }
+
+        for( int i = 0; i < m_allowedPatterns.length; i++ )
+        {
+            if( name.endsWith(m_allowedPatterns[i]) && m_allowedPatterns[i].length() > 0 )
+                return true;
+        }
+
+        return m_allowedPatterns.length == 0;
+    }
+    
+    private void initFileRestrictions()
+    {
+        Properties props = m_engine.getWikiProperties();
+
+        String allowed = TextUtil.getStringProperty( props,
+                                                     AttachmentManager.PROP_ALLOWEDEXTENSIONS,
+                                                     null );
+
+        if( allowed != null && allowed.length() > 0 )
+        {
+            m_allowedPatterns = allowed.toLowerCase().split("\\s");
+        }
+        else
+        {
+            m_allowedPatterns = new String[0];
+        }
+
+        String forbidden = TextUtil.getStringProperty( props,
+                                                       AttachmentManager.PROP_FORDBIDDENEXTENSIONS,
+                                                       null );
+
+        if( forbidden != null && forbidden.length() > 0 )
+        {
+            m_forbiddenPatterns = forbidden.toLowerCase().split("\\s");
+        }
+        else
+        {
+            m_forbiddenPatterns = new String[0];
+        }
+
+        log.debug( "AttachmentManager initialized with allowed/denied file patterns." );
+    }
 }

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/AttachmentServlet.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/AttachmentServlet.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/AttachmentServlet.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/attachment/AttachmentServlet.java Fri Mar  6 23:31:03 2009
@@ -666,7 +666,7 @@
 
         try
         {
-            filename = AttachmentManager.validateFileName( filename );
+            filename = AttachmentManager.cleanFileName( filename );
         }
         catch( WikiException e )
         {

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamFilter.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamFilter.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamFilter.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamFilter.java Fri Mar  6 23:31:03 2009
@@ -32,11 +32,15 @@
 import javax.servlet.jsp.PageContext;
 
 import net.sf.akismet.Akismet;
+import net.sourceforge.stripes.action.RedirectResolution;
+import net.sourceforge.stripes.action.Resolution;
 
 import org.apache.commons.jrcs.diff.*;
 import org.apache.commons.jrcs.diff.myers.MyersDiff;
 import org.apache.commons.lang.time.StopWatch;
 import org.apache.wiki.*;
+import org.apache.wiki.action.ViewActionBean;
+import org.apache.wiki.action.WikiActionBean;
 import org.apache.wiki.action.WikiContextFactory;
 import org.apache.wiki.api.ModuleData;
 import org.apache.wiki.api.WikiPage;
@@ -46,6 +50,7 @@
 import org.apache.wiki.log.LoggerFactory;
 import org.apache.wiki.providers.ProviderException;
 import org.apache.wiki.ui.EditorManager;
+import org.apache.wiki.ui.stripes.WikiActionBeanContext;
 import org.apache.wiki.util.FileUtil;
 import org.apache.wiki.util.TextUtil;
 
@@ -1111,6 +1116,39 @@
         return hash != null ? hash : c_hashName;
     }
 
+    /**
+     *  <p>This method checks if the hash value is still valid, i.e. if it exists at all. This
+     *  can occur in two cases: either this is a spam bot which is not adaptive, or it is
+     *  someone who has been editing one page for too long, and their session has expired.</p>
+     *  <p>If the hash is not valid, this method returns a Stripes
+     *  {@link net.sourceforge.stripes.action.RedirectResolution} that directs
+     *  users to wiki page "SessionExpired" and logs the incident in the spam log
+     *  (it may or may not be spam, but it's rather likely that it is).</p>
+     *  <p>If the hash is valid, this method simply returns <code>null</code>.</p>
+     *  <p>Other than the differences in the method parameters and return syntax, this
+     *  method operates in every other respect identically to
+     *  {@link #checkHash(WikiContext, PageContext)}</p>
+     *
+     *  @param actionBean the WikiActionBean representing the editing activity and page.
+     *  @return <code>null</code> if hash is okay, or a RedirectResolution if not.
+     *  @since 3.0
+     */
+    public static final Resolution checkHash( WikiActionBean actionBean )
+    {
+        WikiActionBeanContext context = actionBean.getContext();
+        String hashName = getHashFieldName( context.getRequest() );
+
+        if( context.getRequest().getParameter(hashName) == null )
+        {
+            Change change = getChange( context, EditorManager.getEditedText( context.getRequest() ) );
+
+            log( context, REJECT, "MissingHash", change.m_change );
+
+            return new RedirectResolution( ViewActionBean.class, "view" ).addParameter( "name", "SessionExpired");
+        }
+
+        return null;
+    }
 
     /**
      *  This method checks if the hash value is still valid, i.e. if it exists at all. This

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/IncludeResourcesTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/IncludeResourcesTag.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/IncludeResourcesTag.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/IncludeResourcesTag.java Fri Mar  6 23:31:03 2009
@@ -28,7 +28,7 @@
  *  tiny marker into the stream, and then a ServletFilter will take
  *  care of the actual inclusion.
  *  
- *
+*  @deprecated use the Stripes <code>layout-component</code> tags instead
  */
 public class IncludeResourcesTag extends WikiTagBase
 {

Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/RequestResourceTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/RequestResourceTag.java?rev=751135&r1=751134&r2=751135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/RequestResourceTag.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/RequestResourceTag.java Fri Mar  6 23:31:03 2009
@@ -27,6 +27,7 @@
  *  any of the request types defined there.
  *
  *  @see TemplateManager
+ *  @deprecated use the Stripes <code>layout-component</code> tags instead
  */
 public class RequestResourceTag extends WikiTagBase
 {