<input type="hidden" name="mode" value="post"/>
<input type="hidden" name="replyTo" value="<?= htmlspecialchars($article['link']) ?>"/>
- <label for="micropub-me">Identity:</label>
- <select id="micropub-me" name="me" size="1">
- <?php foreach ($accounts as $url) { ?>
- <option value="<?= htmlspecialchars($url) ?>"><?= htmlspecialchars($url) ?></option>
- <?php } ?>
- </select><br/>
- <textarea name="content" rows="4" cols="60"></textarea><br/>
+
+ <?php if (count($accounts) == 1) { ?>
+ <input type="hidden" name="me" value="<?= htmlspecialchars(reset($accounts)) ?>"/>
+ <?php } else { ?>
+ <label for="micropub-me">Identity:</label>
+ <select id="micropub-me" name="me" size="1">
+ <?php foreach ($accounts as $url) { ?>
+ <option value="<?= htmlspecialchars($url) ?>"><?= htmlspecialchars($url) ?></option>
+ <?php } ?>
+ </select><br/>
+ <?php } ?>
+
+ <textarea name="content" rows="4" cols="60" width="100%" class="dijitTextArea"></textarea><br/>
<button type="submit">Post comment</button>
</form>
</div>
);
}
- function get_css()
- {
- return file_get_contents(__DIR__ . '/init.css');
- }
-
/**
* @param array $article Article data. Keys:
* - id
// did I tell you I hate dojo/dijit?
$accounts = array_keys(PluginHost::getInstance()->get($this, 'accounts', []));
-
+ if (!count($accounts)) {
+ return $article;
+ }
+ array_shift($accounts);
ob_start();
include __DIR__ . '/commentform.phtml';
$html = ob_get_clean();
$accounts = PluginHost::getInstance()->get($this, 'accounts', []);
+ //FIXME: default identity
include __DIR__ . '/settings.phtml';
}
return $this->action($mode, $args);
}
+ /**
+ * HTTP command.
+ * Also used by micropub() cli command method.
+ *
+ * /backend.php?op=pluginhandler&plugin=micropub&method=action
+ */
public function action($mode = null, $args = [])
{
if (isset($_POST['mode'])) {
} else if ($mode == 'post') {
return $this->postAction();
} else {
- $this->errorOut('Unsupported mode');
+ return $this->errorOut('Unsupported mode');
}
}
return $this->errorOut('No micropub endpoint found');
}
- $res = fetch_file_contents(
- [
- //FIXME: add content-type header once this is fixed:
- // https://discourse.tt-rss.org/t//207
- 'url' => $links['micropub'],
- //we use http_build_query to force cURL
- // to use x-www-form-urlencoded
- 'post_query' => http_build_query(
+ /* 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',
'content' => $content,
]
),
- 'followlocation' => false,
+ 'ignore_errors' => true,
]
+ ];
+ $stream = fopen(
+ $links['micropub'], 'r', false,
+ stream_context_create($opts)
);
-
- if ($GLOBALS['fetch_last_error_code'] == 201) {
- //FIXME: extract location header
- echo "OK, comment post created\n";
- } else {
- $this->errorOut(
+ $meta = stream_get_meta_data($stream);
+ $headers = $meta['wrapper_data'];
+ $content = stream_get_contents($stream);
+
+ //we hope there were no redirects and this is actually the only
+ // HTTP line in the headers
+ $status = array_shift($headers);
+ list($httpver, $code, $text) = explode(' ', $status, 3);
+ if ($code != 201 && $code != 202) {
+ return $this->errorOut(
'An error occured: '
- . $GLOBALS['fetch_last_error_code']
- . ' ' . $GLOBALS['fetch_last_error_code_content']
+ . $code . ' ' . $text
);
}
+
+ $location = null;
+ foreach ($headers as $header) {
+ $parts = explode(':', $header, 2);
+ if (count($parts) == 2 && strtolower($parts[0]) == 'location') {
+ $location = trim($parts[1]);
+ }
+ }
+ if ($location === null) {
+ return $this->errorOut(
+ 'Location header missing in successful creation response.'
+ );
+ }
+
+ header('Content-type: application/json');
+ echo json_encode(
+ [
+ 'code' => intval($code),
+ 'location' => $location,
+ ]
+ );
+ exit();
}
protected function authorizeAction($args = [])
header('Location: prefs.php');
}
+ /**
+ * Send an error message.
+ * Automatically in the correct format (plain text or json)
+ *
+ * @param string $msg Error message
+ *
+ * @return void
+ */
protected function errorOut($msg)
{
- echo $msg . "\n";
+ header('HTTP/1.0 400 Bad Request');
+
+ //this does not take "q"uality values into account, I know.
+ if (isset($_SERVER['HTTP_ACCEPT'])
+ && strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false
+ ) {
+ //send json error
+ header('Content-type: application/json');
+ echo json_encode(
+ [
+ 'error' => $msg,
+ ]
+ );
+ } else {
+ header('Content-type: text/plain');
+ echo $msg . "\n";
+ }
exit(1);
}
+ /**
+ * Extract link relations from a given URL
+ */
protected function getLinks($url)
{
//FIXME: HTTP Link header support with HTTP2
<div dojoType="dijit.layout.AccordionPane" title="Micropub">
<div>
- <h1>Existing identities</h1>
- <table border="1">
+ <h2>Registered identities</h2>
+ <table width="100%">
<thead>
- <tr><th>Identity URL</th></tr>
+ <tr class="title">
+ <td width="5%">Default</td>
+ <td>Identity URL</td>
+ </tr>
</thead>
<tbody>
<?php foreach ($accounts as $accurl => $account) { ?>
<tr>
- <td><?= $accurl ?></td>
+ <td align='center'>
+ <input disabled='1' dojoType="dijit.form.CheckBox" type="checkbox"/>
+ </td>
+ <td>
+ <a href="<?= htmlspecialchars($accurl) ?>"><?= htmlspecialchars($accurl) ?></a>
+ </td>
</tr>
<?php } ?>
</tbody>
</div>
<div>
- <h1>Add new identity</h1>
+ <h2>Add new identity</h2>
<form method="post" action="backend.php">
<input type="hidden" name="op" value="pluginhandler"/>
<input type="hidden" name="plugin" value="micropub"/>
<input type="hidden" name="method" value="action"/>
<input type="hidden" name="mode" value="authorize"/>
- <input name="url" type="url" size="40"/>
+ <input name="url" type="url" size="40" dojoType="dijit.form.TextBox" required="1"/>
<button type="submit">Authorize</button>
</form>
</div>