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