return 2;
}
+
/**
* Register our hooks
*/
public function init(/*PluginHost*/ $host)
{
- parent::init($host);
static::$myhost = $host;
$host->add_hook($host::HOOK_PREFS_TAB, $this);
$host->add_hook($host::HOOK_RENDER_ARTICLE, $this);
. '?reply=' . urlencode($article['link']);
// did I tell you I hate dojo/dijit?
- $accounts = array_keys(PluginHost::getInstance()->get($this, 'accounts', []));
+ $accounts = PluginHost::getInstance()->get($this, 'accounts', []);
if (!count($accounts)) {
return $article;
}
+
+ $accountUrls = array_keys($accounts);
+ $defaultAccount = null;
+ foreach ($accounts as $url => $account) {
+ if ($account['default']) {
+ $defaultAccount = $url;
+ }
+ }
+
ob_start();
include __DIR__ . '/commentform.phtml';
$html = ob_get_clean();
}
$accounts = PluginHost::getInstance()->get($this, 'accounts', []);
+ if (isset($_REQUEST['accordion'])
+ && $_REQUEST['accordion'] == 'micropub'
+ ) {
+ $accordionActive = 'selected="true"';
+ } else {
+ $accordionActive = '';
+ }
+
+ foreach ($accounts as $url => $account) {
+ $accounts[$url]['checked'] = '';
+ if ($account['default']) {
+ $accounts[$url]['checked'] = 'checked="checked"';
+ }
+ }
//FIXME: default identity
include __DIR__ . '/settings.phtml';
}
+ public function get_prefs_js()
+ {
+ return file_get_contents(__DIR__ . '/settings.js');
+ }
+
/**
* CLI command
*/
return $this->authreturnAction();
} else if ($mode == 'post') {
return $this->postAction();
+ } else if ($mode == 'deleteIdentity') {
+ return $this->deleteIdentityAction();
+ } else if ($mode == 'setDefaultIdentity') {
+ return $this->setDefaultIdentityAction();
} else {
return $this->errorOut('Unsupported mode');
}
}
+ /**
+ * Post a comment, like or bookmark via micropub
+ */
protected function postAction()
{
- if (!isset($_POST['me'])) {
- return $this->errorOut('"me" parameter missing');
+ $action = 'comment';
+ if (isset($_POST['action'])) {
+ $action = trim($_POST['action']);
}
- $me = $_POST['me'];
-
- if (!isset($_POST['replyTo'])) {
- return $this->errorOut('"replyTo" parameter missing');
+ if (array_search($action, ['bookmark', 'comment', 'like']) === false) {
+ return $this->errorOut('"action" parameter invalid');
}
- $replyTo = $_POST['replyTo'];
- if (!isset($_POST['content'])) {
- return $this->errorOut('"content" parameter missing');
+ if (!isset($_POST['me'])) {
+ return $this->errorOut('"me" parameter missing');
}
- $content = $_POST['content'];
-
+ $me = trim($_POST['me']);
$accounts = PluginHost::getInstance()->get($this, 'accounts', []);
if (!isset($accounts[$me])) {
return $this->errorOut('"me" parameter invalid');
}
$account = $accounts[$me];
+ if (!isset($_POST['postUrl'])) {
+ return $this->errorOut('"postUrl" parameter missing');
+ }
+ $postUrl = trim($_POST['postUrl']);
+
+ if ($action == 'comment') {
+ if (!isset($_POST['content'])) {
+ return $this->errorOut('"content" parameter missing');
+ }
+ $content = trim($_POST['content']);
+ if (!strlen($_POST['content'])) {
+ return $this->errorOut('"content" is empty');
+ }
+ }
+
+
$links = $this->getLinks($me);
+ if ($links === false) {
+ return $this->errorOut('Error fetching URL: ' . $me);
+ }
if (!count($links)) {
return $this->errorOut('No links found');
}
return $this->errorOut('No micropub endpoint found');
}
+ $parameters = [
+ 'access_token' => $account['access_token'],
+ 'h' => 'entry',
+ ];
+
+ if ($action == 'bookmark') {
+ $parameters['bookmark-of'] = $postUrl;
+
+ } else if ($action == 'comment') {
+ $parameters['in-reply-to'] = $postUrl;
+ $parameters['content'] = $content;
+
+ } else if ($action == 'like') {
+ $parameters['like-of'] = $postUrl;
+ }
+
+
/* unfortunately fetch_file_contents() does not return headers
so we have to bring our own way to POST data */
$opts = [
'http' => [
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
- 'content' => http_build_query(
- [
- 'access_token' => $account['access_token'],
- 'h' => 'entry',
- 'in-reply-to' => $replyTo,
- 'content' => $content,
- ]
- ),
+ 'content' => http_build_query($parameters),
'ignore_errors' => true,
]
];
$status = array_shift($headers);
list($httpver, $code, $text) = explode(' ', $status, 3);
if ($code != 201 && $code != 202) {
+ $errData = json_decode($content);
+ if (isset($errData->error_description)
+ && $errData->error_description != ''
+ ) {
+ return $this->errorOut(
+ 'Error creating post: '
+ . $errData->error_description
+ );
+ }
return $this->errorOut(
- 'An error occured: '
- . $code . ' ' . $text
+ 'Error creating post: '
+ . $code . ' ' . $text.$content
);
}
//step 1: micropub discovery
$links = $this->getLinks($url);
+ if ($links === false) {
+ return $this->errorOut('Error fetching URL: ' . $url);
+ }
if (!count($links)) {
return $this->errorOut('No links found');
}
}
$links = $this->getLinks($_GET['me']);
+ if ($links === false) {
+ return $this->errorOut('Error fetching URL: ' . $_GET['me']);
+ }
if (!isset($links['token_endpoint'])) {
return $this->errorOut('No token endpoint found');
}
'access_token' => $data['access_token'],
'scope' => $data['scope'],
];
+ $accounts = $this->fixDefaultIdentity($accounts);
$host->set($this, 'accounts', $accounts);
//all fine now.
- header('Location: prefs.php');
+ //the accordion parameter will never work
+ // because fox has serious mental problems
+ // https://discourse.tt-rss.org/t/open-a-certain-accordion-in-preferences-by-url-parameter/234
+ header('Location: prefs.php?accordion=micropub');
+ }
+
+ /**
+ * Backend preferences action: Remove a given account
+ */
+ protected function deleteIdentityAction()
+ {
+ if (!isset($_POST['me'])) {
+ return $this->errorOut('"me" parameter missing');
+ }
+ $me = trim($_POST['me']);
+
+ $host = PluginHost::getInstance();
+ $accounts = $host->get($this, 'accounts', []);
+ if (!isset($accounts[$me])) {
+ return $this->errorOut('Unknown identity');
+ }
+
+ unset($accounts[$me]);
+ $accounts = $this->fixDefaultIdentity($accounts);
+ $host->set($this, 'accounts', $accounts);
+
+ header('Content-type: application/json');
+ echo json_encode(
+ [
+ 'code' => '200',
+ 'message' => 'Identity removed',
+ ]
+ );
+ exit();
+ }
+
+ /**
+ * Backend preferences action: Make a given account the default
+ */
+ protected function setDefaultIdentityAction()
+ {
+ if (!isset($_POST['me'])) {
+ return $this->errorOut('"me" parameter missing');
+ }
+ $me = trim($_POST['me']);
+
+ $host = PluginHost::getInstance();
+ $accounts = $host->get($this, 'accounts', []);
+ if (!isset($accounts[$me])) {
+ return $this->errorOut('Unknown identity');
+ }
+ foreach ($accounts as $url => $data) {
+ $accounts[$url]['default'] = ($url == $me);
+ }
+ $host->set($this, 'accounts', $accounts);
+
+ header('Content-type: application/json');
+ echo json_encode(
+ [
+ 'code' => '200',
+ 'message' => 'Default account set',
+ ]
+ );
+ exit();
+ }
+
+ /**
+ * Set the default identity if there is none
+ *
+ * @param array $accounts Array of account data arrays
+ *
+ * @return array Array of account data arrays
+ */
+ protected function fixDefaultIdentity($accounts)
+ {
+ if (!count($accounts)) {
+ return $accounts;
+ }
+
+ $hasDefault = false;
+ foreach ($accounts as $account) {
+ if ($account['default']) {
+ $hasDefault = true;
+ }
+ }
+
+ if (!$hasDefault) {
+ reset($accounts);
+ $accounts[key($accounts)]['default'] = true;
+ }
+ return $accounts;
}
/**
/**
* Extract link relations from a given URL
+ *
+ * @param string $url URL to extract links from
+ *
+ * @return bool|array Array of links, or false on HTTP error
*/
protected function getLinks($url)
{
'url' => $url,
]
);
+ if ($html === false) {
+ return false;
+ }
+
//Loading invalid HTML is tedious.
// quick hack with regex. yay!
preg_match_all('#<link[^>]+?>#', $html, $matches);
return $links;
}
+ /**
+ * If a valid CSRF token is necessary or not
+ *
+ * @param string $method Plugin method name (here: "action")
+ *
+ * @return boolean True if an invalid CSRF token shall be ignored
+ */
function csrf_ignore($method)
{
- return true;
+ $mode = null;
+ if (isset($_POST['mode'])) {
+ $mode = $_POST['mode'];
+ } else if (isset($_GET['mode'])) {
+ $mode = $_GET['mode'];
+ }
+
+ if ($mode == 'authreturn') {
+ return true;
+ }
+
+ return false;
}
/**