public function search(Command $command) { if ($command->hasParameters(1)) { // !!rfcs some-rfc-name return yield from $this->getRFC($command); } /** @var HttpResponse $response */ $response = (yield $this->httpClient->request(self::BASE_URI)); if ($response->getStatus() !== 200) { return $this->chatClient->postMessage($command->getRoom(), "Nope, we can't have nice things."); } $dom = domdocument_load_html($response->getBody()); $list = $dom->getElementById("in_voting_phase")->nextSibling->nextSibling->getElementsByTagName("ul")->item(0); $rfcsInVoting = []; foreach ($list->childNodes as $node) { if ($node instanceof \DOMText) { continue; } /** @var \DOMElement $node */ /** @var \DOMElement $href */ $href = $node->getElementsByTagName("a")->item(0); $rfcsInVoting[] = sprintf("[%s](%s)", trim($href->textContent), \Sabre\Uri\resolve(self::BASE_URI, $href->getAttribute("href"))); } yield from $this->unpinPreviousMessage($command->getRoom()); if (empty($rfcsInVoting)) { if ((yield $this->pluginData->exists('lastpinid', $command->getRoom()))) { (yield $this->pluginData->unset('lastpinid', $command->getRoom())); } return $this->chatClient->postMessage($command->getRoom(), "Sorry, but we can't have nice things."); } /** @var PostedMessage $postedMessage */ $postedMessage = (yield $this->chatClient->postMessage($command->getRoom(), sprintf("[tag:rfc-vote] %s", implode(" | ", $rfcsInVoting)))); (yield $this->pluginData->set('lastpinid', $postedMessage->getId(), $command->getRoom())); return $this->chatClient->pinOrUnpinMessage($postedMessage, $command->getRoom()); }
private function doPollForCertificate(string $location) : Generator { do { /** @var Response $response */ $response = (yield $this->acmeClient->get($location)); if ($response->getStatus() === 202) { if (!$response->hasHeader("retry-after")) { throw new AcmeException("Protocol Violation: No Retry-After Header"); } $waitTime = $this->parseRetryAfter($response->getHeader("retry-after")[0]); $waitTime = min(max($waitTime, 2), 60); (yield new Pause($waitTime * 1000)); continue; } elseif ($response->getStatus() === 200) { $pem = chunk_split(base64_encode($response->getBody()), 64, "\n"); $pem = "-----BEGIN CERTIFICATE-----\n" . $pem . "-----END CERTIFICATE-----\n"; $certificates = [$pem]; // prevent potential infinite loop $maximumChainLength = 5; while ($response->hasHeader("link")) { if (!$maximumChainLength--) { throw new AcmeException("Too long certificate chain"); } $links = $response->getHeader("link"); foreach ($links as $link) { if (preg_match("#<(.*?)>;rel=\"up\"#x", $link, $match)) { $uri = \Sabre\Uri\resolve($response->getRequest()->getUri(), $match[1]); $response = (yield $this->acmeClient->get($uri)); $pem = chunk_split(base64_encode($response->getBody()), 64, "\n"); $pem = "-----BEGIN CERTIFICATE-----\n" . $pem . "-----END CERTIFICATE-----\n"; $certificates[] = $pem; } } } return $certificates; } } while (1); throw new AcmeException("Couldn't fetch certificate"); }
/** * Get all urls from html dom. * * @param string $baseUrl * @param string $string * @return array */ public function getDomUrls($baseUrl, $string) { // Remove all html comments. $string = preg_replace('#<!--.*-->#isU', '', $string); // Store all links to $matches variable. preg_match_all('#(src|href)="(.*)"#iU', $string, $matches); $isOriginalHost = $this->host === \Sabre\Uri\parse($baseUrl)['host']; foreach ($matches[2] as $match) { if (false === parse_url($match)) { continue; } $url = \Sabre\Uri\resolve($baseUrl, $match); $components = \Sabre\Uri\parse($url); if (in_array($components['scheme'], ['http', 'https'])) { $urls[] = ['url' => is_null($components['fragment']) ? $url : strstr($url, '#', true), 'external' => !$isOriginalHost]; } } return isset($urls) ? $urls : []; }
private function api($apiEndpoint) { return function () use($apiEndpoint) { $args = func_get_args(); // Last argument is callable $cb = array_pop($args); if (!is_callable($cb)) { array_push($args, $cb); unset($cb); } // Content body if (in_array($apiEndpoint['method'], ['PATCH', 'POST', 'PUT'])) { $body = array_pop($args); } $querystring = array_pop($args); // Query Strings are associative arrays if (!is_array($querystring) || array_keys($querystring) === range(0, count($querystring) - 1)) { array_push($args, $querystring); unset($querystring); } // If query specified with the endpoint use it ... if (array_key_exists('query', $apiEndpoint)) { if (!isset($querystring)) { $querystring = array(); } // ... override with query from call $querystring = array_merge($apiEndpoint['query'], $querystring); } // rest in args are params $url = preg_replace_callback("/(:[a-zA-Z_][a-zA-Z0-9_]*)/", function ($m) use(&$args) { return array_shift($args); }, \Sabre\Uri\resolve($this->baseURL, $apiEndpoint['path'])); $opts = array_merge(array(), $this->opts); // Add Query strings if (isset($querystring)) { if (!array_key_exists('query', $opts)) { $opts['query'] = array(); } $opts['query'] = array_merge($opts['query'], $querystring); } // Add User-Agent if (!array_key_exists('header', $opts)) { $opts['header'] = array(); } $opts['header'] = array_merge(array('User-Agent' => 'wrapi-client'), $opts['header']); // Add body if (isset($body)) { if (is_array($body) && array_keys($body) !== range(0, count($body) - 1)) { $opts['json'] = $body; } else { $opts['body'] = $body; } } // Request & Response $client = new \GuzzleHttp\Client($this->guzzleOpts); try { $response = $client->request($apiEndpoint['method'], $url, $opts); $respBody = (string) $response->getBody(); // Parse json if content-type is 'appication/json' if ($response->hasHeader('Content-Type') && strpos($response->getHeader('Content-Type')[0], 'application/json') === 0) { $respBody = json_decode($respBody, TRUE); } // Has callback? if (isset($cb)) { $cb(null, $respBody, $response); return; } else { return $respBody; } } catch (RequestException $re) { if (isset($cb)) { $cb($e); } else { throw $e; } } catch (Exception $e) { if (isset($cb)) { $cb($e); } else { throw $e; } } }; }
/** * This method is called during xml parsing. * * This method is called statically, this is because in theory this method * may be used as a type of constructor, or factory method. * * Often you want to return an instance of the current class, but you are * free to return other data as well. * * Important note 2: You are responsible for advancing the reader to the * next element. Not doing anything will result in a never-ending loop. * * If you just want to skip parsing for this element altogether, you can * just call $reader->next(); * * $reader->parseSubTree() will parse the entire sub-tree, and advance to * the next element. * * @param Xml\Reader $reader * @return mixed */ static function xmlDeserialize(Xml\Reader $reader) { return new self(\Sabre\Uri\resolve($reader->contextUri, $reader->readText())); }