$totalBits) { actionLog(null, "error", "isIpInCIDR", null, "bad_prefix_length_".$prefixLength, 4); return false; } $mask = str_repeat("\xFF", (int)($prefixLength / 8)); $remainingBits = $prefixLength % 8; if ($remainingBits > 0) { $mask .= chr((0xFF << (8 - $remainingBits)) & 0xFF); } $mask = str_pad($mask, strlen($networkBinary), "\x00"); return ($ipBinary & $mask) === ($networkBinary & $mask); }else{ actionLog(null, "error", "isIpInCIDR", null, "bad_ip", 4); return false; } } function blockedIP($ip_addr) { // データベースに接続 try { $pdo = new PDO( 'mysql:charset=utf8mb4;dbname=' . DB_NAME . ';host=' . DB_HOST, DB_USER, DB_PASS, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_MULTI_STATEMENTS => false, ] ); } catch (PDOException $e) { error_log("Database connection failed: " . $e->getMessage()); return false; } // IPブロックリストの取得 $search_query = $pdo->prepare('SELECT ipaddr FROM ipblock'); $search_query->execute(); $blocked_ips = $search_query->fetchAll(PDO::FETCH_COLUMN); foreach ($blocked_ips as $blocked_ip) { if (isIpInCIDR($ip_addr, $blocked_ip)) { $fron_uwuzu_errcode = "IP_BANNED"; $url = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://') . $_SERVER['HTTP_HOST'] . "/unsupported.php?errcode=" . $fron_uwuzu_errcode; header("Location: " . $url); require(__DIR__ . '/../unsupported.php'); exit; } } } function stopLoadAvg(){ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { $loadAve = 0; } else { if (function_exists("sys_getloadavg")) { $load = sys_getloadavg(); $loadAve = is_array($load) && isset($load[0]) ? $load[0] : 0; } else { $loadAve = 0; } } if (defined('STOP_LA') && (int)STOP_LA !== -1) { if ($loadAve > (int)STOP_LA) { include_once __DIR__ . '/../errorpage/overcapacity.php'; exit; } } } //通常のログイン処理 function uwuzuUserLogin($session, $cookie, $ip_addr, $operation_permission = "user") { //セッション,クッキー,IPアドレス,閲覧権限(userかadminかの二種類)を受け取る $serversettings_file = $_SERVER['DOCUMENT_ROOT']."/server/serversettings.ini"; $serversettings = parse_ini_file($serversettings_file, true); // データベースに接続 try { $option = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_MULTI_STATEMENTS => false ); $pdo = new PDO('mysql:charset=utf8mb4;dbname='.DB_NAME.';host='.DB_HOST , DB_USER, DB_PASS, $option); } catch(PDOException $e) { actionLog(null, "error", "uwuzuUserLogin", null, $e, 4); return false; } if(isset($session['loginid'])){ $loginid = safetext($session['loginid']); }else if(isset($cookie['loginid'])){ $loginid = safetext($cookie['loginid']); } else { return false; } if(isset($session['loginkey'])) { $loginkey = safetext($session['loginkey']); }else if(isset($cookie['loginkey'])){ $loginkey = safetext($cookie['loginkey']); } else { $loginkey = null; } $loginQuery = $pdo->prepare("SELECT * FROM account WHERE loginid = :loginid"); $loginQuery->bindValue(':loginid', $loginid); $loginQuery->execute(); $loginResponse = $loginQuery->fetch(); if(empty($loginResponse["userid"])){ return false; }elseif($loginid === $loginResponse["loginid"]){ $userEncKey = GenUserEnckey($loginResponse["datetime"]); $userLoginKey = hash_hmac('sha256', $loginResponse["loginid"], $userEncKey); if(!(empty($loginkey))){ if(hash_equals($loginkey, $userLoginKey)){ if($operation_permission == "admin"){ if($loginResponse["admin"] == "yes"){ $is_login = true; }else{ $is_login = false; stopLoadAvg(); } }else{ $is_login = true; stopLoadAvg(); } }else{ $is_login = false; stopLoadAvg(); } }else{ if(isset($session['userid']) && isset($session['username'])){ if($session['userid'] === $loginResponse["userid"] && $session['username'] === $loginResponse["username"]){ if($operation_permission === "admin"){ if($loginResponse["admin"] == "yes"){ $is_login = true; }else{ $is_login = false; stopLoadAvg(); } }else{ $is_login = true; stopLoadAvg(); } }else{ $is_login = false; stopLoadAvg(); } }else if(isset($cookie['userid']) && isset($cookie['username'])){ if($cookie['userid'] === $loginResponse["userid"] && $cookie['username'] === $loginResponse["username"]){ if($operation_permission === "admin"){ if($loginResponse["admin"] == "yes"){ $is_login = true; }else{ $is_login = false; stopLoadAvg(); } }else{ $is_login = true; stopLoadAvg(); } }else{ $is_login = false; stopLoadAvg(); } }else{ $is_login = false; stopLoadAvg(); } } if($is_login === true){ $userid = safetext($loginResponse['userid']); // セッションに格納されている値をそのままセット $username = safetext($loginResponse['username']); // セッションに格納されている値をそのままセット $loginid = safetext($loginResponse["loginid"]); $_SESSION['userid'] = $userid; $_SESSION['username'] = $username; $_SESSION['loginid'] = $loginid; setcookie('loginid', $loginid,[ 'expires' => time() + 60 * 60 * 24 * 28, 'path' => '/', 'samesite' => 'lax', 'secure' => true, 'httponly' => true, ]); setcookie('loginkey', $userLoginKey,[ 'expires' => time() + 60 * 60 * 24 * 28, 'path' => '/', 'samesite' => 'lax', 'secure' => true, 'httponly' => true, ]); //IP保存が有効であれば保存する--------------------------------------------------- if(safetext($serversettings["serverinfo"]["server_get_ip"]) === "true"){ if(filter_var($ip_addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) || filter_var($ip_addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)){ $enc_ip_addr = EncryptionUseEncrKey($ip_addr, $userEncKey, $loginResponse["encryption_ivkey"]); $pdo->beginTransaction(); try { $updateQuery = $pdo->prepare("UPDATE account SET last_ip = :last_ip WHERE userid = :userid"); $updateQuery->bindValue(':last_ip', $enc_ip_addr, PDO::PARAM_STR); $updateQuery->bindValue(':userid', $userid, PDO::PARAM_STR); $res = $updateQuery->execute(); if($res){ $pdo->commit(); }else{ // ロールバック $pdo->rollBack(); actionLog($userid, "error", "uwuzuUserLogin", null, "IPアドレスを記録できませんでした!", 3); } } catch (Exception $e) { // ロールバック $pdo->rollBack(); actionLog($userid, "error", "uwuzuUserLogin", null, $e, 4); } }else{ actionLog($userid, "notice", "uwuzuUserLogin", null, "ユーザーのIPアドレスが不正な値でした!", 2); } } //JobがあればJobを実行する--------------------------------------------------- $job = getJob($pdo, $userid); if(!(empty($job))){ if($job["job"] == "deleteUser"){ deleteUser($pdo, $job["userid"], $job["step"], $job["uniqid"]); } } return $loginResponse; }else{ return false; } }else{ return false; } } //APIなどのログイン処理(loginidとloginkeyが有効かを確かめる) function uwuzuUserLoginCheck($loginid, $loginkey, $operation_permission = "user") { //セッション,クッキー,IPアドレス,閲覧権限(userかadminかの二種類)を受け取る // データベースに接続 try { $option = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_MULTI_STATEMENTS => false ); $pdo = new PDO('mysql:charset=utf8mb4;dbname='.DB_NAME.';host='.DB_HOST , DB_USER, DB_PASS, $option); } catch(PDOException $e) { actionLog(null, "error", "uwuzuUserLogin", null, $e, 4); return false; } if(!(isset($loginid))){ return false; exit; } if(!(isset($loginkey))){ return false; exit; } $loginQuery = $pdo->prepare("SELECT * FROM account WHERE loginid = :loginid"); $loginQuery->bindValue(':loginid', $loginid); $loginQuery->execute(); $loginResponse = $loginQuery->fetch(); if(empty($loginResponse["userid"])){ return false; }elseif($loginid === $loginResponse["loginid"]){ $userEncKey = GenUserEnckey($loginResponse["datetime"]); $userLoginKey = hash_hmac('sha256', $loginResponse["loginid"], $userEncKey); if(!(empty($loginkey))){ if(hash_equals($loginkey, $userLoginKey)){ if($operation_permission == "admin"){ if($loginResponse["admin"] == "yes"){ $is_login = true; }else{ $is_login = false; } }else{ $is_login = true; } }else{ $is_login = false; } }else{ $is_login = false; } return $is_login; }else{ return false; } } //---------UNIQID-MAKER--------- function Legacy_createUniqId(){ list($msec, $sec) = explode(" ", microtime()); $hashCreateTime = $sec.floor($msec*1000000); $hashCreateTime = strrev($hashCreateTime); return base_convert($hashCreateTime,10,36); } function createUniqId($randDigits = 6) { $msec_time = (int)(microtime(true) * 1000); $randMax = pow(10, $randDigits) - 1; $rand_num = str_pad(random_int(0, $randMax), $randDigits, '0', STR_PAD_LEFT); $combined = $msec_time . $rand_num; return base_convert(strrev($combined), 10, 36); } function parseUniqId($id, $randDigits = 6) { $reversed_num_str = base_convert($id, 36, 10); $combined_num_str = strrev($reversed_num_str); $msec_time_str = substr($combined_num_str, 0, -$randDigits); return date("Y-m-d H:i:s.v", (int)($msec_time_str / 1000)); } //----------EXIF_Delete---------- //EXIFを削除するやつです。 function rotate($image, $exif){ $orientation = $exif['Orientation'] ?? 1; switch ($orientation) { case 1: //no rotate break; case 2: //FLIP_HORIZONTAL imageflip($image, IMG_FLIP_HORIZONTAL); break; case 3: //ROTATE 180 $image = imagerotate($image, 180, 0); break; case 4: //FLIP_VERTICAL imageflip($image, IMG_FLIP_VERTICAL); break; case 5: //ROTATE 270 FLIP_HORIZONTAL $image = imagerotate($image, 270, 0); imageflip($image, IMG_FLIP_HORIZONTAL); break; case 6: //ROTATE 90 $image = imagerotate($image, 270, 0); break; case 7: //ROTATE 90 FLIP_HORIZONTAL $image = imagerotate($image, 90, 0); imageflip($image, IMG_FLIP_HORIZONTAL); break; case 8: //ROTATE 270 $image = imagerotate($image, 90, 0); break; } return $image; } function delete_exif($extension, $path){ $exifimgext = array( "jpg", "jpeg", "jfif", "pjpeg", "pjp", "hdp", "wdp", "jxr", "tiff", "tif" ); if(in_array($extension,$exifimgext)){ if(check_mime($path) == "image/jpeg"){ $gd = imagecreatefromjpeg($path); $w = imagesx($gd); $h = imagesy($gd); $gd_out = imagecreatetruecolor($w,$h); imagecopyresampled($gd_out, $gd, 0,0,0,0, $w,$h,$w,$h); $exif = exif_read_data($path); $gd_out = rotate($gd_out, $exif); imagejpeg($gd_out, $path); imagedestroy($gd_out); } } } //----------EXIF_Delete---------- //----------Check_Extension------ //ファイル形式チェック(画像かどうか) function check_mime($tmp_name){ $finfo = new finfo(); $tmp_ext = $finfo->file($tmp_name, FILEINFO_MIME_TYPE); $safe_img_mime = array( "image/gif", "image/jpeg", "image/png", "image/svg+xml", "image/webp", "image/bmp", "image/x-icon", "image/tiff" ); if(in_array($tmp_ext,$safe_img_mime)){ return $tmp_ext; }else{ return false; } } //ファイル形式チェック(画像かどうか) function check_mime_video($tmp_name){ $finfo = new finfo(); $tmp_ext = $finfo->file($tmp_name, FILEINFO_MIME_TYPE); $safe_vid_mime = array( "video/mpeg", "video/mp4", "video/webm", "video/x-msvideo", ); if(in_array($tmp_ext,$safe_vid_mime)){ return $tmp_ext; }else{ return false; } } function convert_mime($mime_type){ $safe_img_mime = array( "image/gif" => 'gif', "image/jpeg" => 'jpg', "image/png" => 'png', "image/svg+xml" => 'svg', "image/webp" => 'webp', "image/bmp" => 'bmp', "image/x-icon" => 'ico', "image/tiff" => 'tiff', "video/mpeg" => 'mpeg', "video/mp4" => 'mp4', "video/webm" => 'webm', "video/x-msvideo" => 'avi', ); if(isset($safe_img_mime[$mime_type])){ return $safe_img_mime[$mime_type]; }else{ return false; } } //ファイル形式チェック(Base64の場合) function base64_mime($Base64,$userid){ $Base64 = base64_decode($Base64); $finfo = finfo_open(FILEINFO_MIME_TYPE); $mime_type = finfo_buffer($finfo, $Base64); $safe_img_mime = [ "image/gif" => 'gif', "image/jpeg" => 'jpg', "image/png" => 'png', "image/svg+xml" => 'svg', "image/webp" => 'webp', "image/bmp" => 'bmp', "image/x-icon" => 'ico', "image/tiff" => 'tiff' ]; if(isset($safe_img_mime[$mime_type])){ $extension = $safe_img_mime[$mime_type]; $temp_file = tempnam(sys_get_temp_dir(), 'img'); file_put_contents($temp_file, $Base64); delete_exif($extension, $temp_file); $newFilename = createUniqId() . '-' . $userid . '.' . $extension; $uploadedPath = '../ueuseimages/' . $newFilename; $result = copy($temp_file, "../".$uploadedPath); if($result){ return $uploadedPath; } else { return false; } } else { return false; } } //APIユーズと通常ユーズ統合時に使うのでけさない function base64_to_files($Base64, $userid) { // Base64デコード $decodedData = base64_decode($Base64); if ($decodedData === false) { return false; } // MIMEタイプの検出 $finfo = finfo_open(FILEINFO_MIME_TYPE); $mime_type = finfo_buffer($finfo, $decodedData); finfo_close($finfo); // 許可されているMIMEタイプと拡張子の対応 $safe_img_mime = [ "image/gif" => 'gif', "image/jpeg" => 'jpg', "image/png" => 'png', "image/svg+xml" => 'svg', "image/webp" => 'webp', "image/bmp" => 'bmp', "image/x-icon" => 'ico', "image/tiff" => 'tiff' ]; if (!(isset($safe_img_mime[$mime_type]))) { return false; } $extension = $safe_img_mime[$mime_type]; // 一時ファイルを作成 $temp_file = tempnam(sys_get_temp_dir(), 'img'); file_put_contents($temp_file, $decodedData); // 必要に応じてEXIFデータを削除 delete_exif($extension, $temp_file); // ファイル名とアップロードパスを生成 $newFilename = createUniqId() . '-' . $userid . '.' . $extension; // $_FILES形式の配列を作成して返す return [ 'name' => $newFilename, 'type' => $mime_type, 'tmp_name' => $temp_file, 'error' => 0, 'size' => filesize($temp_file), ]; } function resizeImage($filePath, $maxWidth, $maxHeight) { if (file_exists($filePath)) { // 元の画像タイプを取得 $imageType = check_mime($filePath); // 画像タイプに応じてリソースを作成 if($imageType == "image/jpeg"){ $originalImage = imagecreatefromjpeg($filePath); } elseif($imageType == "image/png") { $originalImage = imagecreatefrompng($filePath); } elseif($imageType == "image/webp") { $originalImage = imagecreatefromwebp($filePath); } elseif($imageType == "image/bmp") { $originalImage = imagecreatefrombmp($filePath); } else { return; } // 元の画像のサイズを取得 list($originalWidth, $originalHeight) = getimagesize($filePath); // 縦横比を計算 $aspectRatio = $originalWidth / $originalHeight; // 新しいサイズを計算 if ($maxWidth / $maxHeight > $aspectRatio) { $newWidth = $maxHeight * $aspectRatio; $newHeight = $maxHeight; } else { $newWidth = $maxWidth; $newHeight = $maxWidth / $aspectRatio; } // 新しい画像リソースを作成 $resizedImage = imagecreatetruecolor($newWidth, $newHeight); // 画像をリサイズ imagecopyresampled($resizedImage, $originalImage, 0, 0, 0, 0, $newWidth, $newHeight, $originalWidth, $originalHeight); // リサイズされた画像を表示 imagewebp($resizedImage, $filePath); // メモリの解放 imagedestroy($originalImage); imagedestroy($resizedImage); } } function uploadAmazonS3($tmp_name){ if(check_mime_video($tmp_name) == false){ $is_video = false; }else{ $is_video = true; } $credentials = [ 'key' => AMS3_ACCESSKEY, 'secret' => AMS3_SECRETKEY, ]; $bucket = AMS3_BUCKET_NM; $srcFilePath = $tmp_name; if($is_video == true){ $mime = check_mime_video($srcFilePath); $extension = convert_mime($mime); }else{ $mime = check_mime($srcFilePath); $extension = convert_mime($mime); } $key = AMS3_PREFIX_NM.'/'.createUniqId().'' . '.' . $extension; if(AMS3_IS_S3FPS_ == 'true'){ $S3FPS = true; }else{ $S3FPS = false; } try { $s3Client = new Aws\S3\S3Client([ 'endpoint' => AMS3_ENDPOINTS, 'region' => AMS3_REGION_NM, 'version' => 'latest', 'credentials' => $credentials, 'use_path_style_endpoint' => $S3FPS, ]); $result = $s3Client->putObject([ 'Bucket' => $bucket, 'Key' => $key, 'SourceFile' => $srcFilePath, 'ContentType' => $mime, ]); if($result){ $url = AMS3_BASE_URLS . '/' . $key; return $url; }else{ actionLog(null, "error", "uploadAmazonS3", null, "アップロードに失敗しました", 4); return false; } } catch (Aws\S3\Exception\S3Exception $e) { actionLog(null, "error", "uploadAmazonS3", null, $e->getMessage(), 4); return false; } } function deleteAmazonS3($url){ $key = explode("/", mb_substr(parse_url($url, PHP_URL_PATH), 1)); if ($key[0] == AMS3_BUCKET_NM) { array_shift($key); } $key = implode("/", $key); $credentials = [ 'key' => AMS3_ACCESSKEY, 'secret' => AMS3_SECRETKEY, ]; $bucket = AMS3_BUCKET_NM; if(AMS3_IS_S3FPS_ == 'true'){ $S3FPS = true; }else{ $S3FPS = false; } try { $s3Client = new Aws\S3\S3Client([ 'endpoint' => AMS3_ENDPOINTS, 'region' => AMS3_REGION_NM, 'version' => 'latest', 'credentials' => $credentials, 'use_path_style_endpoint' => $S3FPS, ]); $is_hasfile = $s3Client->doesObjectExistV2($bucket, $key, false, []); if($is_hasfile == true){ $result = $s3Client->deleteObject([ 'Bucket' => $bucket, 'Key' => $key ]); if($result){ return true; }else{ actionLog(null, "error", "deleteAmazonS3", null, "削除に失敗しました", 4); return false; } }else{ actionLog(null, "error", "deleteAmazonS3", null, $key."が既に削除されていました", 1); return true; } } catch (Aws\S3\Exception\S3Exception $e) { actionLog(null, "error", "deleteAmazonS3", null, $e->getMessage(), 4); return false; } } //文字装飾・URL変換など function processMarkdownAndWrapEmptyLines($markdownText) { $placeholders = []; // インラインコードをプレースホルダーに置き換える $markdownText = preg_replace_callback('/`([^`\n]+)`/', function($matches) use (&$placeholders) { $placeholder = 'PLACEHOLDER_' . count($placeholders); $placeholders[$placeholder] = '' . $matches[1] . ''; return $placeholder; }, $markdownText); // ここから先の処理はインラインコードとコードブロックに影響しない $markdownText = preg_replace('/\[\[buruburu (.+)\]\]/m', '$1', $markdownText);//ぶるぶる $markdownText = preg_replace_callback('/\[\[time (\d+)\]\]/m', function($matches) { $timestamp = $matches[1]; return '' . date("Y/m/d H:i", htmlentities($timestamp, ENT_QUOTES, 'UTF-8', false)) . ''; }, $markdownText); //太字&斜体------------------------------------------------------------------------ $markdownText = preg_replace('/\*\*\*(.+)\*\*\*(?=\s)/', '$1', $markdownText);//太字&斜体の全部のせセット $markdownText = preg_replace('/\*\*\*(.+)\*\*\*/', '$1', $markdownText);//太字&斜体の全部のせセット $markdownText = preg_replace('/\_\_\_(.+)\_\_\_(?=\s)/', '$1', $markdownText);//太字&斜体の全部のせセット $markdownText = preg_replace('/\b\_\_\_(.+)\_\_\_\b/', '$1', $markdownText);//太字&斜体の全部のせセット //太字----------------------------------------------------------------------------- $markdownText = preg_replace('/\*\*(.+)\*\*/', '$1', $markdownText);//太字 $markdownText = preg_replace('/\b\*\*(.+)\*\*\b/', '$1', $markdownText);//太字 $markdownText = preg_replace('/\_\_(.+)\_\_(?=\s)/', '$1', $markdownText);//太字 $markdownText = preg_replace('/\b\_\_(.+)\_\_\b/', '$1', $markdownText);//太字 //斜体----------------------------------------------------------------------------- $markdownText = preg_replace('/\*(.+)\*/', '$1', $markdownText);//斜体 $markdownText = preg_replace('/\b\*(.+)\*\b/', '$1', $markdownText);//斜体 $markdownText = preg_replace('/\_(.+)\_(?=\s)/', '$1', $markdownText);//斜体 $markdownText = preg_replace('/\b\_(.+)\_\b/', '$1', $markdownText);//斜体 $markdownText = preg_replace('/\~\~(.+)\~\~/m', '$1', $markdownText);//打ち消し線 $markdownText = preg_replace('/>>> (.+)/m', '$1', $markdownText);//>>> 引用 $markdownText = preg_replace('/\|\|(.+)\|\|/m', '$1', $markdownText);//黒塗り // タイトル(#、##、###)をHTMLのhタグに変換 $markdownText = preg_replace('/^# (.+)/m', '

$1

', $markdownText); $markdownText = preg_replace('/^## (.+)/m', '

$1

', $markdownText); $markdownText = preg_replace('/^### (.+)/m', '

$1

', $markdownText); // 箇条書き(-)をHTMLのul/liタグに変換 $markdownText = preg_replace('/^- (.+)/m', '

・ $1

', $markdownText); // 空行の前に何もない行をHTMLのpタグに変換 $markdownText = preg_replace('/(^\s*)(?!\s)(.*)/m', '$1

$2

', $markdownText); // プレースホルダーを元のコードに戻す foreach ($placeholders as $placeholder => $original) { $markdownText = str_replace($placeholder, $original, $markdownText); } return $markdownText; } //Profile function replaceProfileEmojiImages($postText) { $postText = str_replace(''', '\'', $postText); // プロフィール名で絵文字名(:emoji:)を検出して画像に置き換える $emojiPattern = '/:(\w+):/'; $postTextWithImages = preg_replace_callback($emojiPattern, function($matches) { $emojiName = $matches[1]; //絵文字path取得 $dbh = new PDO('mysql:charset=utf8mb4;dbname='.DB_NAME.';host='.DB_HOST, DB_USER, DB_PASS, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, )); $emoji_Query = $dbh->prepare("SELECT emojifile, emojiname FROM emoji WHERE emojiname = :emojiname"); $emoji_Query->bindValue(':emojiname', $emojiName); $emoji_Query->execute(); $emoji_row = $emoji_Query->fetch(); if(empty($emoji_row["emojifile"])){ $emoji_path = "img/sysimage/errorimage/emoji_404.png"; }else{ $emoji_path = $emoji_row["emojifile"]; } return ":$emojiName:"; }, $postText); return $postTextWithImages; } // ユーズ内の絵文字やhashtagを画像に置き換える function replaceEmojisWithImages($postText) { $postText = str_replace(''', '\'', $postText); $emojiPattern = '/:(\w+):/'; $postTextWithImages = preg_replace_callback($emojiPattern, function($matches) { $emojiName = $matches[1]; $dbh = new PDO('mysql:charset=utf8mb4;dbname='.DB_NAME.';host='.DB_HOST, DB_USER, DB_PASS, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, )); $emoji_Query = $dbh->prepare("SELECT emojifile, emojiname FROM emoji WHERE emojiname = :emojiname"); $emoji_Query->bindValue(':emojiname', $emojiName); $emoji_Query->execute(); $emoji_row = $emoji_Query->fetch(); if(empty($emoji_row["emojifile"])){ $emoji_path = "img/sysimage/errorimage/emoji_404.png"; return ":".$emojiName.":"; }else{ $emoji_path = $emoji_row["emojifile"]; return ":$emojiName:"; } }, $postText); $urlPattern = '/https?:\/\/[^\s]+/'; $urlPlaceholders = []; $postTextWithPlaceholders = preg_replace_callback($urlPattern, function($matches) use (&$urlPlaceholders) { $placeholder = 'URL_PLACEHOLDER_' . count($urlPlaceholders); $urlPlaceholders[$placeholder] = $matches[0]; return $placeholder; }, $postTextWithImages); $usernamePattern = '/@(\w+)/'; $postTextWithUsernames = preg_replace_callback($usernamePattern, function($matches) { $username = $matches[1]; $dbh = new PDO('mysql:charset=utf8mb4;dbname='.DB_NAME.';host='.DB_HOST, DB_USER, DB_PASS, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, )); $mentionsuserQuery = $dbh->prepare("SELECT username, userid FROM account WHERE userid = :userid"); $mentionsuserQuery->bindValue(':userid', $username); $mentionsuserQuery->execute(); $mentionsuserData = $mentionsuserQuery->fetch(); if(empty($mentionsuserData)){ return "@".$username.""; }else{ return "@".replaceProfileEmojiImages(htmlentities($mentionsuserData["username"], ENT_QUOTES, 'UTF-8', false)).""; } }, $postTextWithPlaceholders); $postTextWithUrlsRestored = str_replace(array_keys($urlPlaceholders), array_values($urlPlaceholders), $postTextWithUsernames); $hashtagsPattern = '/#([\p{Han}\p{Hiragana}\p{Katakana}A-Za-z0-9ー_!]+)/u'; $postTextWithHashtags = preg_replace_callback($hashtagsPattern, function($matches) { $hashtags = $matches[1]; return "" . '#' . $hashtags . ""; }, $postTextWithUrlsRestored); return $postTextWithHashtags; } function replaceURLsWithLinks($postText, $maxLength = 48) { $pattern = '/(https:\/\/[\w!?\/+\-_~;.,*&@#$%()+|https:\/\/[ぁ-んァ-ヶ一-龠々\w\-\/?=&%.]+)/'; $convertedText = preg_replace_callback($pattern, function($matches) use ($maxLength) { $link = $matches[0]; if(!(preg_match('/:(\w+):/',$link))){ $no_https_link = preg_replace('/https:\/\//', '', $link, 1); if (mb_strlen($link) > $maxLength) { $truncatedLink = mb_substr($no_https_link, 0, $maxLength).'...'; return ''.$truncatedLink.''; } else { return ''.$no_https_link.''; } }else{ return $link; } }, $postText); return $convertedText; } function YouTube_and_nicovideo_Links($postText) { // URLを正規表現を使って検出 $pattern = '/(https:\/\/[^\s<>\[\]\'"]+)/'; // 改良された正規表現 preg_match_all($pattern, $postText, $matches); if(empty($url)){ $postText = ""; } // 検出したURLごとに処理を行う foreach ($matches[0] as $url) { // ドメイン部分を抽出 $parsedUrl = parse_url($url); if(!(empty($parsedUrl['host']))){ $video_time = "0"; $video_id = ""; if($parsedUrl['host'] == "youtube.com" || $parsedUrl['host'] == "youtu.be" || $parsedUrl['host'] == "www.youtube.com" || $parsedUrl['host'] == "m.youtube.com"){ if (isset($parsedUrl['query'])) { // クエリ部分を連想配列に変換する parse_str($parsedUrl['query'], $queryParams); // video_idの取得 if (isset($queryParams['v'])) { $video_id = safetext($queryParams['v']); $iframe = true; } else { $video_id = str_replace('/', '', safetext($parsedUrl['path'])); $iframe = true; } // video_timeの取得 if (isset($queryParams['amp;t'])) { $video_time = safetext($queryParams['amp;t']); if(!(is_numeric($video_time))){ $video_time = "0"; } } else { $video_time = "0"; } $video_id = str_replace('&', '?', $video_id); } elseif (isset($parsedUrl['path'])) { if (preg_match('/^\/watch\/|^\/embed\/|^\/shorts\/|^\/v\/|\//', $parsedUrl['path'])) { $video_id = str_replace('/', '', htmlentities($parsedUrl['path'], ENT_QUOTES, 'UTF-8', false)); $video_time = 0; $iframe = true; } else { // チャンネルや他のパスの場合は動画IDを取得しない $video_id = ""; $video_time = 0; $iframe = false; } } else { $video_id = ""; $video_time = "0"; $iframe = false; } // 不要な文字を削除してaタグを生成 if ($iframe) { $link = ''; } else { $link = ""; } // URLをドメインのみを表示するaタグで置き換え $postText = $link; }elseif($parsedUrl['host'] == "nicovideo.jp" || $parsedUrl['host'] == "www.nicovideo.jp" || $parsedUrl['host'] == "nico.ms"){ if(isset($parsedUrl['path'])){ $video_id = str_replace('/','',str_replace('/watch/', '', safetext($parsedUrl['path']))); $iframe = true; }else{ $video_id = ""; $iframe = false; } if (isset($parsedUrl['query'])) { // クエリ部分を連想配列に変換する parse_str($parsedUrl['query'], $queryParams); // video_timeの取得 if (isset($queryParams['from'])) { $video_time = safetext($queryParams['from']); if(!(is_numeric($video_time))){ $video_time = "0"; } } else { $video_time = "0"; } } // 不要な文字を削除してaタグを生成 if($iframe == true){ $link = '