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