Browse Source

Rough support for types (likes, replies, etc.)

master
Chimo 5 years ago
parent
commit
3e5a5deb8a
4 changed files with 105 additions and 96 deletions
  1. +2
    -1
      composer.json
  2. +30
    -4
      get.php
  3. +66
    -84
      index.php
  4. +7
    -7
      schema.sql

+ 2
- 1
composer.json View File

@@ -1,6 +1,7 @@
{
"require": {
"mf2/mf2": "0.2.10",
"barnabywalters/mf-cleaner": "0.1.4"
"barnabywalters/mf-cleaner": "0.1.4",
"indieweb/comments": "0.1.9"
}
}

+ 30
- 4
get.php View File

@@ -20,7 +20,7 @@ try {
exit('Err');
}

$sth = $dbh->prepare('SELECT rendered FROM webmentions WHERE local_url = ? ORDER BY created');
$sth = $dbh->prepare('SELECT * FROM webmentions WHERE local_url = ? ORDER BY published');

if ($sth === false) {
error_log('Could not prepare SQL statement.');
@@ -36,9 +36,36 @@ if ($res === false) {
error_log('Error info: ' . $dbh->errorInfo());
}

$data = array();
$data = array(
'likes' => array(),
'mentions' => array(),
'replies'=> array(),
'reposts' => array(),
'rsvps' => array()
);

while ($row = $sth->fetch()) {
$data[] = $row[0];
switch($row['type']) {
case "like":
$data['likes'][] = $row;
break;

case "reply":
$data['replies'][] = $row;
break;

case "repost":
$data['reposts'][] = $row;
break;

case "rsvp":
$data['rsvps'][] = $row;
break;

default:
$data['mentions'][] = $row;
break;
}
}

$json = json_encode($data);
@@ -46,7 +73,6 @@ $json = json_encode($data);
if ($json === false) {
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error');
exit;

} else {
header('Content-Type: application/json');
echo $json;


+ 66
- 84
index.php View File

@@ -10,20 +10,24 @@
require_once('config.php');
require_once('extlib/webmention.php');
require_once('vendor/autoload.php');
use BarnabyWalters\Mf2 as Cleaner;

/*********
* Utils *
*********/

function safe($obj, $prop) {
$unsafe = Cleaner\getPlaintext($obj, $prop, "");
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'];

@@ -37,12 +41,13 @@ if (parse_url($target_url, PHP_URL_HOST) !== $config["site"]["host"]) {
exit("Err");
}

// Make sure the page exists
// 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) {
@@ -54,97 +59,74 @@ if ($source_html === null) {
* Mf2 stuffs *
**************/

// TODO: https://github.com/pear2/Services_Linkback/blob/2afd453254c531925484196670e2953f669ae141/src/PEAR2/Services/Linkback/Server/Callback/LinkExists.php#L40
if (stristr($source_html, $target_url)) {
$mf = Mf2\parse($source_html, $source_url);

// FIXME: Just use the first item -- for testing purposes, at least
$hEntry = $mf["items"][0];

$entry_name = safe($hEntry, 'name');
$entry_url = $source_url;
// $entryUrl = safe($hEntry, 'url');

if ($entry_name === "") {
$entry_name = $entry_url;
}

// Truncate this since it could be the entire page
if (strlen($entry_name) > 150) {
$entry_name = substr($entry_name, 0, 150) . '[...]';
}

$hCard = Cleaner\getAuthor($hEntry);
$author_name = safe($hCard, 'name');
$author_url = safe($hCard, 'url');

// Prevent authorship spoofing
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 = '';
}
$mf = Mf2\parse($source_html, $source_url);

if ($author_name !== '') {
$by = 'by ' . $author_name;
$webmention = getWebmention($mf, $target_url);

if ($author_url !== '') {
$by = 'by <a href="' . $author_url . '">' . $author_name . '</a>';
}
}
// 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");
}

$on = '<a href="' . $entry_url . '">' . $entry_name . '</a>' ;
/*************
* DB Stuffs *
*************/

/*************
* DB Stuffs *
*************/
$dsn = 'mysql:dbname=' . $config['db']['name'] . ';host=' . $config['db']['host'];
$user = $config['db']['username'];
$password = $config['db']['password'];

$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");
}

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(?, ?, ?, ?, ?, ?, ?)'
);

$rendered = 'This page has been mentioned ' . $by . ' on ' . $on;
if ($sth === false) {
error_log("Could not prepare SQL statement.");
error_log("Error code: " . $dbh->errorCode());
error_log("Error info: " . $dbh->errorInfo());
}

$sth = $dbh->prepare(
'INSERT INTO webmentions (local_url, remote_url, remote_name, remote_author, remote_author_url, rendered) ' .
'VALUES(?, ?, ?, ?, ?, ?)'
);
$remote_url = safe(($webmention['url'] !== false) ? $webmention['url'] : $source_url);

if ($sth === false) {
error_log("Could not prepare SQL statement.");
error_log("Error code: " . $dbh->errorCode());
error_log("Error info: " . $dbh->errorInfo());
}
// 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,
$entry_url,
$entry_name,
$author_name,
$author_url,
$rendered
));
if ($res === false) {
error_log("Could not execute SQL query.");
error_log("Error code: " . $dbh->errorCode());
error_log("Error info: " . $dbh->errorInfo());
}
$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(
$rendered,
print_r($webmention, true),
4
);

} else {
error_log("Fake webmention from: " . $source_url, 4);
}

+ 7
- 7
schema.sql View File

@@ -1,12 +1,12 @@
CREATE TABLE `webmentions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`local_url` text NOT NULL,
`remote_url` text NOT NULL,
`remote_name` varchar(255) NOT NULL,
`remote_author` varchar(255),
`remote_author_url` text,
`rendered` text NOT NULL,
`created` datetime NOT NULL DEFAULT NOW(),
`last_checked` datetime NOT NULL DEFAULT NOW(),
`url` text NOT NULL,
`name` varchar(255),
`text` text NOT NULL,
`author_name` varchar(255),
`author_url` text,
`type` varchar(255),
`published` datetime NOT NULL DEFAULT NOW(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Loading…
Cancel
Save