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 public Command getCommand() { 596 return m_command; 597 } 598 599 /** 600 * Returns a shallow clone of the WikiContext. 601 * 602 * @since 2.1.37. 603 * @return A shallow clone of the WikiContext 604 */ 605 @Override 606 public WikiContext clone() { 607 try { 608 // super.clone() must always be called to make sure that inherited objects 609 // get the right type 610 final WikiContext copy = (WikiContext)super.clone(); 611 612 copy.m_engine = m_engine; 613 copy.m_command = m_command; 614 615 copy.m_template = m_template; 616 copy.m_variableMap = m_variableMap; 617 copy.m_request = m_request; 618 copy.m_session = m_session; 619 copy.m_page = m_page; 620 copy.m_realPage = m_realPage; 621 return copy; 622 } catch( final CloneNotSupportedException e ){} // Never happens 623 624 return null; 625 } 626 627 /** 628 * Creates a deep clone of the WikiContext. This is useful when you want to be sure that you don't accidentally mess with page 629 * attributes, etc. 630 * 631 * @since 2.8.0 632 * @return A deep clone of the WikiContext. 633 */ 634 @SuppressWarnings("unchecked") 635 public WikiContext deepClone() { 636 try { 637 // super.clone() must always be called to make sure that inherited objects 638 // get the right type 639 final WikiContext copy = (WikiContext)super.clone(); 640 641 // No need to deep clone these 642 copy.m_engine = m_engine; 643 copy.m_command = m_command; // Static structure 644 645 copy.m_template = m_template; 646 copy.m_variableMap = (HashMap<String,Object>)m_variableMap.clone(); 647 copy.m_request = m_request; 648 copy.m_session = m_session; 649 copy.m_page = m_page.clone(); 650 copy.m_realPage = m_realPage.clone(); 651 return copy; 652 } 653 catch( final CloneNotSupportedException e ){} // Never happens 654 655 return null; 656 } 657 658 /** 659 * Returns the Session associated with the context. This method is guaranteed to always return a valid Session. 660 * If this context was constructed without an associated HttpServletRequest, it will return 661 * {@link org.apache.wiki.WikiSession#guestSession(Engine)}. 662 * 663 * @return The Session associated with this context. 664 */ 665 @Override 666 public WikiSession getWikiSession() { 667 return ( WikiSession )m_session; 668 } 669 670 /** 671 * This method can be used to find the WikiContext programmatically from a JSP PageContext. We check the request context. 672 * The wiki context, if it exists, is looked up using the key {@link #ATTR_CONTEXT}. 673 * 674 * @since 2.4 675 * @param pageContext the JSP page context 676 * @return Current WikiContext, or null, of no context exists. 677 * @deprecated use {@link Context#findContext( PageContext )} instead. 678 * @see Context#findContext( PageContext ) 679 */ 680 @Deprecated 681 public static WikiContext findContext( final PageContext pageContext ) { 682 final HttpServletRequest request = ( HttpServletRequest )pageContext.getRequest(); 683 return ( WikiContext )request.getAttribute( ATTR_CONTEXT ); 684 } 685 686 /** 687 * Returns the permission required to successfully execute this context. For example, a wiki context of VIEW for a certain page 688 * means that the PagePermission "view" is required for the page. In some cases, no particular permission is required, in which case 689 * a dummy permission will be returned ({@link java.util.PropertyPermission}<code> "os.name", "read"</code>). This method is guaranteed 690 * to always return a valid, non-null permission. 691 * 692 * @return the permission 693 * @since 2.4 694 */ 695 @Override 696 public Permission requiredPermission() { 697 // This is a filthy rotten hack -- absolutely putrid 698 if ( WikiCommand.INSTALL.equals( m_command ) ) { 699 // See if admin users exists 700 try { 701 final UserManager userMgr = m_engine.getManager( UserManager.class ); 702 final UserDatabase userDb = userMgr.getUserDatabase(); 703 userDb.findByLoginName( Installer.ADMIN_ID ); 704 } catch ( final NoSuchPrincipalException e ) { 705 return DUMMY_PERMISSION; 706 } 707 return new AllPermission( m_engine.getApplicationName() ); 708 } 709 710 // TODO: we should really break the contract so that this 711 // method returns null, but until then we will use this hack 712 if( m_command.requiredPermission() == null ) { 713 return DUMMY_PERMISSION; 714 } 715 716 return m_command.requiredPermission(); 717 } 718 719 /** 720 * Associates a target with the current Command and returns the new targeted Command. If the Command associated with this 721 * WikiContext is already "targeted", it is returned instead. 722 * 723 * @see org.apache.wiki.api.core.Command#targetedCommand(java.lang.Object) 724 * 725 * {@inheritDoc} 726 */ 727 @Override 728 public Command targetedCommand( final Object target ) { 729 if ( m_command.getTarget() == null ) { 730 return m_command.targetedCommand( target ); 731 } 732 return m_command; 733 } 734 735 /** 736 * Returns true, if the current user has administrative permissions (i.e. the omnipotent AllPermission). 737 * 738 * @since 2.4.46 739 * @return true, if the user has all permissions. 740 */ 741 @Override 742 public boolean hasAdminPermissions() { 743 return m_engine.getManager( AuthorizationManager.class ).checkPermission( getWikiSession(), new AllPermission( m_engine.getApplicationName() ) ); 744 } 745 746 /** 747 * Figures out which template a new WikiContext should be using. 748 * @param request the HTTP request 749 */ 750 protected void setDefaultTemplate( final HttpServletRequest request ) { 751 final String defaultTemplate = m_engine.getTemplateDir(); 752 753 // Figure out which template we should be using for this page. 754 String template = null; 755 if ( request != null ) { 756 final String skin = request.getParameter( "skin" ); 757 if( skin != null ) 758 { 759 template = skin.replaceAll("\\p{Punct}", ""); 760 } 761 762 } 763 764 // If request doesn't supply the value, extract from wiki page 765 if( template == null ) { 766 final WikiPage page = getPage(); 767 if ( page != null ) { 768 template = page.getAttribute( Engine.PROP_TEMPLATEDIR ); 769 } 770 771 } 772 773 // If something over-wrote the default, set the new value. 774 if ( template != null ) { 775 setTemplate( template ); 776 } else { 777 setTemplate( defaultTemplate ); 778 } 779 } 780 781 /** 782 * Looks up and returns a PageCommand based on a supplied WikiPage and HTTP request. First, the appropriate Command is obtained by 783 * examining the HTTP request; the default is {@link ContextEnum#PAGE_VIEW}. If the Command is a PageCommand (and it should be, in most 784 * cases), a targeted Command is created using the (non-<code>null</code>) WikiPage as target. 785 * 786 * @param engine the wiki engine 787 * @param request the HTTP request 788 * @param page the wiki page 789 * @return the correct command 790 */ 791 protected static Command findCommand( final Engine engine, final HttpServletRequest request, final Page page ) { 792 final String defaultContext = ContextEnum.PAGE_VIEW.getRequestContext(); 793 Command command = engine.getManager( CommandResolver.class ).findCommand( request, defaultContext ); 794 if ( command instanceof PageCommand && page != null ) { 795 command = command.targetedCommand( page ); 796 } 797 return command; 798 } 799 800 /** 801 * Protected method that updates the internally cached Command. Will always be called when the page name, request context, or variable 802 * changes. 803 * 804 * @param requestContext the desired request context 805 * @since 2.4 806 */ 807 protected void updateCommand( final String requestContext ) { 808 if ( requestContext == null ) { 809 m_command = PageCommand.NONE; 810 } else { 811 final CommandResolver resolver = m_engine.getManager( CommandResolver.class ); 812 m_command = resolver.findCommand( m_request, requestContext ); 813 } 814 815 if ( m_command instanceof PageCommand && m_page != null ) { 816 m_command = m_command.targetedCommand( m_page ); 817 } 818 } 819 820}