Index: jspwiki-war/pom.xml =================================================================== --- jspwiki-war/pom.xml (revision 1653248) +++ jspwiki-war/pom.xml (working copy) @@ -99,6 +99,11 @@ + com.google.code.gson + gson + + + org.jvnet.hudson org.suigeneris.jrcs.diff Index: jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java (revision 0) +++ jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java (working copy) @@ -0,0 +1,70 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.wiki.ajax; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; + +import org.apache.commons.lang.StringUtils; + +import com.google.gson.Gson; + +public class AjaxUtil extends HttpServlet { + private static final long serialVersionUID = 3170439306358345408L; + private static Gson gson = new Gson(); + + public static String toJson(Object input) { + String result = ""; + if (input != null) { + result = gson.toJson(input); + } + return result; + } + + public static String getNextPathPart(String path, String lastPart) throws ServletException { + String result = null; + if (StringUtils.isBlank(path)) { + return result; + } + if (!lastPart.endsWith("/")) { + lastPart += "/"; + } + int index = path.indexOf(lastPart); + if (index<0) { + throw new ServletException("Invalid path provided " + path + " does not contain '" + lastPart + "'"); + } + path = path.substring(index+lastPart.length()); + index = path.indexOf("/"); + if (index == -1) { + index = path.indexOf("#"); + if (index == -1) { + index = path.indexOf("?"); + } + } + if (index == -1) { + result = path; + } + else { + result = path.substring(0,index); + } + + return result; + } + +} Property changes on: jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java (revision 0) +++ jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java (working copy) @@ -0,0 +1,180 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.wiki.ajax; + +import java.io.IOException; +import java.security.Permission; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.wiki.WikiEngine; +import org.apache.wiki.WikiSession; +import org.apache.wiki.auth.permissions.PagePermission; +import org.apache.wiki.util.TextUtil; + +/** + * This provides a simple ajax servlet for handling /ajax/ requests. + * HttpServlet classes need to be registered using {@link WikiAjaxDispatcherServlet.registerServlet(HttpServlet)} + * + * @author David VIttor + * @date 20/01/2015 + * @since 2.10.2-svn10 + */ +public class WikiAjaxDispatcherServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + private static Map ajaxServlets = new HashMap(); + static final Logger log = Logger.getLogger(WikiAjaxDispatcherServlet.class.getName()); + private String PATH_AJAX = "/ajax/"; + + /** + * {@inheritDoc} + */ + public void init(ServletConfig config) + throws ServletException { + super.init(config); + WikiEngine e = WikiEngine.getInstance(config); + PATH_AJAX = "/"+TextUtil.getStringProperty(e.getWikiProperties(), "jspwiki.ajax.url.prefix", "ajax")+"/"; + log.info("WikiAjaxDispatcherServlet initialized."); + } + + /** + * Register a servlet using the class simple name as the alias + */ + public static void registerServlet(HttpServlet servlet) { + registerServlet(servlet.getClass().getSimpleName(),servlet); + } + + /** + * Register a servlet with an alias, using the default permission {@link PagePermission.VIEW}. + */ + public static void registerServlet(String alias, HttpServlet servlet) { + registerServlet(alias, servlet, PagePermission.VIEW); + } + + public static void registerServlet(String alias, HttpServlet servlet, Permission perm) { + log.info("WikiAjaxDispatcherServlet registering "+alias+"="+servlet+" perm="+perm); + ajaxServlets.put(alias,new AjaxServletContainer(alias, servlet, perm)); + } + + /** + * Calls {@link this.performAction} + */ + public void doPost(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + performAction(req,res); + } + + /** + * Calls {@link this.performAction} + */ + public void doGet(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + performAction(req,res); + } + + /** + * The main method which get the requestURI "/ajax/", gets the + * {@link this.getServletName} and finds the servlet using {@link this.findServletByName}. + * It then calls servlet.service(). + * @param req the inbound request + * @param res the outbound response + * @throws IOException + * @throws ServletException if no registered servlet can be found + */ + private void performAction(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + String path = req.getRequestURI(); + String servletName = getServletName(path); + if (servletName!=null) { + AjaxServletContainer container = findServletContainer(servletName); + if (container != null) { + HttpServlet servlet = container.servlet; + if ( validatePermission(req,container) ) { + servlet.service(req, res); + } else { + log.warn("Serlvet container "+container+" not authorised. Permission required."); + } + } else { + log.error("No registered class for servletName=" + servletName + " in path=" + path); + throw new ServletException("No registered class for servletName=" + servletName); + } + } + } + + private boolean validatePermission(HttpServletRequest req, AjaxServletContainer container) { + WikiEngine e = WikiEngine.getInstance(req.getSession().getServletContext(), null); + boolean valid = false; + if (container != null) { + valid = e.getAuthorizationManager().checkPermission(WikiSession.getWikiSession(e, req), container.permission); + } + return valid; + } + + /** + * Get the name of the servlet given the requestURI. + * @param path The requestURI, which must contains "/ajax/" in the path + * @return The ServletName for the requestURI, or null + * @throws ServletException if the path is invalid + */ + public String getServletName(String path) throws ServletException { + return AjaxUtil.getNextPathPart(path, PATH_AJAX); + } + + /** + * Find the servlet as registered in {@link WikiAjaxDispatcherServlet.register}. + * + * @param servletName the name of the servlet from {@link this.getServletName} + * @return The first servlet found, or null. + */ + public AjaxServletContainer findServletContainer(String serlvetAlias) { + return ajaxServlets.get(serlvetAlias); + } + + public HttpServlet findServletByName(String serlvetAlias) { + AjaxServletContainer container = ajaxServlets.get(serlvetAlias); + if (container != null) { + return container.servlet; + } + return null; + } + + private static class AjaxServletContainer { + String alias; + HttpServlet servlet; + Permission permission; + + public AjaxServletContainer(String alias, HttpServlet servlet, Permission permission) { + this.alias = alias; + this.servlet = servlet; + this.permission = permission; + } + + public String toString() { + return getClass().getSimpleName()+" "+alias+"="+servlet.getClass().getSimpleName()+" permission="+permission; + } + } + +} Property changes on: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java (revision 0) +++ jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java (working copy) @@ -0,0 +1,70 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.wiki.ajax; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; + +import org.apache.commons.lang.StringUtils; + +import com.google.gson.Gson; + +public class AjaxUtil extends HttpServlet { + private static final long serialVersionUID = 3170439306358345408L; + private static Gson gson = new Gson(); + + public static String toJson(Object input) { + String result = ""; + if (input != null) { + result = gson.toJson(input); + } + return result; + } + + public static String getNextPathPart(String path, String lastPart) throws ServletException { + String result = null; + if (StringUtils.isBlank(path)) { + return result; + } + if (!lastPart.endsWith("/")) { + lastPart += "/"; + } + int index = path.indexOf(lastPart); + if (index<0) { + throw new ServletException("Invalid path provided " + path + " does not contain '" + lastPart + "'"); + } + path = path.substring(index+lastPart.length()); + index = path.indexOf("/"); + if (index == -1) { + index = path.indexOf("#"); + if (index == -1) { + index = path.indexOf("?"); + } + } + if (index == -1) { + result = path; + } + else { + result = path.substring(0,index); + } + + return result; + } + +} Property changes on: jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java (revision 0) +++ jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java (working copy) @@ -0,0 +1,180 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.wiki.ajax; + +import java.io.IOException; +import java.security.Permission; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.wiki.WikiEngine; +import org.apache.wiki.WikiSession; +import org.apache.wiki.auth.permissions.PagePermission; +import org.apache.wiki.util.TextUtil; + +/** + * This provides a simple ajax servlet for handling /ajax/ requests. + * HttpServlet classes need to be registered using {@link WikiAjaxDispatcherServlet.registerServlet(HttpServlet)} + * + * @author David VIttor + * @date 20/01/2015 + * @since 2.10.2-svn10 + */ +public class WikiAjaxDispatcherServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + private static Map ajaxServlets = new HashMap(); + static final Logger log = Logger.getLogger(WikiAjaxDispatcherServlet.class.getName()); + private String PATH_AJAX = "/ajax/"; + + /** + * {@inheritDoc} + */ + public void init(ServletConfig config) + throws ServletException { + super.init(config); + WikiEngine e = WikiEngine.getInstance(config); + PATH_AJAX = "/"+TextUtil.getStringProperty(e.getWikiProperties(), "jspwiki.ajax.url.prefix", "ajax")+"/"; + log.info("WikiAjaxDispatcherServlet initialized."); + } + + /** + * Register a servlet using the class simple name as the alias + */ + public static void registerServlet(HttpServlet servlet) { + registerServlet(servlet.getClass().getSimpleName(),servlet); + } + + /** + * Register a servlet with an alias, using the default permission {@link PagePermission.VIEW}. + */ + public static void registerServlet(String alias, HttpServlet servlet) { + registerServlet(alias, servlet, PagePermission.VIEW); + } + + public static void registerServlet(String alias, HttpServlet servlet, Permission perm) { + log.info("WikiAjaxDispatcherServlet registering "+alias+"="+servlet+" perm="+perm); + ajaxServlets.put(alias,new AjaxServletContainer(alias, servlet, perm)); + } + + /** + * Calls {@link this.performAction} + */ + public void doPost(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + performAction(req,res); + } + + /** + * Calls {@link this.performAction} + */ + public void doGet(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + performAction(req,res); + } + + /** + * The main method which get the requestURI "/ajax/", gets the + * {@link this.getServletName} and finds the servlet using {@link this.findServletByName}. + * It then calls servlet.service(). + * @param req the inbound request + * @param res the outbound response + * @throws IOException + * @throws ServletException if no registered servlet can be found + */ + private void performAction(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + String path = req.getRequestURI(); + String servletName = getServletName(path); + if (servletName!=null) { + AjaxServletContainer container = findServletContainer(servletName); + if (container != null) { + HttpServlet servlet = container.servlet; + if ( validatePermission(req,container) ) { + servlet.service(req, res); + } else { + log.warn("Serlvet container "+container+" not authorised. Permission required."); + } + } else { + log.error("No registered class for servletName=" + servletName + " in path=" + path); + throw new ServletException("No registered class for servletName=" + servletName); + } + } + } + + private boolean validatePermission(HttpServletRequest req, AjaxServletContainer container) { + WikiEngine e = WikiEngine.getInstance(req.getSession().getServletContext(), null); + boolean valid = false; + if (container != null) { + valid = e.getAuthorizationManager().checkPermission(WikiSession.getWikiSession(e, req), container.permission); + } + return valid; + } + + /** + * Get the name of the servlet given the requestURI. + * @param path The requestURI, which must contains "/ajax/" in the path + * @return The ServletName for the requestURI, or null + * @throws ServletException if the path is invalid + */ + public String getServletName(String path) throws ServletException { + return AjaxUtil.getNextPathPart(path, PATH_AJAX); + } + + /** + * Find the servlet as registered in {@link WikiAjaxDispatcherServlet.register}. + * + * @param servletName the name of the servlet from {@link this.getServletName} + * @return The first servlet found, or null. + */ + public AjaxServletContainer findServletContainer(String serlvetAlias) { + return ajaxServlets.get(serlvetAlias); + } + + public HttpServlet findServletByName(String serlvetAlias) { + AjaxServletContainer container = ajaxServlets.get(serlvetAlias); + if (container != null) { + return container.servlet; + } + return null; + } + + private static class AjaxServletContainer { + String alias; + HttpServlet servlet; + Permission permission; + + public AjaxServletContainer(String alias, HttpServlet servlet, Permission permission) { + this.alias = alias; + this.servlet = servlet; + this.permission = permission; + } + + public String toString() { + return getClass().getSimpleName()+" "+alias+"="+servlet.getClass().getSimpleName()+" permission="+permission; + } + } + +} Property changes on: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jspwiki-war/src/main/java/org/apache/wiki/auth/user/DefaultUserProfile.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/auth/user/DefaultUserProfile.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/auth/user/DefaultUserProfile.java (working copy) @@ -39,25 +39,25 @@ private static final String WHITESPACE = "\\s"; - private Map m_attributes = new HashMap(); + private Map attributes = new HashMap(); - private Date m_created = null; + private Date created = null; - private String m_email = null; + private String email = null; - private String m_fullname = null; + private String fullname = null; - private Date m_lockExpiry = null; + private Date lockExpiry = null; - private String m_loginName = null; + private String loginName = null; - private Date m_modified = null; + private Date modified = null; - private String m_password = null; + private String password = null; - private String m_uid = null; + private String uid = null; - private String m_wikiname = null; + private String wikiname = null; /** * Private constructor to prevent direct instantiation. @@ -86,9 +86,9 @@ if ( ( o != null ) && ( o instanceof UserProfile ) ) { DefaultUserProfile u = (DefaultUserProfile) o; - return same( m_fullname, u.m_fullname ) && same( m_password, u.m_password ) - && same( m_loginName, u.m_loginName ) && same(StringUtils.lowerCase( m_email ), StringUtils.lowerCase( u.m_email ) ) && same( m_wikiname, - u.m_wikiname ); + return same( fullname, u.fullname ) && same( password, u.password ) + && same( loginName, u.loginName ) && same(StringUtils.lowerCase( email ), StringUtils.lowerCase( u.email ) ) && same( wikiname, + u.wikiname ); } return false; @@ -96,11 +96,11 @@ public int hashCode() { - return (m_fullname != null ? m_fullname.hashCode() : 0) ^ - (m_password != null ? m_password.hashCode() : 0) ^ - (m_loginName != null ? m_loginName.hashCode() : 0) ^ - (m_wikiname != null ? m_wikiname.hashCode() : 0) ^ - (m_email != null ? StringUtils.lowerCase( m_email ).hashCode() : 0); + return (fullname != null ? fullname.hashCode() : 0) ^ + (password != null ? password.hashCode() : 0) ^ + (loginName != null ? loginName.hashCode() : 0) ^ + (wikiname != null ? wikiname.hashCode() : 0) ^ + (email != null ? StringUtils.lowerCase( email ).hashCode() : 0); } /** @@ -110,7 +110,7 @@ */ public Date getCreated() { - return m_created; + return created; } /** @@ -119,7 +119,7 @@ */ public String getEmail() { - return m_email; + return email; } /** @@ -128,7 +128,7 @@ */ public String getFullname() { - return m_fullname; + return fullname; } /** @@ -138,7 +138,7 @@ */ public Date getLastModified() { - return m_modified; + return modified; } /** @@ -147,7 +147,7 @@ */ public String getLoginName() { - return m_loginName; + return loginName; } /** @@ -161,7 +161,7 @@ */ public String getPassword() { - return m_password; + return password; } /** @@ -170,7 +170,7 @@ */ public String getWikiName() { - return m_wikiname; + return wikiname; } /** @@ -182,7 +182,7 @@ */ public boolean isNew() { - return m_modified == null; + return modified == null; } /** @@ -191,7 +191,7 @@ */ public void setCreated(Date date) { - m_created = date; + created = date; } /** @@ -200,7 +200,7 @@ */ public void setEmail( String email ) { - m_email = email; + this.email = email; } /** @@ -209,12 +209,12 @@ */ public void setFullname( String arg ) { - m_fullname = arg; + fullname = arg; // Compute wiki name - if ( m_fullname != null ) + if ( fullname != null ) { - m_wikiname = m_fullname.replaceAll(WHITESPACE, EMPTY_STRING); + wikiname = fullname.replaceAll(WHITESPACE, EMPTY_STRING); } } @@ -225,7 +225,7 @@ */ public void setLastModified( Date date ) { - m_modified = date; + modified = date; } /** @@ -238,7 +238,7 @@ */ public void setLoginName( String name ) { - m_loginName = name; + loginName = name; } /** @@ -253,7 +253,7 @@ */ public void setPassword( String arg ) { - m_password = arg; + password = arg; } /** @@ -304,7 +304,7 @@ */ public Map getAttributes() { - return m_attributes; + return attributes; } /** @@ -312,7 +312,7 @@ */ public Date getLockExpiry() { - return isLocked() ? m_lockExpiry : null; + return isLocked() ? lockExpiry : null; } /** @@ -320,7 +320,7 @@ */ public String getUid() { - return m_uid; + return uid; } /** @@ -328,12 +328,12 @@ */ public boolean isLocked() { - boolean locked = m_lockExpiry != null && System.currentTimeMillis() < m_lockExpiry.getTime(); + boolean locked = lockExpiry != null && System.currentTimeMillis() < lockExpiry.getTime(); // Clear the lock if it's expired already - if ( !locked && m_lockExpiry != null ) + if ( !locked && lockExpiry != null ) { - m_lockExpiry = null; + lockExpiry = null; } return locked; } @@ -343,7 +343,7 @@ */ public void setLockExpiry( Date expiry ) { - m_lockExpiry = expiry; + this.lockExpiry = expiry; } /** @@ -351,6 +351,6 @@ */ public void setUid( String uid ) { - m_uid = uid; + this.uid = uid; } } Index: jspwiki-war/src/main/java/org/apache/wiki/auth/UserManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/auth/UserManager.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/auth/UserManager.java (working copy) @@ -18,6 +18,7 @@ */ package org.apache.wiki.auth; +import java.io.IOException; import java.security.Permission; import java.security.Principal; import java.text.MessageFormat; @@ -30,7 +31,10 @@ import javax.mail.MessagingException; import javax.mail.internet.AddressException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; @@ -37,6 +41,8 @@ import org.apache.wiki.WikiContext; import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiSession; +import org.apache.wiki.ajax.AjaxUtil; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; import org.apache.wiki.api.engine.FilterManager; import org.apache.wiki.api.exceptions.NoRequiredPropertyException; import org.apache.wiki.api.exceptions.WikiException; @@ -54,7 +60,6 @@ import org.apache.wiki.i18n.InternationalizationManager; import org.apache.wiki.preferences.Preferences; import org.apache.wiki.rpc.RPCCallable; -import org.apache.wiki.rpc.json.JSONRPCManager; import org.apache.wiki.ui.InputValidator; import org.apache.wiki.util.ClassUtil; import org.apache.wiki.util.MailUtil; @@ -97,6 +102,8 @@ protected static final String PREFS_FULL_NAME = "prefs.fullname"; protected static final String PREFS_EMAIL = "prefs.email"; + public static final String JSON_USERS = "users"; + // private static final String PROP_ACLMANAGER = "jspwiki.aclManager"; /** Associates wiki sessions with profiles */ @@ -124,8 +131,9 @@ // Attach the PageManager as a listener // TODO: it would be better if we did this in PageManager directly addWikiEventListener( engine.getPageManager() ); - - JSONRPCManager.registerGlobalObject( "users", new JSONUserModule(this), new AllPermission(null) ); + + WikiAjaxDispatcherServlet.registerServlet( JSON_USERS, new JSONUserModule(this), new AllPermission(null)); +// JSONRPCManager.registerGlobalObject( JSON_USERS, new JSONUserModule(this), new AllPermission(null) ); } /** @@ -843,7 +851,7 @@ WikiEventManager.fireEvent(this,new WikiSecurityEvent(session,type,profile)); } } - + /** * Implements the JSON API for usermanager. *

@@ -851,9 +859,10 @@ * this gets reinstalled to the session when JSPWiki starts. This means * that it's not actually necessary to save anything. */ - public static final class JSONUserModule implements RPCCallable + public static final class JSONUserModule extends HttpServlet implements RPCCallable { - private volatile UserManager m_manager; + private static final long serialVersionUID = 6154591769798706915L; + private volatile UserManager m_manager; /** * Create a new JSONUserModule. @@ -864,6 +873,18 @@ m_manager = mgr; } + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + try { + String uid = AjaxUtil.getNextPathPart(req.getRequestURI(),JSON_USERS); + log.debug("uid="+uid); + UserProfile prof = getUserInfo(uid); + resp.getWriter().write(AjaxUtil.toJson(prof)); + } catch (NoSuchPrincipalException e) { + throw new ServletException(e); + } + } + /** * Directly returns the UserProfile object attached to an uid. * Index: jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java (working copy) @@ -20,6 +20,7 @@ package org.apache.wiki.plugin; import org.apache.commons.lang.ClassUtils; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.oro.text.regex.MalformedPatternException; import org.apache.oro.text.regex.MatchResult; @@ -29,9 +30,9 @@ import org.apache.oro.text.regex.Perl5Compiler; import org.apache.oro.text.regex.Perl5Matcher; import org.apache.wiki.InternalWikiException; -import org.apache.wiki.WikiAjaxDispatcherServlet; import org.apache.wiki.WikiContext; import org.apache.wiki.WikiEngine; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; import org.apache.wiki.api.engine.PluginManager; import org.apache.wiki.api.exceptions.PluginException; import org.apache.wiki.api.plugin.InitializablePlugin; @@ -546,7 +547,7 @@ m_pluginClassMap.put( name, pluginClass ); } - pluginClass.initializePlugin( m_engine , m_searchPath, m_externalJars); + pluginClass.initializePlugin( pluginClass, m_engine , m_searchPath, m_externalJars); } private void registerPlugins() { @@ -580,6 +581,7 @@ private String m_className; private String m_alias; + private String m_ajaxAlias; private Class m_clazz; private boolean m_initialized = false; @@ -611,7 +613,7 @@ * @param searchPath A List of Strings, containing different package names. * @param externalJars the list of external jars to search */ - protected void initializePlugin( WikiEngine engine , List searchPath, List externalJars) { + protected void initializePlugin( WikiPluginInfo info, WikiEngine engine , List searchPath, List externalJars) { if( !m_initialized ) { // This makes sure we only try once per class, even if init fails. m_initialized = true; @@ -622,7 +624,11 @@ ( ( InitializablePlugin )p ).initialize( engine ); } if( p instanceof HttpServlet ) { - WikiAjaxDispatcherServlet.register( (HttpServlet) p ); + WikiAjaxDispatcherServlet.registerServlet( (HttpServlet) p ); + String ajaxAlias = info.getAjaxAlias(); + if (StringUtils.isNotBlank(ajaxAlias)) { + WikiAjaxDispatcherServlet.registerServlet( info.getAjaxAlias(), (HttpServlet) p ); + } } } catch( Exception e ) { log.info( "Cannot initialize plugin " + m_className, e ); @@ -637,6 +643,7 @@ protected void initializeFromXML( Element el ) { super.initializeFromXML( el ); m_alias = el.getChildText( "alias" ); + m_ajaxAlias = el.getChildText( "ajaxAlias" ); } /** @@ -674,6 +681,14 @@ public String getAlias() { return m_alias; } + + /** + * Returns the ajax alias name for this object. + * @return An ajax alias name for the plugin. + */ + public String getAjaxAlias() { + return m_ajaxAlias; + } /** * Creates a new plugin instance. Index: jspwiki-war/src/main/java/org/apache/wiki/plugin/SampleAjaxPlugin.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/plugin/SampleAjaxPlugin.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/plugin/SampleAjaxPlugin.java (working copy) @@ -29,6 +29,7 @@ import org.apache.wiki.WikiContext; import org.apache.wiki.api.exceptions.PluginException; import org.apache.wiki.api.plugin.WikiPlugin; +import org.apache.wiki.util.TextUtil; /** * @author David VIttor @@ -41,9 +42,8 @@ @Override public String execute(WikiContext context, Map params) throws PluginException { String id = Integer.toString(this.hashCode()); - String baseUrl = context.getEngine().getBaseURL(); - String url = baseUrl+"ajax/SampleAjaxPlugin"; - String html= "

Press Me
\n"+ + String url = "/SampleAjaxPlugin"; + String html= "
Press Me
\n"+ "
"; return html; } Index: jspwiki-war/src/main/java/org/apache/wiki/preferences/Preferences.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/preferences/Preferences.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/preferences/Preferences.java (working copy) @@ -113,6 +113,8 @@ prefs.put("SectionEditing", TextUtil.getStringProperty( props, "jspwiki.defaultprefs.template.sectionediting", "" ) ); + prefs.put("ajaxPrefix", TextUtil.getStringProperty( props, "jspwiki.ajax.url.prefix", "ajax") ); + // FIXME: "editor" property does not get registered, may be related with http://bugs.jspwiki.org/show_bug.cgi?id=117 // disabling it until knowing why it's happening // FIXME: editormanager reads jspwiki.editor -- which of both properties should continue Index: jspwiki-war/src/main/java/org/apache/wiki/rpc/json/JSONRPCManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/rpc/json/JSONRPCManager.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/rpc/json/JSONRPCManager.java (working copy) @@ -27,15 +27,15 @@ import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; - import org.apache.wiki.WikiContext; import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiSession; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; import org.apache.wiki.auth.WikiSecurityException; import org.apache.wiki.auth.permissions.PagePermission; import org.apache.wiki.rpc.RPCCallable; import org.apache.wiki.rpc.RPCManager; -import org.apache.wiki.ui.TemplateManager; + import com.metaparadigm.jsonrpc.InvocationCallback; import com.metaparadigm.jsonrpc.JSONRPCBridge; @@ -51,10 +51,13 @@ * Due to some limitations of the JSON-RPC library, we do not use the * Global bridge object. * + * Deprecated: Use {@link WikiAjaxDispatcherServlet} + * * @see org.apache.wiki.rpc.RPCCallable * @since 2.5.4 */ // FIXME: Must be mootool-ified. +@Deprecated public final class JSONRPCManager extends RPCManager { private static final String JSONRPCBRIDGE = "JSONRPCBridge"; private static HashMap c_globalObjects = new HashMap(); Index: jspwiki-war/src/main/java/org/apache/wiki/rpc/RPCCallable.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/rpc/RPCCallable.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/rpc/RPCCallable.java (working copy) @@ -18,11 +18,16 @@ */ package org.apache.wiki.rpc; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; + /** * Defines an interface for anything which can be called using the RPC methods. * + * Deprecated. Use {@link WikiAjaxDispatcherServlet} + * * @since 2.5.4 */ +@Deprecated public interface RPCCallable { Index: jspwiki-war/src/main/java/org/apache/wiki/search/SearchManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/search/SearchManager.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/search/SearchManager.java (working copy) @@ -24,14 +24,23 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.Set; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.StopWatch; import org.apache.log4j.Logger; import org.apache.wiki.WikiContext; import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiPage; +import org.apache.wiki.ajax.AjaxUtil; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; import org.apache.wiki.api.exceptions.FilterException; import org.apache.wiki.api.exceptions.NoRequiredPropertyException; import org.apache.wiki.api.exceptions.ProviderException; @@ -43,11 +52,9 @@ import org.apache.wiki.modules.InternalModule; import org.apache.wiki.parser.MarkupParser; import org.apache.wiki.rpc.RPCCallable; -import org.apache.wiki.rpc.json.JSONRPCManager; import org.apache.wiki.util.ClassUtil; import org.apache.wiki.util.TextUtil; - /** * Manages searching the Wiki. * @@ -89,14 +96,57 @@ WikiEventUtils.addWikiEventListener(m_engine.getPageManager(), WikiPageEvent.PAGE_DELETE_REQUEST, this); - JSONRPCManager.registerGlobalObject( JSON_SEARCH, new JSONSearch() ); +// JSONRPCManager.registerGlobalObject( JSON_SEARCH, new JSONSearch() ); + WikiAjaxDispatcherServlet.registerServlet( JSON_SEARCH, new JSONSearch() ); } /** * Provides a JSON RPC API to the JSPWiki Search Engine. */ - public class JSONSearch implements RPCCallable + public class JSONSearch extends HttpServlet implements RPCCallable { + private static final long serialVersionUID = -7247458370410462412L; + public static final String AJAX_ACTION_SUGGESTIONS = "suggestions"; + public static final String AJAX_ACTION_PAGES = "pages"; + public static final int DEFAULT_MAX_RESULTS = 20; + public int maxResults = DEFAULT_MAX_RESULTS; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + String action = AjaxUtil.getNextPathPart(req.getRequestURI(), JSON_SEARCH); + log.debug("action="+action); + String result = ""; + if (StringUtils.isNotBlank(action)) { + String itemId = AjaxUtil.getNextPathPart(req.getRequestURI(), action); + log.debug("itemId="+itemId); + + if (StringUtils.isNotBlank(itemId)) { + String maxResultsParam = AjaxUtil.getNextPathPart(req.getRequestURI(), itemId); + log.debug("maxResultsParam="+maxResultsParam); + if (StringUtils.isNotBlank(maxResultsParam) && StringUtils.isNumeric(maxResultsParam)) { + maxResults = Integer.parseInt(maxResultsParam); + } + } + + if (action.equals(AJAX_ACTION_SUGGESTIONS)) { + List callResults = new ArrayList(); + log.debug("Calling getSuggestions() START"); + callResults = getSuggestions(itemId, maxResults); + log.debug("Calling getSuggestions() DONE. "+callResults.size()); + result = AjaxUtil.toJson(callResults); + } else if (action.equals(AJAX_ACTION_PAGES)) { + List> callResults = new ArrayList>(); + log.debug("Calling findPages() START"); + callResults = findPages(itemId, maxResults); + log.debug("Calling findPages() DONE. "+callResults.size()); + result = AjaxUtil.toJson(callResults); + } + } + log.debug("result="+result); + resp.getWriter().write(result); + } + /** * Provides a list of suggestions to use for a page name. * Currently the algorithm just looks into the value parameter, @@ -106,7 +156,7 @@ * @param maxLength maximum number of suggestions * @return the suggestions */ - public List getSuggestions( String wikiName, int maxLength ) + public List getSuggestions( String wikiName, int maxLength ) { StopWatch sw = new StopWatch(); sw.start(); @@ -155,12 +205,12 @@ * @param maxLength How many hits to return * @return the pages found */ - public List findPages( String searchString, int maxLength ) + public List> findPages( String searchString, int maxLength ) { StopWatch sw = new StopWatch(); sw.start(); - List list = new ArrayList(maxLength); + List> list = new ArrayList>(maxLength); if( searchString.length() > 0 ) { @@ -168,11 +218,12 @@ { Collection c; - if( m_searchProvider instanceof LuceneSearchProvider ) + if( m_searchProvider instanceof LuceneSearchProvider ) { c = ((LuceneSearchProvider)m_searchProvider).findPages( searchString, 0 ); - else + } else { c = m_searchProvider.findPages( searchString ); - + } + int count = 0; for( Iterator i = c.iterator(); i.hasNext() && count < maxLength; count++ ) { @@ -195,6 +246,7 @@ } } + /** * This particular method starts off indexing and all sorts of various activities, * so you need to run this last, after things are done. Index: jspwiki-war/src/main/java/org/apache/wiki/ui/progress/ProgressManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ui/progress/ProgressManager.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/ui/progress/ProgressManager.java (working copy) @@ -18,12 +18,19 @@ */ package org.apache.wiki.ui.progress; +import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.apache.log4j.Logger; - +import org.apache.wiki.ajax.AjaxUtil; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; import org.apache.wiki.rpc.RPCCallable; import org.apache.wiki.rpc.json.JSONRPCManager; @@ -52,7 +59,8 @@ */ public ProgressManager() { - JSONRPCManager.registerGlobalObject( JSON_PROGRESSTRACKER, new JSONTracker() ); +// JSONRPCManager.registerGlobalObject( JSON_PROGRESSTRACKER, new JSONTracker() ); + WikiAjaxDispatcherServlet.registerServlet( JSON_PROGRESSTRACKER, new JSONTracker() ); } /** @@ -117,7 +125,7 @@ * Progress of zero (0) means that the progress has just started, and a progress of * 100 means that it is complete. */ - public class JSONTracker implements RPCCallable + public class JSONTracker extends HttpServlet implements RPCCallable { /** * Returns upload progress in percents so far. @@ -129,5 +137,25 @@ { return ProgressManager.this.getProgress( progressId ); } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException + { + log.debug("ProgressManager.doGet() START"); + String progressId = AjaxUtil.getNextPathPart(req.getRequestURI(), JSON_PROGRESSTRACKER); + log.debug("progressId="+progressId); + String progressString = ""; + try { + int progress = getProgress(progressId); + progressString = Integer.toString(progress); + } catch (IllegalArgumentException e) { + // ignore + log.debug("progressId "+progressId+" is no longer valid"); + } + log.debug("progressString="+progressString); + resp.getWriter().write(progressString); + log.debug("ProgressManager.doGet() DONE"); + } } } Index: jspwiki-war/src/main/java/org/apache/wiki/WikiAjaxDispatcherServlet.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/WikiAjaxDispatcherServlet.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/WikiAjaxDispatcherServlet.java (working copy) @@ -1,146 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ -package org.apache.wiki; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; - -/** - * This provides a simple ajax servlet for handling /ajax/ requests. - * Classes need to be registered using {@link WikiAjaxDispatcherServlet.register} - * - * @author David VIttor - * @date 20/01/2015 - * @since 2.10.2-svn10 - */ -public class WikiAjaxDispatcherServlet extends HttpServlet { - private static final long serialVersionUID = 1L; - private static Map ajaxServlets = new HashMap(); - static final Logger log = Logger.getLogger(WikiAjaxDispatcherServlet.class.getName()); - private static final String PATH_AJAX = "/ajax/"; - - /** - * {@inheritDoc} - */ - public void init(ServletConfig config) - throws ServletException { - super.init(config); - - log.info("WikiAjaxDispatcherServlet initialized."); - } - - public static void register(HttpServlet servlet) { - log.info("WikiAjaxDispatcherServlet registering "+servlet.getClass().getSimpleName()+"="+servlet); - ajaxServlets.put(servlet.getClass().getSimpleName(),servlet); - } - - /** - * Calls {@link this.performAction} - */ - public void doPost(HttpServletRequest req, HttpServletResponse res) - throws IOException, ServletException { - performAction(req,res); - } - - /** - * Calls {@link this.performAction} - */ - public void doGet(HttpServletRequest req, HttpServletResponse res) - throws IOException, ServletException { - performAction(req,res); - } - - /** - * The main method which get the requestURI "/ajax/", gets the - * {@link this.getServletName} and finds the servlet using {@link this.findServletByName}. - * It then calls servlet.service(). - * @param req the inbound request - * @param res the outbound response - * @throws IOException - * @throws ServletException if no registered servlet can be found - */ - private void performAction(HttpServletRequest req, HttpServletResponse res) - throws IOException, ServletException { - String path = req.getRequestURI(); - String servletName = getServletName(path); - if (servletName!=null) { - HttpServlet ajaxServlet = findServletByName(servletName); - if (ajaxServlet != null) { - ajaxServlet.service(req, res); - } else { - log.error("No registered class for servletName=" + servletName + " in path=" + path); - throw new ServletException("No registered class for servletName=" + servletName); - } - } - } - - /** - * Get the name of the servlet given the requestURI. - * @param path The requestURI, which must contains "/ajax/" in the path - * @return The ServletName for the requestURI, or null - * @throws ServletException if the path is invalid - */ - public String getServletName(String path) throws ServletException { - String result = null; - if (StringUtils.isBlank(path)) { - return result; - } - int index = path.indexOf(PATH_AJAX); - if (index<0) { - throw new ServletException("Invalid path provided " + path + " does not contain '" + PATH_AJAX + "'"); - } - path = path.substring(index+6); - index = path.indexOf("/"); - if (index == -1) { - index = path.indexOf("#"); - if (index == -1) { - index = path.indexOf("?"); - } - } - if (index == -1) { - result = path; - } - else { - result = path.substring(0,index); - } - - return result; - } - - /** - * Find the servlet as registered in {@link WikiAjaxDispatcherServlet.register}. - * - * @param servletName the name of the servlet from {@link this.getServletNamee} - * @return The first servlet found, or null. - */ - public HttpServlet findServletByName(String servletName) { - return ajaxServlets.get(servletName); - } - -} Index: jspwiki-war/src/main/java/org/apache/wiki/xmlrpc/RPCServlet.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/xmlrpc/RPCServlet.java (revision 1653248) +++ jspwiki-war/src/main/java/org/apache/wiki/xmlrpc/RPCServlet.java (working copy) @@ -32,9 +32,9 @@ import org.apache.log4j.Logger; import org.apache.xmlrpc.*; - import org.apache.wiki.WikiContext; import org.apache.wiki.WikiEngine; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; /** * Handles all incoming servlet requests for XML-RPC calls. @@ -45,8 +45,10 @@ *
  • prefix : The command prefix for that particular handler. * * + * Deprecated. Use {@link WikiAjaxDispatcherServlet} * @since 1.6.6 */ +@Deprecated public class RPCServlet extends HttpServlet { private static final long serialVersionUID = 3976735878410416180L; Index: jspwiki-war/src/main/resources/ini/jspwiki.properties =================================================================== --- jspwiki-war/src/main/resources/ini/jspwiki.properties (revision 1653248) +++ jspwiki-war/src/main/resources/ini/jspwiki.properties (working copy) @@ -941,6 +941,9 @@ # Uncomment the next line to require the Admin group to approve new user profiles #jspwiki.approver.workflow.createUserProfile=Admin +jspwiki-x.adminui.enable=true +jspwiki-x.securityconfig.enable=true + ########################################################################### # # Default Template properties Index: jspwiki-war/src/main/scripts/jspwiki-common.js =================================================================== --- jspwiki-war/src/main/scripts/jspwiki-common.js (revision 1653248) +++ jspwiki-war/src/main/scripts/jspwiki-common.js (working copy) @@ -248,31 +248,37 @@ } /* - * AJAX call starts with this function - */ -function makeRequest(method,url,responseId,loading) { - var xmlHttpRequest = getXMLHttpRequest(); - xmlHttpRequest.onreadystatechange = getReadyStateHandler(xmlHttpRequest,responseId,loading); - xmlHttpRequest.open(method, url, true); - xmlHttpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - xmlHttpRequest.send(null); -} - -/* * Returns a function that waits for the state change in XMLHttpRequest */ -function getReadyStateHandler(xmlHttpRequest,responseId,loading) { +function getReadyStateHandler(xmlHttpRequest,responseId,loading,callback) { // an anonymous function returned // it listens to the XMLHttpRequest instance return function() { if (xmlHttpRequest.readyState >=1 && xmlHttpRequest.readyState <4) { - document.getElementById(responseId).innerHTML = loading; + if (responseId && document.getElementById(responseId) != null) { + document.getElementById(responseId).innerHTML = loading; + } } if (xmlHttpRequest.readyState == 4) { if (xmlHttpRequest.status == 200) { - document.getElementById(responseId).innerHTML = xmlHttpRequest.responseText; + if (responseId && document.getElementById(responseId) != null) { + document.getElementById(responseId).innerHTML = xmlHttpRequest.responseText; + } else { + // Javascript function JSON.parse to parse JSON data + var jsonResponse = xmlHttpRequest.responseText; + if (jsonResponse && jsonResponse.length>0) { + jsonResponse = JSON.parse(jsonResponse); + } + callback(jsonResponse); + } } else { - document.getElementById(responseId).innerHTML("HTTP error " + xmlHttpRequest.status + ": " + xmlHttpRequest.statusText); + var errorMsg = "HTTP error " + xmlHttpRequest.status + ": " + xmlHttpRequest.statusText; + if (responseId && document.getElementById(responseId) != null) { + document.getElementById(responseId).innerHTML(errorMsg); + } else { + console.log(errorMsg); + callback(errorMsg); + } } } }; @@ -439,11 +445,11 @@ submitUpload: function(form, progress){ $('progressbar').setStyle('visibility','visible'); this.progressbar = - Wiki.jsonrpc.periodical(1000, this, ["progressTracker.getProgress",[progress],function(result){ - result = result.stripScripts(); //xss vulnerability - if(!result.code) $('progressbar').getFirst().setStyle('width',result+'%').setHTML(result+'%'); + Wiki.ajaxJsonCall.periodical(500, this, ["/progressTracker/"+progress,function(result){ + if(result) { + $('progressbar').getFirst().setStyle('width',result+'%').setHTML(result+'%'); + } }]); - return Wiki.submitOnce(form); }, @@ -472,6 +478,37 @@ ); }, + /* + * AJAX call starts with this function + */ + ajaxHtmlCall: function (url,responseId,method,loading) { + url = Wiki.JsonUrl + url; + if (!method) { + method = "GET"; + } + if (!loading) { + loading = "Loading..."; + } + var xmlHttpRequest = getXMLHttpRequest(); + xmlHttpRequest.onreadystatechange = getReadyStateHandler(xmlHttpRequest,responseId,loading); + xmlHttpRequest.open(method, url, true); + xmlHttpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xmlHttpRequest.send(null); + }, + + ajaxJsonCall: function (url,callback,method) { + url = Wiki.JsonUrl + url; + if (!method) { + method = "GET"; + } + var xmlHttpRequest = getXMLHttpRequest(); + xmlHttpRequest.onreadystatechange = getReadyStateHandler(xmlHttpRequest,null,null,callback); + xmlHttpRequest.open(method, url, true); + xmlHttpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xmlHttpRequest.send(null); + }, + + /* Removed as deprecated code $jsonid : 10000, jsonrpc: function(method, params, fn) { $$('meta').each(function(el){ @@ -493,6 +530,7 @@ }).request(); } } + */ } @@ -1005,20 +1043,20 @@ $('searchTarget').setHTML('('+qv+') :'); $('searchSpin').show(); - Wiki.jsonrpc('search.findPages', [qv,20], function(result){ - $('searchSpin').hide(); - if(!result.list) return; - var frag = new Element('ul'); + Wiki.ajaxJsonCall("/search/pages/"+qv+"/20", function(result) { + $('searchSpin').hide(); + if(!result || result.length==0) return; + var frag = new Element('ul'); - result.list.each(function(el){ - new Element('li').adopt( - new Element('a',{'href':Wiki.getUrl(el.map.page) }).setHTML(el.map.page), - new Element('span',{'class':'small'}).setHTML(" ("+el.map.score+")") - ).inject(frag); - }); - $('searchOutput').empty().adopt(frag); - Wiki.locatemenu( $('query'), $('searchboxMenu') ); - }); + result.each(function(el){ + new Element('li').adopt( + new Element('a',{'href':Wiki.getUrl(el.page) }).setHTML(el.page), + new Element('span',{'class':'small'}).setHTML(" ("+el.score+")") + ).inject(frag); + }); + $('searchOutput').empty().adopt(frag); + Wiki.locatemenu( $('query'), $('searchboxMenu') ); + }); } , /* navigate to url, after smart pagename handling */ Index: jspwiki-war/src/main/scripts/jspwiki-edit.js =================================================================== --- jspwiki-war/src/main/scripts/jspwiki-edit.js (revision 1653248) +++ jspwiki-war/src/main/scripts/jspwiki-edit.js (working copy) @@ -456,14 +456,14 @@ if(end!=-1) sel.end = sel.start+end; } - Wiki.jsonrpc('search.getSuggestions', [searchword,30], function(result,exception){ + Wiki.ajaxJsonCall('/search/suggestions/'+searchword+'/30', function(result,exception){ if(exception) { alert(exception.message); - } else if(!result.list || (result.list.length == 0)) { + } else if(!result || result.length == 0) { suggest.hide(); } else { var ul = new Element('ul').inject( suggest.empty().show() ); - result.list.each( function(rslt) { + result.each( function(rslt) { new Element('li',{ 'title':rslt, 'events': { Index: jspwiki-war/src/main/scripts/wiki-edit/Wiki.Snips.js =================================================================== --- jspwiki-war/src/main/scripts/wiki-edit/Wiki.Snips.js (revision 1653248) +++ jspwiki-war/src/main/scripts/wiki-edit/Wiki.Snips.js (working copy) @@ -371,17 +371,14 @@ if( !key || (key.trim()=='')) key = Wiki.PageName + '/'; //console.log('json lookup for '+key); - Wiki.jsonrpc('search.getSuggestions', [key,30], function(result,exception){ - - if( result.list && result.list[0] /*length!=0*/ ){ - dialog.setBody( result.list ); - } else { - dialog.hide(); - } - - }); + Wiki.ajaxJsonCall("/search/suggestions/"+key+"/30", function(result,exception) { + if( result && result.size()>0 ){ + dialog.setBody( result ); + } else { + dialog.hide(); + } + }); } - }] Index: jspwiki-war/src/main/scripts/wiki/Findpages.js =================================================================== --- jspwiki-war/src/main/scripts/wiki/Findpages.js (revision 1653248) +++ jspwiki-war/src/main/scripts/wiki/Findpages.js (working copy) @@ -27,7 +27,7 @@ Example: > wiki.add('query', Wiki.SearchBox, { -> rpc: function(value, callback){ wiki.jsonrpc('search.findPages', [value,20], callback }, +> rpc: function(value, callback){ Wiki.ajaxJsonCall('/search/findPages/'+value+'/20', callback }, > toUrl: wiki.toUrl > }); */ Index: jspwiki-war/src/main/scripts/wiki/Wiki.js =================================================================== --- jspwiki-war/src/main/scripts/wiki/Wiki.js (revision 1653248) +++ jspwiki-war/src/main/scripts/wiki/Wiki.js (working copy) @@ -166,7 +166,7 @@ //activate Quick Navigation functionality new wiki.Findpages(element,{ rpc: function(value, callback){ - wiki.jsonrpc('search.findPages', [value,16], callback); + Wiki.ajaxJsonCall('/search/pages/'+value+'/16', callback); }, toUrl: wiki.toUrl.bind(wiki) }); @@ -189,7 +189,7 @@ .add('#files', Form.File, { max:1, //CHECK: jspwiki v.2.10.x seems to only support 1 upload-file at a time ?? rpc: function(progressid, callback){ - wiki.jsonrpc('progressTracker.getProgress', [progressid], callback); + Wiki.ajaxJsonCall('/progressTracker/'+progressId, callback); }, }); @@ -423,18 +423,18 @@ {{{ }}} Supported rpc calls: - - {{search.findPages}} gets the list of pagenames with partial match - - {{progressTracker.getProgress}} get a progress indicator of attachment upload - - {{search.getSuggestions}} gets the list of pagenames with partial match + - {{ajax/users/}} gets the details of the current user id + - {{ajax/search/pages/}} gets the list of pagenames with partial match + - {{ajax/search/suggestions/}} gets the list of pagenames with partial match + - {{ajax/progressTracker/}} get a progress indicator of attachment upload Example: (start code) - Wiki.jsonrpc('search.findPages', ['Janne',20], function(result){ + Wiki.ajaxJsonCall('/search/pages/Janne/20', function(result){ //do something with the resulting json object }); (end) - - */ + jsonid : 1e4, //seed jsonrpc: function(method, params, callback){ @@ -461,6 +461,7 @@ } } + */ }; Index: jspwiki-war/src/main/webapp/templates/default/admin/UserManagement.jsp =================================================================== --- jspwiki-war/src/main/webapp/templates/default/admin/UserManagement.jsp (revision 1653248) +++ jspwiki-war/src/main/webapp/templates/default/admin/UserManagement.jsp (working copy) @@ -41,13 +41,13 @@ if( userid == '--New--' ) return; - Wiki.jsonrpc("users.getUserInfo", [userid], function(userprofile){ - $('loginname').value = userprofile.loginName; - $('loginid').value = userprofile.loginName; - $('fullname').value = userprofile.fullname; - $('email').value = userprofile.email; - $('lastmodified').setHTML(constructdate(userprofile.lastModified)); - $('creationdate').setHTML(constructdate(userprofile.created)); + Wiki.ajaxJsonCall("/users/"+userid, function(userprofile) { + $('loginname').value = userprofile.loginName; + $('loginid').value = userprofile.loginName; + $('fullname').value = userprofile.fullname; + $('email').value = userprofile.email; + $('lastmodified').setHTML(constructdate(userprofile.lastModified)); + $('creationdate').setHTML(constructdate(userprofile.created)); }); } Index: jspwiki-war/src/main/webapp/templates/default/commonheader.jsp =================================================================== --- jspwiki-war/src/main/webapp/templates/default/commonheader.jsp (revision 1653248) +++ jspwiki-war/src/main/webapp/templates/default/commonheader.jsp (working copy) @@ -67,7 +67,7 @@ -<%--unusual pagename--%> +<%--unusual pagename--%> <%--pagename without blanks--%> Index: jspwiki-war/src/main/webapp/templates/haddock/admin/UserManagement.jsp =================================================================== --- jspwiki-war/src/main/webapp/templates/haddock/admin/UserManagement.jsp (revision 1653248) +++ jspwiki-war/src/main/webapp/templates/haddock/admin/UserManagement.jsp (working copy) @@ -41,13 +41,13 @@ if( userid == '--New--' ) return; - Wiki.jsonrpc("users.getUserInfo", [userid], function(userprofile){ - $('loginname').value = userprofile.loginName; - $('loginid').value = userprofile.loginName; - $('fullname').value = userprofile.fullname; - $('email').value = userprofile.email; - $('lastmodified').setHTML(constructdate(userprofile.lastModified)); - $('creationdate').setHTML(constructdate(userprofile.created)); + Wiki.ajaxJsonCall("/users/"+userid, function(userprofile) { + $('loginname').value = userprofile.loginName; + $('loginid').value = userprofile.loginName; + $('fullname').value = userprofile.fullname; + $('email').value = userprofile.email; + $('lastmodified').setHTML(constructdate(userprofile.lastModified)); + $('creationdate').setHTML(constructdate(userprofile.created)); }); } Index: jspwiki-war/src/main/webapp/WEB-INF/web.xml =================================================================== --- jspwiki-war/src/main/webapp/WEB-INF/web.xml (revision 1653248) +++ jspwiki-war/src/main/webapp/WEB-INF/web.xml (working copy) @@ -127,6 +127,13 @@ com.metaparadigm.jsonrpc.JSONRPCServlet com.metaparadigm.jsonrpc.JSONRPCServlet + + + + WikiAjaxDispatcherServlet + org.apache.wiki.ajax.WikiAjaxDispatcherServlet + 1 + @@ -141,13 +148,6 @@ 1 - - - WikiAjaxDispatcherServlet - org.apache.wiki.WikiAjaxDispatcherServlet - 1 - - @@ -170,6 +170,7 @@ WikiAjaxDispatcherServlet /ajax/* + /admin/ajax/* Index: jspwiki-war/src/test/java/org/apache/wiki/WikiAjaxServletTest.java =================================================================== --- jspwiki-war/src/test/java/org/apache/wiki/WikiAjaxServletTest.java (revision 1653248) +++ jspwiki-war/src/test/java/org/apache/wiki/WikiAjaxServletTest.java (working copy) @@ -22,6 +22,7 @@ import junit.framework.TestCase; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; import org.apache.wiki.plugin.SampleAjaxPlugin; import org.apache.wiki.xmlrpc.RPCServlet; @@ -52,12 +53,12 @@ } // The plugin SampleAjaxPlugin - WikiAjaxDispatcherServlet.register(new SampleAjaxPlugin()); + WikiAjaxDispatcherServlet.registerServlet(new SampleAjaxPlugin()); HttpServlet servlet = wikiAjaxDispatcherServlet.findServletByName("SampleAjaxPlugin"); assertNotNull(servlet); assertTrue(servlet instanceof SampleAjaxPlugin); - WikiAjaxDispatcherServlet.register(new RPCServlet()); + WikiAjaxDispatcherServlet.registerServlet(new RPCServlet()); HttpServlet servlet2 = wikiAjaxDispatcherServlet.findServletByName("RPCServlet"); assertNotNull(servlet2); assertTrue(servlet2 instanceof RPCServlet); Index: jspwiki-war/src/test/resources/WEB-INF/web.xml =================================================================== --- jspwiki-war/src/test/resources/WEB-INF/web.xml (revision 1653248) +++ jspwiki-war/src/test/resources/WEB-INF/web.xml (working copy) @@ -148,6 +148,13 @@ com.metaparadigm.jsonrpc.JSONRPCServlet com.metaparadigm.jsonrpc.JSONRPCServlet + + + + WikiAjaxDispatcherServlet + org.apache.wiki.ajax.WikiAjaxDispatcherServlet + 1 + @@ -211,6 +218,12 @@ + WikiAjaxDispatcherServlet + /ajax/* + /admin/ajax/* + + + com.metaparadigm.jsonrpc.JSONRPCServlet /JSON-RPC Index: pom.xml =================================================================== --- pom.xml (revision 1653248) +++ pom.xml (working copy) @@ -73,6 +73,12 @@ + com.google.code.gson + gson + 2.3.1 + + + commons-fileupload commons-fileupload 1.3