Update activitypub.extend.php

This commit is contained in:
Namhyeon Go 2023-08-08 18:25:03 +09:00 committed by GitHub
parent b201e9d789
commit 6bd734d50b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -5,8 +5,8 @@ if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
// Author: Go Namhyeon (Catswords Research) <abuse@catswords.net> // Author: Go Namhyeon (Catswords Research) <abuse@catswords.net>
// ActivityPub: @gnh1201@catswords.social // ActivityPub: @gnh1201@catswords.social
// License: MIT // License: MIT
// Date: 2023-08-06 // Date: 2023-08-08
// Version: 0.1.17-dev // Version: 0.1.17
// References: // References:
// * https://www.w3.org/TR/activitypub/ // * https://www.w3.org/TR/activitypub/
// * https://www.w3.org/TR/activitystreams-core/ // * https://www.w3.org/TR/activitystreams-core/
@ -19,6 +19,7 @@ if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
// * https://github.com/autogestion/pubgate-telegram // * https://github.com/autogestion/pubgate-telegram
// * https://blog.joinmastodon.org/2018/06/how-to-implement-a-basic-activitypub-server/ // * https://blog.joinmastodon.org/2018/06/how-to-implement-a-basic-activitypub-server/
// * https://chat.openai.com/share/4fda7974-cc0b-439a-b0f2-dc828f8acfef // * https://chat.openai.com/share/4fda7974-cc0b-439a-b0f2-dc828f8acfef
// * https://codeberg.org/mro/activitypub/src/commit/4b1319d5363f4a836f23c784ef780b81bc674013/like.sh#L101
define("ACTIVITYPUB_INSTANCE_ID", md5_file(G5_DATA_PATH . "/dbconfig.php")); define("ACTIVITYPUB_INSTANCE_ID", md5_file(G5_DATA_PATH . "/dbconfig.php"));
define("ACTIVITYPUB_INSTANCE_VERSION", "0.1.14-dev"); define("ACTIVITYPUB_INSTANCE_VERSION", "0.1.14-dev");
@ -350,7 +351,7 @@ function activitypub_build_http_headers($headers) {
function activitypub_build_datetime($s='now') { function activitypub_build_datetime($s='now') {
// e.g. 18 Dec 2019 10:08:46 GMT // e.g. 18 Dec 2019 10:08:46 GMT
$format = "d M Y H:i:s e"; $format = "D, d M Y H:i:s e";
$dt = ($s == "now" ? new DateTime('now', new DateTimeZone("GMT")) : DateTime::createFromFormat($format, $s)); $dt = ($s == "now" ? new DateTime('now', new DateTimeZone("GMT")) : DateTime::createFromFormat($format, $s));
return $dt->format($format); return $dt->format($format);
} }
@ -362,7 +363,7 @@ function activitypub_build_digest($body) {
return $digest; return $digest;
} }
function activitypub_build_signature($url, $date, $digest, $mb, $method="POST") { function activitypub_build_signature($url, $date, $digest, $mb, $method="post") {
// get a certificate // get a certificate
list($private_key, $public_key) = activitypub_get_stored_keypair($mb); list($private_key, $public_key) = activitypub_get_stored_keypair($mb);
@ -374,13 +375,24 @@ function activitypub_build_signature($url, $date, $digest, $mb, $method="POST")
$keyId = $activitypub_user_id . "#main-key"; $keyId = $activitypub_user_id . "#main-key";
// build a target data to get signature // build a target data to get signature
/*
$signature = $method . ' ' . $path . "\n" . $signature = $method . ' ' . $path . "\n" .
'HOST: ' . $host . "\n" . 'HOST: ' . $host . "\n" .
'Date: ' . $date . "\n" . 'Date: ' . $date . "\n" .
'Digest: ' . $digest; 'Digest: ' . $digest;
*/
// Ref: https://codeberg.org/mro/activitypub/src/commit/4b1319d5363f4a836f23c784ef780b81bc674013/like.sh#L101
$signature = sprintf(
"%s: %s\n%s: %s\n%s: %s\n%s: %s",
"(request-target)",
"{$method} {$path}",
"host", $host,
"date", $date,
"digest", $digest
);
// create a signature // create a signature
openssl_sign($signature, $signature, $privateKey, OPENSSL_ALGO_SHA256); openssl_sign($signature, $signature, $private_key, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature); $signature = base64_encode($signature);
// create a signature header // create a signature header
@ -391,7 +403,7 @@ function activitypub_http_get($url, $access_token = '') {
// build the header // build the header
$headers = array( $headers = array(
"Date" => activitypub_build_datetime('now'), "Date" => activitypub_build_datetime('now'),
"Accept" => "application/ld+json; profile=\"" . NAMESPACE_ACTIVITYSTREAMS . "\"" "Accept" => "application/activity+json; profile=\"" . NAMESPACE_ACTIVITYSTREAMS . "\""
); );
// set access token // set access token
@ -432,20 +444,20 @@ function activitypub_get_attachments($bo_table, $wr_id) {
return $attachments; return $attachments;
} }
function activitypub_http_post($url, $raw_data, $mb, $access_token = '') { function activitypub_http_post($url, $rawdata, $mb, $access_token = '') {
// get digest // get digest
$date = activitypub_build_datetime('now'); $date = activitypub_build_datetime('now');
$digest = activitypub_build_digest($raw_data); $digest = activitypub_build_digest($rawdata);
// build the headers // build the headers
$headers = array( $headers = array(
"Date" => $date, "Date" => $date,
"Digest" => $digest, "Digest" => $digest,
"Content-Type" => "application/ld+json; profile=\"" . NAMESPACE_ACTIVITYSTREAMS . "\"", "Accept" => "application/activity+json; profile=\"" . NAMESPACE_ACTIVITYSTREAMS . "\"",
); );
// build the signature // build the signature
$signature = activitypub_build_signature($url, $date, $digest, $mb, "POST"); $signature = activitypub_build_signature($url, $date, $digest, $mb);
$headers["Signature"] = $signature; $headers["Signature"] = $signature;
// set access token // set access token
@ -461,12 +473,18 @@ function activitypub_http_post($url, $raw_data, $mb, $access_token = '') {
CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $raw_data, CURLOPT_POSTFIELDS => $rawdata,
CURLOPT_POST => true CURLOPT_POST => true
)); ));
$response = curl_exec($ch); $response = curl_exec($ch);
$errno = curl_errno($ch);
curl_close($ch); curl_close($ch);
// 전송 오류가 있었을 시 쪽지로 알림
if ($errno) {
activitypub_add_memo(ACTIVITYPUB_G5_USERNAME, $mb['mb_id'], "[경고] 메시지 전송 중 오류가 발생함. 오류 번호: " . $errno);
}
return activitypub_json_decode($response, true); return activitypub_json_decode($response, true);
} }
@ -650,6 +668,9 @@ function activitypub_publish_content($content, $object_id, $mb, $_added_object =
// 수신자/내용 생성 // 수신자/내용 생성
$to = array_merge(activitypub_cast_to_array(NAMESPACE_ACTIVITYSTREAMS_PUBLIC), $_added_to); $to = array_merge(activitypub_cast_to_array(NAMESPACE_ACTIVITYSTREAMS_PUBLIC), $_added_to);
$cc = array(); // 참조자
$tag = array(); // 태그
$endpoints = array();
$content = ""; $content = "";
foreach($terms as $term_ctx) { foreach($terms as $term_ctx) {
switch ($term_ctx['type']) { switch ($term_ctx['type']) {
@ -681,7 +702,7 @@ function activitypub_publish_content($content, $object_id, $mb, $_added_object =
// WebFinger 정보 수신을 못한 경우, 쪽지로 알리고 아무 작업도 하지 않음 // WebFinger 정보 수신을 못한 경우, 쪽지로 알리고 아무 작업도 하지 않음
if (empty($webfigner_ctx['subject'])) { if (empty($webfigner_ctx['subject'])) {
activitypub_add_memo(ACTIVITYPUB_G5_USERNAME, $mb['mb_id'], "[발송실패] 수신자를 찾을 수 없음: " . $account); activitypub_add_memo(ACTIVITYPUB_G5_USERNAME, $mb['mb_id'], "[발송실패] 수신자를 찾을 수 없음: @" . $account);
break; break;
} }
@ -689,7 +710,14 @@ function activitypub_publish_content($content, $object_id, $mb, $_added_object =
$webfigner_links = $webfigner_ctx['links']; $webfigner_links = $webfigner_ctx['links'];
foreach($webfigner_links as $link) { foreach($webfigner_links as $link) {
if ($link['rel'] == "self" && $link['type'] == "application/activity+json") { if ($link['rel'] == "self" && $link['type'] == "application/activity+json") {
array_push($to, $link['href']); // 수신자에 반영 // 태그 목록에 추가
array_push($tag, array(
"type" => "Mention",
"href" => $link['href'],
"name" => '@' . $account
));
array_push($cc, $link['href']); // 참조자 목록에 추가
array_push($endpoints, $link['href']); // 글을 전송할 엔드포인트(URL)에 반영
} }
} }
} }
@ -703,11 +731,17 @@ function activitypub_publish_content($content, $object_id, $mb, $_added_object =
// 위치정보가 활성화되어 있으면 // 위치정보가 활성화되어 있으면
if (ACTIVITYPUB_ENABLED_GEOLOCATION) { if (ACTIVITYPUB_ENABLED_GEOLOCATION) {
$object = array_merge($_added_object, array( $_added_object = array_merge($_added_object, array(
"location" => $location_ctx "location" => $location_ctx
)); ));
} }
// 참조자, 태그 추가
$_added_object = array_merge($_added_object, array(
"cc" => $cc,
"tag" => $tag
));
// 전문 생성 // 전문 생성
$object = activitypub_build_note($content, $object_id, $mb, $_added_object); $object = activitypub_build_note($content, $object_id, $mb, $_added_object);
@ -728,23 +762,20 @@ function activitypub_publish_content($content, $object_id, $mb, $_added_object =
// 보낼 전문을 인코딩 // 보낼 전문을 인코딩
$rawdata = activitypub_json_encode($data); $rawdata = activitypub_json_encode($data);
// 수신자 작업 // 수신자 엔드포인트(URL) 작업
foreach($to as $_to) { foreach($endpoints as $endpoint) {
// 공개 네임스페이스인 경우 건너뛰기
if ($_to == NAMESPACE_ACTIVITYSTREAMS_PUBLIC) continue;
// 수신자 정보 조회 // 수신자 정보 조회
$remote_user_ctx = activitypub_http_get($_to); $remote_account_ctx = activitypub_http_get($endpoint);
// inbox 주소 찾기 // inbox 주소 찾기
$remote_inbox_url = $remote_user_ctx['inbox']; $remote_inbox_url = $remote_account_ctx['inbox'];
if (empty($remote_inbox_url)) { if (empty($remote_inbox_url)) {
$remote_inbox_url = $remote_user_ctx['endpoints']['sharedInbox']; $remote_inbox_url = $remote_account_ctx['endpoints']['sharedInbox'];
} }
// inbox 주소가 없으면 건너뛰기 // inbox 주소가 없으면 건너뛰기
if (empty($remote_inbox_url)) { if (empty($remote_inbox_url)) {
activitypub_add_memo(ACTIVITYPUB_G5_USERNAME, $mb['mb_id'], "Could not find the inbox of " . $_to); activitypub_add_memo(ACTIVITYPUB_G5_USERNAME, $mb['mb_id'], "이 사용자 또는 서버는 메시지를 수신할 수 없는 상태임: " . $_to);
continue; continue;
} }
@ -759,7 +790,7 @@ function activitypub_publish_content($content, $object_id, $mb, $_added_object =
} }
// inbox로 데이터 전송 // inbox로 데이터 전송
$response = activitypub_http_post($remote_inbox_url, $rawdata, $mb, $access_token); activitypub_http_post($remote_inbox_url, $rawdata, $mb, $access_token);
} }
// 발행됨(Published)으로 상태 업데이트 // 발행됨(Published)으로 상태 업데이트
@ -1674,7 +1705,7 @@ switch ($route) {
_GNUBOARD_ActivityPub::close(); _GNUBOARD_ActivityPub::close();
break; break;
case "oauth2.authorize": // TODO case "oauth2.authorize": // To be implement
_GNUBOARD_ActivityPub::open(); _GNUBOARD_ActivityPub::open();
echo _GNUBOARD_ActivityPub::authorize(); echo _GNUBOARD_ActivityPub::authorize();
_GNUBOARD_ActivityPub::close(); _GNUBOARD_ActivityPub::close();