    001/*
    002    Licensed to the Apache Software Foundation (ASF) under one
    003    or more contributor license agreements.  See the NOTICE file
    004    distributed with this work for additional information
    005    regarding copyright ownership.  The ASF licenses this file
    006    to you under the Apache License, Version 2.0 (the
    007    "License"); you may not use this file except in compliance
    008    with the License.  You may obtain a copy of the License at
    009
    010       http://www.apache.org/licenses/LICENSE-2.0
    011
    012    Unless required by applicable law or agreed to in writing,
    013    software distributed under the License is distributed on an
    014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015    KIND, either express or implied.  See the License for the
    016    specific language governing permissions and limitations
    017    under the License.
    018 */
    019package org.apache.wiki.url;
    020
    021import jakarta.servlet.http.HttpServletRequest;
    022import org.apache.commons.lang3.Strings;
    023import org.apache.wiki.api.core.Command;
    024import org.apache.wiki.api.core.ContextEnum;
    025import org.apache.wiki.api.core.Engine;
    026import org.apache.wiki.ui.CommandResolver;
    027import org.apache.wiki.util.TextUtil;
    028
    029import java.nio.charset.Charset;
    030import java.util.Properties;
    031
    032
    033/**
    034 *  Implements the default URL constructor using links directly to the JSP pages.  This is what JSPWiki by default is using.  For example,
    035 *  WikiContext.VIEW points at "Wiki.jsp", etc.
    036 *
    037 *  @since 2.2
    038 */
    039public class DefaultURLConstructor implements URLConstructor {
    040
    041    protected Engine m_engine;
    042
    043    /** Contains the absolute path of the JSPWiki Web application without the actual servlet (which is the m_urlPrefix). */
    044    protected String m_pathPrefix = "";
    045
    046    /**
    047     *
    048     * {@inheritDoc}
    049     */
    050    @Override
    051    public void initialize( final Engine engine, final Properties properties ) {
    052        m_engine = engine;
    053        m_pathPrefix = engine.getBaseURL() + "/";
    054    }
    055
    056    /**
    057     *  Does replacement of some particular variables.  The variables are:
    058     *
    059     *  <ul>
    060     *  <li> "%u" - inserts either the base URL (when absolute is required), or the base path (which is an absolute path without the host name).
    061     *  <li> "%U" - always inserts the base URL
    062     *  <li> "%p" - always inserts the base path
    063     *  <li> "%n" - inserts the page name
    064     *  </ul>
    065     *
    066     * @param baseptrn  The pattern to use
    067     * @param name The page name
    068     * @return A replacement.
    069     */
    070    protected final String doReplacement( String baseptrn, final String name ) {
    071        final String baseurl = m_pathPrefix;
    072
    073        baseptrn = TextUtil.replaceString( baseptrn, "%u", baseurl );
    074        baseptrn = TextUtil.replaceString( baseptrn, "%U", m_engine.getBaseURL() );
    075        baseptrn = TextUtil.replaceString( baseptrn, "%n", encodeURI(name) );
    076        baseptrn = TextUtil.replaceString( baseptrn, "%p", m_pathPrefix );
    077
    078        return baseptrn;
    079    }
    080
    081    /**
    082     *  URLEncoder returns pluses, when we want to have the percent encoding.  See http://issues.apache.org/bugzilla/show_bug.cgi?id=39278
    083     *  for more info.
    084     *
    085     *  We also convert any %2F's back to slashes to make nicer-looking URLs.
    086     */
    087    private String encodeURI( String uri ) {
    088        uri = m_engine.encodeName(uri);
    089        uri = Strings.CS.replace( uri, "+", "%20" );
    090        uri = Strings.CS.replace( uri, "%2F", "/" );
    091
    092        return uri;
    093    }
    094
    095    /**
    096     * Returns the URL pattern for a supplied wiki request context.
    097     * @param context the wiki context
    098     * @param name the wiki page
    099     * @return A pattern for replacement.
    100     * @throws IllegalArgumentException if the context cannot be found
    101     */
    102    public static String getURLPattern( final String context, final String name ) throws IllegalArgumentException {
    103        if( context.equals( ContextEnum.PAGE_VIEW.getRequestContext() ) && name == null) {
    104            // FIXME
    105            return "%uWiki.jsp";
    106        }
    107
    108        // Find the action matching our pattern (could throw exception)
    109        final Command command = CommandResolver.findCommand( context );
    110
    111        return command.getURLPattern();
    112    }
    113
    114    /**
    115     *  Constructs the actual URL based on the context.
    116     */
    117    private String makeURL( final String context, final String name ) {
    118        return doReplacement( getURLPattern( context, name ), name );
    119    }
    120
    121    /**
    122     *  Constructs the URL with a bunch of parameters.
    123     *  @param parameters If null or empty, no parameters are added.
    124     *
    125     *  {@inheritDoc}
    126     */
    127    @Override
    128    public String makeURL( final String context, final String name, String parameters ) {
    129        if( parameters != null && !parameters.isEmpty() ) {
    130            if( context.equals( ContextEnum.PAGE_ATTACH.getRequestContext() ) ) {
    131                parameters = "?" + parameters;
    132            } else if( context.equals( ContextEnum.PAGE_NONE.getRequestContext() ) ) {
    133                parameters = name.indexOf( '?' ) != -1 ? "&amp;" : "?" + parameters;
    134            } else {
    135                parameters = "&amp;" + parameters;
    136            }
    137        } else {
    138            parameters = "";
    139        }
    140        return makeURL( context, name ) + parameters;
    141    }
    142
    143    /**
    144     *  Should parse the "page" parameter from the actual request.
    145     *
    146     *  {@inheritDoc}
    147     */
    148    @Override
    149    public String parsePage( final String context, final HttpServletRequest request, final Charset encoding ) {
    150        String pagereq = request.getParameter( "page" );
    151        if( context.equals( ContextEnum.PAGE_ATTACH.getRequestContext() ) ) {
    152            pagereq = URLConstructor.parsePageFromURL( request, encoding );
    153        }
    154
    155        return pagereq;
    156    }
    157
    158    /**
    159     *  This method is not needed for the DefaultURLConstructor.
    160     *
    161     * @param request The HTTP Request that was used to end up in this page.
    162     * @return "Wiki.jsp", "PageInfo.jsp", etc.  Just return the name, JSPWiki will figure out the page.
    163     */
    164    @Override
    165    public String getForwardPage( final HttpServletRequest request ) {
    166        return "Wiki.jsp";
    167    }
    168
    169}