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; 020 021import org.apache.log4j.Logger; 022import org.apache.wiki.api.core.Command; 023import org.apache.wiki.api.core.Context; 024import org.apache.wiki.api.core.ContextEnum; 025import org.apache.wiki.api.core.Engine; 026import org.apache.wiki.api.core.Page; 027import org.apache.wiki.api.core.Session; 028import org.apache.wiki.api.spi.Wiki; 029import org.apache.wiki.auth.AuthorizationManager; 030import org.apache.wiki.auth.NoSuchPrincipalException; 031import org.apache.wiki.auth.UserManager; 032import org.apache.wiki.auth.WikiPrincipal; 033import org.apache.wiki.auth.permissions.AllPermission; 034import org.apache.wiki.auth.user.UserDatabase; 035import org.apache.wiki.pages.PageManager; 036import org.apache.wiki.ui.CommandResolver; 037import org.apache.wiki.ui.Installer; 038import org.apache.wiki.ui.PageCommand; 039import org.apache.wiki.ui.WikiCommand; 040import org.apache.wiki.util.TextUtil; 041 042import javax.servlet.http.HttpServletRequest; 043import javax.servlet.http.HttpSession; 044import javax.servlet.jsp.PageContext; 045import java.security.Permission; 046import java.security.Principal; 047import java.util.HashMap; 048import java.util.PropertyPermission; 049 050/** 051 * <p>Provides state information throughout the processing of a page. A WikiContext is born when the JSP pages that are the main entry 052 * points, are invoked. The JSPWiki engine creates the new WikiContext, which basically holds information about the page, the 053 * handling engine, and in which context (view, edit, etc) the call was done.</p> 054 * <p>A WikiContext also provides request-specific variables, which can be used to communicate between plugins on the same page, or 055 * between different instances of the same plugin. A WikiContext variable is valid until the processing of the page has ended. For 056 * an example, please see the Counter plugin.</p> 057 * <p>When a WikiContext is created, it automatically associates a {@link WikiSession} object with the user's HttpSession. The 058 * WikiSession contains information about the user's authentication status, and is consulted by {@link #getCurrentUser()} object.</p> 059 * <p>Do not cache the page object that you get from the WikiContext; always use getPage()!</p> 060 * 061 * @see org.apache.wiki.plugin.Counter 062 */ 063public class WikiContext implements Context, Command { 064 065 private Command m_command; 066 private WikiPage m_page; 067 private WikiPage m_realPage; 068 private Engine m_engine; 069 private String m_template = "default"; 070 071 private HashMap< String, Object > m_variableMap = new HashMap<>(); 072 073 /** Stores the HttpServletRequest. May be null, if the request did not come from a servlet. */ 074 protected HttpServletRequest m_request; 075 076 private Session m_session; 077 078 /** User is doing administrative things. */ 079 public static final String ADMIN = ContextEnum.WIKI_ADMIN.getRequestContext(); 080 081 /** User is downloading an attachment. */ 082 public static final String ATTACH = ContextEnum.PAGE_ATTACH.getRequestContext(); 083 084 /** User is commenting something. */ 085 public static final String COMMENT = ContextEnum.PAGE_COMMENT.getRequestContext(); 086 087 /** User has an internal conflict, and does quite not know what to do. Please provide some counseling. */ 088 public static final String CONFLICT = ContextEnum.PAGE_CONFLICT.getRequestContext(); 089 090 /** User wishes to create a new group */ 091 public static final String CREATE_GROUP = ContextEnum.WIKI_CREATE_GROUP.getRequestContext(); 092 093 /** User is deleting a page or an attachment. */ 094 public static final String DELETE = ContextEnum.PAGE_DELETE.getRequestContext(); 095 096 /** User is deleting an existing group. */ 097 public static final String DELETE_GROUP = ContextEnum.GROUP_DELETE.getRequestContext(); 098 099 /** User is viewing a DIFF between the two versions of the page. */ 100 public static final String DIFF = ContextEnum.PAGE_DIFF.getRequestContext(); 101 102 /** The EDIT context - the user is editing the page. */ 103 public static final String EDIT = ContextEnum.PAGE_EDIT.getRequestContext(); 104 105 /** User is editing an existing group. */ 106 public static final String EDIT_GROUP = ContextEnum.GROUP_EDIT.getRequestContext(); 107 108 /** An error has been encountered and the user needs to be informed. */ 109 public static final String ERROR = ContextEnum.WIKI_ERROR.getRequestContext(); 110 111 /** User is searching for content. */ 112 public static final String FIND = ContextEnum.WIKI_FIND.getRequestContext(); 113 114 /** User is viewing page history. */ 115 public static final String INFO = ContextEnum.PAGE_INFO.getRequestContext(); 116 117 /** User is administering JSPWiki (Install, SecurityConfig). */ 118 public static final String INSTALL = ContextEnum.WIKI_INSTALL.getRequestContext(); 119 120 /** User is preparing for a login/authentication. */ 121 public static final String LOGIN = ContextEnum.WIKI_LOGIN.getRequestContext(); 122 123 /** User is preparing to log out. */ 124 public static final String LOGOUT = ContextEnum.WIKI_LOGOUT.getRequestContext(); 125 126 /** JSPWiki wants to display a message. */ 127 public static final String MESSAGE = ContextEnum.WIKI_MESSAGE.getRequestContext(); 128 129 /** This is not a JSPWiki context, use it to access static files. */ 130 public static final String NONE = ContextEnum.PAGE_NONE.getRequestContext(); 131 132 /** Same as NONE; this is just a clarification. */ 133 public static final String OTHER = ContextEnum.PAGE_NONE.getRequestContext(); 134 135 /** User is editing preferences */ 136 public static final String PREFS = ContextEnum.WIKI_PREFS.getRequestContext(); 137 138 /** User is previewing the changes he just made. */ 139 public static final String PREVIEW = ContextEnum.PAGE_PREVIEW.getRequestContext(); 140 141 /** User is renaming a page. */ 142 public static final String RENAME = ContextEnum.PAGE_RENAME.getRequestContext(); 143 144 /** RSS feed is being generated. */ 145 public static final String RSS = ContextEnum.PAGE_RSS.getRequestContext(); 146 147 /** User is uploading something. */ 148 public static final String UPLOAD = ContextEnum.PAGE_UPLOAD.getRequestContext(); 149 150 /** The VIEW context - the user just wants to view the page contents. */ 151 public static final String VIEW = ContextEnum.PAGE_VIEW.getRequestContext(); 152 153 /** User is viewing an existing group */ 154 public static final String VIEW_GROUP = ContextEnum.GROUP_VIEW.getRequestContext(); 155 156 /** User wants to view or administer workflows. */ 157 public static final String WORKFLOW = ContextEnum.WIKI_WORKFLOW.getRequestContext(); 158 159 private static final Logger log = Logger.getLogger( WikiContext.class ); 160 161 private static final Permission DUMMY_PERMISSION = new PropertyPermission( "os.name", "read" ); 162 163 /** 164 * Create a new WikiContext for the given WikiPage. Delegates to {@link #WikiContext(Engine, HttpServletRequest, Page)}. 165 * 166 * @param engine The Engine that is handling the request. 167 * @param page The WikiPage. If you want to create a WikiContext for an older version of a page, you must use this constructor. 168 */ 169 public WikiContext( final Engine engine, final Page page ) { 170 this( engine, null, findCommand( engine, null, page ) ); 171 } 172 173 /** 174 * <p> 175 * Creates a new WikiContext for the given Engine, Command and HttpServletRequest. 176 * </p> 177 * <p> 178 * This constructor will also look up the HttpSession associated with the request, and determine if a Session object is present. 179 * If not, a new one is created. 180 * </p> 181 * @param engine The Engine that is handling the request 182 * @param request The HttpServletRequest that should be associated with this context. This parameter may be <code>null</code>. 183 * @param command the command 184 * @throws IllegalArgumentException if <code>engine</code> or <code>command</code> are <code>null</code> 185 */ 186 public WikiContext( final Engine engine, final HttpServletRequest request, final Command command ) throws IllegalArgumentException { 187 if ( engine == null || command == null ) { 188 throw new IllegalArgumentException( "Parameter engine and command must not be null." ); 189 } 190 191 m_engine = engine; 192 m_request = request; 193 m_session = Wiki.session().find( engine, request ); 194 m_command = command; 195 196 // If PageCommand, get the WikiPage 197 if( command instanceof PageCommand ) { 198 m_page = ( WikiPage )command.getTarget(); 199 } 200 201 // If page not supplied, default to front page to avoid NPEs 202 if( m_page == null ) { 203 m_page = ( WikiPage )m_engine.getManager( PageManager.class ).getPage( m_engine.getFrontPage() ); 204 205 // Front page does not exist? 206 if( m_page == null ) { 207 m_page = ( WikiPage )Wiki.contents().page( m_engine, m_engine.getFrontPage() ); 208 } 209 } 210 211 m_realPage = m_page; 212 213 // Special case: retarget any empty 'view' PageCommands to the front page 214 if ( PageCommand.VIEW.equals( command ) && command.getTarget() == null ) { 215 m_command = command.targetedCommand( m_page ); 216 } 217 218 // Debugging... 219 if( log.isDebugEnabled() ) { 220 final HttpSession session = ( request == null ) ? null : request.getSession( false ); 221 final String sid = session == null ? "(null)" : session.getId(); 222 log.debug( "Creating WikiContext for session ID=" + sid + "; target=" + getName() ); 223 } 224 225 // Figure out what template to use 226 setDefaultTemplate( request ); 227 } 228 229 /** 230 * Creates a new WikiContext for the given Engine, WikiPage and HttpServletRequest. This method simply looks up the appropriate 231 * Command using {@link #findCommand(Engine, HttpServletRequest, Page)} and delegates to 232 * {@link #WikiContext(Engine, HttpServletRequest, Command)}. 233 * 234 * @param engine The Engine that is handling the request 235 * @param request The HttpServletRequest that should be associated with this context. This parameter may be <code>null</code>. 236 * @param page The WikiPage. If you want to create a WikiContext for an older version of a page, you must supply this parameter 237 */ 238 public WikiContext( final Engine engine, final HttpServletRequest request, final Page page ) { 239 this( engine, request, findCommand( engine, request, page ) ); 240 } 241 242 /** 243 * Creates a new WikiContext from a supplied HTTP request, using a default wiki context. 244 * 245 * @param engine The Engine that is handling the request 246 * @param request the HTTP request 247 * @param requestContext the default context to use 248 * @see org.apache.wiki.ui.CommandResolver 249 * @see org.apache.wiki.api.core.Command 250 * @since 2.1.15. 251 */ 252 public WikiContext( final Engine engine, final HttpServletRequest request, final String requestContext ) { 253 this( engine, request, engine.getManager( CommandResolver.class ).findCommand( request, requestContext ) ); 254 if( !engine.isConfigured() ) { 255 throw new InternalWikiException( "Engine has not been properly started. It is likely that the configuration is faulty. Please check all logs for the possible reason." ); 256 } 257 } 258 259 /** 260 * {@inheritDoc} 261 * @see org.apache.wiki.api.core.Command#getContentTemplate() 262 */ 263 @Override 264 public String getContentTemplate() 265 { 266 return m_command.getContentTemplate(); 267 } 268 269 /** 270 * {@inheritDoc} 271 * @see org.apache.wiki.api.core.Command#getJSP() 272 */ 273 @Override 274 public String getJSP() 275 { 276 return m_command.getContentTemplate(); 277 } 278 279 /** 280 * Sets a reference to the real page whose content is currently being rendered. 281 * <p> 282 * Sometimes you may want to render the page using some other page's context. In those cases, it is highly recommended that you set 283 * the setRealPage() to point at the real page you are rendering. Please see InsertPageTag for an example. 284 * <p> 285 * Also, if your plugin e.g. does some variable setting, be aware that if it is embedded in the LeftMenu or some other page added 286 * with InsertPageTag, you should consider what you want to do - do you wish to really reference the "master" page or the included 287 * page. 288 * 289 * @param page The real page which is being rendered. 290 * @return The previous real page 291 * @since 2.3.14 292 * @see org.apache.wiki.tags.InsertPageTag 293 */ 294 @Override 295 public WikiPage setRealPage( final Page page ) { 296 final WikiPage old = m_realPage; 297 m_realPage = ( WikiPage )page; 298 updateCommand( m_command.getRequestContext() ); 299 return old; 300 } 301 302 /** 303 * Gets a reference to the real page whose content is currently being rendered. If your plugin e.g. does some variable setting, be 304 * aware that if it is embedded in the LeftMenu or some other page added with InsertPageTag, you should consider what you want to 305 * do - do you wish to really reference the "master" page or the included page. 306 * <p> 307 * For example, in the default template, there is a page called "LeftMenu". Whenever you access a page, e.g. "Main", the master 308 * page will be Main, and that's what the getPage() will return - regardless of whether your plugin resides on the LeftMenu or on 309 * the Main page. However, getRealPage() will return "LeftMenu". 310 * 311 * @return A reference to the real page. 312 * @see org.apache.wiki.tags.InsertPageTag 313 * @see org.apache.wiki.parser.JSPWikiMarkupParser 314 */ 315 @Override 316 public WikiPage getRealPage() 317 { 318 return m_realPage; 319 } 320 321 /** 322 * Figure out to which page we are really going to. Considers special page names from the jspwiki.properties, and possible aliases. 323 * This method forwards requests to {@link org.apache.wiki.ui.CommandResolver#getSpecialPageReference(String)}. 324 * @return A complete URL to the new page to redirect to 325 * @since 2.2 326 */ 327 @Override 328 public String getRedirectURL() { 329 final String pagename = m_page.getName(); 330 String redirURL = m_engine.getManager( CommandResolver.class ).getSpecialPageReference( pagename ); 331 if( redirURL == null ) { 332 final String alias = m_page.getAttribute( WikiPage.ALIAS ); 333 if( alias != null ) { 334 redirURL = getViewURL( alias ); 335 } else { 336 redirURL = m_page.getAttribute( WikiPage.REDIRECT ); 337 } 338 } 339 340 return redirURL; 341 } 342 343 /** 344 * Returns the handling engine. 345 * 346 * @return The engine owning this context. 347 */ 348 @Override 349 public WikiEngine getEngine() { 350 return ( WikiEngine )m_engine; 351 } 352 353 /** 354 * Returns the page that is being handled. 355 * 356 * @return the page which was fetched. 357 */ 358 @Override 359 public WikiPage getPage() 360 { 361 return m_page; 362 } 363 364 /** 365 * Sets the page that is being handled. 366 * 367 * @param page The wikipage 368 * @since 2.1.37. 369 */ 370 @Override 371 public void setPage( final Page page ) { 372 m_page = (WikiPage)page; 373 updateCommand( m_command.getRequestContext() ); 374 } 375 376 /** 377 * Returns the request context. 378 * 379 * @return The name of the request context (e.g. VIEW). 380 */ 381 @Override 382 public String getRequestContext() 383 { 384 return m_command.getRequestContext(); 385 } 386 387 /** 388 * Sets the request context. See above for the different request contexts (VIEW, EDIT, etc.) 389 * 390 * @param arg The request context (one of the predefined contexts.) 391 */ 392 @Override 393 public void setRequestContext( final String arg ) 394 { 395 updateCommand( arg ); 396 } 397 398 /** 399 * {@inheritDoc} 400 * @see org.apache.wiki.api.core.Command#getTarget() 401 */ 402 @Override 403 public Object getTarget() 404 { 405 return m_command.getTarget(); 406 } 407 408 /** 409 * {@inheritDoc} 410 * @see org.apache.wiki.api.core.Command#getURLPattern() 411 */ 412 @Override 413 public String getURLPattern() 414 { 415 return m_command.getURLPattern(); 416 } 417 418 /** 419 * Gets a previously set variable. 420 * 421 * @param key The variable name. 422 * @return The variable contents. 423 */ 424 @Override 425 @SuppressWarnings( "unchecked" ) 426 public < T > T getVariable( final String key ) { 427 return ( T )m_variableMap.get( key ); 428 } 429 430 /** 431 * Sets a variable. The variable is valid while the WikiContext is valid, i.e. while page processing continues. The variable data 432 * is discarded once the page processing is finished. 433 * 434 * @param key The variable name. 435 * @param data The variable value. 436 */ 437 @Override 438 public void setVariable( final String key, final Object data ) { 439 m_variableMap.put( key, data ); 440 updateCommand( m_command.getRequestContext() ); 441 } 442 443 /** 444 * This is just a simple helper method which will first check the context if there is already an override in place, and if there is not, 445 * it will then check the given properties. 446 * 447 * @param key What key are we searching for? 448 * @param defValue Default value for the boolean 449 * @return {@code true} or {@code false}. 450 */ 451 @Override 452 public boolean getBooleanWikiProperty( final String key, final boolean defValue ) { 453 final String bool = getVariable( key ); 454 if( bool != null ) { 455 return TextUtil.isPositive( bool ); 456 } 457 458 return TextUtil.getBooleanProperty( getEngine().getWikiProperties(), key, defValue ); 459 } 460 461 /** 462 * This method will safely return any HTTP parameters that might have been defined. You should use this method instead 463 * of peeking directly into the result of getHttpRequest(), since this method is smart enough to do all of the right things, 464 * figure out UTF-8 encoded parameters, etc. 465 * 466 * @since 2.0.13. 467 * @param paramName Parameter name to look for. 468 * @return HTTP parameter, or null, if no such parameter existed. 469 */ 470 @Override 471 public String getHttpParameter( final String paramName ) { 472 String result = null; 473 if( m_request != null ) { 474 result = m_request.getParameter( paramName ); 475 } 476 477 return result; 478 } 479 480 /** 481 * If the request did originate from a HTTP request, then the HTTP request can be fetched here. However, it the request 482 * did NOT originate from a HTTP request, then this method will return null, and YOU SHOULD CHECK FOR IT! 483 * 484 * @return Null, if no HTTP request was done. 485 * @since 2.0.13. 486 */ 487 @Override 488 public HttpServletRequest getHttpRequest() 489 { 490 return m_request; 491 } 492 493 /** 494 * Sets the template to be used for this request. 495 * 496 * @param dir The template name 497 * @since 2.1.15. 498 */ 499 @Override 500 public void setTemplate( final String dir ) 501 { 502 m_template = dir; 503 } 504 505 /** 506 * Returns the target of this wiki context: a page, group name or JSP. If the associated Command is a PageCommand, this method 507 * returns the page's name. Otherwise, this method delegates to the associated Command's {@link org.apache.wiki.api.core.Command#getName()} 508 * method. Calling classes can rely on the results of this method for looking up canonically-correct page or group names. Because it 509 * does not automatically assume that the wiki context is a PageCommand, calling this method is inherently safer than calling 510 * {@code getPage().getName()}. 511 * 512 * @return the name of the target of this wiki context 513 * @see org.apache.wiki.ui.PageCommand#getName() 514 * @see org.apache.wiki.ui.GroupCommand#getName() 515 */ 516 @Override 517 public String getName() { 518 if ( m_command instanceof PageCommand ) { 519 return m_page != null ? m_page.getName() : "<no page>"; 520 } 521 return m_command.getName(); 522 } 523 524 /** 525 * Gets the template that is to be used throughout this request. 526 * 527 * @since 2.1.15. 528 * @return template name 529 */ 530 @Override 531 public String getTemplate() 532 { 533 return m_template; 534 } 535 536 /** 537 * Convenience method that gets the current user. Delegates the lookup to the WikiSession associated with this WikiContect. 538 * May return null, in case the current user has not yet been determined; or this is an internal system. If the WikiSession has not 539 * been set, <em>always</em> returns null. 540 * 541 * @return The current user; or maybe null in case of internal calls. 542 */ 543 @Override 544 public Principal getCurrentUser() { 545 if (m_session == null) { 546 // This shouldn't happen, really... 547 return WikiPrincipal.GUEST; 548 } 549 return m_session.getUserPrincipal(); 550 } 551 552 /** 553 * A shortcut to generate a VIEW url. 554 * 555 * @param page The page to which to link. 556 * @return An URL to the page. This honours the current absolute/relative setting. 557 */ 558 @Override 559 public String getViewURL( final String page ) { 560 return getURL( ContextEnum.PAGE_VIEW.getRequestContext(), page, null ); 561 } 562 563 /** 564 * Creates an URL for the given request context. 565 * 566 * @param context e.g. WikiContext.EDIT 567 * @param page The page to which to link 568 * @return An URL to the page, honours the absolute/relative setting in jspwiki.properties 569 */ 570 @Override 571 public String getURL( final String context, final String page ) { 572 return getURL( context, page, null ); 573 } 574 575 /** 576 * Returns an URL from a page. It this WikiContext instance was constructed with an actual HttpServletRequest, we will attempt to 577 * construct the URL using HttpUtil, which preserves the HTTPS portion if it was used. 578 * 579 * @param context The request context (e.g. WikiContext.UPLOAD) 580 * @param page The page to which to link 581 * @param params A list of parameters, separated with "&" 582 * 583 * @return An URL to the given context and page. 584 */ 585 @Override 586 public String getURL( final String context, final String page, final String params ) { 587 // FIXME: is rather slow 588 return m_engine.getURL( context, page, params ); 589 } 590 591 /** 592 * Returns the Command associated with this WikiContext. 593 * 594 * @return the command 595 */ 596 public Command getCommand() { 597 return m_command; 598 } 599 600 /** 601 * Returns a shallow clone of the WikiContext. 602 * 603 * @since 2.1.37. 604 * @return A shallow clone of the WikiContext 605 */ 606 @Override 607 public WikiContext clone() { 608 try { 609 // super.clone() must always be called to make sure that inherited objects 610 // get the right type 611 final WikiContext copy = (WikiContext)super.clone(); 612 613 copy.m_engine = m_engine; 614 copy.m_command = m_command; 615 616 copy.m_template = m_template; 617 copy.m_variableMap = m_variableMap; 618 copy.m_request = m_request; 619 copy.m_session = m_session; 620 copy.m_page = m_page; 621 copy.m_realPage = m_realPage; 622 return copy; 623 } catch( final CloneNotSupportedException e ){} // Never happens 624 625 return null; 626 } 627 628 /** 629 * Creates a deep clone of the WikiContext. This is useful when you want to be sure that you don't accidentally mess with page 630 * attributes, etc. 631 * 632 * @since 2.8.0 633 * @return A deep clone of the WikiContext. 634 */ 635 @SuppressWarnings("unchecked") 636 public WikiContext deepClone() { 637 try { 638 // super.clone() must always be called to make sure that inherited objects 639 // get the right type 640 final WikiContext copy = (WikiContext)super.clone(); 641 642 // No need to deep clone these 643 copy.m_engine = m_engine; 644 copy.m_command = m_command; // Static structure 645 646 copy.m_template = m_template; 647 copy.m_variableMap = (HashMap<String,Object>)m_variableMap.clone(); 648 copy.m_request = m_request; 649 copy.m_session = m_session; 650 copy.m_page = m_page.clone(); 651 copy.m_realPage = m_realPage.clone(); 652 return copy; 653 } 654 catch( final CloneNotSupportedException e ){} // Never happens 655 656 return null; 657 } 658 659 /** 660 * Returns the Session associated with the context. This method is guaranteed to always return a valid Session. 661 * If this context was constructed without an associated HttpServletRequest, it will return 662 * {@link org.apache.wiki.WikiSession#guestSession(Engine)}. 663 * 664 * @return The Session associated with this context. 665 */ 666 @Override 667 public WikiSession getWikiSession() { 668 return ( WikiSession )m_session; 669 } 670 671 /** 672 * This method can be used to find the WikiContext programmatically from a JSP PageContext. We check the request context. 673 * The wiki context, if it exists, is looked up using the key {@link #ATTR_CONTEXT}. 674 * 675 * @since 2.4 676 * @param pageContext the JSP page context 677 * @return Current WikiContext, or null, of no context exists. 678 * @deprecated use {@link Context#findContext( PageContext )} instead. 679 * @see Context#findContext( PageContext ) 680 */ 681 @Deprecated 682 public static WikiContext findContext( final PageContext pageContext ) { 683 final HttpServletRequest request = ( HttpServletRequest )pageContext.getRequest(); 684 return ( WikiContext )request.getAttribute( ATTR_CONTEXT ); 685 } 686 687 /** 688 * Returns the permission required to successfully execute this context. For example, the a wiki context of VIEW for a certain page 689 * means that the PagePermission "view" is required for the page. In some cases, no particular permission is required, in which case 690 * a dummy permission will be returned ({@link java.util.PropertyPermission}<code> "os.name", "read"</code>). This method is guaranteed 691 * to always return a valid, non-null permission. 692 * 693 * @return the permission 694 * @since 2.4 695 */ 696 @Override 697 public Permission requiredPermission() { 698 // This is a filthy rotten hack -- absolutely putrid 699 if ( WikiCommand.INSTALL.equals( m_command ) ) { 700 // See if admin users exists 701 try { 702 final UserManager userMgr = m_engine.getManager( UserManager.class ); 703 final UserDatabase userDb = userMgr.getUserDatabase(); 704 userDb.findByLoginName( Installer.ADMIN_ID ); 705 } catch ( final NoSuchPrincipalException e ) { 706 return DUMMY_PERMISSION; 707 } 708 return new AllPermission( m_engine.getApplicationName() ); 709 } 710 711 // TODO: we should really break the contract so that this 712 // method returns null, but until then we will use this hack 713 if( m_command.requiredPermission() == null ) { 714 return DUMMY_PERMISSION; 715 } 716 717 return m_command.requiredPermission(); 718 } 719 720 /** 721 * Associates a target with the current Command and returns the new targeted Command. If the Command associated with this 722 * WikiContext is already "targeted", it is returned instead. 723 * 724 * @see org.apache.wiki.api.core.Command#targetedCommand(java.lang.Object) 725 * 726 * {@inheritDoc} 727 */ 728 @Override 729 public Command targetedCommand( final Object target ) { 730 if ( m_command.getTarget() == null ) { 731 return m_command.targetedCommand( target ); 732 } 733 return m_command; 734 } 735 736 /** 737 * Returns true, if the current user has administrative permissions (i.e. the omnipotent AllPermission). 738 * 739 * @since 2.4.46 740 * @return true, if the user has all permissions. 741 */ 742 @Override 743 public boolean hasAdminPermissions() { 744 return m_engine.getManager( AuthorizationManager.class ).checkPermission( getWikiSession(), new AllPermission( m_engine.getApplicationName() ) ); 745 } 746 747 /** 748 * Figures out which template a new WikiContext should be using. 749 * @param request the HTTP request 750 */ 751 protected void setDefaultTemplate( final HttpServletRequest request ) { 752 final String defaultTemplate = m_engine.getTemplateDir(); 753 754 // Figure out which template we should be using for this page. 755 String template = null; 756 if ( request != null ) { 757 final String skin = request.getParameter( "skin" ); 758 if( skin != null ) 759 { 760 template = skin.replaceAll("\\p{Punct}", ""); 761 } 762 763 } 764 765 // If request doesn't supply the value, extract from wiki page 766 if( template == null ) { 767 final WikiPage page = getPage(); 768 if ( page != null ) { 769 template = page.getAttribute( Engine.PROP_TEMPLATEDIR ); 770 } 771 772 } 773 774 // If something over-wrote the default, set the new value. 775 if ( template != null ) { 776 setTemplate( template ); 777 } else { 778 setTemplate( defaultTemplate ); 779 } 780 } 781 782 /** 783 * Looks up and returns a PageCommand based on a supplied WikiPage and HTTP request. First, the appropriate Command is obtained by 784 * examining the HTTP request; the default is {@link ContextEnum#PAGE_VIEW}. If the Command is a PageCommand (and it should be, in most 785 * cases), a targeted Command is created using the (non-<code>null</code>) WikiPage as target. 786 * 787 * @param engine the wiki engine 788 * @param request the HTTP request 789 * @param page the wiki page 790 * @return the correct command 791 */ 792 protected static Command findCommand( final Engine engine, final HttpServletRequest request, final Page page ) { 793 final String defaultContext = ContextEnum.PAGE_VIEW.getRequestContext(); 794 Command command = engine.getManager( CommandResolver.class ).findCommand( request, defaultContext ); 795 if ( command instanceof PageCommand && page != null ) { 796 command = command.targetedCommand( page ); 797 } 798 return command; 799 } 800 801 /** 802 * Protected method that updates the internally cached Command. Will always be called when the page name, request context, or variable 803 * changes. 804 * 805 * @param requestContext the desired request context 806 * @since 2.4 807 */ 808 protected void updateCommand( final String requestContext ) { 809 if ( requestContext == null ) { 810 m_command = PageCommand.NONE; 811 } else { 812 final CommandResolver resolver = m_engine.getManager( CommandResolver.class ); 813 m_command = resolver.findCommand( m_request, requestContext ); 814 } 815 816 if ( m_command instanceof PageCommand && m_page != null ) { 817 m_command = m_command.targetedCommand( m_page ); 818 } 819 } 820 821}