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.plugin;
020
021import java.util.ArrayList;
022import java.util.List;
023import java.util.Map;
024
025import org.apache.wiki.WikiContext;
026import org.apache.wiki.WikiEngine;
027import org.apache.wiki.WikiPage;
028import org.apache.wiki.api.exceptions.PluginException;
029import org.apache.wiki.api.exceptions.ProviderException;
030import org.apache.wiki.api.plugin.WikiPlugin;
031import org.apache.wiki.auth.AuthorizationManager;
032import org.apache.wiki.auth.permissions.PermissionFactory;
033import org.apache.wiki.util.TextUtil;
034
035/**
036 *  Inserts page contents.  Muchos thanks to Scott Hurlbert for the initial code.
037 *
038 *  <p>Parameters : </p>
039 *  <ul>
040 *  <li><b>page</b> - the name of the page to be inserted</li>
041 *  <li><b>style</b> - the style to use</li>
042 *  <li><b>maxlength</b> - the maximum length of the page to be inserted (page contents)</li>
043 *  <li><b>class</b> - the class to use</li>
044 *  <li><b>section</b> - the section of the page that has to be inserted (separated by "----"</li>
045 *  <li><b>default</b> - the text to insert if the requested page does not exist</li>
046 *  </ul>
047 *
048 *  @since 2.1.37
049 */
050public class InsertPage
051    implements WikiPlugin
052{
053    /** Parameter name for setting the page.  Value is <tt>{@value}</tt>. */
054    public static final String PARAM_PAGENAME  = "page";
055    /** Parameter name for setting the style.  Value is <tt>{@value}</tt>. */
056    public static final String PARAM_STYLE     = "style";
057    /** Parameter name for setting the maxlength.  Value is <tt>{@value}</tt>. */
058    public static final String PARAM_MAXLENGTH = "maxlength";
059    /** Parameter name for setting the class.  Value is <tt>{@value}</tt>. */
060    public static final String PARAM_CLASS     = "class";
061    /** Parameter name for setting the section.  Value is <tt>{@value}</tt>. */
062    public static final String PARAM_SECTION   = "section";
063    /** Parameter name for setting the default.  Value is <tt>{@value}</tt>. */
064    public static final String PARAM_DEFAULT   = "default";
065
066    private static final String DEFAULT_STYLE = "";
067
068    /** This attribute is stashed in the WikiContext to make sure that we don't
069     *  have circular references.
070     */
071    public static final String ATTR_RECURSE    = "org.apache.wiki.plugin.InsertPage.recurseCheck";
072
073    /**
074     *  {@inheritDoc}
075     */
076    @SuppressWarnings("unchecked")
077    public String execute( WikiContext context, Map<String, String> params )
078        throws PluginException
079    {
080        WikiEngine engine = context.getEngine();
081
082        StringBuilder res = new StringBuilder();
083
084        String clazz        = params.get( PARAM_CLASS );
085        String includedPage = params.get( PARAM_PAGENAME );
086        String style        = params.get( PARAM_STYLE );
087        String defaultstr   = params.get( PARAM_DEFAULT );
088        int    section      = TextUtil.parseIntParameter(params.get( PARAM_SECTION ), -1 );
089        int    maxlen       = TextUtil.parseIntParameter(params.get( PARAM_MAXLENGTH ), -1 );
090
091        if( style == null ) style = DEFAULT_STYLE;
092
093        if( maxlen == -1 ) maxlen = Integer.MAX_VALUE;
094
095        if( includedPage != null )
096        {
097            WikiPage page = null;
098            try
099            {
100                String pageName = engine.getFinalPageName( includedPage );
101                if( pageName != null )
102                {
103                    page = engine.getPage( pageName );
104                }
105                else
106                {
107                    page = engine.getPage( includedPage );
108                }
109            }
110            catch( ProviderException e )
111            {
112                res.append( "<span class=\"error\">Page could not be found by the page provider.</span>" );
113                return res.toString();
114            }
115
116            if( page != null )
117            {
118                //
119                //  Check for recursivity
120                //
121
122                List<String> previousIncludes = (List<String>)context.getVariable( ATTR_RECURSE );
123
124                if( previousIncludes != null )
125                {
126                    if( previousIncludes.contains( page.getName() ) )
127                    {
128                        return "<span class=\"error\">Error: Circular reference - you can't include a page in itself!</span>";
129                    }
130                }
131                else
132                {
133                    previousIncludes = new ArrayList<String>();
134                }
135
136                previousIncludes.add( page.getName() );
137                context.setVariable( ATTR_RECURSE, previousIncludes );
138
139                //
140                // Check for permissions
141                //
142                AuthorizationManager mgr = engine.getAuthorizationManager();
143
144                if( !mgr.checkPermission( context.getWikiSession(),
145                                          PermissionFactory.getPagePermission( page, "view") ) )
146                {
147                    res.append("<span class=\"error\">You do not have permission to view this included page.</span>");
148                    return res.toString();
149                }
150
151                /**
152                 *  We want inclusion to occur within the context of
153                 *  its own page, because we need the links to be correct.
154                 */
155
156                WikiContext includedContext = (WikiContext) context.clone();
157                includedContext.setPage( page );
158
159                String pageData = engine.getPureText( page );
160                String moreLink = "";
161
162                if( section != -1 )
163                {
164                    try
165                    {
166                        pageData = TextUtil.getSection( pageData, section );
167                    }
168                    catch( IllegalArgumentException e )
169                    {
170                        throw new PluginException( e.getMessage() );
171                    }
172                }
173
174                if( pageData.length() > maxlen )
175                {
176                    pageData = pageData.substring( 0, maxlen )+" ...";
177                    moreLink = "<p><a href=\""+context.getURL(WikiContext.VIEW,includedPage)+"\">More...</a></p>";
178                }
179
180                res.append("<div style=\""+style+"\""+(clazz != null ? " class=\""+clazz+"\"" : "")+">");
181                res.append( engine.textToHTML( includedContext, pageData ) );
182                res.append( moreLink );
183                res.append("</div>");
184
185                //
186                //  Remove the name from the stack; we're now done with this.
187                //
188                previousIncludes.remove( page.getName() );
189                context.setVariable( ATTR_RECURSE, previousIncludes );
190            }
191            else
192            {
193                if( defaultstr != null )
194                {
195                    res.append( defaultstr );
196                }
197                else
198                {
199                    res.append("There is no page called '"+includedPage+"'.  Would you like to ");
200                    res.append("<a href=\""+context.getURL( WikiContext.EDIT, includedPage )+"\">create it?</a>");
201                }
202            }
203        }
204        else
205        {
206            res.append("<span class=\"error\">");
207            res.append("You have to define a page!");
208            res.append("</span>");
209        }
210
211        return res.toString();
212    }
213
214}