/**
  * @phutil-external-symbol class PhabricatorStartup
  */
 public function buildRequest()
 {
     $parser = new PhutilQueryStringParser();
     $data = array();
     // If the request has "multipart/form-data" content, we can't use
     // PhutilQueryStringParser to parse it, and the raw data supposedly is not
     // available anyway (according to the PHP documentation, "php://input" is
     // not available for "multipart/form-data" requests). However, it is
     // available at least some of the time (see T3673), so double check that
     // we aren't trying to parse data we won't be able to parse correctly by
     // examining the Content-Type header.
     $content_type = idx($_SERVER, 'CONTENT_TYPE');
     $is_form_data = preg_match('@^multipart/form-data@i', $content_type);
     $raw_input = PhabricatorStartup::getRawInput();
     if (strlen($raw_input) && !$is_form_data) {
         $data += $parser->parseQueryString($raw_input);
     } else {
         if ($_POST) {
             $data += $_POST;
         }
     }
     $data += $parser->parseQueryString(idx($_SERVER, 'QUERY_STRING', ''));
     $cookie_prefix = PhabricatorEnv::getEnvConfig('phabricator.cookie-prefix');
     $request = new AphrontRequest($this->getHost(), $this->getPath());
     $request->setRequestData($data);
     $request->setApplicationConfiguration($this);
     $request->setCookiePrefix($cookie_prefix);
     return $request;
 }
 /**
  * @phutil-external-symbol class PhabricatorStartup
  */
 public function handleRequest(AphrontRequest $request)
 {
     $raw_body = PhabricatorStartup::getRawInput();
     $body = phutil_json_decode($raw_body);
     $payload = $body['payload'];
     $parameters = idx($payload, 'build_parameters');
     if (!$parameters) {
         $parameters = array();
     }
     $target_phid = idx($parameters, 'HARBORMASTER_BUILD_TARGET_PHID');
     // NOTE: We'll get callbacks here for builds we triggered, but also for
     // arbitrary builds the system executes for other reasons. So it's normal
     // to get some notifications with no Build Target PHID. We just ignore
     // these under the assumption that they're routine builds caused by events
     // like branch updates.
     if ($target_phid) {
         $viewer = PhabricatorUser::getOmnipotentUser();
         $target = id(new HarbormasterBuildTargetQuery())->setViewer($viewer)->withPHIDs(array($target_phid))->needBuildSteps(true)->executeOne();
         if ($target) {
             $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
             $this->updateTarget($target, $payload);
         }
     }
     $response = new AphrontWebpageResponse();
     $response->setContent(pht("Request OK\n"));
     return $response;
 }
 /**
  * @phutil-external-symbol class PhabricatorStartup
  */
 protected function executeChecks()
 {
     $upload_limit = PhabricatorEnv::getEnvConfig('storage.upload-size-limit');
     if (!$upload_limit) {
         $message = pht('The Phabricator file upload limit is not configured. You may only ' . 'be able to upload very small files until you configure it, because ' . 'some PHP default limits are very low (as low as 2MB).');
         $this->newIssue('config.storage.upload-size-limit')->setShortName(pht('Upload Limit'))->setName(pht('Upload Limit Not Yet Configured'))->setMessage($message)->addPhabricatorConfig('storage.upload-size-limit');
     } else {
         $memory_limit = PhabricatorStartup::getOldMemoryLimit();
         if ($memory_limit && (int) $memory_limit > 0) {
             $memory_limit_bytes = phutil_parse_bytes($memory_limit);
             $memory_usage_bytes = memory_get_usage();
             $upload_limit_bytes = phutil_parse_bytes($upload_limit);
             $available_bytes = $memory_limit_bytes - $memory_usage_bytes;
             if ($upload_limit_bytes > $available_bytes) {
                 $summary = pht('Your PHP memory limit is configured in a way that may prevent ' . 'you from uploading large files.');
                 $message = pht('When you upload a file via drag-and-drop or the API, the entire ' . 'file is buffered into memory before being written to permanent ' . 'storage. Phabricator needs memory available to store these ' . 'files while they are uploaded, but PHP is currently configured ' . 'to limit the available memory.' . "\n\n" . 'Your Phabricator %s is currently set to a larger value (%s) than ' . 'the amount of available memory (%s) that a PHP process has ' . 'available to use, so uploads via drag-and-drop and the API will ' . 'hit the memory limit before they hit other limits.' . "\n\n" . '(Note that the application itself must also fit in available ' . 'memory, so not all of the memory under the memory limit is ' . 'available for buffering file uploads.)' . "\n\n" . "The easiest way to resolve this issue is to set %s to %s in your " . "PHP configuration, to disable the memory limit. There is " . "usually little or no value to using this option to limit " . "Phabricator process memory." . "\n\n" . "You can also increase the limit, or decrease %s, or ignore this " . "issue and accept that these upload mechanisms will be limited " . "in the size of files they can handle.", phutil_tag('tt', array(), 'storage.upload-size-limit'), phutil_format_bytes($upload_limit_bytes), phutil_format_bytes($available_bytes), phutil_tag('tt', array(), 'memory_limit'), phutil_tag('tt', array(), '-1'), phutil_tag('tt', array(), 'storage.upload-size-limit'));
                 $this->newIssue('php.memory_limit.upload')->setName(pht('Memory Limit Restricts File Uploads'))->setSummary($summary)->setMessage($message)->addPHPConfig('memory_limit')->addPHPConfigOriginalValue('memory_limit', $memory_limit)->addPhabricatorConfig('storage.upload-size-limit');
             }
         }
     }
     $local_path = PhabricatorEnv::getEnvConfig('storage.local-disk.path');
     if (!$local_path) {
         return;
     }
     if (!Filesystem::pathExists($local_path) || !is_readable($local_path) || !is_writable($local_path)) {
         $message = pht('Configured location for storing uploaded files on disk ("%s") does ' . 'not exist, or is not readable or writable. Verify the directory ' . 'exists and is readable and writable by the webserver.', $local_path);
         $this->newIssue('config.storage.local-disk.path')->setShortName(pht('Local Disk Storage'))->setName(pht('Local Disk Storage Not Readable/Writable'))->setMessage($message)->addPhabricatorConfig('storage.local-disk.path');
     }
 }
 /**
  * @phutil-external-symbol class PhabricatorStartup
  */
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     // NOTE: Throws if valid CSRF token is not present in the request.
     $request->validateCSRF();
     $name = $request->getStr('name');
     $file_phid = $request->getStr('phid');
     // If there's no explicit view policy, make it very restrictive by default.
     // This is the correct policy for files dropped onto objects during
     // creation, comment and edit flows.
     $view_policy = $request->getStr('viewPolicy');
     if (!$view_policy) {
         $view_policy = $viewer->getPHID();
     }
     $is_chunks = $request->getBool('querychunks');
     if ($is_chunks) {
         $params = array('filePHID' => $file_phid);
         $result = id(new ConduitCall('file.querychunks', $params))->setUser($viewer)->execute();
         return id(new AphrontAjaxResponse())->setContent($result);
     }
     $is_allocate = $request->getBool('allocate');
     if ($is_allocate) {
         $params = array('name' => $name, 'contentLength' => $request->getInt('length'), 'viewPolicy' => $view_policy);
         $result = id(new ConduitCall('file.allocate', $params))->setUser($viewer)->execute();
         $file_phid = $result['filePHID'];
         if ($file_phid) {
             $file = $this->loadFile($file_phid);
             $result += $this->getFileDictionary($file);
         }
         return id(new AphrontAjaxResponse())->setContent($result);
     }
     // Read the raw request data. We're either doing a chunk upload or a
     // vanilla upload, so we need it.
     $data = PhabricatorStartup::getRawInput();
     $is_chunk_upload = $request->getBool('uploadchunk');
     if ($is_chunk_upload) {
         $params = array('filePHID' => $file_phid, 'byteStart' => $request->getInt('byteStart'), 'data' => $data);
         $result = id(new ConduitCall('file.uploadchunk', $params))->setUser($viewer)->execute();
         $file = $this->loadFile($file_phid);
         if ($file->getIsPartial()) {
             $result = array();
         } else {
             $result = array('complete' => true) + $this->getFileDictionary($file);
         }
         return id(new AphrontAjaxResponse())->setContent($result);
     }
     $file = PhabricatorFile::newFromXHRUpload($data, array('name' => $request->getStr('name'), 'authorPHID' => $viewer->getPHID(), 'viewPolicy' => $view_policy, 'isExplicitUpload' => true));
     $result = $this->getFileDictionary($file);
     return id(new AphrontAjaxResponse())->setContent($result);
 }
 /**
  * @phutil-external-symbol class PhabricatorStartup
  */
 protected function executeChecks()
 {
     $engines = PhabricatorFileStorageEngine::loadWritableChunkEngines();
     $chunk_engine_active = (bool) $engines;
     $this->checkS3();
     if (!$chunk_engine_active) {
         $doc_href = PhabricatorEnv::getDocLink('Configuring File Storage');
         $message = pht('Large file storage has not been configured, which will limit ' . 'the maximum size of file uploads. See %s for ' . 'instructions on configuring uploads and storage.', phutil_tag('a', array('href' => $doc_href, 'target' => '_blank'), pht('Configuring File Storage')));
         $this->newIssue('large-files')->setShortName(pht('Large Files'))->setName(pht('Large File Storage Not Configured'))->setMessage($message);
     }
     $post_max_size = ini_get('post_max_size');
     if ($post_max_size && (int) $post_max_size > 0) {
         $post_max_bytes = phutil_parse_bytes($post_max_size);
         $post_max_need = 32 * 1024 * 1024;
         if ($post_max_need > $post_max_bytes) {
             $summary = pht('Set %s in your PHP configuration to at least 32MB ' . 'to support large file uploads.', phutil_tag('tt', array(), 'post_max_size'));
             $message = pht('Adjust %s in your PHP configuration to at least 32MB. When ' . 'set to smaller value, large file uploads may not work properly.', phutil_tag('tt', array(), 'post_max_size'));
             $this->newIssue('php.post_max_size')->setName(pht('PHP post_max_size Not Configured'))->setSummary($summary)->setMessage($message)->setGroup(self::GROUP_PHP)->addPHPConfig('post_max_size');
         }
     }
     // This is somewhat arbitrary, but make sure we have enough headroom to
     // upload a default file at the chunk threshold (8MB), which may be
     // base64 encoded, then JSON encoded in the request, and may need to be
     // held in memory in the raw and as a query string.
     $need_bytes = 64 * 1024 * 1024;
     $memory_limit = PhabricatorStartup::getOldMemoryLimit();
     if ($memory_limit && (int) $memory_limit > 0) {
         $memory_limit_bytes = phutil_parse_bytes($memory_limit);
         $memory_usage_bytes = memory_get_usage();
         $available_bytes = $memory_limit_bytes - $memory_usage_bytes;
         if ($need_bytes > $available_bytes) {
             $summary = pht('Your PHP memory limit is configured in a way that may prevent ' . 'you from uploading large files or handling large requests.');
             $message = pht('When you upload a file via drag-and-drop or the API, chunks must ' . 'be buffered into memory before being written to permanent ' . 'storage. Phabricator needs memory available to store these ' . 'chunks while they are uploaded, but PHP is currently configured ' . 'to severly limit the available memory.' . "\n\n" . 'PHP processes currently have very little free memory available ' . '(%s). To work well, processes should have at least %s.' . "\n\n" . '(Note that the application itself must also fit in available ' . 'memory, so not all of the memory under the memory limit is ' . 'available for running workloads.)' . "\n\n" . "The easiest way to resolve this issue is to set %s to %s in your " . "PHP configuration, to disable the memory limit. There is " . "usually little or no value to using this option to limit " . "Phabricator process memory." . "\n\n" . "You can also increase the limit or ignore this issue and accept " . "that you may encounter problems uploading large files and " . "processing large requests.", phutil_format_bytes($available_bytes), phutil_format_bytes($need_bytes), phutil_tag('tt', array(), 'memory_limit'), phutil_tag('tt', array(), '-1'));
             $this->newIssue('php.memory_limit.upload')->setName(pht('Memory Limit Restricts File Uploads'))->setSummary($summary)->setMessage($message)->setGroup(self::GROUP_PHP)->addPHPConfig('memory_limit')->addPHPConfigOriginalValue('memory_limit', $memory_limit);
         }
     }
     $local_path = PhabricatorEnv::getEnvConfig('storage.local-disk.path');
     if (!$local_path) {
         return;
     }
     if (!Filesystem::pathExists($local_path) || !is_readable($local_path) || !is_writable($local_path)) {
         $message = pht('Configured location for storing uploaded files on disk ("%s") does ' . 'not exist, or is not readable or writable. Verify the directory ' . 'exists and is readable and writable by the webserver.', $local_path);
         $this->newIssue('config.storage.local-disk.path')->setShortName(pht('Local Disk Storage'))->setName(pht('Local Disk Storage Not Readable/Writable'))->setMessage($message)->addPhabricatorConfig('storage.local-disk.path');
     }
 }
 /**
  * @phutil-external-symbol class PhabricatorStartup
  */
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     // NOTE: Throws if valid CSRF token is not present in the request.
     $request->validateCSRF();
     $data = PhabricatorStartup::getRawInput();
     $name = $request->getStr('name');
     // If there's no explicit view policy, make it very restrictive by default.
     // This is the correct policy for files dropped onto objects during
     // creation, comment and edit flows.
     $view_policy = $request->getStr('viewPolicy');
     if (!$view_policy) {
         $view_policy = $viewer->getPHID();
     }
     $file = PhabricatorFile::newFromXHRUpload($data, array('name' => $request->getStr('name'), 'authorPHID' => $viewer->getPHID(), 'viewPolicy' => $view_policy, 'isExplicitUpload' => true));
     return id(new AphrontAjaxResponse())->setContent(array('id' => $file->getID(), 'phid' => $file->getPHID(), 'uri' => $file->getBestURI()));
 }
Beispiel #7
0
function phabricator_startup()
{
    // Load the PhabricatorStartup class itself.
    $t_startup = microtime(true);
    $root = dirname(dirname(__FILE__));
    require_once $root . '/support/PhabricatorStartup.php';
    // If the preamble script exists, load it.
    $t_preamble = microtime(true);
    $preamble_path = $root . '/support/preamble.php';
    if (file_exists($preamble_path)) {
        require_once $preamble_path;
    }
    $t_hook = microtime(true);
    PhabricatorStartup::didStartup($t_startup);
    PhabricatorStartup::recordStartupPhase('startup.init', $t_startup);
    PhabricatorStartup::recordStartupPhase('preamble', $t_preamble);
    PhabricatorStartup::recordStartupPhase('hook', $t_hook);
}
 private function getGitLFSInput()
 {
     if (!$this->gitLFSInput) {
         $input = PhabricatorStartup::getRawInput();
         $input = phutil_json_decode($input);
         $this->gitLFSInput = $input;
     }
     return $this->gitLFSInput;
 }
Beispiel #9
0
 /**
  * Build a new @{class:HTTPSFuture} which proxies this request to another
  * node in the cluster.
  *
  * IMPORTANT: This is very dangerous!
  *
  * The future forwards authentication information present in the request.
  * Proxied requests must only be sent to trusted hosts. (We attempt to
  * enforce this.)
  *
  * This is not a general-purpose proxying method; it is a specialized
  * method with niche applications and severe security implications.
  *
  * @param string URI identifying the host we are proxying the request to.
  * @return HTTPSFuture New proxy future.
  *
  * @phutil-external-symbol class PhabricatorStartup
  */
 public function newClusterProxyFuture($uri)
 {
     $uri = new PhutilURI($uri);
     $domain = $uri->getDomain();
     $ip = gethostbyname($domain);
     if (!$ip) {
         throw new Exception(pht('Unable to resolve domain "%s"!', $domain));
     }
     if (!PhabricatorEnv::isClusterAddress($ip)) {
         throw new Exception(pht('Refusing to proxy a request to IP address ("%s") which is not ' . 'in the cluster address block (this address was derived by ' . 'resolving the domain "%s").', $ip, $domain));
     }
     $uri->setPath($this->getPath());
     $uri->setQueryParams(self::flattenData($_GET));
     $input = PhabricatorStartup::getRawInput();
     $future = id(new HTTPSFuture($uri))->addHeader('Host', self::getHost())->addHeader('X-Phabricator-Cluster', true)->setMethod($_SERVER['REQUEST_METHOD'])->write($input);
     if (isset($_SERVER['PHP_AUTH_USER'])) {
         $future->setHTTPBasicAuthCredentials($_SERVER['PHP_AUTH_USER'], new PhutilOpaqueEnvelope(idx($_SERVER, 'PHP_AUTH_PW', '')));
     }
     $headers = array();
     $seen = array();
     // NOTE: apache_request_headers() might provide a nicer way to do this,
     // but isn't available under FCGI until PHP 5.4.0.
     foreach ($_SERVER as $key => $value) {
         if (preg_match('/^HTTP_/', $key)) {
             // Unmangle the header as best we can.
             $key = str_replace('_', ' ', $key);
             $key = strtolower($key);
             $key = ucwords($key);
             $key = str_replace(' ', '-', $key);
             $headers[] = array($key, $value);
             $seen[$key] = true;
         }
     }
     // In some situations, this may not be mapped into the HTTP_X constants.
     // CONTENT_LENGTH is similarly affected, but we trust cURL to take care
     // of that if it matters, since we're handing off a request body.
     if (empty($seen['Content-Type'])) {
         if (isset($_SERVER['CONTENT_TYPE'])) {
             $headers[] = array('Content-Type', $_SERVER['CONTENT_TYPE']);
         }
     }
     foreach ($headers as $header) {
         list($key, $value) = $header;
         switch ($key) {
             case 'Host':
             case 'Authorization':
                 // Don't forward these headers, we've already handled them elsewhere.
                 unset($headers[$key]);
                 break;
             default:
                 break;
         }
     }
     foreach ($headers as $header) {
         list($key, $value) = $header;
         $future->addHeader($key, $value);
     }
     return $future;
 }
 /**
  * @phutil-external-symbol class PhabricatorStartup
  */
 public function getCSRFToken()
 {
     $salt = PhabricatorStartup::getGlobal('csrf.salt');
     if (!$salt) {
         $salt = Filesystem::readRandomCharacters(self::CSRF_SALT_LENGTH);
         PhabricatorStartup::setGlobal('csrf.salt', $salt);
     }
     // Generate a token hash to mitigate BREACH attacks against SSL. See
     // discussion in T3684.
     $token = $this->getRawCSRFToken();
     $hash = PhabricatorHash::digest($token, $salt);
     return 'B@' . $salt . substr($hash, 0, self::CSRF_TOKEN_LENGTH);
 }
 public function processRequest(AphrontRequest $request, PhutilDeferredLog $access_log, AphrontHTTPSink $sink, MultimeterControl $multimeter)
 {
     $this->setRequest($request);
     list($controller, $uri_data) = $this->buildController();
     $controller_class = get_class($controller);
     $access_log->setData(array('C' => $controller_class));
     $multimeter->setEventContext('web.' . $controller_class);
     $request->setURIMap($uri_data);
     $controller->setRequest($request);
     // If execution throws an exception and then trying to render that
     // exception throws another exception, we want to show the original
     // exception, as it is likely the root cause of the rendering exception.
     $original_exception = null;
     try {
         $response = $controller->willBeginExecution();
         if ($request->getUser() && $request->getUser()->getPHID()) {
             $access_log->setData(array('u' => $request->getUser()->getUserName(), 'P' => $request->getUser()->getPHID()));
             $multimeter->setEventViewer('user.' . $request->getUser()->getPHID());
         }
         if (!$response) {
             $controller->willProcessRequest($uri_data);
             $response = $controller->handleRequest($request);
         }
     } catch (Exception $ex) {
         $original_exception = $ex;
         $response = $this->handleException($ex);
     }
     try {
         $response = $controller->didProcessRequest($response);
         $response = $this->willSendResponse($response, $controller);
         $response->setRequest($request);
         $unexpected_output = PhabricatorStartup::endOutputCapture();
         if ($unexpected_output) {
             $unexpected_output = pht("Unexpected output:\n\n%s", $unexpected_output);
             phlog($unexpected_output);
             if ($response instanceof AphrontWebpageResponse) {
                 echo phutil_tag('div', array('style' => 'background: #eeddff;' . 'white-space: pre-wrap;' . 'z-index: 200000;' . 'position: relative;' . 'padding: 8px;' . 'font-family: monospace'), $unexpected_output);
             }
         }
         $sink->writeResponse($response);
     } catch (Exception $ex) {
         if ($original_exception) {
             throw $original_exception;
         }
         throw $ex;
     }
     return $response;
 }
 /**
  * @phutil-external-symbol class PhabricatorStartup
  */
 public static function getProfileFilePHID()
 {
     if (!self::isProfilerRunning()) {
         return;
     }
     PhabricatorStartup::beginStartupPhase('profiler.stop');
     self::stopProfiler();
     PhabricatorStartup::beginStartupPhase('profiler.done');
     return self::$profileFilePHID;
 }
 /**
  * Adjust the permissible rate limit score.
  *
  * By default, the limit is `1000`. You can use this method to set it to
  * a larger or smaller value. If you set it to `2000`, users may make twice
  * as many requests before rate limiting.
  *
  * @param int Maximum score before rate limiting.
  * @return void
  * @task ratelimit
  */
 public static function setMaximumRate($rate)
 {
     self::$maximumRate = $rate;
 }
 /**
  * @phutil-external-symbol class PhabricatorStartup
  */
 public function generateData()
 {
     $should_analyze = self::isQueryAnalyzerRequested();
     $log = PhutilServiceProfiler::getInstance()->getServiceCallLog();
     foreach ($log as $key => $entry) {
         $config = idx($entry, 'config', array());
         unset($log[$key]['config']);
         if (!$should_analyze) {
             $log[$key]['explain'] = array('sev' => 7, 'size' => null, 'reason' => pht('Disabled'));
             // Query analysis is disabled for this request, so don't do any of it.
             continue;
         }
         if ($entry['type'] != 'query') {
             continue;
         }
         // For each SELECT query, go issue an EXPLAIN on it so we can flag stuff
         // causing table scans, etc.
         if (preg_match('/^\\s*SELECT\\b/i', $entry['query'])) {
             $conn = PhabricatorEnv::newObjectFromConfig('mysql.implementation', array($entry['config']));
             try {
                 $explain = queryfx_all($conn, 'EXPLAIN %Q', $entry['query']);
                 $badness = 0;
                 $size = 1;
                 $reason = null;
                 foreach ($explain as $table) {
                     $size *= (int) $table['rows'];
                     switch ($table['type']) {
                         case 'index':
                             $cur_badness = 1;
                             $cur_reason = 'Index';
                             break;
                         case 'const':
                             $cur_badness = 1;
                             $cur_reason = 'Const';
                             break;
                         case 'eq_ref':
                             $cur_badness = 2;
                             $cur_reason = 'EqRef';
                             break;
                         case 'range':
                             $cur_badness = 3;
                             $cur_reason = 'Range';
                             break;
                         case 'ref':
                             $cur_badness = 3;
                             $cur_reason = 'Ref';
                             break;
                         case 'fulltext':
                             $cur_badness = 3;
                             $cur_reason = 'Fulltext';
                             break;
                         case 'ALL':
                             if (preg_match('/Using where/', $table['Extra'])) {
                                 if ($table['rows'] < 256 && !empty($table['possible_keys'])) {
                                     $cur_badness = 2;
                                     $cur_reason = pht('Small Table Scan');
                                 } else {
                                     $cur_badness = 6;
                                     $cur_reason = pht('TABLE SCAN!');
                                 }
                             } else {
                                 $cur_badness = 3;
                                 $cur_reason = pht('Whole Table');
                             }
                             break;
                         default:
                             if (preg_match('/No tables used/i', $table['Extra'])) {
                                 $cur_badness = 1;
                                 $cur_reason = pht('No Tables');
                             } else {
                                 if (preg_match('/Impossible/i', $table['Extra'])) {
                                     $cur_badness = 1;
                                     $cur_reason = pht('Empty');
                                 } else {
                                     $cur_badness = 4;
                                     $cur_reason = pht("Can't Analyze");
                                 }
                             }
                             break;
                     }
                     if ($cur_badness > $badness) {
                         $badness = $cur_badness;
                         $reason = $cur_reason;
                     }
                 }
                 $log[$key]['explain'] = array('sev' => $badness, 'size' => $size, 'reason' => $reason);
             } catch (Exception $ex) {
                 $log[$key]['explain'] = array('sev' => 5, 'size' => null, 'reason' => $ex->getMessage());
             }
         }
     }
     return array('start' => PhabricatorStartup::getStartTime(), 'end' => microtime(true), 'log' => $log, 'analyzeURI' => (string) $this->getRequestURI()->alter('__analyze__', true), 'didAnalyze' => $should_analyze);
 }
 /**
  * @phutil-external-symbol class PhabricatorStartup
  */
 public function generateData()
 {
     return PhabricatorStartup::getPhases();
 }
Beispiel #16
0
            if ($response instanceof AphrontWebpageResponse) {
                echo phutil_tag('div', array('style' => 'background: #eeddff;' . 'white-space: pre-wrap;' . 'z-index: 200000;' . 'position: relative;' . 'padding: 8px;' . 'font-family: monospace'), $unexpected_output);
            }
        }
        $sink->writeResponse($response);
    } catch (Exception $ex) {
        $write_guard->dispose();
        $access_log->write();
        if ($original_exception) {
            $ex = new PhutilAggregateException('Multiple exceptions during processing and rendering.', array($original_exception, $ex));
        }
        PhabricatorStartup::didEncounterFatalException('Rendering Exception', $ex, $show_unexpected_traces);
    }
    $write_guard->dispose();
    $access_log->setData(array('c' => $response->getHTTPResponseCode(), 'T' => PhabricatorStartup::getMicrosecondsSinceStart()));
    DarkConsoleXHProfPluginAPI::saveProfilerSample($access_log);
    // Add points to the rate limits for this request.
    if (isset($_SERVER['REMOTE_ADDR'])) {
        $user_ip = $_SERVER['REMOTE_ADDR'];
        // The base score for a request allows users to make 30 requests per
        // minute.
        $score = 1000 / 30;
        // If the user was logged in, let them make more requests.
        if ($request->getUser() && $request->getUser()->getPHID()) {
            $score = $score / 5;
        }
        PhabricatorStartup::addRateLimitScore($user_ip, $score);
    }
} catch (Exception $ex) {
    PhabricatorStartup::didEncounterFatalException('Core Exception', $ex, $show_unexpected_traces);
}
 private static function writeResponse(AphrontHTTPSink $sink, AphrontResponse $response)
 {
     $unexpected_output = PhabricatorStartup::endOutputCapture();
     if ($unexpected_output) {
         $unexpected_output = pht("Unexpected output:\n\n%s", $unexpected_output);
         phlog($unexpected_output);
         if ($response instanceof AphrontWebpageResponse) {
             echo phutil_tag('div', array('style' => 'background: #eeddff;' . 'white-space: pre-wrap;' . 'z-index: 200000;' . 'position: relative;' . 'padding: 8px;' . 'font-family: monospace'), $unexpected_output);
         }
     }
     $sink->writeResponse($response);
 }
 private function serveMercurialRequest(PhabricatorRepository $repository, PhabricatorUser $viewer)
 {
     $request = $this->getRequest();
     $bin = Filesystem::resolveBinary('hg');
     if (!$bin) {
         throw new Exception(pht('Unable to find `%s` in %s!', 'hg', '$PATH'));
     }
     $env = $this->getCommonEnvironment($viewer);
     $input = PhabricatorStartup::getRawInput();
     $cmd = $request->getStr('cmd');
     $args = $this->getMercurialArguments();
     $args = $this->formatMercurialArguments($cmd, $args);
     if (strlen($input)) {
         $input = strlen($input) . "\n" . $input . "0\n";
     }
     $command = csprintf('%s serve --stdio', $bin);
     $command = PhabricatorDaemon::sudoCommandAsDaemonUser($command);
     list($err, $stdout, $stderr) = id(new ExecFuture('%C', $command))->setEnv($env, true)->setCWD($repository->getLocalPath())->write("{$cmd}\n{$args}{$input}")->resolve();
     if ($err) {
         return new PhabricatorVCSResponse(500, pht('Error %d: %s', $err, $stderr));
     }
     if ($cmd == 'getbundle' || $cmd == 'changegroup' || $cmd == 'changegroupsubset') {
         // We're not completely sure that "changegroup" and "changegroupsubset"
         // actually work, they're for very old Mercurial.
         $body = gzcompress($stdout);
     } else {
         if ($cmd == 'unbundle') {
             // This includes diagnostic information and anything echoed by commit
             // hooks. We ignore `stdout` since it just has protocol garbage, and
             // substitute `stderr`.
             $body = strlen($stderr) . "\n" . $stderr;
         } else {
             list($length, $body) = explode("\n", $stdout, 2);
             if ($cmd == 'capabilities') {
                 $body = DiffusionMercurialWireProtocol::filterBundle2Capability($body);
             }
         }
     }
     return id(new DiffusionMercurialResponse())->setContent($body);
 }
Beispiel #19
0
$phabricator_root = dirname(dirname(__FILE__));
require_once $phabricator_root . '/support/PhabricatorStartup.php';
// If the preamble script exists, load it.
$preamble_path = $phabricator_root . '/support/preamble.php';
if (file_exists($preamble_path)) {
    require_once $preamble_path;
}
PhabricatorStartup::didStartup();
try {
    PhabricatorStartup::loadCoreLibraries();
    PhabricatorCaches::destroyRequestCache();
    $sink = new AphrontPHPHTTPSink();
    try {
        AphrontApplicationConfiguration::runHTTPRequest($sink);
    } catch (Exception $ex) {
        try {
            $response = new AphrontUnhandledExceptionResponse();
            $response->setException($ex);
            PhabricatorStartup::endOutputCapture();
            $sink->writeResponse($response);
        } catch (Exception $response_exception) {
            // If we hit a rendering exception, ignore it and throw the original
            // exception. It is generally more interesting and more likely to be
            // the root cause.
            throw $ex;
        }
    }
} catch (Exception $ex) {
    PhabricatorStartup::didEncounterFatalException('Core Exception', $ex, false);
}