diff --git a/index.php b/index.php index 8b79586..cfb995a 100644 --- a/index.php +++ b/index.php @@ -244,17 +244,17 @@ function inbox() { global $body, $server, $username, $key_private, $directories; - // Get the message and type + // Get the message, type, and ID $inbox_message = $body; $inbox_type = $inbox_message["type"]; + $inbox_id = $inbox_message["id"]; - // If this is an Undo or Delete message, try to process it - if ( "Undo" == $inbox_type || "Delete" == $inbox_type ) { + // If this is an Undo, Delete, or Update message, try to process it + if ( "Undo" == $inbox_type || "Delete" == $inbox_type || "Update" == $inbox_type ) { undo( $inbox_message ); die(); } - // Messages to ignore. // Some servers are very chatty. They send lots of irrelevant messages. // Before even bothering to validate them, we can delete them. @@ -293,7 +293,7 @@ if ( !verifyHTTPSignature() ) { die(); } // If the message is valid, save the message in `/data/inbox/` - $uuid = uuid(); + $uuid = uuid( $inbox_message ); $inbox_filename = $uuid . "." . urlencode( $inbox_type ) . ".json"; file_put_contents( $directories["inbox"] . "/{$inbox_filename}", json_encode( $inbox_message ) ); @@ -345,14 +345,30 @@ // Every message sent should have a unique ID. // This can be anything you like. Some servers use a random number. // I prefer a date-sortable string. - function uuid() { - return sprintf( "%08x-%04x-%04x-%04x-%012x", - time(), - mt_rand(0, 0xffff), - mt_rand(0, 0xffff), - mt_rand(0, 0x3fff) | 0x8000, - mt_rand(0, 0xffffffffffff) - ); + function uuid( $message = null) { + // UUIDs that this server *sends* will be [timestamp]-[random] + // 65e99ab4-5d43-f074-b43e-463f9c5cf05c + if ( is_null( $message ) ) { + return sprintf( "%08x-%04x-%04x-%04x-%012x", + time(), + mt_rand(0, 0xffff), + mt_rand(0, 0xffff), + mt_rand(0, 0x3fff) | 0x8000, + mt_rand(0, 0xffffffffffff) + ); + } else { + // UUIDs that this server *saves* will be [timestamp]-[hash of message ID] + // 65eadace-8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4 + + // The message might have its own object + if ( isset( $message["object"]["id"] ) ) { + $id = $message["object"]["id"]; + } else { + $id = $message["id"]; + } + + return sprintf( "%08x", time() ) . "-" . hash( "sha256", $id ); + } } // Headers: @@ -1673,7 +1689,7 @@ HTML; } // Perform the Undo action requested - function undo( $message) { + function undo( $message ) { global $server, $directories; // Validate HTTP Message Signature @@ -1681,27 +1697,44 @@ HTML; // Get some basic data $type = $message["type"]; + $id = $message["id"]; // The thing being undone $object = $message["object"]; - $object_id = $object["id"]; - $object_type = $object["type"]; + + // Does the thing being undone have its own ID or Type? + if ( isset( $object["id"] ) ) { + $object_id = $object["id"]; + } else { + $object_id = $id; + } + + if ( isset( $object["type"] ) ) { + $object_type = $object["type"]; + } else { + $object_type = $type; + } + + // Inbox items are stored as the hash of the original ID + $object_id_hash = hash( "sha256", $object_id ); // Find all the inbox messages which have that ID $inbox_files = glob( $directories["inbox"] . "/*.json" ); foreach ( $inbox_files as $inbox_file ) { - // Load the contents - $inbox_item = json_decode( file_get_contents( $inbox_file ), true ); - // Find the ID - if ( isset( $inbox_item["object"]["id"] ) ) { - $inbox_id = $inbox_item["object"]["id"]; - } else if ( isset ($inbox_item["id"] )) { - $inbox_id = $inbox_item["id"]; + // Filenames are `data/inbox/[date]-[SHA256 hash0].[Type].json + // Find the position of the first hyphen and the first dot + $hyphenPosition = strpos( $inbox_file, '-' ); + $dotPosition = strpos( $inbox_file, '.' ); + + if ( $hyphenPosition !== false && $dotPosition !== false ) { + // Extract the text between the hyphen and the first dot + $file_id_hash = substr( $inbox_file, $hyphenPosition + 1, $dotPosition - $hyphenPosition - 1); } else { + // Ignore the file and move to the next. continue; } - // If this has the same ID as the item being undone - if ( $inbox_id == $object_id ) { + // If this has the same hash as the item being undone + if ( $object_id_hash == $file_id_hash ) { // Delete the file unlink( $inbox_file ); @@ -1716,14 +1749,12 @@ HTML; } } - // If the message is valid, save the message in `/data/inbox/` - $uuid = uuid(); + $uuid = uuid( $message ); $filename = $uuid . "." . urlencode( $type ) . ".json"; file_put_contents( $directories["inbox"] . "/{$filename}", json_encode( $message ) ); } - // "One to stun, two to kill, three to make sure" die(); die();