function postContent() { $this->adminGatekeeper(); $request = $this->getInput('request'); $key = $this->getInput('key'); $username = $this->getInput('username'); $json = $this->getInput('json'); $follow_redirects = $this->getInput('follow_redirects'); $method = $this->getInput('method', 'GET'); $url = \Idno\Core\Idno::site()->config()->getURL(); if (strripos($url, '/') == strlen($url) - 1) { $url = substr($url, 0, strlen($url) - 1); } $url .= $request; $client = new Webservice(); if ($method == 'POST') { $result = $client->post($url, $json, array('X-KNOWN-USERNAME: '******'X-KNOWN-SIGNATURE: ' . base64_encode(hash_hmac('sha256', $request, $key, true)))); } else { $result = $client->get($url, null, array('X-KNOWN-USERNAME: '******'X-KNOWN-SIGNATURE: ' . base64_encode(hash_hmac('sha256', $request, $key, true)))); } $response = Webservice::getLastResponse(); $sent_request = Webservice::getLastRequest() . $json; $api_request = array('request' => $request, 'key' => $key, 'username' => $username, 'json' => $json, 'sent_request' => $sent_request, 'response' => gzencode($response, 9), 'method' => $method); \Idno\Core\Idno::site()->session()->set('api_request', $api_request); $this->forward(\Idno\Core\Idno::site()->config()->getURL() . 'admin/apitester/'); }
/** * Get parsed items from this feed * @return array|bool */ function retrieveItems() { $ws = new Webservice(); if ($content = $ws->get($this->getFeedURL())) { return \Idno\Core\site()->reader()->parseFeed($content['content'], $this->getFeedURL()); } return false; }
function postContent() { $this->createGatekeeper(); // Logged-in only please $email = $this->getInput('email'); $message = $this->getInput('message'); if (!empty($email) && !empty($message)) { $web_client = new Webservice(); $results = $web_client->post('http://withknown.com/vendor-services/feedback/', ['url' => \Idno\Core\site()->config()->getURL(), 'title' => \Idno\Core\site()->config()->getTitle(), 'version' => \Idno\Core\site()->getVersion(), 'public' => \Idno\Core\site()->config()->isPublicSite(), 'hub' => \Idno\Core\site()->config()->known_hub, 'email' => $email, 'message' => $message]); \Idno\Core\site()->session()->addMessage("Thanks! We received your feedback."); } $this->forward(\Idno\Core\site()->config()->getURL() . 'account/settings/feedback/confirm/'); }
/** * If this idno installation has a PubSubHubbub hub, send a publish notification to the hub * @param string $url * @return array */ static function publish($url) { if ($hub = \Idno\Core\site()->config()->hub) { return \Idno\Core\Webservice::post($hub, ['hub.mode' => 'publish', 'hub.url' => $url]); } return false; }
/** * Get parsed items from this feed * @return array|bool */ function retrieveItems() { if ($content = Webservice::get($this->getFeedURL())) { return \Idno\Core\Idno::site()->reader()->parseFeed($content['content'], $this->getFeedURL()); } return false; }
function registerEventHooks() { \Idno\Core\site()->events()->addListener('syndicate', function (\Idno\Core\Event $event) { $eventdata = $event->data(); if (!empty($eventdata['object'])) { if (!empty(site()->config()->wayback_machine)) { if ($eventdata['object'] instanceof Entity) { if ($eventdata['object']->isPublic()) { Webservice::get('https://web.archive.org/save/' . $eventdata['object']->getDisplayURL()); } } } $content_type = $eventdata['object']->getActivityStreamsObjectType(); if ($services = \Idno\Core\site()->syndication()->getServices($content_type)) { if ($selected_services = \Idno\Core\site()->currentPage()->getInput('syndication')) { if (!empty($selected_services) && is_array($selected_services)) { foreach ($selected_services as $selected_service) { $event->data()['syndication_account'] = false; if (in_array($selected_service, $services)) { site()->triggerEvent('post/' . $content_type . '/' . $selected_service, $eventdata); } else { if ($implied_service = $this->getServiceByAccountString($selected_service)) { $eventdata['syndication_account'] = $this->getAccountFromAccountString($selected_service); site()->triggerEvent('post/' . $content_type . '/' . $implied_service, $eventdata); } } } } } } } }); }
function getContent() { $this->createGatekeeper(); $user = \Idno\Core\site()->session()->currentUser(); $u = $this->getInput('u'); if ($content = \Idno\Core\Webservice::get($u)['content']) { $parser = new \Mf2\Parser($content, $u); if ($return = $parser->parse()) { if (isset($return['items'])) { $t = \Idno\Core\site()->template(); $body = ''; $hcard = []; $this->findHcard($return['items'], $hcard); $hcard = $this->removeDuplicateProfiles($hcard); if (!count($hcard)) { throw new \Exception("Sorry, could not find any users on that page, perhaps they need to mark up their profile in <a href=\"http://microformats.org/wiki/microformats-2\">Microformats</a>?"); } // TODO: Add a manual way to add the user foreach ($hcard as $card) { $body .= $t->__(['mf2' => $card])->draw('account/settings/following/mf2user'); } // List user $t->body = $body; $t->title = 'Found users'; $t->drawPage(); } } else { throw new \Exception("Sorry, there was a problem parsing the page!"); } } else { throw new \Exception("Sorry, {$u} could not be retrieved!"); } // forward back $this->forward($_SERVER['HTTP_REFERER']); }
function postContent() { $body = strip_tags($this->getInput('body')); $name = strip_tags($this->getInput('name')); $url = trim($this->getInput('url')); $url2 = trim($this->getInput('url-2')); $validator = $this->getInput('validator'); if (!empty($url2)) { $this->deniedContent(); } $this->referrerGatekeeper(); if (!empty($body) && !empty($name) && !empty($validator)) { if ($object = Entity::getByUUID($validator)) { if ($url = Webservice::sanitizeURL($url)) { if ($content = Webservice::get($url)) { if ($content['response'] == '200') { $icon = Webmention::getIconFromWebsiteContent($content['content'], $url); } } } if (empty($icon)) { $bn = hexdec(substr(md5($url), 0, 15)); $number = 1 + $bn % 5; $icon = \Idno\Core\site()->config()->url . 'gfx/users/default-' . str_pad($number, 2, '0', STR_PAD_LEFT) . '.png'; } $object->addAnnotation('reply', $name, $url, $icon, $body); $this->forward($object->getDisplayURL()); } } }
/** * Given a URL, returns the page title. * @param $Url * @return mixed */ function getTitleFromURL($Url) { $str = \Idno\Core\Webservice::file_get_contents($Url); if (strlen($str) > 0) { preg_match("/\\<title\\>(.*)\\<\\/title\\>/siu", $str, $title); return htmlspecialchars_decode($title[1]); } return ''; }
function registerEventHooks() { \Idno\Core\site()->syndication()->registerService('webhooks', function () { return $this->hasWebhooks(); }, array('note', 'bookmark', 'event', 'article')); if ($this->hasWebhooks()) { if (!empty(\Idno\Core\site()->config()->webhook_syndication)) { foreach (\Idno\Core\site()->config()->webhook_syndication as $hook) { \Idno\Core\site()->syndication()->registerServiceAccount('webhooks', $hook['url'], $hook['title']); } } if (\Idno\Core\site()->session()->isLoggedIn()) { if (!empty(\Idno\Core\site()->session()->currentUser()->webhook_syndication)) { foreach (\Idno\Core\site()->session()->currentUser()->webhook_syndication as $hook) { \Idno\Core\site()->syndication()->registerServiceAccount('webhooks', $hook['url'], $hook['title']); } } } } $hook_function = function (\Idno\Core\Event $event) { $eventdata = $event->data(); if ($this->hasWebhooks()) { $object = $eventdata['object']; if (!empty($object) && $object instanceof Entity && !empty($eventdata['syndication_account'])) { $payload = array(); $hook_url = $eventdata['syndication_account']; if ($owner = $object->getOwner()) { $payload['icon_url'] = $owner->getIcon(); $payload['username'] = $owner->getHandle(); } $payload['content_type'] = $object->getActivityStreamsObjectType(); $payload['text'] = $object->getTitle() . ' <' . $object->getURL() . '>'; $payload['title'] = $object->getTitle(); $client = new Webservice(); $client->post($hook_url, json_encode($payload)); } } }; \Idno\Core\site()->addEventHook('post/note/webhooks', $hook_function); \Idno\Core\site()->addEventHook('post/article/webhooks', $hook_function); \Idno\Core\site()->addEventHook('post/bookmark/webhooks', $hook_function); \Idno\Core\site()->addEventHook('post/event/webhooks', $hook_function); }
/** * Given a URL, returns the page title. * @param $Url * @return mixed */ function getTitleFromURL($Url) { $str = \Idno\Core\Webservice::file_get_contents($Url); //@file_get_contents($Url); if (strlen($str) > 0) { preg_match("/\\<title\\>(.*)\\<\\/title\\>/i", $str, $title); return $title[1]; } return ''; }
function parseTitle($url) { $response = Webservice::get($url); if ($response['response'] == 200) { $doc = \DOMDocument::loadHTML($response['content']); foreach ($doc->getElementsByTagName('title') as $title) { return trim($title->textContent); } } return false; }
public function getAccessToken($endpointUrl, $grant_type = 'authorization_code', array $parameters) { if ($parameters['state'] != \Idno\Core\site()->plugins()->get('AppNet')->getState()) { throw new \Exception('State value not correct, possible CSRF attempt.'); } unset($parameters['state']); $parameters['client_id'] = $this->key; $parameters['client_secret'] = $this->secret; $parameters['grant_type'] = $grant_type; return \Idno\Core\Webservice::post(\IdnoPlugins\AppNet\Main::$TOKEN_ENDPOINT, $parameters); }
public function testAuthenticated() { $user = \Tests\KnownTestCase::user(); $result = \Idno\Core\Webservice::post(\Idno\Core\Idno::site()->config()->url . 'status/edit', ['body' => "Making a nice test post via the api"], ['Accept: application/json', 'X-KNOWN-USERNAME: '******'X-KNOWN-SIGNATURE: ' . base64_encode(hash_hmac('sha256', '/status/edit', $user->getAPIkey(), true))]); print_r($result); $content = json_decode($result['content']); $response = $result['response']; $this->assertTrue(empty($result['error'])); $this->assertTrue(!empty($content)); $this->assertTrue(!empty($content->location)); $this->assertTrue($response == 200); }
public function testUpload() { $user = \Tests\KnownTestCase::user(); $result = \Idno\Core\Webservice::post(\Idno\Core\Idno::site()->config()->url . 'photo/edit', ['title' => 'A Photo upload', 'body' => "Uploading a pretty picture via the api", 'photo' => \Idno\Core\WebserviceFile::createFromCurlString("@" . dirname(__FILE__) . "/" . self::$file . ";filename=Photo.jpg;type=image/jpeg")], ['Accept: application/json', 'X-KNOWN-USERNAME: '******'X-KNOWN-SIGNATURE: ' . base64_encode(hash_hmac('sha256', '/photo/edit', $user->getAPIkey(), true))]); print_r($result); $content = json_decode($result['content']); $response = $result['response']; $this->assertTrue(empty($result['error'])); $this->assertTrue(!empty($content)); $this->assertTrue(!empty($content->location)); $this->assertTrue($response == 200); }
public function getAccessToken($endpointUrl, $grant_type = 'authorization_code', array $parameters) { if ($parameters['state'] != \Idno\Core\site()->plugins()->get('LinkedIn')->getState()) { throw new \Exception('State value not correct, possible CSRF attempt.'); } unset($parameters['state']); $parameters['client_id'] = $this->key; $parameters['client_secret'] = $this->secret; $parameters['grant_type'] = $grant_type; /** * Note from the original OAuth 2 library: * * Passing an array to CURLOPT_POSTFIELDS will encode the data as multipart/form-data, * while passing a URL-encoded string will encode the data as application/x-www-form-urlencoded. * http://php.net/manual/en/function.curl-setopt.php * * ... Linked in API will only accept the latter at this stage. */ $result = \Idno\Core\Webservice::post(\IdnoPlugins\LinkedIn\Main::$TOKEN_ENDPOINT, http_build_query($parameters, null, '&')); return json_decode($result['content']); }
/** * Given an array of URLs (or an empty array) and a target URL to check, * adds and rel="syndication" URLs in the target to the array * @param $url * @param array $inreplyto * @return array */ static function addSyndicatedReplyTargets($url, $inreplyto = []) { if (!is_array($inreplyto)) { $inreplyto = [$inreplyto]; } if ($content = \Idno\Core\Webservice::get($url)) { if ($mf2 = self::parseContent($content['content'], $url)) { $mf2 = (array) $mf2; $mf2['rels'] = (array) $mf2['rels']; if (!empty($mf2['rels']['syndication'])) { if (is_array($mf2['rels']['syndication'])) { foreach ($mf2['rels']['syndication'] as $syndication) { if (!in_array($syndication, $inreplyto) && !empty($syndication)) { $inreplyto[] = $syndication; } } } } } } return $inreplyto; }
function post() { // Get parameters $code = $this->getInput('code'); $me = $this->getInput('me'); $redirect_uri = $this->getInput('redirect_uri'); $state = $this->getInput('state'); $client_id = $this->getInput('client_id'); // Verify code $response = Webservice::post('https://indieauth.com/auth', array('me' => $me, 'code' => $code, 'redirect_uri' => $redirect_uri, 'state' => $state, 'client_id' => $client_id)); if ($response['response'] == 200) { parse_str($response['content'], $content); if (!empty($content['me']) && (parse_url($content['me'], PHP_URL_HOST) == parse_url(\Idno\Core\site()->config()->getURL(), PHP_URL_HOST) || 'www.' . parse_url($content['me'], PHP_URL_HOST) == parse_url(\Idno\Core\site()->config()->getURL(), PHP_URL_HOST))) { // Get user & existing tokens $user = \Idno\Entities\User::getOne(array('admin' => true)); $indieauth_tokens = $user->indieauth_tokens; if (empty($indieauth_tokens)) { $indieauth_tokens = array(); } // Generate access token and save it to the user $token = md5(rand(0, 99999) . time() . $user->getUUID() . $client_id . $state . rand(0, 999999)); $indieauth_tokens[$token] = array('me' => $me, 'redirect_uri' => $redirect_uri, 'scope' => 'post', 'client_id' => $client_id, 'issued_at' => time(), 'nonce' => mt_rand(1000000, pow(2, 30))); $user->indieauth_tokens = $indieauth_tokens; $user->save(); if (\Idno\Core\site()->session()->isLoggedOn() && $user->getUUID() == \Idno\Core\site()->session()->currentUser()->getUUID()) { \Idno\Core\site()->session()->refreshSessionUser($user); } // Output to the browser $this->setResponse(200); header('Content-Type: application/x-www-form-urlencoded'); echo http_build_query(array('access_token' => $token, 'scope' => 'post', 'me' => $me)); exit; } else { $this->setResponse(404); echo "Client mismatch."; } } }
function getContent() { $this->createGatekeeper(); $user = \Idno\Core\site()->session()->currentUser(); $u = $this->getInput('u'); if ($content = \Idno\Core\Webservice::get($u)['content']) { $parser = new \Mf2\Parser($content, $u); if ($return = $parser->parse()) { if (isset($return['items'])) { $t = \Idno\Core\site()->template(); $body = ''; $hcard = array(); $this->findHcard($return['items'], $hcard); $hcard = $this->removeDuplicateProfiles($hcard); if (!count($hcard)) { //throw new \Exception("Sorry, could not find any users on that page, perhaps they need to mark up their profile in <a href=\"http://microformats.org/wiki/microformats-2\">Microformats</a>?"); // TODO: Add a manual way to add the user // No entry could be found, so lets fake one and allow manual entry $hcard[] = ['properties' => ['name' => [$this->findPageTitle($content)], 'photo' => [], 'email' => [], 'nickname' => [], 'url' => [$u]]]; // Display a warning \Idno\Core\site()->session()->addErrorMessage('Page did not contain any <a href=\\"http://microformats.org/wiki/microformats-2\\">Microformats</a> markup... doing my best with what I have!'); } foreach ($hcard as $card) { $body .= $t->__(array('mf2' => $card))->draw('account/settings/following/mf2user'); } // List user $t->body = $body; $t->title = 'Found users'; $t->drawPage(); } } else { throw new \Exception("Sorry, there was a problem parsing the page!"); } } else { throw new \Exception("Sorry, {$u} could not be retrieved!"); } // forward back $this->forward($_SERVER['HTTP_REFERER']); }
function getContent() { $user = \Idno\Entities\User::getOne(array('admin' => true)); // This is for single user sites; will retrieve the main user $code = $this->getInput('code'); if (!empty($code)) { $client = new Webservice(); $response = Webservice::post('http://indieauth.com/auth', array('code' => $code, 'redirect_uri' => \Idno\Core\Idno::site()->config()->getURL(), 'client_id' => \Idno\Core\Idno::site()->config()->getURL())); if ($response['response'] == 200) { parse_str($response['content'], $content); if (!empty($content['me']) && parse_url($content['me'], PHP_URL_HOST) == parse_url(\Idno\Core\Idno::site()->config()->getURL, PHP_URL_HOST)) { $user = \Idno\Core\Idno::site()->session()->currentUser(); $user->indieauth_code = $code; $user->save(); \Idno\Core\Idno::site()->session()->logUserOn($user); } else { \Idno\Core\Idno::site()->session()->addMessage("Couldn't log you in: the token hostname didn't match."); } } else { \Idno\Core\Idno::site()->session()->addMessage("Uh oh! We got a " . $response['response'] . " response."); } } }
public function testAdminGatekeeper() { $result = \Idno\Core\Webservice::get(\Idno\Core\Idno::site()->config()->url . 'admin/', [], []); $response = $result['response']; $this->assertTrue(empty($result['error'])); $this->assertTrue($response == 403); $user = \Tests\KnownTestCase::user(); $this->assertTrue(is_object(\Idno\Core\Idno::site()->session()->logUserOn($user))); // Try normal user \Idno\Core\Idno::site()->session()->logUserOff(); $result = \Idno\Core\Webservice::get(\Idno\Core\Idno::site()->config()->url . 'admin/', [], ['X-KNOWN-USERNAME: '******'X-KNOWN-SIGNATURE: ' . base64_encode(hash_hmac('sha256', '/admin/', $user->getAPIkey(), true))]); $response = $result['response']; $this->assertTrue(empty($result['error'])); $this->assertTrue($response == 403); // Try admin $user = \Tests\KnownTestCase::admin(); $this->assertTrue(is_object(\Idno\Core\Idno::site()->session()->logUserOn($user))); $result = \Idno\Core\Webservice::get(\Idno\Core\Idno::site()->config()->url . 'admin/', [], ['X-KNOWN-USERNAME: '******'X-KNOWN-SIGNATURE: ' . base64_encode(hash_hmac('sha256', '/admin/', $user->getAPIkey(), true))]); $response = $result['response']; $this->assertTrue(empty($result['error'])); $this->assertTrue($response == 200); \Idno\Core\Idno::site()->session()->logUserOff(); }
/** * Fetch and parse the Bridgy user page for this service, * update its status and return true if it has changed. */ function checkService($user, $service) { if (!isset($user->bridgy) || !isset($user->bridgy[$service])) { return false; } $bridgy_url = $user->bridgy[$service]['user']; if (!empty($bridgy_url) and $resp = \Idno\Core\Webservice::get($bridgy_url)) { $parsed = (new \Mf2\Parser($resp['content'], $bridgy_url))->parse(); $status = 'disabled'; if (!empty($parsed['items'])) { $hcard = $parsed['items'][0]; if (!empty($hcard['properties']['bridgy-account-status']) && $hcard['properties']['bridgy-account-status'][0] == 'enabled' && !empty($hcard['properties']['bridgy-listen-status']) && $hcard['properties']['bridgy-listen-status'][0] == 'enabled') { $status = 'enabled'; } } if ($user->bridgy[$service]['status'] != $status) { $user->bridgy[$service]['status'] = $status; $user->save(); return true; } return false; } }
/** * Makes a call to the hub * * @param $endpoint * @param $contents * @param bool $user * @return array|bool */ function makeCall($endpoint, $contents, $user = false) { if (!$user) { $user = site()->session()->currentUser(); } if ($user instanceof User) { if ($this->userIsRegistered($user)) { $web_client = new Webservice(); $contents = json_encode($contents); $time = time(); $details = $user->hub_settings; $results = $web_client->post($this->server . $endpoint, array('content' => $contents, 'time' => $time, 'auth_token' => $details['token'], 'signature' => hash_hmac('sha1', $contents . $time . $details['token'], $details['secret']))); return $results; } } return false; }
/** * Takes an address and returns OpenStreetMap data via Nominatim, including latitude and longitude * * @param string $address * @return array|bool */ static function queryAddress($address, $limit = 1) { $query = self::getNominatimEndpoint() . "search?q=" . urlencode($address) . "&format=json"; $http_response = \Idno\Core\Webservice::get($query)['content']; if (!empty($http_response)) { if ($contents = @json_decode($http_response)) { $contents = (array) $contents; $contents = (array) array_pop($contents); // This will have been an array wrapped in an array $contents['latitude'] = $contents['lat']; $contents['longitude'] = $contents['lon']; return $contents; } } return false; }
/** * Retrieve a user's icon from a given homepage * @param $content The content of the page * @param $url The URL of the page * @return $icon_url */ static function getIconFromWebsiteContent($content, $url) { if ($mf2 = self::parseContent($content, $url)) { $mf2 = (array) $mf2; foreach ($mf2['items'] as $item) { // Figure out what kind of Microformats 2 item we have if (!empty($item['type']) && is_array($item['type'])) { foreach ($item['type'] as $type) { switch ($type) { case 'h-card': if (!empty($item['properties'])) { if (!empty($item['properties']['name'])) { $mentions['owner']['name'] = $item['properties']['name'][0]; } if (!empty($item['properties']['url'])) { $mentions['owner']['url'] = $item['properties']['url'][0]; } if (!empty($item['properties']['photo'])) { //$mentions['owner']['photo'] = $item['properties']['photo'][0]; $tmpfname = tempnam(sys_get_temp_dir(), 'webmention_avatar'); file_put_contents($tmpfname, \Idno\Core\Webservice::file_get_contents($item['properties']['photo'][0])); $name = md5($item['properties']['url'][0]); // TODO: Don't update the cache image for every webmention if ($icon = \Idno\Entities\File::createThumbnailFromFile($tmpfname, $name, 300)) { return \Idno\Core\Idno::site()->config()->url . 'file/' . (string) $icon; } else { if ($icon = \Idno\Entities\File::createFromFile($tmpfname, $name)) { return \Idno\Core\Idno::site()->config()->url . 'file/' . (string) $icon; } } unlink($tmpfname); } } break; } } } } } return false; }
function post() { parse_str(trim(file_get_contents("php://input")), $vars); // Check that both source and target are non-empty if (!empty($vars['source']) && !empty($vars['target']) && $vars['source'] != $vars['target']) { $source = $vars['source']; $target = $vars['target']; // Remove anchors from target URL, but save them to '#' input so we can still reference them later if (strpos($target, '#')) { list($target, $fragment) = explode('#', $target, 2); if (!empty($fragment)) { $this->setInput('#', $fragment); } } // Get the page handler for target if ($page = \Idno\Core\Idno::site()->getPageHandler($target)) { // First of all, make sure the target page isn't the source page. Let's not webmention ourselves! $webmention_ok = true; if (\Idno\Common\Entity::isLocalUUID($source)) { if ($source_page = \Idno\Core\Idno::site()->getPageHandler($source)) { if ($source_page == $page) { $webmention_ok = false; } } } // Check that source exists, parse it for mf2 content, // and ensure that it genuinely mentions this page if ($webmention_ok) { if ($source_content = \Idno\Core\Webservice::get($source)) { if (substr_count($source_content['content'], $target) || $source_content['response'] == 410) { $source_mf2 = \Idno\Core\Webmention::parseContent($source_content['content'], $source); // Set source and target information as input variables $page->setPermalink(); if ($page->webmentionContent($source, $target, $source_content, $source_mf2)) { $this->setResponse(202); // Webmention received a-ok. exit; } else { $error = 'target_not_supported'; $error_text = 'This is not webmentionable.'; } } else { $error = 'no_link_found'; $error_text = 'The source URI does not contain a link to the target URI.'; \Idno\Core\Idno::site()->logging->warning('No link from ' . $source . ' to ' . $target); } } else { $error = 'source_not_found'; $error_text = 'The source content for ' . $source . ' could not be obtained.'; \Idno\Core\Idno::site()->logging->warning('No content from ' . $source); } } else { $error = 'target_not_supported'; $error_text = 'A page can\'t webmention itself.'; } } else { $error = 'target_not_found'; $error_text = 'The target page ' . $target . ' does not exist.'; \Idno\Core\Idno::site()->logging()->error('Could not find handler for ' . $target); } } $this->setResponse(400); // Webmention failed. if (empty($error)) { $error = 'unknown_error'; $error_text = 'Not all the required webmention variables were set.'; } echo json_encode(array('error' => $error, 'error_text' => $error_text)); }
function registerEventHooks() { // Register syndication services \Idno\Core\site()->syndication()->registerService('linkedin', function () { return $this->hasLinkedIn(); }, ['note', 'article', 'image']); if ($this->hasLinkedIn()) { if (is_array(\Idno\Core\site()->session()->currentUser()->linkedin)) { foreach (\Idno\Core\site()->session()->currentUser()->linkedin as $id => $details) { if ($id != 'access_token') { \Idno\Core\site()->syndication()->registerServiceAccount('linkedin', $id, $details['name']); } else { \Idno\Core\site()->syndication()->registerServiceAccount('linkedin', $id, 'LinkedIn'); } } } } // Push "notes" to LinkedIn \Idno\Core\site()->addEventHook('post/note/linkedin', function (\Idno\Core\Event $event) { $eventdata = $event->data(); $object = $eventdata['object']; if ($this->hasLinkedIn()) { if ($linkedinAPI = $this->connect($eventdata['syndication_account'])) { if (!empty(\Idno\Core\site()->session()->currentUser()->linkedin[$eventdata['syndication_account']]['name'])) { $name = \Idno\Core\site()->session()->currentUser()->linkedin[$eventdata['syndication_account']]['name']; } else { $name = 'LinkedIn'; } $message = strip_tags($object->getDescription()); //$message .= "\n\n" . $object->getURL(); if (!empty($message) && substr($message, 0, 1) != '@') { try { $result = \Idno\Core\Webservice::post(self::$SHARE_URL . '?oauth2_access_token=' . $linkedinAPI->access_token, ' <share> <comment>' . htmlentities($message) . '</comment> <visibility> <code>anyone</code> </visibility> </share> ', ["Content-Type: application/xml"]); if ($result['response'] == 201) { // Success $link = ""; if (preg_match('/<update-url>(.*?)<\\/update-url>/', $result['content'], $matches)) { $link = $matches[1]; } $object->setPosseLink('linkedin', $link, $name); $object->save(); } else { if (preg_match('/<message>(.*?)<\\/message>/', $result['content'], $matches)) { $message = $matches[1]; } \Idno\Core\site()->logging->log("LinkedIn Syndication: " . print_r($result, true), LOGLEVEL_ERROR); \Idno\Core\site()->session()->addErrorMessage("Linkedin returned error code: {$result['response']} - {$message}"); } } catch (\Exception $e) { \Idno\Core\site()->session()->addErrorMessage('There was a problem posting to LinkedIn: ' . $e->getMessage()); } } } } }); // Push "articles" to LinkedIn \Idno\Core\site()->addEventHook('post/article/linkedin', function (\Idno\Core\Event $event) { $eventdata = $event->data(); $object = $eventdata['object']; if ($this->hasLinkedIn()) { if ($linkedinAPI = $this->connect($eventdata['syndication_account'])) { if (!empty(\Idno\Core\site()->session()->currentUser()->linkedin[$eventdata['syndication_account']]['name'])) { $name = \Idno\Core\site()->session()->currentUser()->linkedin[$eventdata['syndication_account']]['name']; } else { $name = 'LinkedIn'; } $result = \Idno\Core\Webservice::post(self::$SHARE_URL . '?oauth2_access_token=' . $linkedinAPI->access_token, ' <share> <content> <title>' . htmlentities(strip_tags($object->getTitle())) . '</title> <submitted-url>' . htmlentities($object->getUrl()) . '</submitted-url> </content> <visibility> <code>anyone</code> </visibility> </share> ', ["Content-Type: application/xml"]); if ($result['response'] == 201) { // Success $link = ""; if (preg_match('/<update-url>(.*?)<\\/update-url>/', $result['content'], $matches)) { $link = $matches[1]; } $object->setPosseLink('linkedin', $link, $name); $object->save(); } else { if (preg_match('/<message>(.*?)<\\/message>/', $result['content'], $matches)) { $message = $matches[1]; } \Idno\Core\site()->session()->addErrorMessage("Linkedin returned error code: {$result['response']} - {$message}"); \Idno\Core\site()->logging->log("LinkedIn Syndication: " . print_r($result, true), LOGLEVEL_ERROR); } } } }); // Push "images" to LinkedIn \Idno\Core\site()->addEventHook('post/image/linkedin', function (\Idno\Core\Event $event) { $eventdata = $event->data(); $object = $eventdata['object']; if ($attachments = $object->getAttachments()) { foreach ($attachments as $attachment) { if ($this->hasLinkedIn()) { if ($linkedinAPI = $this->connect($eventdata['syndication_account'])) { if (!empty(\Idno\Core\site()->session()->currentUser()->linkedin[$eventdata['syndication_account']]['name'])) { $name = \Idno\Core\site()->session()->currentUser()->linkedin[$eventdata['syndication_account']]['name']; } else { $name = 'LinkedIn'; } $message = strip_tags($object->getDescription()); $message .= "\n\nOriginal: " . $object->getURL(); $result = \Idno\Core\Webservice::post(self::$SHARE_URL . '?oauth2_access_token=' . $linkedinAPI->access_token, ' <share> <content> <title>' . htmlentities(strip_tags($object->getTitle())) . '</title> <description>' . htmlentities($message) . '</description> <submitted-url>' . htmlentities($object->getUrl()) . '</submitted-url> <submitted-image-url>' . $attachment['url'] . '</submitted-image-url> </content> <visibility> <code>anyone</code> </visibility> </share> ', ["Content-Type: application/xml"]); if ($result['response'] == 201) { // Success $link = ""; if (preg_match('/<update-url>(.*?)<\\/update-url>/', $result['content'], $matches)) { $link = $matches[1]; } $object->setPosseLink('linkedin', $link, $name); $object->save(); } else { if (preg_match('/<message>(.*?)<\\/message>/', $result['content'], $matches)) { $message = $matches[1]; } \Idno\Core\site()->session()->addErrorMessage("Linkedin returned error code: {$result['response']} - {$message}"); \Idno\Core\site()->logging->log("LinkedIn Syndication: " . print_r($result, true), LOGLEVEL_ERROR); } } } } } }); }
/** * Recursive helper function for parsing webmentions. * * @param $item * @param $mentions * @return array */ function addWebmentionItem($item, $mentions, $source, $target, $title = '') { if (!empty($item['properties']['author'])) { foreach ($item['properties']['author'] as $author) { if (!empty($author['type'])) { foreach ($author['type'] as $type) { if ($type == 'h-card') { if (!empty($author['properties']['name'])) { $mentions['owner']['name'] = $author['properties']['name'][0]; } if (!empty($author['properties']['url'])) { $mentions['owner']['url'] = $author['properties']['url'][0]; } if (!empty($author['properties']['photo'])) { //$mentions['owner']['photo'] = $author['properties']['photo'][0]; $tmpfname = tempnam(sys_get_temp_dir(), 'webmention_avatar'); file_put_contents($tmpfname, \Idno\Core\Webservice::file_get_contents($author['properties']['photo'][0])); $name = md5($author['properties']['url'][0]); // TODO: Don't update the cache image for every webmention if ($icon = \Idno\Entities\File::createThumbnailFromFile($tmpfname, $name, 300)) { $mentions['owner']['photo'] = \Idno\Core\Idno::site()->config()->url . 'file/' . (string) $icon; } else { if ($icon = \Idno\Entities\File::createFromFile($tmpfname, $name)) { $mentions['owner']['photo'] = \Idno\Core\Idno::site()->config()->url . 'file/' . (string) $icon; } } unlink($tmpfname); } } } } } } if (!empty($item['type'])) { if (in_array('h-entry', $item['type'])) { $mention = array(); if (!empty($item['properties'])) { if (!empty($item['properties']['content'])) { $mention['content'] = ''; if (is_array($item['properties']['content'])) { foreach ($item['properties']['content'] as $content) { if (!empty($content['value'])) { $parsed_content = \Idno\Core\Idno::site()->template()->sanitize_html($content['value']); if (!substr_count($mention['content'], $parsed_content)) { $mention['content'] .= $parsed_content; } } } } else { $mention['content'] = $item['properties']['content']; } } else { if (!empty($item['properties']['summary'])) { if (is_array($item['properties']['summary'])) { $mention['content'] = \Idno\Core\Idno::site()->template()->sanitize_html(implode(' ', $item['properties']['summary'])); } else { $mention['content'] = $item['properties']['summary']; } } else { if (!empty($item['properties']['name'])) { if (is_array($item['properties']['name'])) { $mention['content'] = \Idno\Core\Idno::site()->template()->sanitize_html(implode(' ', $item['properties']['name'])); } else { $mention['content'] = $item['properties']['name']; } } } } if (!empty($item['properties']['published'])) { if (is_array($item['properties']['published'])) { $mention['created'] = @strtotime(array_shift(array_pop($item['properties']['published']))); } else { $mention['created'] = @strtotime($item['properties']['content']); } } if (empty($mention['created'])) { $mention['created'] = time(); } if (!empty($item['properties']['url'])) { if (!empty($item['properties']['uid'])) { $mention['url'] = array_intersect($item['properties']['uid'], $item['properties']['url']); } if (empty($mention['url'])) { $mention['url'] = $item['properties']['url']; } } if (!empty($item['properties']['like']) && is_array($item['properties']['like'])) { if (in_array($target, static::getStringURLs($item['properties']['like']))) { $mention['type'] = 'like'; } } if (!empty($item['properties']['like-of']) && is_array($item['properties']['like-of'])) { if (in_array($target, static::getStringURLs($item['properties']['like-of']))) { $mention['type'] = 'like'; } } if (!empty($item['properties']['rsvp']) && is_array($item['properties']['rsvp'])) { $mention['type'] = 'rsvp'; $mention['content'] = implode(' ', $item['properties']['rsvp']); } foreach (array('share', 'repost', 'repost-of') as $verb) { if (!empty($item['properties'][$verb]) && is_array($item['properties'][$verb])) { if (in_array($target, static::getStringURLs($item['properties'][$verb]))) { $mention['type'] = 'share'; } } } if (!empty($item['properties']['in-reply-to']) && is_array($item['properties']['in-reply-to'])) { if (in_array($target, static::getStringURLs($item['properties']['in-reply-to']))) { $mention['type'] = 'reply'; } } if (empty($mention['type'])) { $mention['type'] = 'mention'; } } if (empty($mention['content'])) { $mention['content'] = ''; } $mention['title'] = $title; if (!empty($mention['type'])) { $mentions['mentions'][] = $mention; } } } if (in_array('h-feed', $item['type'])) { if (!empty($item['children'])) { foreach ($item['children'] as $child) { $mentions = $this->addWebmentionItem($child, $mentions, $source, $target, $title); } } } return $mentions; }
/** * If this Known installation has a PubSubHubbub hub, send a publish notification to the hub * @param ActivityStreamPost $act_stream_post * @return array */ static function publish($act_stream_post) { if ($hub = \Idno\Core\Idno::site()->config()->hub) { if (!$act_stream_post instanceof ActivityStreamPost) { return false; } $object = $act_stream_post->getObject(); $base = \Idno\Core\Idno::site()->config()->getDisplayURL(); $feeds = array(); // Check to make sure there's an entity if (!$object instanceof Entity) { return false; } // homepage feed $homepage_types = \Idno\Core\Idno::site()->config()->getHomepageContentTypes(); $type_in_homepage = false; if ($object instanceof Entity) { if (in_array($object->getContentType(), $homepage_types)) { $type_in_homepage = true; } } if (empty($homepage_types) || $type_in_homepage) { $feeds[] = $base; } // type-specific feeds if ($object instanceof Entity) { $feeds[] = $base . 'content/' . $object->getContentTypeCategorySlug() . '/'; } $feeds[] = $base . 'content/all/'; // tag feeds foreach ($object->getTags() as $tag) { $feeds[] = $base . 'tag/' . $tag; } if (!empty($feeds)) { // encode the feeds and their RSS counterparts $encurls = array(); foreach ($feeds as $feed) { $encurls[] = urlencode($feed); $encurls[] = urlencode(\Idno\Core\Idno::site()->template()->getURLWithVar('_t', 'rss', $feed)); } $formdata = 'hub.mode=publish&hub.url=' . implode(',', $encurls); \Idno\Core\Idno::site()->logging()->log('Pinging ' . $hub . ' with data ' . $formdata); \Idno\Core\Webservice::post($hub, $formdata, array('Content-Type' => 'application/x-www-form-urlencoded')); } return true; } return false; }
/** * Retrieves a feed object for the given URL, or creates one if it's new to the system * @param $url * @param $update Set to true in order to refresh saved feed details. False by default. * @return bool|false|\Idno\Common\Entity|Feed */ function getFeedObject($url, $update = false) { $wc = new Webservice(); $url = $wc->sanitizeURL($url); if ($feed_details = $this->getFeedDetails($url)) { if ($feed_array = Feed::get(array('feed_url' => $feed_details['url']))) { foreach ($feed_array as $feed_item) { $feed = $feed_item; break; } } else { $feed = new Feed(); } if ($feed->getID() && !$update) { return $feed; } $feed->url = $url; if (!empty($feed_details['title'])) { $feed->setTitle($feed_details['title']); } if (!empty($feed_details['type'])) { $feed->setType($feed_details['type']); } if (!empty($feed_details['url'])) { $feed->setFeedURL($feed_details['url']); if ($feed->save()) { return $feed; } } } return false; }