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 jakarta.servlet.http.HttpServletRequest; 044import jakarta.servlet.http.HttpSession; 045import jakarta.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 * Note: it is preferred to use the DSL API for creating a wiki context. 166 * Example: Wiki.contex().create( .. ) 167 * 168 * Create a new WikiContext for the given WikiPage. Delegates to {@link #WikiContext(Engine, HttpServletRequest, Page)}. 169 * 170 * @param engine The Engine that is handling the request. 171 * @param page The WikiPage. If you want to create a WikiContext for an older version of a page, you must use this constructor. 172 */ 173 public WikiContext( final Engine engine, final Page page ) { 174 this( engine, null, findCommand( engine, null, page ) ); 175 } 176 177 /** 178 * <p> 179 * Creates a new WikiContext for the given Engine, Command and HttpServletRequest. 180 * </p> 181 * Note: it is preferred to use the DSL API for creating a wiki context. 182 * Example: Wiki.contex().create( .. ) 183 * <p> 184 * This constructor will also look up the HttpSession associated with the request, and determine if a Session object is present. 185 * If not, a new one is created. 186 * </p> 187 * @param engine The Engine that is handling the request 188 * @param request The HttpServletRequest that should be associated with this context. This parameter may be <code>null</code>. 189 * @param command the command 190 * @throws IllegalArgumentException if <code>engine</code> or <code>command</code> are <code>null</code> 191 */ 192 public WikiContext( final Engine engine, final HttpServletRequest request, final Command command ) throws IllegalArgumentException { 193 if ( engine == null || command == null ) { 194 throw new IllegalArgumentException( "Parameter engine and command must not be null." ); 195 } 196 197 m_engine = engine; 198 m_request = request; 199 m_session = Wiki.session().find( engine, request ); 200 m_command = command; 201 202 // If PageCommand, get the WikiPage 203 if( command instanceof PageCommand ) { 204 m_page = ( WikiPage )command.getTarget(); 205 } 206 207 // If page not supplied, default to front page to avoid NPEs 208 if( m_page == null ) { 209 m_page = ( WikiPage )m_engine.getManager( PageManager.class ).getPage( m_engine.getFrontPage() ); 210 211 // Front page does not exist? 212 if( m_page == null ) { 213 m_page = ( WikiPage )Wiki.contents().page( m_engine, m_engine.getFrontPage() ); 214 } 215 } 216 217 m_realPage = m_page; 218 219 // Special case: retarget any empty 'view' PageCommands to the front page 220 if ( PageCommand.VIEW.equals( command ) && command.getTarget() == null ) { 221 m_command = command.targetedCommand( m_page ); 222 } 223 224 // Debugging... 225 final HttpSession session = ( request == null ) ? null : request.getSession( false ); 226 final String sid = session == null ? "(null)" : session.getId(); 227 LOG.debug( "Creating WikiContext for session ID={}; target={}", sid, getName() ); 228 229 // Figure out what template to use 230 setDefaultTemplate( request ); 231 } 232 233 /** 234 * Creates a new WikiContext for the given Engine, WikiPage and HttpServletRequest. This method simply looks up the appropriate 235 * Command using {@link #findCommand(Engine, HttpServletRequest, Page)} and delegates to 236 * {@link #WikiContext(Engine, HttpServletRequest, Command)}. 237 * 238 * Note: it is preferred to use the DSL API for creating a wiki context. 239 * Example: Wiki.contex().create( .. ) 240 * 241 * @param engine The Engine that is handling the request 242 * @param request The HttpServletRequest that should be associated with this context. This parameter may be <code>null</code>. 243 * @param page The WikiPage. If you want to create a WikiContext for an older version of a page, you must supply this parameter 244 */ 245 public WikiContext( final Engine engine, final HttpServletRequest request, final Page page ) { 246 this( engine, request, findCommand( engine, request, page ) ); 247 } 248 249 /** 250 * Creates a new WikiContext from a supplied HTTP request, using a default wiki context. 251 * 252 * Note: it is preferred to use the DSL API for creating a wiki context. 253 * Example: Wiki.contex().create( .. ) 254 * 255 * @param engine The Engine that is handling the request 256 * @param request the HTTP request 257 * @param requestContext the default context to use 258 * @see org.apache.wiki.ui.CommandResolver 259 * @see org.apache.wiki.api.core.Command 260 * @since 2.1.15. 261 */ 262 public WikiContext( final Engine engine, final HttpServletRequest request, final String requestContext ) { 263 this( engine, request, engine.getManager( CommandResolver.class ).findCommand( request, requestContext ) ); 264 if( !engine.isConfigured() ) { 265 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." ); 266 } 267 } 268 269 /** 270 * {@inheritDoc} 271 * @see org.apache.wiki.api.core.Command#getContentTemplate() 272 */ 273 @Override 274 public String getContentTemplate() 275 { 276 return m_command.getContentTemplate(); 277 } 278 279 /** 280 * {@inheritDoc} 281 * @see org.apache.wiki.api.core.Command#getJSP() 282 */ 283 @Override 284 public String getJSP() 285 { 286 return m_command.getContentTemplate(); 287 } 288 289 /** 290 * Sets a reference to the real page whose content is currently being rendered. 291 * <p> 292 * Sometimes you may want to render the page using some other page's context. In those cases, it is highly recommended that you set 293 * the setRealPage() to point at the real page you are rendering. Please see InsertPageTag for an example. 294 * <p> 295 * 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 296 * with InsertPageTag, you should consider what you want to do - do you wish to really reference the "master" page or the included 297 * page. 298 * 299 * @param page The real page which is being rendered. 300 * @return The previous real page 301 * @since 2.3.14 302 * @see org.apache.wiki.tags.InsertPageTag 303 */ 304 @Override 305 public WikiPage setRealPage( final Page page ) { 306 final WikiPage old = m_realPage; 307 m_realPage = ( WikiPage )page; 308 updateCommand( m_command.getRequestContext() ); 309 return old; 310 } 311 312 /** 313 * Gets a reference to the real page whose content is currently being rendered. If your plugin e.g. does some variable setting, be 314 * aware that if it is embedded in the LeftMenu or some other page added with InsertPageTag, you should consider what you want to 315 * do - do you wish to really reference the "master" page or the included page. 316 * <p> 317 * For example, in the default template, there is a page called "LeftMenu". Whenever you access a page, e.g. "Main", the master 318 * page will be Main, and that's what the getPage() will return - regardless of whether your plugin resides on the LeftMenu or on 319 * the Main page. However, getRealPage() will return "LeftMenu". 320 * 321 * @return A reference to the real page. 322 * @see org.apache.wiki.tags.InsertPageTag 323 * @see org.apache.wiki.parser.JSPWikiMarkupParser 324 */ 325 @Override 326 public WikiPage getRealPage() 327 { 328 return m_realPage; 329 } 330 331 /** 332 * Figure out to which page we are really going to. Considers special page names from the jspwiki.properties, and possible aliases. 333 * This method forwards requests to {@link org.apache.wiki.ui.CommandResolver#getSpecialPageReference(String)}. 334 * @return A complete URL to the new page to redirect to 335 * @since 2.2 336 */ 337 @Override 338 public String getRedirectURL() { 339 final String pagename = m_page.getName(); 340 String redirURL = m_engine.getManager( CommandResolver.class ).getSpecialPageReference( pagename ); 341 if( redirURL == null ) { 342 final String alias = m_page.getAttribute( WikiPage.ALIAS ); 343 if( alias != null ) { 344 redirURL = getViewURL( alias ); 345 } else { 346 redirURL = m_page.getAttribute( WikiPage.REDIRECT ); 347 } 348 } 349 350 return redirURL; 351 } 352 353 /** 354 * Returns the handling engine. 355 * 356 * @return The engine owning this context. 357 */ 358 @Override 359 public WikiEngine getEngine() { 360 return ( WikiEngine )m_engine; 361 } 362 363 /** 364 * Returns the page that is being handled. 365 * 366 * @return the page which was fetched. 367 */ 368 @Override 369 public WikiPage getPage() 370 { 371 return m_page; 372 } 373 374 /** 375 * Sets the page that is being handled. 376 * 377 * @param page The wikipage 378 * @since 2.1.37. 379 */ 380 @Override 381 public void setPage( final Page page ) { 382 m_page = (WikiPage)page; 383 updateCommand( m_command.getRequestContext() ); 384 } 385 386 /** 387 * Returns the request context. 388 * 389 * @return The name of the request context (e.g. VIEW). 390 */ 391 @Override 392 public String getRequestContext() 393 { 394 return m_command.getRequestContext(); 395 } 396 397 /** 398 * Sets the request context. See above for the different request contexts (VIEW, EDIT, etc.) 399 * 400 * @param arg The request context (one of the predefined contexts.) 401 */ 402 @Override 403 public void setRequestContext( final String arg ) 404 { 405 updateCommand( arg ); 406 } 407 408 /** 409 * {@inheritDoc} 410 * @see org.apache.wiki.api.core.Command#getTarget() 411 */ 412 @Override 413 public Object getTarget() 414 { 415 return m_command.getTarget(); 416 } 417 418 /** 419 * {@inheritDoc} 420 * @see org.apache.wiki.api.core.Command#getURLPattern() 421 */ 422 @Override 423 public String getURLPattern() 424 { 425 return m_command.getURLPattern(); 426 } 427 428 /** 429 * Gets a previously set variable. 430 * 431 * @param key The variable name. 432 * @return The variable contents. 433 */ 434 @Override 435 @SuppressWarnings( "unchecked" ) 436 public < T > T getVariable( final String key ) { 437 return ( T )m_variableMap.get( key ); 438 } 439 440 /** 441 * Sets a variable. The variable is valid while the WikiContext is valid, i.e. while page processing continues. The variable data 442 * is discarded once the page processing is finished. 443 * 444 * @param key The variable name. 445 * @param data The variable value. 446 */ 447 @Override 448 public void setVariable( final String key, final Object data ) { 449 m_variableMap.put( key, data ); 450 updateCommand( m_command.getRequestContext() ); 451 } 452 453 /** 454 * 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, 455 * it will then check the given properties. 456 * 457 * @param key What key are we searching for? 458 * @param defValue Default value for the boolean 459 * @return {@code true} or {@code false}. 460 */ 461 @Override 462 public boolean getBooleanWikiProperty( final String key, final boolean defValue ) { 463 final String bool = getVariable( key ); 464 if( bool != null ) { 465 return TextUtil.isPositive( bool ); 466 } 467 468 return TextUtil.getBooleanProperty( getEngine().getWikiProperties(), key, defValue ); 469 } 470 471 /** 472 * This method will safely return any HTTP parameters that might have been defined. You should use this method instead 473 * of peeking directly into the result of getHttpRequest(), since this method is smart enough to do all the right things, 474 * figure out UTF-8 encoded parameters, etc. 475 * 476 * @since 2.0.13. 477 * @param paramName Parameter name to look for. 478 * @return HTTP parameter, or null, if no such parameter existed. 479 */ 480 @Override 481 public String getHttpParameter( final String paramName ) { 482 String result = null; 483 if( m_request != null ) { 484 result = m_request.getParameter( paramName ); 485 } 486 487 return result; 488 } 489 490 /** 491 * If the request did originate from an HTTP request, then the HTTP request can be fetched here. However, if the request 492 * did NOT originate from an HTTP request, then this method will return null, and YOU SHOULD CHECK FOR IT! 493 * 494 * @return Null, if no HTTP request was done. 495 * @since 2.0.13. 496 */ 497 @Override 498 public HttpServletRequest getHttpRequest() 499 { 500 return m_request; 501 } 502 503 /** 504 * Sets the template to be used for this request. 505 * 506 * @param dir The template name 507 * @since 2.1.15. 508 */ 509 @Override 510 public void setTemplate( final String dir ) 511 { 512 m_template = dir; 513 } 514 515 /** 516 * Returns the target of this wiki context: a page, group name or JSP. If the associated Command is a PageCommand, this method 517 * returns the page's name. Otherwise, this method delegates to the associated Command's {@link org.apache.wiki.api.core.Command#getName()} 518 * method. Calling classes can rely on the results of this method for looking up canonically-correct page or group names. Because it 519 * does not automatically assume that the wiki context is a PageCommand, calling this method is inherently safer than calling 520 * {@code getPage().getName()}. 521 * 522 * @return the name of the target of this wiki context 523 * @see org.apache.wiki.ui.PageCommand#getName() 524 * @see org.apache.wiki.ui.GroupCommand#getName() 525 */ 526 @Override 527 public String getName() { 528 if ( m_command instanceof PageCommand ) { 529 return m_page != null ? m_page.getName() : "<no page>"; 530 } 531 return m_command.getName(); 532 } 533 534 /** 535 * Gets the template that is to be used throughout this request. 536 * 537 * @since 2.1.15. 538 * @return template name 539 */ 540 @Override 541 public String getTemplate() 542 { 543 return m_template; 544 } 545 546 /** 547 * Convenience method that gets the current user. Delegates the lookup to the WikiSession associated with this WikiContect. 548 * May return null, in case the current user has not yet been determined; or this is an internal system. If the WikiSession has not 549 * been set, <em>always</em> returns null. 550 * 551 * @return The current user; or maybe null in case of internal calls. 552 */ 553 @Override 554 public Principal getCurrentUser() { 555 if (m_session == null) { 556 // This shouldn't happen, really... 557 return WikiPrincipal.GUEST; 558 } 559 return m_session.getLoginPrincipal(); 560 } 561 562 /** 563 * A shortcut to generate a VIEW url. 564 * 565 * @param page The page to which to link. 566 * @return A URL to the page. This honours the current absolute/relative setting. 567 */ 568 @Override 569 public String getViewURL( final String page ) { 570 return getURL( ContextEnum.PAGE_VIEW.getRequestContext(), page, null ); 571 } 572 573 /** 574 * Creates a URL for the given request context. 575 * 576 * @param context e.g. WikiContext.EDIT 577 * @param page The page to which to link 578 * @return A URL to the page, honours the absolute/relative setting in jspwiki.properties 579 */ 580 @Override 581 public String getURL( final String context, final String page ) { 582 return getURL( context, page, null ); 583 } 584 585 /** 586 * Returns a URL from a page. It this WikiContext instance was constructed with an actual HttpServletRequest, we will attempt to 587 * construct the URL using HttpUtil, which preserves the HTTPS portion if it was used. 588 * 589 * @param context The request context (e.g. WikiContext.UPLOAD) 590 * @param page The page to which to link 591 * @param params A list of parameters, separated with "&" 592 * 593 * @return A URL to the given context and page. 594 */ 595 @Override 596 public String getURL( final String context, final String page, final String params ) { 597 // FIXME: is rather slow 598 return m_engine.getURL( context, page, params ); 599 } 600 601 /** 602 * Returns the Command associated with this WikiContext. 603 * 604 * @return the command 605 */ 606 @Override 607 public Command getCommand() { 608 return m_command; 609 } 610 611 /** 612 * Returns a shallow clone of the WikiContext. 613 * 614 * @since 2.1.37. 615 * @return A shallow clone of the WikiContext 616 */ 617 @Override 618 public WikiContext clone() { 619 try { 620 // super.clone() must always be called to make sure that inherited objects 621 // get the right type 622 final WikiContext copy = (WikiContext)super.clone(); 623 624 copy.m_engine = m_engine; 625 copy.m_command = m_command; 626 627 copy.m_template = m_template; 628 copy.m_variableMap = m_variableMap; 629 copy.m_request = m_request; 630 copy.m_session = m_session; 631 copy.m_page = m_page; 632 copy.m_realPage = m_realPage; 633 return copy; 634 } catch( final CloneNotSupportedException e ){ 635 // Never happens 636 LOG.debug(e.getMessage(), e); 637 } 638 639 return null; 640 } 641 642 /** 643 * Creates a deep clone of the WikiContext. This is useful when you want to be sure that you don't accidentally mess with page 644 * attributes, etc. 645 * 646 * @since 2.8.0 647 * @return A deep clone of the WikiContext. 648 */ 649 @Override 650 @SuppressWarnings("unchecked") 651 public WikiContext deepClone() { 652 try { 653 // super.clone() must always be called to make sure that inherited objects 654 // get the right type 655 final WikiContext copy = (WikiContext)super.clone(); 656 657 // No need to deep clone these 658 copy.m_engine = m_engine; 659 copy.m_command = m_command; // Static structure 660 661 copy.m_template = m_template; 662 copy.m_variableMap = (HashMap<String,Object>)m_variableMap.clone(); 663 copy.m_request = m_request; 664 copy.m_session = m_session; 665 copy.m_page = m_page.clone(); 666 copy.m_realPage = m_realPage.clone(); 667 return copy; 668 } 669 catch( final CloneNotSupportedException e ){ 670 LOG.debug(e.getMessage(), e); 671 // Never happens 672 } 673 674 return null; 675 } 676 677 /** 678 * Returns the Session associated with the context. This method is guaranteed to always return a valid Session. 679 * If this context was constructed without an associated HttpServletRequest, it will return 680 * {@link org.apache.wiki.WikiSession#guestSession(Engine)}. 681 * 682 * @return The Session associated with this context. 683 */ 684 @Override 685 public WikiSession getWikiSession() { 686 return ( WikiSession )m_session; 687 } 688 689 /** 690 * This method can be used to find the WikiContext programmatically from a JSP PageContext. We check the request context. 691 * The wiki context, if it exists, is looked up using the key {@link #ATTR_CONTEXT}. 692 * 693 * @since 2.4 694 * @param pageContext the JSP page context 695 * @return Current WikiContext, or null, of no context exists. 696 * @deprecated use {@link Context#findContext( PageContext )} instead. 697 * @see Context#findContext( PageContext ) 698 */ 699 @Deprecated 700 public static WikiContext findContext( final PageContext pageContext ) { 701 final HttpServletRequest request = ( HttpServletRequest )pageContext.getRequest(); 702 return ( WikiContext )request.getAttribute( ATTR_CONTEXT ); 703 } 704 705 /** 706 * Returns the permission required to successfully execute this context. For example, a wiki context of VIEW for a certain page 707 * means that the PagePermission "view" is required for the page. In some cases, no particular permission is required, in which case 708 * a dummy permission will be returned ({@link java.util.PropertyPermission}<code> "os.name", "read"</code>). This method is guaranteed 709 * to always return a valid, non-null permission. 710 * 711 * @return the permission 712 * @since 2.4 713 */ 714 @Override 715 public Permission requiredPermission() { 716 // This is a filthy rotten hack -- absolutely putrid 717 if ( WikiCommand.INSTALL.equals( m_command ) ) { 718 // See if admin users exists 719 try { 720 final UserManager userMgr = m_engine.getManager( UserManager.class ); 721 final UserDatabase userDb = userMgr.getUserDatabase(); 722 userDb.findByLoginName( Installer.ADMIN_ID ); 723 } catch ( final NoSuchPrincipalException e ) { 724 return DUMMY_PERMISSION; 725 } 726 return new AllPermission( m_engine.getApplicationName() ); 727 } 728 729 // TODO: we should really break the contract so that this 730 // method returns null, but until then we will use this hack 731 if( m_command.requiredPermission() == null ) { 732 return DUMMY_PERMISSION; 733 } 734 735 return m_command.requiredPermission(); 736 } 737 738 /** 739 * Associates a target with the current Command and returns the new targeted Command. If the Command associated with this 740 * WikiContext is already "targeted", it is returned instead. 741 * 742 * @see org.apache.wiki.api.core.Command#targetedCommand(java.lang.Object) 743 * 744 * {@inheritDoc} 745 */ 746 @Override 747 public Command targetedCommand( final Object target ) { 748 if ( m_command.getTarget() == null ) { 749 return m_command.targetedCommand( target ); 750 } 751 return m_command; 752 } 753 754 /** 755 * Returns true, if the current user has administrative permissions (i.e. the omnipotent AllPermission). 756 * 757 * @since 2.4.46 758 * @return true, if the user has all permissions. 759 */ 760 @Override 761 public boolean hasAdminPermissions() { 762 return m_engine.getManager( AuthorizationManager.class ).checkPermission( getWikiSession(), new AllPermission( m_engine.getApplicationName() ) ); 763 } 764 765 /** 766 * Figures out which template a new WikiContext should be using. 767 * @param request the HTTP request 768 */ 769 protected void setDefaultTemplate( final HttpServletRequest request ) { 770 final String defaultTemplate = m_engine.getTemplateDir(); 771 772 // Figure out which template we should be using for this page. 773 String template = null; 774 if ( request != null ) { 775 final String skin = request.getParameter( "skin" ); 776 if( skin != null ) 777 { 778 template = skin.replaceAll("\\p{Punct}", ""); 779 } 780 781 } 782 783 // If request doesn't supply the value, extract from wiki page 784 if( template == null ) { 785 final WikiPage page = getPage(); 786 if ( page != null ) { 787 template = page.getAttribute( Engine.PROP_TEMPLATEDIR ); 788 } 789 790 } 791 792 // If something over-wrote the default, set the new value. 793 if ( template != null ) { 794 setTemplate( template ); 795 } else { 796 setTemplate( defaultTemplate ); 797 } 798 } 799 800 /** 801 * Looks up and returns a PageCommand based on a supplied WikiPage and HTTP request. First, the appropriate Command is obtained by 802 * examining the HTTP request; the default is {@link ContextEnum#PAGE_VIEW}. If the Command is a PageCommand (and it should be, in most 803 * cases), a targeted Command is created using the (non-<code>null</code>) WikiPage as target. 804 * 805 * @param engine the wiki engine 806 * @param request the HTTP request 807 * @param page the wiki page 808 * @return the correct command 809 */ 810 protected static Command findCommand( final Engine engine, final HttpServletRequest request, final Page page ) { 811 final String defaultContext = ContextEnum.PAGE_VIEW.getRequestContext(); 812 Command command = engine.getManager( CommandResolver.class ).findCommand( request, defaultContext ); 813 if ( command instanceof PageCommand && page != null ) { 814 command = command.targetedCommand( page ); 815 } 816 return command; 817 } 818 819 /** 820 * Protected method that updates the internally cached Command. Will always be called when the page name, request context, or variable 821 * changes. 822 * 823 * @param requestContext the desired request context 824 * @since 2.4 825 */ 826 protected void updateCommand( final String requestContext ) { 827 if ( requestContext == null ) { 828 m_command = PageCommand.NONE; 829 } else { 830 final CommandResolver resolver = m_engine.getManager( CommandResolver.class ); 831 m_command = resolver.findCommand( m_request, requestContext ); 832 } 833 834 if ( m_command instanceof PageCommand && m_page != null ) { 835 m_command = m_command.targetedCommand( m_page ); 836 } 837 } 838 839}