function handle_start(&$event, $param)
 {
     if (!isset($_FILES['imageshack_file'])) {
         return;
     }
     if ($_FILES['imageshack_file']['error'] || !is_uploaded_file($_FILES['imageshack_file']['tmp_name'])) {
         msg(sprintf('The was a problem receiving the file from you (error %d)', $_FILES['imageshack_file']['error']), -1);
         return;
     }
     require_once DOKU_INC . '/inc/HTTPClient.php';
     $http = new HTTPClient();
     $http->timeout = 60;
     $http->headers['Content-Type'] = 'multipart/form-data';
     $data = array('xml' => 'yes', 'fileupload' => array('filename' => $_FILES['imageshack_file']['name'], 'mimetype' => $_FILES['imageshack_file']['type'], 'body' => file_get_contents($_FILES['imageshack_file']['tmp_name'])));
     $xml = $http->post('http://imageshack.us/index.php', $data);
     if (!$xml) {
         msg('There was a problem with uploading your file to imageshack: ' . $http->error, -1);
         return;
     }
     $xml = new SimpleXMLElement($xml);
     if (!$xml) {
         msg('ImageShack did not accept your upload', -1);
         return;
     }
     list($w, $h) = explode('x', (string) $xml->resolution[0]);
     $_SESSION['imageshack'][] = array('link' => (string) $xml->image_link[0], 'adlink' => (string) $xml->ad_link[0], 'name' => (string) $xml->image_name[0], 'width' => $w, 'height' => $h, 'size' => (string) $xml->filesize[0]);
 }
Пример #2
0
 /**
  * Sign and post the given Atom entry as a Salmon message.
  *
  * Side effects: may generate a keypair on-demand for the given user,
  * which can be very slow on some systems.
  *
  * @param string $endpoint_uri
  * @param string $xml string representation of payload
  * @param Profile $actor local user profile whose keys to sign with
  * @return boolean success
  */
 public function post($endpoint_uri, $xml, $actor)
 {
     if (empty($endpoint_uri)) {
         return false;
     }
     foreach ($this->formatClasses() as $class) {
         try {
             $envelope = $this->createMagicEnv($xml, $actor, $class);
         } catch (Exception $e) {
             common_log(LOG_ERR, "Salmon unable to sign: " . $e->getMessage());
             return false;
         }
         $headers = array('Content-Type: application/magic-envelope+xml');
         try {
             $client = new HTTPClient();
             $client->setBody($envelope);
             $response = $client->post($endpoint_uri, $headers);
         } catch (HTTP_Request2_Exception $e) {
             common_log(LOG_ERR, "Salmon ({$class}) post to {$endpoint_uri} failed: " . $e->getMessage());
             continue;
         }
         if ($response->getStatus() != 200) {
             common_log(LOG_ERR, "Salmon ({$class}) at {$endpoint_uri} returned status " . $response->getStatus() . ': ' . $response->getBody());
             continue;
         }
         // Success!
         return true;
     }
     return false;
 }
 function testPostRequestIsUnsuccessful()
 {
     \VCR\VCR::insertCassette('gathercontent_post_projects_failure.yml');
     $subject = new HTTPClient('*****@*****.**', 'bogus-api-key');
     $response = $subject->post('https://api.gathercontent.com/projects', ['account_id' => '20225', 'name' => 'Project Name'], ['Accept: application/vnd.gathercontent.v0.5+json']);
     $this->assertNotEquals(200, $response->status);
     $this->assertEquals('Invalid credentials.', $response->body);
 }
Пример #4
0
 /**
  * @group internet
  */
 function test_simplepost()
 {
     $http = new HTTPClient();
     $data = $http->post($this->server . '/post', array('foo' => 'bar'));
     $this->assertFalse($data === false, 'HTTP response');
     $resp = json_decode($data, true);
     $this->assertTrue(is_array($resp), 'JSON response');
     $this->assertArrayHasKey('form', $resp);
     $this->assertEquals(array('foo' => 'bar'), $resp['form']);
 }
Пример #5
0
 /**
  * Sign and post the given Atom entry as a Salmon message.
  *
  * Side effects: may generate a keypair on-demand for the given user,
  * which can be very slow on some systems (like those without php5-gmp).
  *
  * @param string $endpoint_uri
  * @param string $xml string representation of payload
  * @param User $user local user profile whose keys we sign with
  * @return boolean success
  */
 public static function post($endpoint_uri, $xml, User $user)
 {
     if (empty($endpoint_uri)) {
         common_debug('No endpoint URI for Salmon post to ' . $user->getUri());
         return false;
     }
     try {
         $magic_env = MagicEnvelope::signAsUser($xml, $user);
         $envxml = $magic_env->toXML();
     } catch (Exception $e) {
         common_log(LOG_ERR, "Salmon unable to sign: " . $e->getMessage());
         return false;
     }
     $headers = array('Content-Type: application/magic-envelope+xml');
     try {
         $client = new HTTPClient();
         $client->setBody($envxml);
         $response = $client->post($endpoint_uri, $headers);
     } catch (HTTP_Request2_Exception $e) {
         common_log(LOG_ERR, "Salmon post to {$endpoint_uri} failed: " . $e->getMessage());
         return false;
     }
     // Diaspora wants a slightly different formatting on the POST (other Content-type, so body needs "xml=")
     if ($response->getStatus() === 422) {
         common_debug(sprintf('Salmon (from profile %d) endpoint %s returned status %s. Diaspora? Will try again! Body: %s', $user->id, $endpoint_uri, $response->getStatus(), $response->getBody()));
         $headers = array('Content-Type: application/x-www-form-urlencoded');
         $client->setBody('xml=' . Magicsig::base64_url_encode($envxml));
         $response = $client->post($endpoint_uri, $headers);
     }
     // 200 OK is the best response
     // 202 Accepted is what we get from Diaspora for example
     if (!in_array($response->getStatus(), array(200, 202))) {
         common_log(LOG_ERR, sprintf('Salmon (from profile %d) endpoint %s returned status %s: %s', $user->id, $endpoint_uri, $response->getStatus(), $response->getBody()));
         return false;
     }
     // Success!
     return true;
 }
 /**
  * Ping external hub about this update.
  * The hub will pull the feed and check for new items later.
  * Not guaranteed safe in an environment with database replication.
  *
  * @param string $feed feed topic URI
  * @param string $hub PuSH hub URI
  * @fixme can consolidate pings for user & group posts
  */
 function pushFeedExternal($feed, $hub)
 {
     $client = new HTTPClient();
     try {
         $data = array('hub.mode' => 'publish', 'hub.url' => $feed);
         $response = $client->post($hub, array(), $data);
         if ($response->getStatus() == 204) {
             common_log(LOG_INFO, "PuSH ping to hub {$hub} for {$feed} ok");
             return true;
         } else {
             common_log(LOG_ERR, "PuSH ping to hub {$hub} for {$feed} failed with HTTP " . $response->getStatus() . ': ' . $response->getBody());
         }
     } catch (Exception $e) {
         common_log(LOG_ERR, "PuSH ping to hub {$hub} for {$feed} failed: " . $e->getMessage());
         return false;
     }
 }
Пример #7
0
 protected function doSubscribe($mode)
 {
     $orig = clone $this;
     $this->verify_token = common_good_rand(16);
     if ($mode == 'subscribe') {
         $this->secret = common_good_rand(32);
     }
     $this->sub_state = $mode;
     $this->update($orig);
     unset($orig);
     try {
         $callback = common_local_url('pushcallback', array('feed' => $this->id));
         $headers = array('Content-Type: application/x-www-form-urlencoded');
         $post = array('hub.mode' => $mode, 'hub.callback' => $callback, 'hub.verify' => 'sync', 'hub.verify_token' => $this->verify_token, 'hub.secret' => $this->secret, 'hub.topic' => $this->uri);
         $client = new HTTPClient();
         if ($this->huburi) {
             $hub = $this->huburi;
         } else {
             if (common_config('feedsub', 'fallback_hub')) {
                 $hub = common_config('feedsub', 'fallback_hub');
                 if (common_config('feedsub', 'hub_user')) {
                     $u = common_config('feedsub', 'hub_user');
                     $p = common_config('feedsub', 'hub_pass');
                     $client->setAuth($u, $p);
                 }
             } else {
                 throw new FeedSubException('WTF?');
             }
         }
         $response = $client->post($hub, $headers, $post);
         $status = $response->getStatus();
         if ($status == 202) {
             common_log(LOG_INFO, __METHOD__ . ': sub req ok, awaiting verification callback');
             return true;
         } else {
             if ($status == 204) {
                 common_log(LOG_INFO, __METHOD__ . ': sub req ok and verified');
                 return true;
             } else {
                 if ($status >= 200 && $status < 300) {
                     common_log(LOG_ERR, __METHOD__ . ": sub req returned unexpected HTTP {$status}: " . $response->getBody());
                     return false;
                 } else {
                     common_log(LOG_ERR, __METHOD__ . ": sub req failed with HTTP {$status}: " . $response->getBody());
                     return false;
                 }
             }
         }
     } catch (Exception $e) {
         // wtf!
         common_log(LOG_ERR, __METHOD__ . ": error \"{$e->getMessage()}\" hitting hub {$this->huburi} subscribing to {$this->uri}");
         $orig = clone $this;
         $this->verify_token = '';
         $this->sub_state = 'inactive';
         $this->update($orig);
         unset($orig);
         return false;
     }
 }
Пример #8
0
 /**
  * HTTP POST a notification that a feed has been updated
  * ('ping the cloud').
  *
  * @param String $endpoint URL of the notification handler
  * @param String $feed     the feed being subscribed to
  *
  * @return boolean success
  */
 function postUpdate($endpoint, $feed)
 {
     $headers = array();
     $postdata = array('url' => $feed);
     try {
         $client = new HTTPClient();
         $response = $client->post($endpoint, $headers, $postdata);
     } catch (HTTP_Request2_Exception $e) {
         common_log(LOG_INFO, 'RSSCloud plugin - failure notifying ' . $endpoint . ' that feed ' . $feed . ' has changed: ' . $e->getMessage());
         return false;
     }
     $status = $response->getStatus();
     if ($status >= 200 && $status < 300) {
         common_log(LOG_INFO, 'RSSCloud plugin - success notifying ' . $endpoint . ' that feed ' . $feed . ' has changed.');
         return true;
     } else {
         common_log(LOG_INFO, 'RSSCloud plugin - failure notifying ' . $endpoint . ' that feed ' . $feed . ' has changed: got HTTP ' . $status);
         return false;
     }
 }
Пример #9
0
 protected function pingHttp($target, $data)
 {
     $client = new HTTPClient();
     $result = $client->post($target, array(), $data);
     if (!$result->isOk()) {
         common_log(LOG_ERR, __METHOD__ . ' HTTP ' . $result->getStatus() . ': ' . $result->getBody());
     }
 }
Пример #10
0
function apiCall($call, $data = array())
{
    global $CONF;
    $http = new HTTPClient();
    $input = array('api_key' => $CONF['api_key'], 'user_app_key' => $CONF['app_key']);
    $input = array_merge($input, $data);
    $xml = $http->post('http://api.ping.fm/v1/' . $call, $input);
    if ($xml === false) {
        return $false;
    }
    $xml = new SimpleXMLElement($xml);
    if ($xml['status'] != 'OK') {
        return false;
    }
    return $xml;
}
Пример #11
0
print "\n\n";
echo "== Testing local verification ==\n\n";
$magic_env = new MagicEnvelope($envxml);
$activity = new Activity($magic_env->getPayload()->documentElement);
$actprofile = Profile::fromUri($activity->actor->id);
$ok = $magic_env->verify($actprofile);
if ($ok) {
    print "OK\n\n";
} else {
    print "FAIL\n\n";
}
if (have_option('--verify')) {
    $url = 'http://www.madebymonsieur.com/ostatus_discovery/magic_env/validate/';
    echo "== Testing remote verification ==\n\n";
    print "Sending for verification to {$url} ...\n";
    $client = new HTTPClient();
    $response = $client->post($url, array(), array('magic_env' => $envxml));
    print $response->getStatus() . "\n\n";
    print $response->getBody() . "\n\n";
}
if (have_option('--slap')) {
    $url = get_option_value('--slap');
    echo "== Remote salmon slap ==\n\n";
    print "Sending signed Salmon slap to {$url} ...\n";
    $ok = Salmon::post($url, $entry, $profile->getUser());
    if ($ok) {
        print "OK\n\n";
    } else {
        print "FAIL\n\n";
    }
}
Пример #12
0
 /**
  * Send a 'fat ping' to the subscriber's callback endpoint
  * containing the given Atom feed chunk.
  *
  * Determination of which items to send should be done at
  * a higher level; don't just shove in a complete feed!
  *
  * @param string $atom well-formed Atom feed
  * @throws Exception (HTTP or general)
  */
 function push($atom)
 {
     $headers = array('Content-Type: application/atom+xml');
     if ($this->secret) {
         $hmac = hash_hmac('sha1', $atom, $this->secret);
         $headers[] = "X-Hub-Signature: sha1={$hmac}";
     } else {
         $hmac = '(none)';
     }
     common_log(LOG_INFO, "About to push feed to {$this->callback} for {$this->topic}, HMAC {$hmac}");
     $request = new HTTPClient();
     $request->setBody($atom);
     $response = $request->post($this->callback, $headers);
     if ($response->isOk()) {
         return true;
     } else {
         // TRANS: Exception. %1$s is a response status code, %2$s is the body of the response.
         throw new Exception(sprintf(_m('Callback returned status: %1$s. Body: %2$s'), $response->getStatus(), trim($response->getBody())));
     }
 }
Пример #13
0
 function login($formatter, $params)
 {
     global $DBInfo;
     global $g4, $g4_root_dir;
     $g4_root_dir = !empty($DBInfo->g4_root_dir) ? $DBInfo->g4_root_dir : __DIR__ . '/../../../gb4';
     $g4_root_url = !empty($DBInfo->g4_root_url) ? $DBInfo->g4_root_url : '/gb4';
     include_once "{$g4_root_dir}/config.php";
     // g4 config file
     if (!defined('G5_VERSION')) {
         include_once "{$g4_root_dir}/lib/constant.php";
         // constants
     }
     //include_once("$g4_root_dir/lib/common.lib.php"); // common library
     $post_params = array();
     if (defined('G5_VERSION')) {
         $login_path = G5_BBS_URL . '/login_check.php';
     } else {
         $login_path = $g4_root_url . $g4['bbs_path'] . '/login_check.php';
     }
     // set post parameters
     $post_params['mb_id'] = $params['login_id'];
     $post_params['mb_password'] = $params['password'];
     // setup post url
     $port = $_SERVER['SERVER_PORT'] != 80 ? ':' . $_SERVER['SERVER_PORT'] : '';
     $http = 'http' . (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : '') . '://';
     $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
     if (isset($_SERVER['HTTP_HOST']) && preg_match('/:[0-9]+$/', $host)) {
         $host = preg_replace('/:[0-9]+$/', '', $host);
     }
     $login_path = $http . $host . $port . $login_path;
     require_once dirname(__FILE__) . "/../../lib/HTTPClient.php";
     $http = new HTTPClient();
     $http->cookie = $_COOKIE;
     // set current cookies
     $http->max_redirect = 0;
     // do not redirect
     $http->post($login_path, $post_params);
     if (isset($http->resp_headers['set-cookie'])) {
         foreach ((array) $http->resp_headers['set-cookie'] as $c) {
             header('Set-Cookie: ' . $c, false);
         }
     }
 }
Пример #14
0
 public function onSalmonSlap($endpoint_uri, MagicEnvelope $magic_env, Profile $target = null)
 {
     $envxml = $magic_env->toXML($target);
     $headers = array('Content-Type: application/magic-envelope+xml');
     try {
         $client = new HTTPClient();
         $client->setBody($envxml);
         $response = $client->post($endpoint_uri, $headers);
     } catch (HTTP_Request2_Exception $e) {
         common_log(LOG_ERR, "Salmon post to {$endpoint_uri} failed: " . $e->getMessage());
         return false;
     }
     if ($response->getStatus() === 422) {
         common_debug(sprintf('Salmon (from profile %d) endpoint %s returned status %s. We assume it is a Diaspora seed; will adapt and try again if that plugin is enabled!', $magic_env->getActor()->getID(), $endpoint_uri, $response->getStatus()));
         return true;
     }
     // 200 OK is the best response
     // 202 Accepted is what we get from Diaspora for example
     if (!in_array($response->getStatus(), array(200, 202))) {
         common_log(LOG_ERR, sprintf('Salmon (from profile %d) endpoint %s returned status %s: %s', $magic_env->getActor()->getID(), $endpoint_uri, $response->getStatus(), $response->getBody()));
         return true;
     }
     // Since we completed the salmon slap, we discontinue the event
     return false;
 }
Пример #15
0
 public function onSalmonSlap($endpoint_uri, MagicEnvelope $magic_env, Profile $target = null)
 {
     $envxml = $magic_env->toXML($target, 'diaspora');
     // Diaspora wants another POST format (base64url-encoded POST variable 'xml')
     $headers = array('Content-Type: application/x-www-form-urlencoded');
     // Another way to distinguish Diaspora from GNU social is that a POST with
     // $headers=array('Content-Type: application/magic-envelope+xml') would return
     // HTTP status code 422 Unprocessable Entity, at least as of 2015-10-04.
     try {
         $client = new HTTPClient();
         $client->setBody('xml=' . Magicsig::base64_url_encode($envxml));
         $response = $client->post($endpoint_uri, $headers);
     } catch (HTTP_Request2_Exception $e) {
         common_log(LOG_ERR, "Diaspora-flavoured Salmon post to {$endpoint_uri} failed: " . $e->getMessage());
         return false;
     }
     // 200 OK is the best response
     // 202 Accepted is what we get from Diaspora for example
     if (!in_array($response->getStatus(), array(200, 202))) {
         common_log(LOG_ERR, sprintf('Salmon (from profile %d) endpoint %s returned status %s: %s', $magic_env->getActor()->getID(), $endpoint_uri, $response->getStatus(), $response->getBody()));
         return true;
     }
     // Success!
     return false;
 }
Пример #16
0
 /**
  * Send a 'fat ping' to the subscriber's callback endpoint
  * containing the given Atom feed chunk.
  *
  * Determination of which items to send should be done at
  * a higher level; don't just shove in a complete feed!
  *
  * @param string $atom well-formed Atom feed
  * @throws Exception (HTTP or general)
  */
 function push($atom)
 {
     $headers = array('Content-Type: application/atom+xml');
     if ($this->secret) {
         $hmac = hash_hmac('sha1', $atom, $this->secret);
         $headers[] = "X-Hub-Signature: sha1={$hmac}";
     } else {
         $hmac = '(none)';
     }
     common_log(LOG_INFO, "About to push feed to {$this->callback} for {$this->topic}, HMAC {$hmac}");
     $request = new HTTPClient();
     $request->setBody($atom);
     $response = $request->post($this->callback, $headers);
     if ($response->isOk()) {
         return true;
     } else {
         throw new Exception("Callback returned status: " . $response->getStatus() . "; body: " . trim($response->getBody()));
     }
 }
Пример #17
0
    /**
     * @group internet
     */
    function test_lint()
    {
        // prepare a simple multipart message
        $mail = new TestMailer();
        $mail->to(array('Möp <*****@*****.**> ', ' foo <*****@*****.**>'));
        $mail->from('Me <*****@*****.**>');
        $mail->subject('This is a töst');
        $mail->setBody('Hello Wörld,

        please don\'t burn, okay?
        ');
        $mail->attachContent('some test data', 'text/plain', 'a text.txt');
        $msg = $mail->dump();
        $msglines = explode("\n", $msg);
        //echo $msg;
        // ask message lint if it is okay
        $html = new HTTPClient();
        $results = $html->post('http://tools.ietf.org/tools/msglint/msglint', array('msg' => $msg));
        if ($results === false) {
            $this->markTestSkipped('no response from validator');
            return;
        }
        // parse the result lines
        $lines = explode("\n", $results);
        $rows = count($lines);
        $i = 0;
        while (trim($lines[$i]) != '-----------' && $i < $rows) {
            $i++;
        }
        //skip preamble
        for ($i = $i + 1; $i < $rows; $i++) {
            $line = trim($lines[$i]);
            if ($line == '-----------') {
                break;
            }
            //skip appendix
            // get possible continuation of the line
            while ($lines[$i + 1][0] == ' ') {
                $line .= ' ' . trim($lines[$i + 1]);
                $i++;
            }
            // check the line for errors
            if (substr($line, 0, 5) == 'ERROR' || substr($line, 0, 7) == 'WARNING') {
                // ignore some errors
                if (strpos($line, "missing mandatory header 'return-path'")) {
                    continue;
                }
                #set by MDA
                if (strpos($line, "bare newline in text body decoded")) {
                    continue;
                }
                #seems to be false positive
                // get the context in which the error occured
                $errorin = '';
                if (preg_match('/line (\\d+)$/', $line, $m)) {
                    $errorin .= "\n" . $msglines[$m[1] - 1];
                }
                if (preg_match('/lines (\\d+)-(\\d+)$/', $line, $m)) {
                    for ($x = $m[1] - 1; $x < $m[2]; $x++) {
                        $errorin .= "\n" . $msglines[$x];
                    }
                }
                // raise the error
                throw new Exception($line . $errorin);
            }
        }
    }
Пример #18
0
 function login($formatter, $params)
 {
     global $Config;
     @session_start();
     // confirm session start
     // set xe_root_dir config option
     $xe_root_dir = !empty($Config['xe_root_dir']) ? $Config['xe_root_dir'] : dirname(__FILE__) . '/../../../xe';
     $xe_root_url = !empty($Config['xe_root_url']) ? $Config['xe_root_url'] : '/xe';
     // default xe_root_dir is 'xe' subdirectory of the parent dir of the moniwiki
     // init XE17, XE18
     define('__XE__', true);
     require_once $xe_root_dir . "/config/config.inc.php";
     // setup post params
     $post_params = array();
     $login_path = $xe_root_url . '/index.php';
     $post_params['user_id'] = $params['login_id'];
     $post_params['password'] = $params['password'];
     $post_params['act'] = 'procMemberLogin';
     // setup post url
     $port = $_SERVER['SERVER_PORT'] != 80 ? ':' . $_SERVER['SERVER_PORT'] : '';
     $http = 'http' . (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : '') . '://';
     $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
     if (isset($_SERVER['HTTP_HOST']) && preg_match('/:[0-9]+$/', $host)) {
         $host = preg_replace('/:[0-9]+$/', '', $host);
     }
     $login_path = $http . $host . $port . $login_path;
     $_SERVER['SCRIPT_NAME'] = $xe_root_url . '/index.php';
     require_once dirname(__FILE__) . "/../../lib/HTTPClient.php";
     $http = new HTTPClient();
     $http->cookie = $_COOKIE;
     // set current cookies
     $http->max_redirect = 0;
     // do not redirect
     $http->post($login_path, $post_params);
     if (isset($http->resp_headers['set-cookie'])) {
         foreach ((array) $http->resp_headers['set-cookie'] as $c) {
             header('Set-Cookie: ' . $c, false);
         }
     }
 }
Пример #19
0
 /**
  * Setting to subscribe means it is _waiting_ to become active. This
  * cannot be done in a transaction because there is a chance that the
  * remote script we're calling (as in the case of PuSHpress) performs
  * the lookup _while_ we're POSTing data, which means the transaction
  * never completes (PushcallbackAction gets an 'inactive' state).
  *
  * @return boolean true when everything is ok (throws Exception on fail)
  * @throws Exception on failure, can be HTTPClient's or our own.
  */
 protected function doSubscribe($mode)
 {
     $orig = clone $this;
     if ($mode == 'subscribe') {
         $this->secret = common_random_hexstr(32);
     }
     $this->sub_state = $mode;
     $this->update($orig);
     unset($orig);
     try {
         $callback = common_local_url('pushcallback', array('feed' => $this->id));
         $headers = array('Content-Type: application/x-www-form-urlencoded');
         $post = array('hub.mode' => $mode, 'hub.callback' => $callback, 'hub.verify' => 'async', 'hub.verify_token' => 'Deprecated-since-PuSH-0.4', 'hub.secret' => $this->secret, 'hub.topic' => $this->getUri());
         $client = new HTTPClient();
         if ($this->huburi) {
             $hub = $this->huburi;
         } else {
             if (common_config('feedsub', 'fallback_hub')) {
                 $hub = common_config('feedsub', 'fallback_hub');
                 if (common_config('feedsub', 'hub_user')) {
                     $u = common_config('feedsub', 'hub_user');
                     $p = common_config('feedsub', 'hub_pass');
                     $client->setAuth($u, $p);
                 }
             } else {
                 throw new FeedSubException('Server could not find a usable PuSH hub.');
             }
         }
         $response = $client->post($hub, $headers, $post);
         $status = $response->getStatus();
         // PuSH specificed response status code
         if ($status == 202) {
             common_log(LOG_INFO, __METHOD__ . ': sub req ok, awaiting verification callback');
             return;
         } else {
             if ($status >= 200 && $status < 300) {
                 common_log(LOG_ERR, __METHOD__ . ": sub req returned unexpected HTTP {$status}: " . $response->getBody());
             } else {
                 common_log(LOG_ERR, __METHOD__ . ": sub req failed with HTTP {$status}: " . $response->getBody());
             }
         }
     } catch (Exception $e) {
         common_log(LOG_ERR, __METHOD__ . ": error \"{$e->getMessage()}\" hitting hub {$this->huburi} subscribing to {$this->getUri()}");
         // Reset the subscription state.
         $orig = clone $this;
         $this->sub_state = 'inactive';
         $this->update($orig);
         // Throw the Exception again.
         throw $e;
     }
     throw new ServerException("{$mode} request failed.");
 }