You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

132 lines
3.5 KiB

<?php
// TODO: Better logging
// TODO: Normalize target_url
/**
* Simple, Mf2-aware, quick & dirty script to handle webmentions
*/
require_once('config.php');
require_once('extlib/webmention.php');
require_once('vendor/autoload.php');
/*********
* Utils *
*********/
function safe($unsafe) {
$unsafe = strip_tags($unsafe);
$safe = htmlspecialchars($unsafe, ENT_QUOTES);
return $safe;
}
// Returns author info as well as truncated post text suitable for display.
function getWebmention($mf, $url) {
foreach($mf['items'] as $microformat) {
return IndieWeb\comments\parse($microformat, $url);
}
}
$source_url = $_POST['source'];
$target_url = $_POST['target'];
/************************
* House-keeping stuffs *
************************/
// Make sure the mentioned page is from our host
if (parse_url($target_url, PHP_URL_HOST) !== $config["site"]["host"]) {
error_log("Webmention for another host: " . $source_url, 4);
exit("Err");
}
// Make sure the mentioned page exists
if (head($target_url) === null) {
error_log("Webmention for a page that doesn't exist: " . $target_url, 4);
exit("Err");
}
// HTTP GET
$source_html = get($source_url, $target_url);
if ($source_html === null) {
error_log("Failed to fetch remote page: " . $source_url, 4);
exit("Err");
}
/**************
* Mf2 stuffs *
**************/
$mf = Mf2\parse($source_html, $source_url);
$webmention = getWebmention($mf, $target_url);
// FIXME:
// https://github.com/pear2/Services_Linkback/blob/2afd453254c531925484196670e2953f669ae141/src/PEAR2/Services/Linkback/Server/Callback/LinkExists.php#L40
// https://github.com/indieweb/php-mf2/blob/master/Mf2/Parser.php#L966
// https://stackoverflow.com/questions/2087103/how-to-get-innerhtml-of-domnode
if (!stristr($source_html, $target_url) || $webmention === null) {
error_log("Fake webmention from: " . $source_url, 4);
exit("Fake");
}
/*************
* DB Stuffs *
*************/
$dsn = 'mysql:dbname=' . $config['db']['name'] . ';host=' . $config['db']['host'];
$user = $config['db']['username'];
$password = $config['db']['password'];
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
error_log('Connection failed: ' . $e->getMessage(), 4);
exit("Err");
}
$sth = $dbh->prepare(
'INSERT INTO webmentions (local_url, url, name, text, author_name, author_url, type) ' .
'VALUES(?, ?, ?, ?, ?, ?, ?)'
);
if ($sth === false) {
error_log("Could not prepare SQL statement.");
error_log("Error code: " . $dbh->errorCode());
error_log("Error info: " . $dbh->errorInfo());
}
$remote_url = safe(($webmention['url'] !== false) ? $webmention['url'] : $source_url);
// Prevent authorship spoofing
// FIXME: make better.
$author_url = $webmention['author']['url'];
if (parse_url($author_url, PHP_URL_HOST) !== parse_url($source_url, PHP_URL_HOST)) {
error_log('Author URL host does not match source url host; discarding...', 4);
error_log('Author URL: ' . $author_url, 4);
error_log('Source URL: ' . $source_url, 4);
$author_url = '';
}
$res = $sth->execute(array(
$target_url,
$remote_url,
safe($webmention['name']),
safe($webmention['text']),
safe($webmention['author']['name']),
safe($author_url),
safe($webmention['type'])
));
if ($res === false) {
error_log("Could not execute SQL query.");
error_log("Error code: " . $dbh->errorCode());
error_log("Error info: " . print_r($dbh->errorInfo(), true));
error_log(
print_r($webmention, true),
4
);
}