public function handleException(Exception $ex)
 {
     // Always log the unhandled exception.
     phlog($ex);
     $class = phutil_escape_html(get_class($ex));
     $message = phutil_escape_html($ex->getMessage());
     if (PhabricatorEnv::getEnvConfig('phabricator.show-stack-traces')) {
         $trace = $this->renderStackTrace($ex->getTrace());
     } else {
         $trace = null;
     }
     $content = '<div class="aphront-unhandled-exception">' . '<div class="exception-message">' . $message . '</div>' . $trace . '</div>';
     $user = $this->getRequest()->getUser();
     if (!$user) {
         // If we hit an exception very early, we won't have a user.
         $user = new PhabricatorUser();
     }
     $dialog = new AphrontDialogView();
     $dialog->setTitle('Unhandled Exception ("' . $class . '")')->setClass('aphront-exception-dialog')->setUser($user)->appendChild($content);
     if ($this->getRequest()->isAjax()) {
         $dialog->addCancelButton('/', 'Close');
     }
     $response = new AphrontDialogResponse();
     $response->setDialog($dialog);
     return $response;
 }
 public function processRequest()
 {
     // No CSRF for SendGrid.
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
     $request = $this->getRequest();
     $user = $request->getUser();
     $raw_headers = $request->getStr('headers');
     $raw_headers = explode("\n", rtrim($raw_headers));
     $raw_dict = array();
     foreach (array_filter($raw_headers) as $header) {
         list($name, $value) = explode(':', $header, 2);
         $raw_dict[$name] = ltrim($value);
     }
     $headers = array('to' => $request->getStr('to'), 'from' => $request->getStr('from'), 'subject' => $request->getStr('subject')) + $raw_dict;
     $received = new PhabricatorMetaMTAReceivedMail();
     $received->setHeaders($headers);
     $received->setBodies(array('text' => $request->getStr('text'), 'html' => $request->getStr('from')));
     $file_phids = array();
     foreach ($_FILES as $file_raw) {
         try {
             $file = PhabricatorFile::newFromPHPUpload($file_raw, array('authorPHID' => $user->getPHID()));
             $file_phids[] = $file->getPHID();
         } catch (Exception $ex) {
             phlog($ex);
         }
     }
     $received->setAttachments($file_phids);
     $received->save();
     $received->processReceivedMail();
     $response = new AphrontWebpageResponse();
     $response->setContent("Got it! Thanks, SendGrid!\n");
     return $response;
 }
 protected function doWork()
 {
     $lock = $this->acquireTaskLock();
     $task = $this->loadTask();
     $status = $task->getStatus();
     switch ($task->getStatus()) {
         case PhabricatorWorkerBulkTask::STATUS_WAITING:
             // This is what we expect.
             break;
         default:
             throw new PhabricatorWorkerPermanentFailureException(pht('Found unexpected task status ("%s").', $status));
     }
     $task->setStatus(PhabricatorWorkerBulkTask::STATUS_RUNNING)->save();
     $lock->unlock();
     $job = $this->loadJob();
     $actor = $this->loadActor($job);
     try {
         $job->runTask($actor, $task);
         $status = PhabricatorWorkerBulkTask::STATUS_DONE;
     } catch (Exception $ex) {
         phlog($ex);
         $status = PhabricatorWorkerBulkTask::STATUS_FAIL;
     }
     $task->setStatus($status)->save();
     $this->updateJob($job);
 }
 private function assertParserResult(array $expect, $input, $file)
 {
     list($x, $y) = PhutilSocketChannel::newChannelPair();
     $xp = new DiffusionMercurialWireClientSSHProtocolChannel($x);
     $y->write($input);
     $y->flush();
     $y->closeWriteChannel();
     $messages = array();
     for ($ii = 0; $ii < count($expect); $ii++) {
         try {
             $messages[] = $xp->waitForMessage();
         } catch (Exception $ex) {
             // This is probably the parser not producing as many messages as
             // we expect. Log the exception, but continue to the assertion below
             // since that will often be easier to diagnose.
             phlog($ex);
             break;
         }
     }
     $this->assertEqual($expect, $messages, $file);
     // Now, make sure the channel doesn't have *more* messages than we expect.
     // Specifically, it should throw when we try to read another message.
     $caught = null;
     try {
         $xp->waitForMessage();
     } catch (Exception $ex) {
         $caught = $ex;
     }
     $this->assertTrue($caught instanceof Exception, pht("No extra messages for '%s'.", $file));
 }
 public function getKeys(array $keys)
 {
     $results = array();
     if ($keys) {
         $map = $this->digestKeys($keys);
         $rows = queryfx_all($this->establishConnection('r'), 'SELECT * FROM %T WHERE cacheKeyHash IN (%Ls)', $this->getTableName(), $map);
         $rows = ipull($rows, null, 'cacheKey');
         foreach ($keys as $key) {
             if (empty($rows[$key])) {
                 continue;
             }
             $row = $rows[$key];
             if ($row['cacheExpires'] && $row['cacheExpires'] < time()) {
                 continue;
             }
             try {
                 $results[$key] = $this->didReadValue($row['cacheFormat'], $row['cacheData']);
             } catch (Exception $ex) {
                 // Treat this as a cache miss.
                 phlog($ex);
             }
         }
     }
     return $results;
 }
 public function addRemarkupSection($header, $text)
 {
     try {
         $engine = PhabricatorMarkupEngine::newMarkupEngine(array());
         $engine->setConfig('viewer', $this->getViewer());
         $engine->setMode(PhutilRemarkupEngine::MODE_TEXT);
         $styled_text = $engine->markupText($text);
         $this->addPlaintextSection($header, $styled_text);
     } catch (Exception $ex) {
         phlog($ex);
         $this->addTextSection($header, $text);
     }
     try {
         $mail_engine = PhabricatorMarkupEngine::newMarkupEngine(array());
         $mail_engine->setConfig('viewer', $this->getViewer());
         $mail_engine->setMode(PhutilRemarkupEngine::MODE_HTML_MAIL);
         $mail_engine->setConfig('uri.base', PhabricatorEnv::getProductionURI('/'));
         $html = $mail_engine->markupText($text);
         $this->addHTMLSection($header, $html);
     } catch (Exception $ex) {
         phlog($ex);
         $this->addHTMLSection($header, $text);
     }
     return $this;
 }
 public function destroyObject(PhabricatorDestructionEngine $engine, $object)
 {
     $src_phid = $object->getPHID();
     try {
         $edges = id(new PhabricatorEdgeQuery())->withSourcePHIDs(array($src_phid))->execute();
     } catch (Exception $ex) {
         // This is (presumably) a "no edges for this PHID type" exception.
         return;
     }
     $editor = new PhabricatorEdgeEditor();
     foreach ($edges as $type => $type_edges) {
         foreach ($type_edges as $src => $src_edges) {
             foreach ($src_edges as $dst => $edge) {
                 try {
                     $editor->removeEdge($edge['src'], $edge['type'], $edge['dst']);
                 } catch (Exception $ex) {
                     // We can run into an exception while removing the edge if the
                     // edge type no longer exists. This prevents us from figuring out
                     // if there's an inverse type. Just ignore any errors here and
                     // continue, since the best we can do is clean up all the edges
                     // we still have information about. See T11201.
                     phlog($ex);
                 }
             }
         }
     }
     $editor->save();
 }
 public function handleRequest(AphrontRequest $request)
 {
     // No CSRF for Mailgun.
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
     if (!$this->verifyMessage()) {
         throw new Exception(pht('Mail signature is not valid. Check your Mailgun API key.'));
     }
     $user = $request->getUser();
     $raw_headers = $request->getStr('headers');
     $raw_headers = explode("\n", rtrim($raw_headers));
     $raw_dict = array();
     foreach (array_filter($raw_headers) as $header) {
         list($name, $value) = explode(':', $header, 2);
         $raw_dict[$name] = ltrim($value);
     }
     $headers = array('to' => $request->getStr('recipient'), 'from' => $request->getStr('from'), 'subject' => $request->getStr('subject')) + $raw_dict;
     $received = new PhabricatorMetaMTAReceivedMail();
     $received->setHeaders($headers);
     $received->setBodies(array('text' => $request->getStr('stripped-text'), 'html' => $request->getStr('stripped-html')));
     $file_phids = array();
     foreach ($_FILES as $file_raw) {
         try {
             $file = PhabricatorFile::newFromPHPUpload($file_raw, array('viewPolicy' => PhabricatorPolicies::POLICY_NOONE));
             $file_phids[] = $file->getPHID();
         } catch (Exception $ex) {
             phlog($ex);
         }
     }
     $received->setAttachments($file_phids);
     $received->save();
     $received->processReceivedMail();
     $response = new AphrontWebpageResponse();
     $response->setContent(pht("Got it! Thanks, Mailgun!\n"));
     return $response;
 }
 public function handleRequestException(AphrontRequest $request, Exception $ex)
 {
     $viewer = $this->getViewer($request);
     // Some types of uninteresting request exceptions don't get logged, usually
     // because they are caused by the background radiation of bot traffic on
     // the internet. These include requests with bad CSRF tokens and
     // questionable "Host" headers.
     $should_log = true;
     if ($ex instanceof AphrontMalformedRequestException) {
         $should_log = !$ex->getIsUnlogged();
     }
     if ($should_log) {
         phlog($ex);
     }
     $class = get_class($ex);
     $message = $ex->getMessage();
     if ($ex instanceof AphrontSchemaQueryException) {
         $message .= "\n\n" . pht("NOTE: This usually indicates that the MySQL schema has not been " . "properly upgraded. Run '%s' to ensure your schema is up to date.", 'bin/storage upgrade');
     }
     if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) {
         $trace = id(new AphrontStackTraceView())->setUser($viewer)->setTrace($ex->getTrace());
     } else {
         $trace = null;
     }
     $content = phutil_tag('div', array('class' => 'aphront-unhandled-exception'), array(phutil_tag('div', array('class' => 'exception-message'), $message), $trace));
     $dialog = new AphrontDialogView();
     $dialog->setTitle(pht('Unhandled Exception ("%s")', $class))->setClass('aphront-exception-dialog')->setUser($viewer)->appendChild($content);
     if ($request->isAjax()) {
         $dialog->addCancelButton('/', pht('Close'));
     }
     return id(new AphrontDialogResponse())->setDialog($dialog)->setHTTPResponseCode(500);
 }
 public function setKeys(array $keys, $ttl = null)
 {
     $this->validateKeys(array_keys($keys));
     $this->lockCache(15);
     if ($ttl) {
         $ttl_epoch = time() + $ttl;
     } else {
         $ttl_epoch = null;
     }
     foreach ($keys as $key => $value) {
         $dict = array('value' => $value);
         if ($ttl_epoch) {
             $dict['ttl'] = $ttl_epoch;
         }
         try {
             $key_file = $this->getKeyFile($key);
             $key_dir = dirname($key_file);
             if (!Filesystem::pathExists($key_dir)) {
                 Filesystem::createDirectory($key_dir, $mask = 0755, $recursive = true);
             }
             $new_file = $key_file . '.new';
             Filesystem::writeFile($new_file, serialize($dict));
             Filesystem::rename($new_file, $key_file);
         } catch (FilesystemException $ex) {
             phlog($ex);
         }
     }
     $this->unlockCache();
     return $this;
 }
 private function establishConnection()
 {
     $host = $this->getConfiguration('host');
     $database = $this->getConfiguration('database');
     $profiler = PhutilServiceProfiler::getInstance();
     $call_id = $profiler->beginServiceCall(array('type' => 'connect', 'host' => $host, 'database' => $database));
     $retries = max(1, $this->getConfiguration('retries', 3));
     while ($retries--) {
         try {
             $conn = $this->connect();
             $profiler->endServiceCall($call_id, array());
             break;
         } catch (AphrontQueryException $ex) {
             if ($retries && $ex->getCode() == 2003) {
                 $class = get_class($ex);
                 $message = $ex->getMessage();
                 phlog(pht('Retrying (%d) after %s: %s', $retries, $class, $message));
             } else {
                 $profiler->endServiceCall($call_id, array());
                 throw $ex;
             }
         }
     }
     $this->connection = $conn;
 }
 public function indexDocumentByPHID($phid)
 {
     try {
         $document = $this->buildAbstractDocumentByPHID($phid);
         $object = $this->loadDocumentByPHID($phid);
         // Automatically rebuild CustomField indexes if the object uses custom
         // fields.
         if ($object instanceof PhabricatorCustomFieldInterface) {
             $this->indexCustomFields($document, $object);
         }
         // Automatically rebuild subscriber indexes if the object is subscribable.
         if ($object instanceof PhabricatorSubscribableInterface) {
             $this->indexSubscribers($document);
         }
         $engine = PhabricatorSearchEngineSelector::newSelector()->newEngine();
         try {
             $engine->reindexAbstractDocument($document);
         } catch (Exception $ex) {
             $phid = $document->getPHID();
             $class = get_class($engine);
             phlog("Unable to index document {$phid} with engine {$class}.");
             phlog($ex);
         }
         $this->dispatchDidUpdateIndexEvent($phid, $document);
     } catch (Exception $ex) {
         $class = get_class($this);
         phlog("Unable to build document {$phid} with indexer {$class}.");
         phlog($ex);
     }
     return $this;
 }
 public function addRemarkupSection($text)
 {
     try {
         $engine = PhabricatorMarkupEngine::newMarkupEngine(array());
         $engine->setConfig('viewer', $this->getViewer());
         $engine->setMode(PhutilRemarkupEngine::MODE_TEXT);
         $styled_text = $engine->markupText($text);
         $this->sections[] = $styled_text;
     } catch (Exception $ex) {
         phlog($ex);
         $this->sections[] = $text;
     }
     try {
         $mail_engine = PhabricatorMarkupEngine::newMarkupEngine(array());
         $mail_engine->setConfig('viewer', $this->getViewer());
         $mail_engine->setMode(PhutilRemarkupEngine::MODE_HTML_MAIL);
         $mail_engine->setConfig('uri.base', PhabricatorEnv::getProductionURI('/'));
         $html = $mail_engine->markupText($text);
         $this->htmlSections[] = $html;
     } catch (Exception $ex) {
         phlog($ex);
         $this->htmlSections[] = phutil_escape_html_newlines(phutil_tag('div', array(), $text));
     }
     return $this;
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $results = array();
     $user = $request->getUser();
     $view_type = $request->getValue('view');
     if (!$view_type) {
         $view_type = 'data';
     }
     $limit = $request->getValue('limit');
     if (!$limit) {
         $limit = $this->getDefaultLimit();
     }
     $filter_phids = $request->getValue('filterPHIDs');
     if (!$filter_phids) {
         $filter_phids = array();
     }
     $query = id(new PhabricatorFeedQuery())->setLimit($limit)->setFilterPHIDs($filter_phids)->setViewer($user);
     $after = $request->getValue('after');
     if (strlen($after)) {
         $query->setAfterID($after);
     }
     $before = $request->getValue('before');
     if (strlen($before)) {
         $query->setBeforeID($before);
     }
     $stories = $query->execute();
     if ($stories) {
         foreach ($stories as $story) {
             $story_data = $story->getStoryData();
             $data = null;
             try {
                 $view = $story->renderView();
             } catch (Exception $ex) {
                 // When stories fail to render, just fail that story.
                 phlog($ex);
                 continue;
             }
             $view->setEpoch($story->getEpoch());
             $view->setUser($user);
             switch ($view_type) {
                 case 'html':
                     $data = $view->render();
                     break;
                 case 'html-summary':
                     $data = $view->render();
                     break;
                 case 'data':
                     $data = array('class' => $story_data->getStoryType(), 'epoch' => $story_data->getEpoch(), 'authorPHID' => $story_data->getAuthorPHID(), 'chronologicalKey' => $story_data->getChronologicalKey(), 'data' => $story_data->getStoryData());
                     break;
                 case 'text':
                     $data = array('class' => $story_data->getStoryType(), 'epoch' => $story_data->getEpoch(), 'authorPHID' => $story_data->getAuthorPHID(), 'chronologicalKey' => $story_data->getChronologicalKey(), 'objectPHID' => $story->getPrimaryObjectPHID(), 'text' => $story->renderText());
                     break;
                 default:
                     throw new ConduitException('ERR-UNKNOWN-TYPE');
             }
             $results[$story_data->getPHID()] = $data;
         }
     }
     return $results;
 }
 public function execute(PhutilArgumentParser $args)
 {
     $console = PhutilConsole::getConsole();
     $iterator = $this->buildIterator($args);
     if (!$iterator) {
         throw new PhutilArgumentUsageException(pht('Either specify a list of files to compact, or use `--all` ' . 'to compact all files.'));
     }
     $is_dry_run = $args->getArg('dry-run');
     foreach ($iterator as $file) {
         $monogram = $file->getMonogram();
         $hash = $file->getContentHash();
         if (!$hash) {
             $console->writeOut("%s\n", pht('%s: No content hash.', $monogram));
             continue;
         }
         // Find other files with the same content hash. We're going to point
         // them at the data for this file.
         $similar_files = id(new PhabricatorFile())->loadAllWhere('contentHash = %s AND id != %d AND
       (storageEngine != %s OR storageHandle != %s)', $hash, $file->getID(), $file->getStorageEngine(), $file->getStorageHandle());
         if (!$similar_files) {
             $console->writeOut("%s\n", pht('%s: No other files with the same content hash.', $monogram));
             continue;
         }
         // Only compact files into this one if we can load the data. This
         // prevents us from breaking working files if we're missing some data.
         try {
             $data = $file->loadFileData();
         } catch (Exception $ex) {
             $data = null;
         }
         if ($data === null) {
             $console->writeOut("%s\n", pht('%s: Unable to load file data; declining to compact.', $monogram));
             continue;
         }
         foreach ($similar_files as $similar_file) {
             if ($is_dry_run) {
                 $console->writeOut("%s\n", pht('%s: Would compact storage with %s.', $monogram, $similar_file->getMonogram()));
                 continue;
             }
             $console->writeOut("%s\n", pht('%s: Compacting storage with %s.', $monogram, $similar_file->getMonogram()));
             $old_instance = null;
             try {
                 $old_instance = $similar_file->instantiateStorageEngine();
                 $old_engine = $similar_file->getStorageEngine();
                 $old_handle = $similar_file->getStorageHandle();
             } catch (Exception $ex) {
                 // If the old stuff is busted, we just won't try to delete the
                 // old data.
                 phlog($ex);
             }
             $similar_file->setStorageEngine($file->getStorageEngine())->setStorageHandle($file->getStorageHandle())->save();
             if ($old_instance) {
                 $similar_file->deleteFileDataIfUnused($old_instance, $old_engine, $old_handle);
             }
         }
     }
     return 0;
 }
Exemplo n.º 16
0
 protected function doWork()
 {
     $target = $this->loadBuildTarget();
     $build = $target->getBuild();
     $viewer = $this->getViewer();
     $target->setDateStarted(time());
     try {
         if ($target->getBuildGeneration() !== $build->getBuildGeneration()) {
             throw new HarbormasterBuildAbortedException();
         }
         $status_pending = HarbormasterBuildTarget::STATUS_PENDING;
         if ($target->getTargetStatus() == $status_pending) {
             $target->setTargetStatus(HarbormasterBuildTarget::STATUS_BUILDING);
             $target->save();
         }
         $implementation = $target->getImplementation();
         $implementation->setCurrentWorkerTaskID($this->getCurrentWorkerTaskID());
         $implementation->execute($build, $target);
         $next_status = HarbormasterBuildTarget::STATUS_PASSED;
         if ($implementation->shouldWaitForMessage($target)) {
             $next_status = HarbormasterBuildTarget::STATUS_WAITING;
         }
         $target->setTargetStatus($next_status);
         if ($target->isComplete()) {
             $target->setDateCompleted(PhabricatorTime::getNow());
         }
         $target->save();
     } catch (PhabricatorWorkerYieldException $ex) {
         // If the target wants to yield, let that escape without further
         // processing. We'll resume after the task retries.
         throw $ex;
     } catch (HarbormasterBuildFailureException $ex) {
         // A build step wants to fail explicitly.
         $target->setTargetStatus(HarbormasterBuildTarget::STATUS_FAILED);
         $target->setDateCompleted(PhabricatorTime::getNow());
         $target->save();
     } catch (HarbormasterBuildAbortedException $ex) {
         // A build step is aborting because the build has been restarted.
         $target->setTargetStatus(HarbormasterBuildTarget::STATUS_ABORTED);
         $target->setDateCompleted(PhabricatorTime::getNow());
         $target->save();
     } catch (Exception $ex) {
         phlog($ex);
         try {
             $log = $build->createLog($target, 'core', 'exception');
             $start = $log->start();
             $log->append((string) $ex);
             $log->finalize($start);
         } catch (Exception $log_ex) {
             phlog($log_ex);
         }
         $target->setTargetStatus(HarbormasterBuildTarget::STATUS_FAILED);
         $target->setDateCompleted(time());
         $target->save();
     }
     id(new HarbormasterBuildEngine())->setViewer($viewer)->setBuild($build)->continueBuild();
 }
 public function handleRequestException(AphrontRequest $request, Exception $ex)
 {
     // Log these; they don't get shown on the client and can be difficult
     // to debug.
     phlog($ex);
     $response = new AphrontAjaxResponse();
     $response->setError(array('code' => get_class($ex), 'info' => $ex->getMessage()));
     return $response;
 }
 public function receiveMessage(PhabricatorBotMessage $message)
 {
     switch ($message->getCommand()) {
         case 'MESSAGE':
             $matches = null;
             $text = $message->getBody();
             $target_name = $message->getTarget()->getName();
             if (empty($this->recentlyMentioned[$target_name])) {
                 $this->recentlyMentioned[$target_name] = array();
             }
             $pattern = '@^' . '(?:' . $this->getConfig('nick', 'phabot') . ')?' . '.?\\s*tell me about ' . '(.*)' . '$@';
             if (preg_match($pattern, $text, $matches)) {
                 $slug = $matches[1];
                 $quiet_until = idx($this->recentlyMentioned[$target_name], $slug, 0) + 60 * 10;
                 if (time() < $quiet_until) {
                     // Remain quiet on this channel.
                     break;
                 } else {
                     $this->recentlyMentioned[$target_name][$slug] = time();
                 }
                 try {
                     $result = $this->getConduit()->callMethodSynchronous('phriction.info', array('slug' => 'docbot/docs/' . $slug));
                 } catch (ConduitClientException $ex) {
                     phlog($ex);
                     $result = null;
                 }
                 $response = array();
                 if ($result) {
                     $content = phutil_split_lines($result['content'], $retain_newlines = false);
                     foreach ($content as $line) {
                         $response = array_merge($response, str_split($line, 400));
                         if (count($response) >= 3) {
                             break;
                         }
                     }
                 } else {
                     $response[] = "Nothing to say about " . $slug;
                 }
                 foreach (array_slice($response, 0, 3) as $output) {
                     $this->replyTo($message, html_entity_decode($output));
                 }
                 break;
             }
             $pattern = '@' . $this->getConfig('nick', 'phabot') . ' remember ' . '(.*?)' . ' as:' . '(.*)$' . '@';
             if (preg_match($pattern, $text, $matches)) {
                 $result = $this->getConduit()->callMethodSynchronous('phriction.edit', array('slug' => 'docbot/docs/' . $matches[1], 'content' => $matches[2]));
                 $slug = explode('/', trim($result['slug'], '/'), 3);
                 $output = "Saved as '{$slug[2]}' at {$result['uri']}";
                 $this->replyTo($message, $output);
                 unset($this->recentlyMentioned[$target_name][$slug[2]]);
                 unset($this->recentlyMentioned[$target_name][$matches[1]]);
                 break;
             }
             break;
     }
 }
 private function mirrorRepository(PhabricatorRepository $repository)
 {
     try {
         id(new PhabricatorRepositoryMirrorEngine())->setRepository($repository)->pushToMirrors();
     } catch (Exception $ex) {
         // TODO: We should report these into the UI properly, but for now just
         // complain. These errors are much less severe than pull errors.
         $proxy = new PhutilProxyException(pht('Error while pushing "%s" repository to mirrors.', $repository->getMonogram()), $ex);
         phlog($proxy);
     }
 }
 protected static final function reindexAbstractDocument(PhabricatorSearchAbstractDocument $document)
 {
     $engine = PhabricatorSearchEngineSelector::newSelector()->newEngine();
     try {
         $engine->reindexAbstractDocument($document);
     } catch (Exception $ex) {
         $phid = $document->getPHID();
         $class = get_class($engine);
         phlog("Unable to index document {$phid} by engine {$class}.");
     }
 }
Exemplo n.º 21
0
 /**
  * Publishes stories into JIRA using the JIRA API.
  */
 protected function publishFeedStory()
 {
     $story = $this->getFeedStory();
     $viewer = $this->getViewer();
     $provider = $this->getProvider();
     $object = $this->getStoryObject();
     $publisher = $this->getPublisher();
     $jira_issue_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), PhabricatorJiraIssueHasObjectEdgeType::EDGECONST);
     if (!$jira_issue_phids) {
         $this->log("%s\n", pht('Story is about an object with no linked JIRA issues.'));
         return;
     }
     $do_anything = $this->shouldPostComment() || $this->shouldPostLink();
     if (!$do_anything) {
         $this->log("%s\n", pht('JIRA integration is configured not to post anything.'));
         return;
     }
     $xobjs = id(new DoorkeeperExternalObjectQuery())->setViewer($viewer)->withPHIDs($jira_issue_phids)->execute();
     if (!$xobjs) {
         $this->log("%s\n", pht('Story object has no corresponding external JIRA objects.'));
         return;
     }
     $try_users = $this->findUsersToPossess();
     if (!$try_users) {
         $this->log("%s\n", pht('No users to act on linked JIRA objects.'));
         return;
     }
     $xobjs = mgroup($xobjs, 'getApplicationDomain');
     foreach ($xobjs as $domain => $xobj_list) {
         $accounts = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs($try_users)->withAccountTypes(array($provider->getProviderType()))->withAccountDomains(array($domain))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
         // Reorder accounts in the original order.
         // TODO: This needs to be adjusted if/when we allow you to link multiple
         // accounts.
         $accounts = mpull($accounts, null, 'getUserPHID');
         $accounts = array_select_keys($accounts, $try_users);
         foreach ($xobj_list as $xobj) {
             foreach ($accounts as $account) {
                 try {
                     $jira_key = $xobj->getObjectID();
                     if ($this->shouldPostComment()) {
                         $this->postComment($account, $jira_key);
                     }
                     if ($this->shouldPostLink()) {
                         $this->postLink($account, $jira_key);
                     }
                     break;
                 } catch (HTTPFutureResponseStatus $ex) {
                     phlog($ex);
                     $this->log("%s\n", pht('Failed to update object %s using user %s.', $xobj->getObjectID(), $account->getUserPHID()));
                 }
             }
         }
     }
 }
 public function pullRefs(array $refs)
 {
     $token = $this->getGitHubAccessToken();
     if (!strlen($token)) {
         return null;
     }
     $template = id(new PhutilGitHubFuture())->setAccessToken($token);
     $futures = array();
     $id_map = mpull($refs, 'getObjectID', 'getObjectKey');
     foreach ($id_map as $key => $id) {
         list($user, $repository, $number) = $this->parseGitHubIssueID($id);
         $uri = "/repos/{$user}/{$repository}/issues/{$number}";
         $data = array();
         $futures[$key] = id(clone $template)->setRawGitHubQuery($uri, $data);
     }
     $results = array();
     $failed = array();
     foreach (new FutureIterator($futures) as $key => $future) {
         try {
             $results[$key] = $future->resolve();
         } catch (Exception $ex) {
             if ($ex instanceof HTTPFutureResponseStatus && $ex->getStatusCode() == 404) {
                 // TODO: Do we end up here for deleted objects and invisible
                 // objects?
             } else {
                 phlog($ex);
                 $failed[$key] = $ex;
             }
         }
     }
     $viewer = $this->getViewer();
     foreach ($refs as $ref) {
         $ref->setAttribute('name', pht('GitHub Issue %s', $ref->getObjectID()));
         $did_fail = idx($failed, $ref->getObjectKey());
         if ($did_fail) {
             $ref->setSyncFailed(true);
             continue;
         }
         $result = idx($results, $ref->getObjectKey());
         if (!$result) {
             continue;
         }
         $body = $result->getBody();
         $ref->setIsVisible(true);
         $ref->setAttribute('api.raw', $body);
         $ref->setAttribute('name', $body['title']);
         $obj = $ref->getExternalObject();
         $this->fillObjectFromData($obj, $result);
         $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
         $obj->save();
         unset($unguarded);
     }
 }
 public static function tryToPostMessage(array $data)
 {
     if (!PhabricatorEnv::getEnvConfig('notification.enabled')) {
         return;
     }
     try {
         self::postMessage($data);
     } catch (Exception $ex) {
         // Just ignore any issues here.
         phlog($ex);
     }
 }
 public function execute(PhutilArgumentParser $args)
 {
     $console = PhutilConsole::getConsole();
     $is_all = $args->getArg('all');
     $is_type = $args->getArg('type');
     $is_force = $args->getArg('force');
     $obj_names = $args->getArg('objects');
     if ($obj_names && ($is_all || $is_type)) {
         throw new PhutilArgumentUsageException(pht("You can not name objects to index alongside the '%s' or '%s' flags.", '--all', '--type'));
     } else {
         if (!$obj_names && !($is_all || $is_type)) {
             throw new PhutilArgumentUsageException(pht("Provide one of '%s', '%s' or a list of object names.", '--all', '--type'));
         }
     }
     if ($obj_names) {
         $phids = $this->loadPHIDsByNames($obj_names);
     } else {
         $phids = $this->loadPHIDsByTypes($is_type);
     }
     if (!$phids) {
         throw new PhutilArgumentUsageException(pht('Nothing to index!'));
     }
     if ($args->getArg('background')) {
         $is_background = true;
     } else {
         PhabricatorWorker::setRunAllTasksInProcess(true);
         $is_background = false;
     }
     if (!$is_background) {
         $console->writeOut("%s\n", pht('Run this workflow with "%s" to queue tasks for the daemon workers.', '--background'));
     }
     $groups = phid_group_by_type($phids);
     foreach ($groups as $group_type => $group) {
         $console->writeOut("%s\n", pht('Indexing %d object(s) of type %s.', count($group), $group_type));
     }
     $bar = id(new PhutilConsoleProgressBar())->setTotal(count($phids));
     $parameters = array('force' => $is_force);
     $any_success = false;
     foreach ($phids as $phid) {
         try {
             PhabricatorSearchWorker::queueDocumentForIndexing($phid, $parameters);
             $any_success = true;
         } catch (Exception $ex) {
             phlog($ex);
         }
         $bar->update(1);
     }
     $bar->done();
     if (!$any_success) {
         throw new Exception(pht('Failed to rebuild search index for any documents.'));
     }
 }
Exemplo n.º 25
0
 public function runBackgroundTasks()
 {
     foreach ($this->futures as $key => $future) {
         try {
             if ($future->isReady()) {
                 unset($this->futures[$key]);
             }
         } catch (Exception $ex) {
             unset($this->futures[$key]);
             phlog($ex);
         }
     }
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $diff_id = $request->getValue('diff_id');
     if (!$diff_id) {
         throw new ConduitException('ERR_BAD_DIFF');
     }
     $file = $request->getValue('file');
     $name = $request->getValue('name');
     $message = $request->getValue('message');
     $result = $request->getValue('result');
     $diff_property = id(new DifferentialDiffProperty())->loadOneWhere('diffID = %d AND name = %s', $diff_id, 'arc:unit');
     if (!$diff_property) {
         throw new ConduitException('ERR_NO_RESULTS');
     }
     $diff = id(new DifferentialDiff())->load($diff_id);
     $unit_results = $diff_property->getData();
     $postponed_count = 0;
     $unit_status = null;
     foreach ($unit_results as &$unit_result) {
         // Update the results for the test that has the same path.
         if (($unit_result['name'] === $file || $unit_result['name'] === $diff->getSourcePath() . $file) && $unit_result['result'] === DifferentialUnitTestResult::RESULT_POSTPONED) {
             $unit_result['name'] = $name;
             $unit_result['result'] = $result;
             $unit_result['userdata'] = $message;
             $unit_status = $result;
             break;
         }
     }
     unset($unit_result);
     if (!$unit_status) {
         phlog("Could not update test results: {$diff_id} {$file} {$name}" . " {$result} {$message}");
         return;
     }
     $diff_property->setData($unit_results);
     $diff_property->save();
     foreach ($unit_results as $unit_result) {
         if ($unit_result['result'] == DifferentialUnitTestResult::RESULT_POSTPONED) {
             $postponed_count++;
         }
     }
     $status_codes = array(DifferentialUnitTestResult::RESULT_PASS => DifferentialUnitStatus::UNIT_OKAY, DifferentialUnitTestResult::RESULT_UNSOUND => DifferentialUnitStatus::UNIT_WARN, DifferentialUnitTestResult::RESULT_FAIL => DifferentialUnitStatus::UNIT_FAIL, DifferentialUnitTestResult::RESULT_SKIP => DifferentialUnitStatus::UNIT_SKIP, DifferentialUnitTestResult::RESULT_POSTPONED => DifferentialUnitStatus::UNIT_POSTPONED);
     if ($diff->getUnitStatus() == DifferentialUnitStatus::UNIT_POSTPONED) {
         if ($postponed_count == 0 || $unit_status != DifferentialUnitTestResult::RESULT_PASS) {
             $diff->setUnitStatus(idx($status_codes, $unit_status, DifferentialUnitStatus::UNIT_NONE));
             $diff->save();
         }
     }
     return;
 }
 public function handleRequest(AphrontRequest $request)
 {
     // No CSRF for Mailgun.
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
     if (!$this->verifyMessage()) {
         throw new Exception(pht('Mail signature is not valid. Check your Mailgun API key.'));
     }
     $raw_headers = $request->getStr('message-headers');
     $raw_dict = array();
     if (strlen($raw_headers)) {
         $raw_headers = phutil_json_decode($raw_headers);
         foreach ($raw_headers as $raw_header) {
             list($name, $value) = $raw_header;
             $raw_dict[$name] = $value;
         }
     }
     $headers = array('to' => $request->getStr('recipient'), 'from' => $request->getStr('from'), 'subject' => $request->getStr('subject')) + $raw_dict;
     $received = new PhabricatorMetaMTAReceivedMail();
     $received->setHeaders($headers);
     $received->setBodies(array('text' => $request->getStr('stripped-text'), 'html' => $request->getStr('stripped-html')));
     $file_phids = array();
     foreach ($_FILES as $file_raw) {
         try {
             $file = PhabricatorFile::newFromPHPUpload($file_raw, array('viewPolicy' => PhabricatorPolicies::POLICY_NOONE));
             $file_phids[] = $file->getPHID();
         } catch (Exception $ex) {
             phlog($ex);
         }
     }
     $received->setAttachments($file_phids);
     try {
         $received->save();
         $received->processReceivedMail();
     } catch (Exception $ex) {
         // We can get exceptions here in two cases.
         // First, saving the message may throw if we have already received a
         // message with the same Message ID. In this case, we're declining to
         // process a duplicate message, so failing silently is correct.
         // Second, processing the message may throw (for example, if it contains
         // an invalid !command). This will generate an email as a side effect,
         // so we don't need to explicitly handle the exception here.
         // In these cases, we want to return HTTP 200. If we do not, MailGun will
         // re-transmit the message later.
         phlog($ex);
     }
     $response = new AphrontWebpageResponse();
     $response->setContent(pht("Got it! Thanks, Mailgun!\n"));
     return $response;
 }
 public function setException(Exception $exception)
 {
     // Log the exception unless it's specifically a silent malformed request
     // exception.
     $should_log = true;
     if ($exception instanceof AphrontMalformedRequestException) {
         if ($exception->getIsUnlogged()) {
             $should_log = false;
         }
     }
     if ($should_log) {
         phlog($exception);
     }
     $this->exception = $exception;
     return $this;
 }
Exemplo n.º 29
0
 /**
  * Publishes stories into JIRA using the JIRA API.
  */
 protected function publishFeedStory()
 {
     $story = $this->getFeedStory();
     $viewer = $this->getViewer();
     $provider = $this->getProvider();
     $object = $this->getStoryObject();
     $publisher = $this->getPublisher();
     $jira_issue_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($object->getPHID(), PhabricatorEdgeConfig::TYPE_PHOB_HAS_JIRAISSUE);
     if (!$jira_issue_phids) {
         $this->log("Story is about an object with no linked JIRA issues.\n");
         return;
     }
     $xobjs = id(new DoorkeeperExternalObjectQuery())->setViewer($viewer)->withPHIDs($jira_issue_phids)->execute();
     if (!$xobjs) {
         $this->log("Story object has no corresponding external JIRA objects.\n");
         return;
     }
     $try_users = $this->findUsersToPossess();
     if (!$try_users) {
         $this->log("No users to act on linked JIRA objects.\n");
         return;
     }
     $story_text = $this->renderStoryText();
     $xobjs = mgroup($xobjs, 'getApplicationDomain');
     foreach ($xobjs as $domain => $xobj_list) {
         $accounts = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs($try_users)->withAccountTypes(array($provider->getProviderType()))->withAccountDomains(array($domain))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
         // Reorder accounts in the original order.
         // TODO: This needs to be adjusted if/when we allow you to link multiple
         // accounts.
         $accounts = mpull($accounts, null, 'getUserPHID');
         $accounts = array_select_keys($accounts, $try_users);
         foreach ($xobj_list as $xobj) {
             foreach ($accounts as $account) {
                 try {
                     $provider->newJIRAFuture($account, 'rest/api/2/issue/' . $xobj->getObjectID() . '/comment', 'POST', array('body' => $story_text))->resolveJSON();
                     break;
                 } catch (HTTPFutureResponseStatus $ex) {
                     phlog($ex);
                     $this->log("Failed to update object %s using user %s.\n", $xobj->getObjectID(), $account->getUserPHID());
                 }
             }
         }
     }
 }
 public final function handleRequest(AphrontRequest $request)
 {
     $data = $request->getURIMap();
     $project = $data['gerritProject'];
     if (!isset(self::$projects[$project])) {
         return new Aphront404Response();
     }
     $CALLSIGN = self::$projects[$project];
     if ($data['action'] == 'branch') {
         if (!isset($data['branch'])) {
             return new Aphront404Response();
         }
         $branch = $data['branch'];
         // get rid of refs/heads prefix
         $branch = str_replace('refs/heads', '', $branch);
         $branch = trim($branch, '/');
         $branch = str_replace('HEAD', '', $branch);
         // double encode any forward slashes in ref.
         $branch = str_replace('/', '%252F', $branch);
         if (strlen($branch) == 0) {
             return id(new AphrontRedirectResponse())->setURI("/diffusion/{$CALLSIGN}/browse/");
         } else {
             return id(new AphrontRedirectResponse())->setURI("/diffusion/{$CALLSIGN}/browse/{$branch}/");
         }
     }
     if ($data['action'] == 'browse') {
         if (!isset($data['branch']) || !isset($data['file'])) {
             return new Aphront404Response();
         }
         $branch = $data['branch'];
         $file = $data['file'];
         return id(new AphrontRedirectResponse())->setURI("/diffusion/{$CALLSIGN}/browse/{$branch}/{$file}");
     }
     if ($data['action'] == 'revision') {
         $sha = isset($data['sha']) ? $data['sha'] : $data['branch'];
         return id(new AphrontRedirectResponse())->setURI('/r' . $CALLSIGN . $sha);
     }
     if ($data['action'] == 'project') {
         return id(new AphrontRedirectResponse())->setURI("/diffusion/{$CALLSIGN}/");
     }
     phlog('did not match any repository redirect action');
     return new Aphront404Response();
 }