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     */
019    package org.apache.wiki.plugin;
020    
021    import java.util.ArrayList;
022    import java.util.List;
023    import java.util.Map;
024    
025    import org.apache.wiki.WikiContext;
026    import org.apache.wiki.WikiEngine;
027    import org.apache.wiki.WikiPage;
028    import org.apache.wiki.api.exceptions.PluginException;
029    import org.apache.wiki.api.exceptions.ProviderException;
030    import org.apache.wiki.api.plugin.WikiPlugin;
031    import org.apache.wiki.auth.AuthorizationManager;
032    import org.apache.wiki.auth.permissions.PermissionFactory;
033    import 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     */
050    public 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            StringBuffer res = new StringBuffer();
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)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    }