ActivityPubユニットテストの追加、CURLの変更、認証にログの追加

This commit is contained in:
2025-12-22 23:04:08 +09:00
parent 3b96986a85
commit 05f02e74d5
6 changed files with 110 additions and 78 deletions

View File

@@ -16,6 +16,7 @@ class ActivityPub {
private string $desc; private string $desc;
private string $icon; private string $icon;
private array $posts = []; private array $posts = [];
private string $https;
/** /**
* コンストラクタ * コンストラクタ
@@ -23,11 +24,13 @@ class ActivityPub {
* @param array $posts 投稿データの配列 * @param array $posts 投稿データの配列
*/ */
public function __construct(array $posts = []) { public function __construct(array $posts = []) {
$this->domain = $_SERVER['SERVER_NAME']; if (!ACTIVITYPUB_ENABLED) return;
$this->https = 'http'.((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 's' : '').'://';
$this->domain = $this->https.($_SERVER['SERVER_NAME'] ?? '127.0.0.1:8000');
$this->actor = FEDIINFO['actor']; $this->actor = FEDIINFO['actor'];
$this->actorNick = FEDIINFO['actorNick']; $this->actorNick = FEDIINFO['actorNick'];
$this->desc = FEDIINFO['desc']; $this->desc = FEDIINFO['desc'];
$this->icon = "https://{$this->domain}".FEDIINFO['icon']; $this->icon = "{$this->domain}".FEDIINFO['icon'];
$this->posts = $posts; $this->posts = $posts;
} }
@@ -38,6 +41,7 @@ class ActivityPub {
* @throws \Exception 公開鍵の読み込みに失敗した場合 * @throws \Exception 公開鍵の読み込みに失敗した場合
*/ */
public function getActor(): string { public function getActor(): string {
if (!ACTIVITYPUB_ENABLED) return '';
$pubkey = file_get_contents(FEDIINFO['pubkey']); $pubkey = file_get_contents(FEDIINFO['pubkey']);
if ($pubkey === false) { if ($pubkey === false) {
throw new \Exception('公開鍵の受取に失敗。パス:'.FEDIINFO['pubkey']); throw new \Exception('公開鍵の受取に失敗。パス:'.FEDIINFO['pubkey']);
@@ -48,7 +52,7 @@ class ActivityPub {
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
], ],
'id' => "https://{$this->domain}/ap/actor", 'id' => "{$this->domain}/ap/actor",
'name' => $this->actorNick, 'name' => $this->actorNick,
'summary' => $this->desc, 'summary' => $this->desc,
'manuallyApprovesFollowers' => false, 'manuallyApprovesFollowers' => false,
@@ -59,22 +63,21 @@ class ActivityPub {
], ],
'image' => [ 'image' => [
'type' => 'Image', 'type' => 'Image',
'url' => 'url' => "{$this->domain}/static/article/o_53803618dc1691.28179609.jpg",
"https://{$this->domain}/static/article/o_53803618dc1691.28179609.jpg",
'mediaType' => 'image/jpeg', 'mediaType' => 'image/jpeg',
], ],
'type' => 'Person', 'type' => 'Person',
'url' => "https://{$this->domain}", 'url' => "{$this->domain}",
'preferredUsername' => $this->actor, 'preferredUsername' => $this->actor,
'inbox' => "https://{$this->domain}/ap/inbox", 'inbox' => "{$this->domain}/ap/inbox",
'outbox' => "https://{$this->domain}/ap/outbox", 'outbox' => "{$this->domain}/ap/outbox",
'followers' => "https://{$this->domain}/ap/followers", 'followers' => "{$this->domain}/ap/followers",
'following' => "https://{$this->domain}/ap/following", 'following' => "{$this->domain}/ap/following",
'published' => '2025-03-28T18:00:00Z', 'published' => '2025-03-28T18:00:00Z',
'updated' => gmdate('c'), 'updated' => gmdate('c'),
'publicKey' => [ 'publicKey' => [
'id' => "https://{$this->domain}/ap/actor#main-key", 'id' => "{$this->domain}/ap/actor#main-key",
'owner' => "https://{$this->domain}/ap/actor", 'owner' => "{$this->domain}/ap/actor",
'publicKeyPem' => $pubkey, 'publicKeyPem' => $pubkey,
], ],
]; ];
@@ -89,6 +92,7 @@ class ActivityPub {
* @return string JSONエンコードされたアクティビティデータ * @return string JSONエンコードされたアクティビティデータ
*/ */
public function getActivity(string $uuid): string { public function getActivity(string $uuid): string {
if (!ACTIVITYPUB_ENABLED) return '';
$items = []; $items = [];
foreach ($this->posts as $post) { foreach ($this->posts as $post) {
@@ -107,28 +111,27 @@ class ActivityPub {
'toot' => 'http://joinmastodon.org/ns#', 'toot' => 'http://joinmastodon.org/ns#',
], ],
], ],
'id' => "https://{$this->domain}/ap/activities/create/{$post['uuid']}", 'id' => "{$this->domain}/ap/activities/create/{$post['uuid']}",
'type' => 'Create', 'type' => 'Create',
'actor' => "https://{$this->domain}/ap/actor", 'actor' => "{$this->domain}/ap/actor",
'cc' => [ 'cc' => [
"https://{$this->domain}/ap/followers", "{$this->domain}/ap/followers",
], ],
'published' => date("Y-m-d\TH:i:s.u\Z", strtotime($post['date'])), 'published' => date("Y-m-d\TH:i:s.u\Z", strtotime($post['date'])),
'to' => ['https://www.w3.org/ns/activitystreams#Public'], 'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'object' => [ 'object' => [
'id' => "https://{$this->domain}/ap/objects/{$post['uuid']}", 'id' => "{$this->domain}/ap/objects/{$post['uuid']}",
'type' => 'Note', 'type' => 'Note',
'name' => $post['title'], 'name' => $post['title'],
'attributedTo' => "https://{$this->domain}/ap/actor", 'attributedTo' => "{$this->domain}/ap/actor",
'cc' => [ 'cc' => [
"https://{$this->domain}/ap/followers", "{$this->domain}/ap/followers",
], ],
'to' => ['https://www.w3.org/ns/activitystreams#Public'], 'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'content' => 'content' => $post['preview']."<br /><br /><a href=\"{$this->domain}/blog/{$post['slug']}\">読み続き</a>",
$post['preview']."<br /><br /><a href=\"https://{$this->domain}/blog/{$post['slug']}\">読み続き</a>", 'url' => "{$this->domain}/blog/{$post['slug']}",
'url' => "https://{$this->domain}/blog/{$post['slug']}",
'published' => date("Y-m-d\TH:i:s.u\Z", strtotime($post['date'])), 'published' => date("Y-m-d\TH:i:s.u\Z", strtotime($post['date'])),
'replies' => "https://{$this->domain}/ap/objects/{$uuid}/replies", 'replies' => "{$this->domain}/ap/objects/{$uuid}/replies",
'sensitive' => false, 'sensitive' => false,
], ],
]; ];
@@ -141,7 +144,7 @@ class ActivityPub {
} }
if (isset($post['thumbnail']) && $post['thumbnail'] != '') { if (isset($post['thumbnail']) && $post['thumbnail'] != '') {
$imgurl = "https://technicalsuwako.moe/static/article/{$post['thumbnail']}"; $imgurl = "{$this->domain}/static/article/{$post['thumbnail']}";
$imgpath = ROOT."/public/static/article/{$post['thumbnail']}"; $imgpath = ROOT."/public/static/article/{$post['thumbnail']}";
$imgraw = file_get_contents($imgpath); $imgraw = file_get_contents($imgpath);
@@ -167,6 +170,7 @@ class ActivityPub {
* @return string JSONエンコードされたアウトボックスデータ * @return string JSONエンコードされたアウトボックスデータ
*/ */
public function getOutbox(): string { public function getOutbox(): string {
if (!ACTIVITYPUB_ENABLED) return '';
$items = []; $items = [];
$counter = 0; $counter = 0;
@@ -186,28 +190,27 @@ class ActivityPub {
'toot' => 'http://joinmastodon.org/ns#', 'toot' => 'http://joinmastodon.org/ns#',
], ],
], ],
'id' => "https://{$this->domain}/ap/activities/create/{$uid}", 'id' => "{$this->domain}/ap/activities/create/{$uid}",
'type' => 'Create', 'type' => 'Create',
'actor' => "https://{$this->domain}/ap/actor", 'actor' => "{$this->domain}/ap/actor",
'cc' => [ 'cc' => [
"https://{$this->domain}/ap/followers", "{$this->domain}/ap/followers",
], ],
'published' => date("Y-m-d\TH:i:s.u\Z", strtotime($post['date'])), 'published' => date("Y-m-d\TH:i:s.u\Z", strtotime($post['date'])),
'to' => ['https://www.w3.org/ns/activitystreams#Public'], 'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'object' => [ 'object' => [
'id' => "https://{$this->domain}/ap/objects/{$uid}", 'id' => "{$this->domain}/ap/objects/{$uid}",
'type' => 'Note', 'type' => 'Note',
'name' => $post['title'], 'name' => $post['title'],
'attributedTo' => "https://{$this->domain}/ap/actor", 'attributedTo' => "{$this->domain}/ap/actor",
'cc' => [ 'cc' => [
"https://{$this->domain}/ap/followers", "{$this->domain}/ap/followers",
], ],
'to' => ['https://www.w3.org/ns/activitystreams#Public'], 'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'content' => 'content' => $post['preview']."<br /><br /><a href=\"{$this->domain}/blog/{$post['slug']}\">読み続き</a>",
$post['preview']."<br /><br /><a href=\"https://{$this->domain}/blog/{$post['slug']}\">読み続き</a>", 'url' => "{$this->domain}/blog/{$post['slug']}",
'url' => "https://{$this->domain}/blog/{$post['slug']}",
'published' => date("Y-m-d\TH:i:s.u\Z", strtotime($post['date'])), 'published' => date("Y-m-d\TH:i:s.u\Z", strtotime($post['date'])),
'replies' => "https://{$this->domain}/ap/objects/{$uid}/replies", 'replies' => "{$this->domain}/ap/objects/{$uid}/replies",
'sensitive' => false, 'sensitive' => false,
], ],
]; ];
@@ -220,7 +223,7 @@ class ActivityPub {
} }
if (isset($post['thumbnail']) && $post['thumbnail'] != '') { if (isset($post['thumbnail']) && $post['thumbnail'] != '') {
$imgurl = "https://technicalsuwako.moe/static/article/{$post['thumbnail']}"; $imgurl = "{$this->domain}/static/article/{$post['thumbnail']}";
$imgpath = ROOT."/public/static/article/{$post['thumbnail']}"; $imgpath = ROOT."/public/static/article/{$post['thumbnail']}";
$imgraw = file_get_contents($imgpath); $imgraw = file_get_contents($imgpath);
@@ -242,7 +245,7 @@ class ActivityPub {
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
], ],
'id' => "https://{$this->domain}/ap/outbox", 'id' => "{$this->domain}/ap/outbox",
'type' => 'OrderedCollection', 'type' => 'OrderedCollection',
'totalItems' => count($items), 'totalItems' => count($items),
'orderedItems' => $items, 'orderedItems' => $items,
@@ -257,13 +260,14 @@ class ActivityPub {
* @return string JSONエンコードされたWebFingerデータ * @return string JSONエンコードされたWebFingerデータ
*/ */
public function getWebfinger(): string { public function getWebfinger(): string {
if (!ACTIVITYPUB_ENABLED) return '';
$webfinger = [ $webfinger = [
'subject' => "acct:{$this->actor}@{$this->domain}", 'subject' => "acct:{$this->actor}@{$this->domain}",
'links' => [ 'links' => [
[ [
'rel' => 'self', 'rel' => 'self',
'type' => 'application/activity+json', 'type' => 'application/activity+json',
'href' => "https://{$this->domain}/ap/actor", 'href' => "{$this->domain}/ap/actor",
], ],
], ],
]; ];
@@ -277,6 +281,7 @@ class ActivityPub {
* @return string JSONエンコードされたフォロワーのリスト * @return string JSONエンコードされたフォロワーのリスト
*/ */
public function getFollowers(): string { public function getFollowers(): string {
if (!ACTIVITYPUB_ENABLED) return '';
$f = array_filter(explode("\n", file_get_contents(ROOT.'/data/followers.txt'))); $f = array_filter(explode("\n", file_get_contents(ROOT.'/data/followers.txt')));
$followers = [ $followers = [
@@ -284,7 +289,7 @@ class ActivityPub {
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
], ],
'id' => "https://{$this->domain}/ap/followers", 'id' => "{$this->domain}/ap/followers",
'type' => 'OrderredCollection', 'type' => 'OrderredCollection',
'totalItems' => count($f), 'totalItems' => count($f),
'orderedItems' => $f, 'orderedItems' => $f,
@@ -299,6 +304,7 @@ class ActivityPub {
* @return string JSONエンコードされたフォローリスト * @return string JSONエンコードされたフォローリスト
*/ */
public function getFollowing(): string { public function getFollowing(): string {
if (!ACTIVITYPUB_ENABLED) return '';
$f = array_filter(explode("\n", file_get_contents(ROOT.'/data/following.txt'))); $f = array_filter(explode("\n", file_get_contents(ROOT.'/data/following.txt')));
$following = [ $following = [
@@ -306,7 +312,7 @@ class ActivityPub {
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
], ],
'id' => "https://{$this->domain}/ap/following", 'id' => "{$this->domain}/ap/following",
'type' => 'OrderredCollection', 'type' => 'OrderredCollection',
'totalItems' => count($f), 'totalItems' => count($f),
'orderedItems' => $f, 'orderedItems' => $f,
@@ -322,6 +328,7 @@ class ActivityPub {
* @return void * @return void
*/ */
public function postInbox(array $activity): void { public function postInbox(array $activity): void {
if (!ACTIVITYPUB_ENABLED) return;
switch ($activity['type']) { switch ($activity['type']) {
case 'Follow': case 'Follow':
$this->acceptFollower($activity); $this->acceptFollower($activity);
@@ -329,8 +336,7 @@ class ActivityPub {
default: default:
header('HTTP/1.1 501 Not Implemented'); header('HTTP/1.1 501 Not Implemented');
header('Content-Type: application/activity+json'); header('Content-Type: application/activity+json');
echo json_encode(['error' => echo json_encode(['error' => '未対応なアクティビティタイプ: '.$activity['type']]);
'未対応なアクティビティタイプ: '.$activity['type']]);
exit; exit;
} }
@@ -346,14 +352,15 @@ class ActivityPub {
* @return string JSONエンコードされた更新アクティビティ * @return string JSONエンコードされた更新アクティビティ
*/ */
public function update(): string { public function update(): string {
if (!ACTIVITYPUB_ENABLED) return '';
$update = [ $update = [
'@context' => [ '@context' => [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
], ],
'id' => "https://{$this->domain}/ap/activities/update/".uuid(), 'id' => "{$this->domain}/ap/activities/update/".uuid(),
'type' => 'Update', 'type' => 'Update',
'actor' => "https://{$this->domain}/ap/actor", 'actor' => "{$this->domain}/ap/actor",
'to' => ['https://www.w3.org/ns/activitystreams#Public'], 'to' => ['https://www.w3.org/ns/activitystreams#Public'],
'object' => json_decode($this->getActor(), true), 'object' => json_decode($this->getActor(), true),
]; ];
@@ -368,14 +375,13 @@ class ActivityPub {
* @return void * @return void
*/ */
public function sendActorUpdate(array $params): void { public function sendActorUpdate(array $params): void {
if (!ACTIVITYPUB_ENABLED) return;
$f = array_filter(explode("\n", file_get_contents(ROOT.'/data/followers.txt'))); $f = array_filter(explode("\n", file_get_contents(ROOT.'/data/followers.txt')));
$ap = new Activitypub(); $ap = new Activitypub();
$inboxes = implode("\n", $f); $inboxes = implode("\n", $f);
$update = json_decode($ap->update(), true); $update = json_decode($ap->update(), true);
foreach ($f as $inbox) { foreach ($f as $inbox) $this->sendActivity($inbox, $update);
$this->sendActivity($inbox, $update);
}
} }
// 機能性メソッド // 機能性メソッド
@@ -410,9 +416,7 @@ class ActivityPub {
'Digest' => "SHA-256=$digest", 'Digest' => "SHA-256=$digest",
]; ];
$stringToSign = "host: {$headers['Host']}\n" $stringToSign = "host: {$headers['Host']}\n"."date: {$headers['Date']}\n"."digest: {$headers['Digest']}";
."date: {$headers['Date']}\n"
."digest: {$headers['Digest']}";
logger(\LogType::ActivityPub, "署名対象: {$stringToSign}"); logger(\LogType::ActivityPub, "署名対象: {$stringToSign}");
if (!openssl_sign($stringToSign, $signature, $priv, OPENSSL_ALGO_SHA256)) { if (!openssl_sign($stringToSign, $signature, $priv, OPENSSL_ALGO_SHA256)) {
@@ -425,18 +429,16 @@ class ActivityPub {
} }
$sigValue = base64_encode($signature); $sigValue = base64_encode($signature);
$headers['Signature'] = "keyId=\"https://{$this->domain}/ap/actor#main-key\","; $headers['Signature'] = "keyId=\"{$this->domain}/ap/actor#main-key\",";
$headers['Signature'] .= 'algorithm="rsa-sha256",'; $headers['Signature'] .= 'algorithm="rsa-sha256",';
$headers['Signature'] .= 'headers="host date digest",'; $headers['Signature'] .= 'headers="host date digest",';
$headers['Signature'] .= 'signature="'.$sigValue.'"'; $headers['Signature'] .= 'signature="'.$sigValue.'"';
logger(\LogType::ActivityPub, logger(\LogType::ActivityPub, "署名: {$headers['Signature']}\n送信データ: {$body}");
"署名: {$headers['Signature']}\n送信データ: {$body}");
$curl = new Curl($inboxUrl); $curl = new Curl($inboxUrl);
$curl->setMethod('POST') $curl->setMethod('POST')
->setPostRaw($body) ->setPostRaw($body)
->setHeaders(array_map(fn($k, $v) => "$k: $v", ->setHeaders(array_map(fn($k, $v) => "$k: $v", array_keys($headers), $headers))
array_keys($headers), $headers))
->setCaInfo('/etc/ssl/cert.pem') ->setCaInfo('/etc/ssl/cert.pem')
->setVerbose(true) ->setVerbose(true)
->setStderr(fopen(ROOT.'/log/ap_log.txt', 'a')); ->setStderr(fopen(ROOT.'/log/ap_log.txt', 'a'));
@@ -447,8 +449,7 @@ class ActivityPub {
$err = $curl->getError(); $err = $curl->getError();
var_dump(print_r($res)); var_dump(print_r($res));
logger(\LogType::ActivityPub, logger(\LogType::ActivityPub, "アクティビティは「{$inboxUrl}」に送信しました: HTTP {$code}");
"アクティビティは「{$inboxUrl}」に送信しました: HTTP {$code}");
logger(\LogType::ActivityPub, "エラー: {$err}"); logger(\LogType::ActivityPub, "エラー: {$err}");
logger(\LogType::ActivityPub, "レスポンス: {$res}"); logger(\LogType::ActivityPub, "レスポンス: {$res}");
} }
@@ -483,9 +484,9 @@ class ActivityPub {
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
], ],
'id' => "https://{$this->domain}/ap/activities/".uniqid(), 'id' => "{$this->domain}/ap/activities/".uniqid(),
'type' => 'Accept', 'type' => 'Accept',
'actor' => "https://{$this->domain}/ap/actor", 'actor' => "{$this->domain}/ap/actor",
'object' => $activity, 'object' => $activity,
]; ];
@@ -506,9 +507,7 @@ class ActivityPub {
} }
$followers = $this->getFollowersList(); $followers = $this->getFollowersList();
if (!in_array($followerActor, $followers)) { if (!in_array($followerActor, $followers)) file_put_contents($file, "$followerActor\n", FILE_APPEND);
file_put_contents($file, "$followerActor\n", FILE_APPEND);
}
} }
/** /**
@@ -519,8 +518,7 @@ class ActivityPub {
private function getFollowersList(): array { private function getFollowersList(): array {
$file = ROOT.'/data/followers.txt'; $file = ROOT.'/data/followers.txt';
$f = array_filter(explode("\n", file_get_contents($file))); $f = array_filter(explode("\n", file_get_contents($file)));
return file_exists($file) return file_exists($file) ? array_filter(explode("\n", file_get_contents($file))) : [];
? array_filter(explode("\n", file_get_contents($file))) : [];
} }
/** /**

View File

@@ -89,6 +89,7 @@ class Auth {
$json = json_encode($userData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $json = json_encode($userData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if (file_put_contents($path, $json) === false) { if (file_put_contents($path, $json) === false) {
logger(\LogType::Auth, '【setToken】JSONファイルにユーザーデータを保存出来なかった。パス'.$path);
return \Result::error('エラー:ユーザーデータの保存に失敗。'); return \Result::error('エラー:ユーザーデータの保存に失敗。');
} }
@@ -100,6 +101,7 @@ class Auth {
'httponly' => true, 'httponly' => true,
'samesite' => 'Strict' 'samesite' => 'Strict'
])) { ])) {
logger(\LogType::Auth, '【setToken】クッキーを設定出来なかった。トークン'.$token);
return \Result::error('エラー:クッキーを設定に失敗。'); return \Result::error('エラー:クッキーを設定に失敗。');
} }
@@ -147,7 +149,7 @@ class Auth {
if ($username === $user) return \Result::Success("ユーザー「{$username}」は既に存在します。"); if ($username === $user) return \Result::Success("ユーザー「{$username}」は既に存在します。");
} }
return \Result::Error("エラー:ユーザー「{$username}」は存在しません。"); return \Result::Error('');
} }
public function mkUser(?string $username = null, #[SensitiveParameter] ?string $password = null, ?string $passwordVerify = null, ?string $email = null): \Result { public function mkUser(?string $username = null, #[SensitiveParameter] ?string $password = null, ?string $passwordVerify = null, ?string $email = null): \Result {
@@ -167,6 +169,7 @@ class Auth {
$err = ''; $err = '';
if (!mkdir($this->assDir.$username, 0755)) { if (!mkdir($this->assDir.$username, 0755)) {
logger(\LogType::Auth, '【mkUser】アセットディレクトリを作成出来なかった。chownをご確認下さい。パス'.$this->assDir.$username);
return \Result::Error('エラー:ユーザーのアイコンディレクトリの作成に失敗。'); return \Result::Error('エラー:ユーザーのアイコンディレクトリの作成に失敗。');
} }
@@ -203,6 +206,7 @@ class Auth {
$json = json_encode($user, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $json = json_encode($user, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if (file_put_contents($path, $json) === false) { if (file_put_contents($path, $json) === false) {
logger(\LogType::Auth, '【mkUser】JSONファイルを作成出来なかった。パス'.$path);
rmdir($this->assDir.$username); rmdir($this->assDir.$username);
return \Result::Error('エラー:ユーザーデータの保存に失敗。'); return \Result::Error('エラー:ユーザーデータの保存に失敗。');
} }
@@ -225,6 +229,7 @@ class Auth {
$json = json_encode($userData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $json = json_encode($userData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if (file_put_contents($path, $json) === false) { if (file_put_contents($path, $json) === false) {
logger(\LogType::Auth, '【verifyLogin】JSONファイルを変更出来なかった。chownをご確認下さい。パス'.$path);
return \Result::Error('エラー:ユーザーデータの保存に失敗。'); return \Result::Error('エラー:ユーザーデータの保存に失敗。');
} }
} }
@@ -244,6 +249,7 @@ class Auth {
$json = json_encode($userData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $json = json_encode($userData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if (file_put_contents($path, $json) === false) { if (file_put_contents($path, $json) === false) {
logger(\LogType::Auth, '【purgeOldTokens】JSONファイルを変更出来なかった。chownをご確認下さい。パス'.$path);
return \Result::Error('エラー:ユーザーデータの保存に失敗。'); return \Result::Error('エラー:ユーザーデータの保存に失敗。');
} }

View File

@@ -37,6 +37,7 @@ class Curl {
* @param string|null $url リクエスト先のURL * @param string|null $url リクエスト先のURL
*/ */
public function __construct(?string $url = null) { public function __construct(?string $url = null) {
if (!CURL_ENABLED) return;
if ($url !== null) { if ($url !== null) {
$this->url = $url; $this->url = $url;
} }
@@ -247,12 +248,13 @@ class Curl {
/** /**
* リクエストを実行する * リクエストを実行する
* *
* @return bool 成功または失敗 * @return Result 成功または失敗
*/ */
public function execute(): bool { public function execute(): \Result {
if (!CURL_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
if (empty($this->url)) { if (empty($this->url)) {
$this->responseError = 'URLがありません'; $this->responseError = 'URLがありません';
return false; return \Result::Error($this->responseError);
} }
// レスポンスデータのリセット // レスポンスデータのリセット
@@ -286,7 +288,7 @@ class Curl {
$parsed = parse_url($currentUrl); $parsed = parse_url($currentUrl);
if (!$parsed) { if (!$parsed) {
$this->responseError = "無効なURL: {$currentUrl}"; $this->responseError = "無効なURL: {$currentUrl}";
return false; return \Result::Error($this->responseError);
} }
$scheme = isset($parsed['scheme']) ? strtolower($parsed['scheme']) : 'http'; $scheme = isset($parsed['scheme']) ? strtolower($parsed['scheme']) : 'http';
@@ -403,7 +405,7 @@ class Curl {
if ($this->verbose && $this->stderr) { if ($this->verbose && $this->stderr) {
fwrite($this->stderr, "* エラー: {$this->responseError}\n"); fwrite($this->stderr, "* エラー: {$this->responseError}\n");
} }
return false; return \Result::Error($this->responseError);
} }
// タイムアウトを設定 // タイムアウトを設定
@@ -523,7 +525,7 @@ class Curl {
$this->method = $originalMethod; $this->method = $originalMethod;
$this->info['total_time'] = microtime(true) - $startTime; $this->info['total_time'] = microtime(true) - $startTime;
return true; return \Result::Success();
} }
/** /**

View File

@@ -65,7 +65,7 @@ if (CURL_ENABLED) {
$curl = new Curl('https://076.moe'); $curl = new Curl('https://076.moe');
$result = $curl->execute(); $result = $curl->execute();
$test->assertTrue($result); $test->assertTrue($result->isSuccess);
$test->assertEquals(200, $curl->getResponseCode()); $test->assertEquals(200, $curl->getResponseCode());
$test->assertNotNull($curl->getResponseBody()); $test->assertNotNull($curl->getResponseBody());
$test->assertStringContains('<html', $curl->getResponseBody()); $test->assertStringContains('<html', $curl->getResponseBody());
@@ -81,7 +81,7 @@ if (CURL_ENABLED) {
]); ]);
$result = $curl->execute(); $result = $curl->execute();
$test->assertTrue($result); $test->assertTrue($result->isSuccess);
$test->assertEquals(200, $curl->getResponseCode()); $test->assertEquals(200, $curl->getResponseCode());
$responseBody = $curl->getResponseBody(); $responseBody = $curl->getResponseBody();

View File

@@ -1,8 +1,9 @@
<?php <?php
require_once __DIR__.DIRECTORY_SEPARATOR.'/autoload.php'; require_once __DIR__.DIRECTORY_SEPARATOR.'/autoload.php';
define('ROOT', realpath(__DIR__)); define('ROOT', realpath(__DIR__));
require_once ROOT.'/util.php';
require_once ROOT.'/config/config.php'; require_once ROOT.'/config/config.php';
require_once ROOT.'/util.php';
if (!CURL_ENABLED) define('ACTIVITYPUB_ENABLED', false);
mb_internal_encoding('UTF-8'); mb_internal_encoding('UTF-8');
header('Content-Type: text/plain; charset=UTF-8'); header('Content-Type: text/plain; charset=UTF-8');

View File

@@ -1,9 +1,12 @@
<?php <?php
if (!CURL_ENABLED) define('ACTIVITYPUB_ENABLED', false);
enum LogType { enum LogType {
case ActivityPub; case ActivityPub;
case Auth;
case Csv;
case Mailer; case Mailer;
case MySQL; case MySQL;
case Csv;
} }
class Result { class Result {
@@ -112,13 +115,35 @@ function base58btc_encode(string $bin): string {
function logger(LogType $section, mixed $arg): void { function logger(LogType $section, mixed $arg): void {
if (LOGGING_ENABLED) { if (LOGGING_ENABLED) {
$success = false;
$logfile = ROOT.'/log/'; $logfile = ROOT.'/log/';
if ($section == LogType::ActivityPub) $logfile .= 'ap_log.txt';
else if ($section == LogType::Mailer) $logfile .= 'mail_log.txt';
else if ($section == LogType::MySQL) $logfile .= 'mysql_log.txt';
else if ($section == LogType::Csv) $logfile .= 'csv_log.txt';
file_put_contents($logfile, $arg."\n", FILE_APPEND); switch ($section) {
case LogType::ActivityPub:
$logfile .= 'ap_log.text';
$success = true;
break;
case LogType::Auth:
$logfile .= 'auth_log.text';
$success = true;
break;
case LogType::Csv:
$logfile .= 'csv_log.text';
$success = true;
break;
case LogType::Mailer:
$logfile .= 'mail_log.text';
$success = true;
break;
case LogType::MySQL:
$logfile .= 'mysql_log.text';
$success = true;
break;
default:
break;
}
if ($success) file_put_contents($logfile, $arg."\n", FILE_APPEND);
} }
} }