[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/aphront/response/ -> AphrontRedirectResponse.php (source)

   1  <?php
   2  
   3  /**
   4   * TODO: Should be final but isn't because of AphrontReloadResponse.
   5   */
   6  class AphrontRedirectResponse extends AphrontResponse {
   7  
   8    private $uri;
   9    private $stackWhenCreated;
  10    private $isExternal;
  11  
  12    public function setIsExternal($external) {
  13      $this->isExternal = $external;
  14      return $this;
  15    }
  16  
  17    public function __construct() {
  18      if ($this->shouldStopForDebugging()) {
  19        // If we're going to stop, capture the stack so we can print it out.
  20        $this->stackWhenCreated = id(new Exception())->getTrace();
  21      }
  22    }
  23  
  24    public function setURI($uri) {
  25      $this->uri = $uri;
  26      return $this;
  27    }
  28  
  29    public function getURI() {
  30      // NOTE: When we convert a RedirectResponse into an AjaxResponse, we pull
  31      // the URI through this method. Make sure it passes checks before we
  32      // hand it over to callers.
  33      return self::getURIForRedirect($this->uri, $this->isExternal);
  34    }
  35  
  36    public function shouldStopForDebugging() {
  37      return PhabricatorEnv::getEnvConfig('debug.stop-on-redirect');
  38    }
  39  
  40    public function getHeaders() {
  41      $headers = array();
  42      if (!$this->shouldStopForDebugging()) {
  43        $uri = self::getURIForRedirect($this->uri, $this->isExternal);
  44        $headers[] = array('Location', $uri);
  45      }
  46      $headers = array_merge(parent::getHeaders(), $headers);
  47      return $headers;
  48    }
  49  
  50    public function buildResponseString() {
  51      if ($this->shouldStopForDebugging()) {
  52        $request = $this->getRequest();
  53        $viewer = $request->getUser();
  54  
  55        $view = new PhabricatorStandardPageView();
  56        $view->setRequest($this->getRequest());
  57        $view->setApplicationName(pht('Debug'));
  58        $view->setTitle(pht('Stopped on Redirect'));
  59  
  60        $dialog = new AphrontDialogView();
  61        $dialog->setUser($viewer);
  62        $dialog->setTitle(pht('Stopped on Redirect'));
  63  
  64        $dialog->appendParagraph(
  65          pht(
  66            'You were stopped here because %s is set in your configuration.',
  67            phutil_tag('tt', array(), 'debug.stop-on-redirect')));
  68  
  69        $dialog->appendParagraph(
  70          pht(
  71            'You are being redirected to: %s',
  72            phutil_tag('tt', array(), $this->getURI())));
  73  
  74        $dialog->addCancelButton($this->getURI(), pht('Continue'));
  75  
  76        $dialog->appendChild(phutil_tag('br'));
  77  
  78        $dialog->appendChild(
  79          id(new AphrontStackTraceView())
  80            ->setUser($viewer)
  81            ->setTrace($this->stackWhenCreated));
  82  
  83        $dialog->setIsStandalone(true);
  84        $dialog->setWidth(AphrontDialogView::WIDTH_FULL);
  85  
  86        $box = id(new PHUIBoxView())
  87          ->addMargin(PHUI::MARGIN_LARGE)
  88          ->appendChild($dialog);
  89  
  90        $view->appendChild($box);
  91  
  92        return $view->render();
  93      }
  94  
  95      return '';
  96    }
  97  
  98  
  99    /**
 100     * Format a URI for use in a "Location:" header.
 101     *
 102     * Verifies that a URI redirects to the expected type of resource (local or
 103     * remote) and formats it for use in a "Location:" header.
 104     *
 105     * The HTTP spec says "Location:" headers must use absolute URIs. Although
 106     * browsers work with relative URIs, we return absolute URIs to avoid
 107     * ambiguity. For example, Chrome interprets "Location: /\evil.com" to mean
 108     * "perform a protocol-relative redirect to evil.com".
 109     *
 110     * @param   string  URI to redirect to.
 111     * @param   bool    True if this URI identifies a remote resource.
 112     * @return  string  URI for use in a "Location:" header.
 113     */
 114    public static function getURIForRedirect($uri, $is_external) {
 115      $uri_object = new PhutilURI($uri);
 116      if ($is_external) {
 117        // If this is a remote resource it must have a domain set. This
 118        // would also be caught below, but testing for it explicitly first allows
 119        // us to raise a better error message.
 120        if (!strlen($uri_object->getDomain())) {
 121          throw new Exception(
 122            pht(
 123              'Refusing to redirect to external URI "%s". This URI '.
 124              'is not fully qualified, and is missing a domain name. To '.
 125              'redirect to a local resource, remove the external flag.',
 126              (string)$uri));
 127        }
 128  
 129        // Check that it's a valid remote resource.
 130        if (!PhabricatorEnv::isValidRemoteWebResource($uri)) {
 131          throw new Exception(
 132            pht(
 133              'Refusing to redirect to external URI "%s". This URI '.
 134              'is not a valid remote web resource.',
 135              (string)$uri));
 136        }
 137      } else {
 138        // If this is a local resource, it must not have a domain set. This allows
 139        // us to raise a better error message than the check below can.
 140        if (strlen($uri_object->getDomain())) {
 141          throw new Exception(
 142            pht(
 143              'Refusing to redirect to local resource "%s". The URI has a '.
 144              'domain, but the redirect is not marked external. Mark '.
 145              'redirects as external to allow redirection off the local '.
 146              'domain.',
 147              (string)$uri));
 148        }
 149  
 150        // If this is a local resource, it must be a valid local resource.
 151        if (!PhabricatorEnv::isValidLocalWebResource($uri)) {
 152          throw new Exception(
 153            pht(
 154              'Refusing to redirect to local resource "%s". This URI is not '.
 155              'formatted in a recognizable way.',
 156              (string)$uri));
 157        }
 158  
 159        // Fully qualify the result URI.
 160        $uri = PhabricatorEnv::getURI((string)$uri);
 161      }
 162  
 163      return (string)$uri;
 164    }
 165  
 166  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1