@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at upstream/main 123 lines 3.0 kB view raw
1<?php 2 3abstract class PhabricatorSSHWorkflow 4 extends PhutilArgumentWorkflow { 5 6 // NOTE: We are explicitly extending "PhutilArgumentWorkflow", not 7 // "PhabricatorManagementWorkflow". We want to avoid inheriting "getViewer()" 8 // and other methods which assume workflows are administrative commands 9 // like `bin/storage`. 10 11 private $sshUser; 12 private $iochannel; 13 private $errorChannel; 14 private $isClusterRequest; 15 private $originalArguments; 16 private $requestIdentifier; 17 18 public function isExecutable() { 19 return false; 20 } 21 22 public function setErrorChannel(PhutilChannel $error_channel) { 23 $this->errorChannel = $error_channel; 24 return $this; 25 } 26 27 public function getErrorChannel() { 28 return $this->errorChannel; 29 } 30 31 public function setSSHUser(PhabricatorUser $ssh_user) { 32 $this->sshUser = $ssh_user; 33 return $this; 34 } 35 36 public function getSSHUser() { 37 return $this->sshUser; 38 } 39 40 public function setIOChannel(PhutilChannel $channel) { 41 $this->iochannel = $channel; 42 return $this; 43 } 44 45 public function getIOChannel() { 46 return $this->iochannel; 47 } 48 49 public function readAllInput() { 50 $channel = $this->getIOChannel(); 51 while ($channel->update()) { 52 PhutilChannel::waitForAny(array($channel)); 53 if (!$channel->isOpenForReading()) { 54 break; 55 } 56 } 57 return $channel->read(); 58 } 59 60 public function writeIO($data) { 61 $this->getIOChannel()->write($data); 62 return $this; 63 } 64 65 public function writeErrorIO($data) { 66 $this->getErrorChannel()->write($data); 67 return $this; 68 } 69 70 protected function newPassthruCommand() { 71 return id(new PhabricatorSSHPassthruCommand()) 72 ->setErrorChannel($this->getErrorChannel()); 73 } 74 75 public function setIsClusterRequest($is_cluster_request) { 76 $this->isClusterRequest = $is_cluster_request; 77 return $this; 78 } 79 80 public function getIsClusterRequest() { 81 return $this->isClusterRequest; 82 } 83 84 public function setOriginalArguments(array $original_arguments) { 85 $this->originalArguments = $original_arguments; 86 return $this; 87 } 88 89 public function getOriginalArguments() { 90 return $this->originalArguments; 91 } 92 93 public function setRequestIdentifier($request_identifier) { 94 $this->requestIdentifier = $request_identifier; 95 return $this; 96 } 97 98 public function getRequestIdentifier() { 99 return $this->requestIdentifier; 100 } 101 102 public function getSSHRemoteAddress() { 103 $ssh_client = getenv('SSH_CLIENT'); 104 if (!$ssh_client || !strlen($ssh_client)) { 105 return null; 106 } 107 108 // TODO: When commands are proxied, the original remote address should 109 // also be proxied. 110 111 // This has the format "<ip> <remote-port> <local-port>". Grab the IP. 112 $remote_address = head(explode(' ', $ssh_client)); 113 114 try { 115 $address = PhutilIPAddress::newAddress($remote_address); 116 } catch (Exception $ex) { 117 return null; 118 } 119 120 return $address->getAddress(); 121 } 122 123}