Move GET and POST into their own functions
rodzic
098e1a23e5
commit
5fdfd84e6f
303
index.php
303
index.php
|
@ -43,7 +43,7 @@
|
||||||
$server = $_SERVER["SERVER_NAME"]; // Do not change this!
|
$server = $_SERVER["SERVER_NAME"]; // Do not change this!
|
||||||
|
|
||||||
// Set up where logs and messages go.
|
// Set up where logs and messages go.
|
||||||
// If you want to, you can change these directories to something more suitable for you.
|
// You can change these directories to something more suitable if you like.
|
||||||
$data = "data";
|
$data = "data";
|
||||||
$directories = array(
|
$directories = array(
|
||||||
"inbox" => "{$data}/inbox",
|
"inbox" => "{$data}/inbox",
|
||||||
|
@ -53,6 +53,7 @@
|
||||||
"posts" => "posts",
|
"posts" => "posts",
|
||||||
"images" => "images",
|
"images" => "images",
|
||||||
);
|
);
|
||||||
|
// Create the directories if they don't already exist.
|
||||||
foreach ( $directories as $directory ) {
|
foreach ( $directories as $directory ) {
|
||||||
if( !is_dir( $directory ) ) { mkdir( $data ); mkdir( $directory ); }
|
if( !is_dir( $directory ) ) { mkdir( $data ); mkdir( $directory ); }
|
||||||
}
|
}
|
||||||
|
@ -71,6 +72,7 @@
|
||||||
$bodyData = print_r( $body, true );
|
$bodyData = print_r( $body, true );
|
||||||
$requestData = print_r( $_REQUEST, true );
|
$requestData = print_r( $_REQUEST, true );
|
||||||
$serverData = print_r( $_SERVER, true );
|
$serverData = print_r( $_SERVER, true );
|
||||||
|
// If the root has been requested, manually set the path to `/`
|
||||||
!empty( $_GET["path"] ) ? $path = $_GET["path"] : $path = "/";
|
!empty( $_GET["path"] ) ? $path = $_GET["path"] : $path = "/";
|
||||||
|
|
||||||
// Get the type of request - used in the log filename
|
// Get the type of request - used in the log filename
|
||||||
|
@ -123,21 +125,21 @@
|
||||||
case "outbox":
|
case "outbox":
|
||||||
outbox(); // Optional. Dynamic.
|
outbox(); // Optional. Dynamic.
|
||||||
case "write":
|
case "write":
|
||||||
write(); // User interface for writing posts
|
write(); // User interface for writing posts.
|
||||||
case "send":
|
case "send":
|
||||||
send(); // API for posting content to the Fediverse
|
send(); // API for posting content to the Fediverse.
|
||||||
case "follow":
|
case "follow":
|
||||||
follow(); // User interface for following an external user
|
follow(); // User interface for following an external user.
|
||||||
case "follow_user":
|
case "follow_user":
|
||||||
follow_user(); // API for following a user
|
follow_user(); // API for following a user.
|
||||||
case "read":
|
case "read":
|
||||||
view( "read" ); // User interface for reading posts
|
view( "read" );// User interface for reading posts.
|
||||||
case ".well-known/nodeinfo":
|
case ".well-known/nodeinfo":
|
||||||
wk_nodeinfo(); // Optional. Static.
|
wk_nodeinfo(); // Optional. Static.
|
||||||
case "nodeinfo/2.1":
|
case "nodeinfo/2.1":
|
||||||
nodeinfo(); // Optional. Static.
|
nodeinfo(); // Optional. Static.
|
||||||
case "/":
|
case "/":
|
||||||
view( "home" ); // Optional. Can be dynamic
|
view( "home" );// Optional. Can be dynamic
|
||||||
default:
|
default:
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
@ -221,7 +223,7 @@
|
||||||
// Create a list of all the followers
|
// Create a list of all the followers
|
||||||
$items = array();
|
$items = array();
|
||||||
foreach ( $following_files as $following_file ) {
|
foreach ( $following_files as $following_file ) {
|
||||||
$following = json_decode( file_get_contents( $following_file ),true );
|
$following = json_decode( file_get_contents( $following_file ), true );
|
||||||
$items[] = $following["id"];
|
$items[] = $following["id"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,8 +240,8 @@
|
||||||
}
|
}
|
||||||
function followers() {
|
function followers() {
|
||||||
global $server, $directories;
|
global $server, $directories;
|
||||||
// The number of followers is self-reported
|
// The number of followers is self-reported.
|
||||||
// You can set this to any number you like
|
// You can set this to any number you like.
|
||||||
|
|
||||||
// Get all the files
|
// Get all the files
|
||||||
$follower_files = glob( $directories["followers"] . "/*.json");
|
$follower_files = glob( $directories["followers"] . "/*.json");
|
||||||
|
@ -322,13 +324,13 @@
|
||||||
$inbox_actor_json = curl_exec( $ch );
|
$inbox_actor_json = curl_exec( $ch );
|
||||||
|
|
||||||
// Check for errors
|
// Check for errors
|
||||||
if (curl_errno($ch)) {
|
if ( curl_errno( $ch ) ) {
|
||||||
// TODO: Handle cURL error
|
// TODO: Handle cURL error
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close cURL session
|
// Close cURL session
|
||||||
curl_close($ch);
|
curl_close( $ch );
|
||||||
|
|
||||||
// Save the actor's data in `/data/followers/`
|
// Save the actor's data in `/data/followers/`
|
||||||
$follower_filename = urlencode( $follower_actor );
|
$follower_filename = urlencode( $follower_actor );
|
||||||
|
@ -362,24 +364,7 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
// The Accept is POSTed to the inbox on the server of the user who requested the follow
|
// The Accept is POSTed to the inbox on the server of the user who requested the follow
|
||||||
$follower_inbox_path = parse_url( $follower_inbox, PHP_URL_PATH );
|
sentMessageToSingle( $follower_inbox, $message );
|
||||||
// Generate the signed headers
|
|
||||||
$headers = generate_signed_headers( $message, $follower_host, $follower_inbox_path, "POST" );
|
|
||||||
|
|
||||||
// POST the message and header to the requester's inbox
|
|
||||||
$ch = curl_init( $follower_inbox );
|
|
||||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
|
||||||
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
|
|
||||||
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $message ) );
|
|
||||||
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
|
|
||||||
curl_exec( $ch );
|
|
||||||
|
|
||||||
// Check for errors
|
|
||||||
if( curl_errno( $ch ) ) {
|
|
||||||
$timestamp = ( new DateTime() )->format( DATE_RFC3339_EXTENDED );
|
|
||||||
file_put_contents( $directories["logs"] . "/{$timestamp}.Error.txt", curl_error( $ch ) );
|
|
||||||
}
|
|
||||||
curl_close( $ch );
|
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,7 +398,7 @@
|
||||||
// Timestamp this message was sent
|
// Timestamp this message was sent
|
||||||
$date = date( "D, d M Y H:i:s \G\M\T" );
|
$date = date( "D, d M Y H:i:s \G\M\T" );
|
||||||
|
|
||||||
// There are subtly different signing requirements for POST and GET
|
// There are subtly different signing requirements for POST and GET.
|
||||||
if ( "POST" == $method ) {
|
if ( "POST" == $method ) {
|
||||||
// Encode the message object to JSON
|
// Encode the message object to JSON
|
||||||
$message_json = json_encode( $message );
|
$message_json = json_encode( $message );
|
||||||
|
@ -497,15 +482,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Counters for followers, following, and posts
|
// Counters for followers, following, and posts
|
||||||
$follower_files = glob( $directories["followers"] . "/*.json");
|
$follower_files = glob( $directories["followers"] . "/*.json" );
|
||||||
$totalFollowers = count( $follower_files );
|
$totalFollowers = count( $follower_files );
|
||||||
$following_files = glob( $directories["following"] . "/*.json");
|
$following_files = glob( $directories["following"] . "/*.json" );
|
||||||
$totalFollowing = count( $following_files );
|
$totalFollowing = count( $following_files );
|
||||||
|
|
||||||
// Show the HTML page
|
// Show the HTML page
|
||||||
echo <<< HTML
|
echo <<< HTML
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en-GB">
|
<html lang="en-GB">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
@ -612,16 +597,21 @@ HTML;
|
||||||
|
|
||||||
// Set up the common components
|
// Set up the common components
|
||||||
$object = $message["object"];
|
$object = $message["object"];
|
||||||
|
|
||||||
|
// Get the message's ID.
|
||||||
|
// Set up the HTML representation
|
||||||
if ( isset( $message["object"]["id"] ) ) {
|
if ( isset( $message["object"]["id"] ) ) {
|
||||||
$id = $message["object"]["id"];
|
$id = $message["object"]["id"];
|
||||||
$timeHTML = "<time datetime=\"{$published}\" class=\"u-url\" rel=\"bookmark\"><a href=\"{$id}\">{$published}</a></time>";
|
$publishedHTML = "<a href=\"{$id}\">{$published}</a>";
|
||||||
} else if ( isset( $message["id"] ) ) {
|
} else if ( isset( $message["id"] ) ) {
|
||||||
$id = $message["id"];
|
$id = $message["id"];
|
||||||
$timeHTML = "<time datetime=\"{$published}\" class=\"u-url\" rel=\"bookmark\"><a href=\"{$id}\">{$published}</a></time>";
|
$publishedHTML = "<a href=\"{$id}\">{$published}</a>";
|
||||||
} else {
|
} else {
|
||||||
$id = "";
|
$id = "";
|
||||||
$timeHTML = "<time datetime=\"{$published}\" class=\"u-url\" rel=\"bookmark\">{$published}</time>";
|
$publishedHTML = $published;
|
||||||
}
|
}
|
||||||
|
// For displaying the post's information
|
||||||
|
$timeHTML = "<time datetime=\"{$published}\" class=\"u-url\" rel=\"bookmark\">{$publishedHTML}</time>";
|
||||||
|
|
||||||
// Get the actor who authored the message
|
// Get the actor who authored the message
|
||||||
if ( isset( $message["actor"] ) ) {
|
if ( isset( $message["actor"] ) ) {
|
||||||
|
@ -656,9 +646,10 @@ HTML;
|
||||||
|
|
||||||
// Render the message according to type
|
// Render the message according to type
|
||||||
if ( "Create" == $type || "Update" == $type || "Note" == $type ) {
|
if ( "Create" == $type || "Update" == $type || "Note" == $type ) {
|
||||||
// Get the HTML content and sanitise it.
|
// Get the HTML content
|
||||||
// There is a slight difference between the formatting of sent and received messages
|
// There is a slight difference between the formatting of sent and received messages
|
||||||
"Note" == $type ? $content = $message["content"] : $content = $object["content"];
|
"Note" == $type ? $content = $message["content"] : $content = $object["content"];
|
||||||
|
// Sanitise the HTML
|
||||||
$content = strip_tags( $content, $allowed_elements );
|
$content = strip_tags( $content, $allowed_elements );
|
||||||
|
|
||||||
// Is this a reply to something?
|
// Is this a reply to something?
|
||||||
|
@ -680,7 +671,7 @@ HTML;
|
||||||
if ( isset( $object["summary"] ) ) {
|
if ( isset( $object["summary"] ) ) {
|
||||||
$summary = $object["summary"];
|
$summary = $object["summary"];
|
||||||
$summary = strip_tags( $summary, $allowed_elements );
|
$summary = strip_tags( $summary, $allowed_elements );
|
||||||
|
// Hide the content until the user interacts with it.
|
||||||
$content = "<details><summary>{$summary}</summary>{$content}</details>";
|
$content = "<details><summary>{$summary}</summary>{$content}</details>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,16 +703,20 @@ HTML;
|
||||||
|
|
||||||
// Only use things which have a MIME Type set
|
// Only use things which have a MIME Type set
|
||||||
if ( isset( $attachment["mediaType"] ) ) {
|
if ( isset( $attachment["mediaType"] ) ) {
|
||||||
$mediaType = explode( "/", $attachment["mediaType"])[0];
|
$mediaURl = $attachment["url"];
|
||||||
|
$mime = $attachment["mediaType"];
|
||||||
|
// Use the first half of the MIME Type.
|
||||||
|
// For example `image/png` or `video/mp4`
|
||||||
|
$mediaType = explode( "/", $mime )[0];
|
||||||
|
|
||||||
if ( "image" == $mediaType ) {
|
if ( "image" == $mediaType ) {
|
||||||
// Get the alt text
|
// Get the alt text
|
||||||
isset( $attachment["name"] ) ? $alt = $attachment["name"] : $alt = "";
|
isset( $attachment["name"] ) ? $alt = $attachment["name"] : $alt = "";
|
||||||
$content .= "<img src='" . $attachment["url"] . "' alt='{$alt}'>";
|
$content .= "<img src='{$mediaURl}' alt='{$alt}'>";
|
||||||
} else if ( "video" == $mediaType ) {
|
} else if ( "video" == $mediaType ) {
|
||||||
$content .= "<video controls><source src='" . $attachment["url"] . "' type='" . $attachment["mediaType"] . "' /></video>";
|
$content .= "<video controls><source src='{$mediaURl}' type='{$mime}'></video>";
|
||||||
}else if ( "audio" == $mediaType ) {
|
}else if ( "audio" == $mediaType ) {
|
||||||
$content .= "<audio controls src='" . $attachment["url"] . "' type='" . $attachment["mediaType"] . "'></audio>";
|
$content .= "<audio controls src='{$mediaURl}' type='{$mime}'></audio>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -767,7 +762,6 @@ HTML;
|
||||||
}
|
}
|
||||||
echo <<< HTML
|
echo <<< HTML
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -866,7 +860,7 @@ HTML;
|
||||||
$type = $_POST["type"];
|
$type = $_POST["type"];
|
||||||
|
|
||||||
// Likes and Announces have an identical message structure
|
// Likes and Announces have an identical message structure
|
||||||
if ( $type == "Like" || $type == "Announce" ) {
|
if ( "Like" == $type || "Announce" == $type ) {
|
||||||
// Was a URl sent?
|
// Was a URl sent?
|
||||||
if ( isset( $_POST["postURl"] ) && filter_var( $_POST["postURl"], FILTER_VALIDATE_URL ) ) {
|
if ( isset( $_POST["postURl"] ) && filter_var( $_POST["postURl"], FILTER_VALIDATE_URL ) ) {
|
||||||
$postURl = $_POST["postURl"];
|
$postURl = $_POST["postURl"];
|
||||||
|
@ -875,6 +869,11 @@ HTML;
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( "Like" == $type ) {
|
||||||
|
// The message will need to be sent to the inbox of the author of the message
|
||||||
|
$inbox_single = getInboxFromMessageURl( $postURl );
|
||||||
|
}
|
||||||
|
|
||||||
// Outgoing Message ID
|
// Outgoing Message ID
|
||||||
$guid = uuid();
|
$guid = uuid();
|
||||||
|
|
||||||
|
@ -888,16 +887,14 @@ HTML;
|
||||||
"object" => $postURl
|
"object" => $postURl
|
||||||
];
|
];
|
||||||
|
|
||||||
// Annouces are sent to an audience
|
// Announces are sent to an audience
|
||||||
// The audience is public and it is sent to all followers
|
// The audience is public and it is sent to all followers
|
||||||
if ( $type == "Announce") {
|
// TODO: Let the original poster know we boosted them
|
||||||
|
if ( $type == "Announce" ) {
|
||||||
$message = array_merge( $message,
|
$message = array_merge( $message,
|
||||||
array("to" => [
|
array(
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||||
],
|
"cc" => ["https://{$server}/followers"])
|
||||||
"cc" => [
|
|
||||||
"https://{$server}/followers"
|
|
||||||
])
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -920,7 +917,7 @@ HTML;
|
||||||
list( "HTML" => $content, "TagArray" => $tags ) = process_content( $content );
|
list( "HTML" => $content, "TagArray" => $tags ) = process_content( $content );
|
||||||
|
|
||||||
// Is there an image attached?
|
// Is there an image attached?
|
||||||
if ( isset( $_FILES['image']['tmp_name'] ) && ("" != $_FILES['image']['tmp_name'] ) ) {
|
if ( isset( $_FILES['image']['tmp_name'] ) && ( "" != $_FILES['image']['tmp_name'] ) ) {
|
||||||
// Get information about the image
|
// Get information about the image
|
||||||
$image = $_FILES['image']['tmp_name'];
|
$image = $_FILES['image']['tmp_name'];
|
||||||
$image_info = getimagesize( $image );
|
$image_info = getimagesize( $image );
|
||||||
|
@ -949,7 +946,6 @@ HTML;
|
||||||
"url" => "https://{$server}/{$image_full_path}",
|
"url" => "https://{$server}/{$image_full_path}",
|
||||||
"name" => $alt
|
"name" => $alt
|
||||||
];
|
];
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$attachment = [];
|
$attachment = [];
|
||||||
}
|
}
|
||||||
|
@ -1000,6 +996,54 @@ HTML;
|
||||||
$note_json = json_encode( $note );
|
$note_json = json_encode( $note );
|
||||||
file_put_contents( $directories["posts"] . "/{$guid}.json", print_r( $note_json, true ) );
|
file_put_contents( $directories["posts"] . "/{$guid}.json", print_r( $note_json, true ) );
|
||||||
|
|
||||||
|
// Is this message going to one user? (Usually a Like)
|
||||||
|
if ( isset( $inbox_single ) ) {
|
||||||
|
$messageSent = sentMessageToSingle( $inbox_single, $message );
|
||||||
|
} else { // Send to all the user's followers
|
||||||
|
$messageSent = sendMessageToFollowers( $message );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the JSON so the user can see the POST has worked
|
||||||
|
if ( $messageSent ) {
|
||||||
|
header( "Location: https://{$server}/posts/{$guid}.json" );
|
||||||
|
die();
|
||||||
|
} else {
|
||||||
|
echo "ERROR!";
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST a signed message to a single inbox
|
||||||
|
function sentMessageToSingle( $inbox, $message ) {
|
||||||
|
global $directories;
|
||||||
|
|
||||||
|
$inbox_host = parse_url( $inbox, PHP_URL_HOST );
|
||||||
|
$inbox_path = parse_url( $inbox, PHP_URL_PATH );
|
||||||
|
|
||||||
|
// Generate the signed headers
|
||||||
|
$headers = generate_signed_headers( $message, $inbox_host, $inbox_path, "POST" );
|
||||||
|
|
||||||
|
// POST the message and header to the requester's inbox
|
||||||
|
$ch = curl_init( $inbox );
|
||||||
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
||||||
|
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
|
||||||
|
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $message ) );
|
||||||
|
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
|
||||||
|
curl_exec( $ch );
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if( curl_errno( $ch ) ) {
|
||||||
|
$timestamp = ( new DateTime() )->format( DATE_RFC3339_EXTENDED );
|
||||||
|
file_put_contents( $directories["logs"] . "/{$timestamp}.Error.txt", curl_error( $ch ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
curl_close($ch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST a signed message to the inboxes of all followers
|
||||||
|
function sendMessageToFollowers( $message ) {
|
||||||
|
global $directories;
|
||||||
// Read existing followers
|
// Read existing followers
|
||||||
$followers = glob( $directories["followers"] . "/*.json" );
|
$followers = glob( $directories["followers"] . "/*.json" );
|
||||||
|
|
||||||
|
@ -1062,9 +1106,7 @@ HTML;
|
||||||
// Close the multi-handle
|
// Close the multi-handle
|
||||||
curl_multi_close( $mh );
|
curl_multi_close( $mh );
|
||||||
|
|
||||||
// Render the JSON so the user can see the POST has worked
|
return true;
|
||||||
header( "Location: https://{$server}/posts/{$guid}.json" );
|
|
||||||
die();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content can be plain text. But to add clickable links and hashtags, it needs to be turned into HTML.
|
// Content can be plain text. But to add clickable links and hashtags, it needs to be turned into HTML.
|
||||||
|
@ -1115,7 +1157,7 @@ HTML;
|
||||||
|
|
||||||
// Construct the mentions value for the note object
|
// Construct the mentions value for the note object
|
||||||
// This goes in the generic "tag" property
|
// This goes in the generic "tag" property
|
||||||
// TODO: Add this to the CC field
|
// TODO: Add this to the CC field & appropriate inbox
|
||||||
foreach ( $usernames as $username ) {
|
foreach ( $usernames as $username ) {
|
||||||
list( , $user, $domain ) = explode( "@", $username );
|
list( , $user, $domain ) = explode( "@", $username );
|
||||||
$tags[] = array(
|
$tags[] = array(
|
||||||
|
@ -1142,6 +1184,64 @@ HTML;
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When given the URl of a post, this looks up the post, finds the user, then returns their inbox or shared inbox
|
||||||
|
function getInboxFromMessageURl( $url ) {
|
||||||
|
|
||||||
|
// Get details about the message
|
||||||
|
$messageData = getDataFromURl( $url );
|
||||||
|
|
||||||
|
// The author is the user who the message is attributed to
|
||||||
|
if ( isset ( $messageData["attributedTo"] ) && filter_var( $messageData["attributedTo"], FILTER_VALIDATE_URL) ) {
|
||||||
|
$profileData = getDataFromURl( $messageData["attributedTo"] );
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the shared inbox or personal inbox
|
||||||
|
if( isset( $profileData["endpoints"]["sharedInbox"] ) ) {
|
||||||
|
$inbox = $profileData["endpoints"]["sharedInbox"];
|
||||||
|
} else {
|
||||||
|
// If not, use the individual inbox
|
||||||
|
$inbox = $profileData["inbox"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the destination inbox if it is valid
|
||||||
|
if ( filter_var( $inbox, FILTER_VALIDATE_URL) ) {
|
||||||
|
return $inbox;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET a request to a URl and returns structured data
|
||||||
|
function getDataFromURl ( $url ) {
|
||||||
|
// Split the URL
|
||||||
|
$url_host = parse_url( $url, PHP_URL_HOST );
|
||||||
|
$url_path = parse_url( $url, PHP_URL_PATH );
|
||||||
|
|
||||||
|
// Generate signed headers for this request
|
||||||
|
$headers = generate_signed_headers( null, $url_host, $url_path, "GET" );
|
||||||
|
|
||||||
|
// Set cURL options
|
||||||
|
$ch = curl_init( $url );
|
||||||
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
|
||||||
|
|
||||||
|
// Execute the cURL session
|
||||||
|
$urlJSON = curl_exec( $ch );
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (curl_errno( $ch )) {
|
||||||
|
// Handle cURL error
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close cURL session
|
||||||
|
curl_close( $ch );
|
||||||
|
|
||||||
|
return json_decode( $urlJSON, true );
|
||||||
|
}
|
||||||
|
|
||||||
// The Outbox contains a date-ordered list (newest first) of all the user's posts
|
// The Outbox contains a date-ordered list (newest first) of all the user's posts
|
||||||
// This is optional.
|
// This is optional.
|
||||||
function outbox() {
|
function outbox() {
|
||||||
|
@ -1239,41 +1339,10 @@ HTML;
|
||||||
if ( !isset( $profileURl ) ) { echo "No profile"; die(); }
|
if ( !isset( $profileURl ) ) { echo "No profile"; die(); }
|
||||||
|
|
||||||
// Get the user's details
|
// Get the user's details
|
||||||
// This request does not need to be signed normally.
|
$profileData = getDataFromURl( $profileURl );
|
||||||
// Some servers will only respond to signed requests.
|
|
||||||
// It need to specify that it wants a JSON response
|
|
||||||
|
|
||||||
$profileURl_host = parse_url( $profileURl, PHP_URL_HOST );
|
|
||||||
$profileURl_path = parse_url( $profileURl, PHP_URL_PATH );
|
|
||||||
|
|
||||||
// Request the JSON representation of the the user
|
|
||||||
$ch = curl_init( $profileURl );
|
|
||||||
|
|
||||||
// Generate signed headers for this request
|
|
||||||
$headers = generate_signed_headers( null, $profileURl_host, $profileURl_path, "GET" );
|
|
||||||
|
|
||||||
// Set cURL options
|
|
||||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
|
|
||||||
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
|
|
||||||
|
|
||||||
// Execute the cURL session
|
|
||||||
$profileJSON = curl_exec( $ch );
|
|
||||||
|
|
||||||
// Check for errors
|
|
||||||
if (curl_errno($ch)) {
|
|
||||||
// Handle cURL error
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close cURL session
|
|
||||||
curl_close($ch);
|
|
||||||
|
|
||||||
$profileData = json_decode( $profileJSON, true );
|
|
||||||
|
|
||||||
// Get the user's inbox
|
// Get the user's inbox
|
||||||
$profileInbox = $profileData["inbox"];
|
$profileInbox = $profileData["inbox"];
|
||||||
$inbox_host = parse_url( $profileInbox, PHP_URL_HOST );
|
|
||||||
$inbox_path = parse_url( $profileInbox, PHP_URL_PATH );
|
|
||||||
|
|
||||||
// Create a follow request
|
// Create a follow request
|
||||||
$guid = uuid();
|
$guid = uuid();
|
||||||
|
@ -1287,27 +1356,11 @@ HTML;
|
||||||
|
|
||||||
// Sign a request to follow
|
// Sign a request to follow
|
||||||
// The Accept is POSTed to the inbox on the server of the user who requested the follow
|
// The Accept is POSTed to the inbox on the server of the user who requested the follow
|
||||||
// Get the signed headers
|
sentMessageToSingle( $profileInbox, $message );
|
||||||
$headers = generate_signed_headers( $message, $inbox_host, $inbox_path, "POST" );
|
|
||||||
|
|
||||||
// POST the message and header to the requester's inbox
|
|
||||||
$ch = curl_init( $profileInbox );
|
|
||||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
|
||||||
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
|
|
||||||
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $message ) );
|
|
||||||
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
|
|
||||||
curl_exec( $ch );
|
|
||||||
|
|
||||||
// Check for errors
|
|
||||||
if( curl_errno( $ch ) ) {
|
|
||||||
$timestamp = ( new DateTime() )->format( DATE_RFC3339_EXTENDED );
|
|
||||||
file_put_contents( $directories["logs"] . "/{$timestamp}.Error.txt", curl_error( $ch ) );
|
|
||||||
}
|
|
||||||
curl_close($ch);
|
|
||||||
|
|
||||||
// Save the user's details
|
// Save the user's details
|
||||||
$following_filename = urlencode( $profileURl );
|
$following_filename = urlencode( $profileURl );
|
||||||
file_put_contents( $directories["following"] . "/{$following_filename}.json", $profileJSON );
|
file_put_contents( $directories["following"] . "/{$following_filename}.json", json_encode( $profileData ) );
|
||||||
|
|
||||||
// Render the JSON so the user can see the POST has worked
|
// Render the JSON so the user can see the POST has worked
|
||||||
header( "Location: https://{$server}/data/following/" . urlencode( $following_filename ) . ".json" );
|
header( "Location: https://{$server}/data/following/" . urlencode( $following_filename ) . ".json" );
|
||||||
|
@ -1422,36 +1475,8 @@ HTML;
|
||||||
// This is usually in the form `https://example.com/user/username#main-key`
|
// This is usually in the form `https://example.com/user/username#main-key`
|
||||||
// This is to differentiate if the user has multiple keys
|
// This is to differentiate if the user has multiple keys
|
||||||
// TODO: Check the actual key
|
// TODO: Check the actual key
|
||||||
// This request does not need to be signed normally.
|
|
||||||
// Some servers will only respond to signed requests.
|
|
||||||
// It need to specify that it wants a JSON response
|
|
||||||
|
|
||||||
$publicKeyURL_host = parse_url( $publicKeyURL, PHP_URL_HOST );
|
$userData = getDataFromURl( $publicKeyURL );
|
||||||
$publicKeyURL_path = parse_url( $publicKeyURL, PHP_URL_PATH );
|
|
||||||
|
|
||||||
// Request the JSON representation of the the user
|
|
||||||
$ch = curl_init( $publicKeyURL );
|
|
||||||
|
|
||||||
// Generate signed headers for this request
|
|
||||||
$headers = generate_signed_headers( null, $publicKeyURL_host, $publicKeyURL_path, "GET" );
|
|
||||||
|
|
||||||
// Set cURL options
|
|
||||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
|
|
||||||
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
|
|
||||||
|
|
||||||
// Execute the cURL session
|
|
||||||
$userJSON = curl_exec( $ch );
|
|
||||||
|
|
||||||
// Check for errors
|
|
||||||
if (curl_errno($ch)) {
|
|
||||||
// Handle cURL error
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close cURL session
|
|
||||||
curl_close($ch);
|
|
||||||
|
|
||||||
$userData = json_decode( $userJSON, true );
|
|
||||||
$publicKey = $userData["publicKey"]["publicKeyPem"];
|
$publicKey = $userData["publicKey"]["publicKeyPem"];
|
||||||
|
|
||||||
// Get the remaining parts
|
// Get the remaining parts
|
||||||
|
|
Ładowanie…
Reference in New Issue