From 5522cdd7f214f91ef403b9a3110f726d8370a33d Mon Sep 17 00:00:00 2001 From: satopian Date: Fri, 1 May 2026 16:37:06 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E9=9D=99=E7=9A=84=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E3=83=84=E3=83=BC=E3=83=AB=E3=81=AE=E3=83=A1=E3=83=83=E3=82=BB?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=82=92=E3=82=82=E3=81=A8=E3=81=AB=E6=9C=AA?= =?UTF-8?q?=E5=AE=9A=E7=BE=A9=E5=A4=89=E6=95=B0=E5=AF=BE=E7=AD=96=E3=82=92?= =?UTF-8?q?=E8=A1=8C=E3=81=84=E3=82=BF=E3=82=A4=E3=83=97=E3=83=92=E3=83=B3?= =?UTF-8?q?=E3=83=86=E3=82=A3=E3=83=B3=E3=82=B0=E3=82=92=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E3=81=97=E3=81=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- petitnote/functions.php | 139 +++++++++++++++--------- petitnote/index.php | 85 ++++++++++++--- petitnote/misskey_note.inc.php | 5 +- petitnote/noticemail.inc.php | 2 +- petitnote/save.inc.php | 25 ++++- petitnote/search.inc.php | 8 +- petitnote/template/basic/paint_neo.html | 3 + petitnote/thumbnail_gd.inc.php | 37 +++++-- 8 files changed, 215 insertions(+), 89 deletions(-) diff --git a/petitnote/functions.php b/petitnote/functions.php index 855af9fa..592222fa 100644 --- a/petitnote/functions.php +++ b/petitnote/functions.php @@ -2,7 +2,7 @@ //Petit Note (c)さとぴあ @satopian 2021-2026 MIT License //https://paintbbs.sakura.ne.jp/ -$functions_ver=20260228; +$functions_ver=20260501; //編集モードログアウト function logout(): void { @@ -53,7 +53,7 @@ function aikotoba(): void { } //記事の表示に合言葉を必須にする -function aikotoba_required_to_view($required_flag=false): void { +function aikotoba_required_to_view(bool $required_flag=false): void { global $use_aikotoba,$aikotoba_required_to_view,$skindir,$en,$petit_lot,$boardname; @@ -131,7 +131,7 @@ function age_check_required_to_view(): void { } //管理者パスワードを確認 -function is_adminpass($pwd): bool { +function is_adminpass(?string $pwd): bool { global $admin_pass,$second_pass; $pwd=(string)$pwd; return ($pwd && $admin_pass && $second_pass && !hash_equals($admin_pass,$second_pass) && hash_equals($admin_pass,$pwd)); @@ -344,7 +344,7 @@ function location_paintcom(): void { redirect('./?mode=paintcom'); } //リダイレクト -function redirect($url): void { +function redirect(?string $url): void { header("Location: {$url}"); exit(); } @@ -397,12 +397,12 @@ function set_app_select_enabled_session() : void { } //設定済みのペイントツール名かどうか調べる -function is_paint_tool_name($tool): string { +function is_paint_tool_name(?string $tool): string { return in_array($tool,['neo','chi','klecks','tegaki','axnos']) ? $tool : '???'; } //ログ出力の前処理 行から情報を取り出す -function create_res($line,$options=[]): array { +function create_res(array $line,array $options=[]): array { global $root_url,$boardname,$do_not_change_posts_time,$en,$mark_sensitive_image,$set_all_images_to_nsfw,$all_hide_painttime,$hide_userid; list($no,$sub,$name,$verified,$com,$url,$imgfile,$w,$h,$thumbnail,$paintsec,$log_hash_img,$abbr_toolname,$pchext,$time,$first_posted_time,$host,$userid,$hash,$oya)=$line; @@ -507,7 +507,7 @@ function create_res($line,$options=[]): array { return $res; } -function switch_tool($tool): string { +function switch_tool(?string $tool): string { global $en; switch($tool){ case 'neo': @@ -542,7 +542,7 @@ function switch_tool($tool): string { } //重複チェックのための配列を全体ログを元に作成 -function create_chk_lins($chk_log_arr,$resno): array { +function create_chk_lins(array $chk_log_arr,?string $resno): array { $chk_resnos=[]; foreach($chk_log_arr as $chk_log){ @@ -585,7 +585,11 @@ function create_post_time(): string { return $time; } -//ログファイルを1行ずつ読み込んで配列に入れる +/** + * ログファイルを1行ずつ読み込んで配列に入れる + * @param resource|false $fp + * @return array + */ function create_array_from_fp($fp): array { global $en; if(!$fp){ @@ -605,7 +609,7 @@ function create_array_from_fp($fp): array { //ページング //最初と最後のページ番号を取得 -function calc_pagination_range($page,$pagedef): array { +function calc_pagination_range(int $page,int $pagedef): array { $start_page=$page-$pagedef*8; $end_page=$page+($pagedef*8); @@ -617,7 +621,7 @@ function calc_pagination_range($page,$pagedef): array { } //ページング //前のページと次のページのページの番号を取得 -function get_prev_next_pages($page,$pagedef,$count_alllog): array { +function get_prev_next_pages(int $page,int $pagedef,int $count_alllog): array { $next=(($page+$pagedef)<$count_alllog) ? $page+$pagedef : false;//ページ番号がmaxを超える時はnextのリンクを出さない $prev=((int)$page<=0) ? false : ($page-$pagedef);//ページ番号が0の時はprevのリンクを出さない $prev=($prev<0) ? 0 : $prev; @@ -641,17 +645,17 @@ function get_uip(): string { } //タブ除去 -function t($str): string { +function t(?string $str): string { if(zero_check($str)){ return '0'; } if(!$str){ return ''; } - return str_replace("\t","",(string)$str); + return (string)str_replace("\t","",(string)$str); } //タグ除去 -function s($str): string { +function s(?string $str): string { if(zero_check($str)){ return '0'; } @@ -661,7 +665,7 @@ function s($str): string { return strip_tags((string)$str); } //エスケープ -function h($str) :string{ +function h(?string $str) :string{ if(zero_check($str)){ return '0'; } @@ -670,12 +674,16 @@ function h($str) :string{ } return htmlspecialchars($str,ENT_QUOTES,"utf-8",false); } -// 0 または "0" かどうか + +/** + * 0 または "0" かどうか + * @param int|string|null $str + */ function zero_check($str): bool { return($str === 0 || $str === '0'); } //コメント出力 -function com($str,$verified=false): string { +function com(?string $str,?string $verified=""): string { global $use_autolink; if(!$str){ @@ -690,7 +698,7 @@ function com($str,$verified=false): string { } //マークダウン記法のリンクをHTMLに変換 -function md_link($str, $verified = false): string { +function md_link(?string $str, ?string $verified = ""): string { $rel = $verified ? 'rel="noopener noreferrer"' : 'rel="nofollow noopener noreferrer"'; // 正規表現パターンを使用してマークダウンリンクを検出 @@ -714,7 +722,7 @@ function md_link($str, $verified = false): string { } // 自動リンク -function auto_link($str, $verified = false): string { +function auto_link(?string $str,?string $verified = ""): string { if(strpos($str, '$1',$str); } - return $str; + return (string)$str; } //mime typeを取得して拡張子を返す -function get_image_type ($img_file): string { +function get_image_type (string $img_file): string { $img_type = mime_content_type($img_file); @@ -740,7 +748,7 @@ function get_image_type ($img_file): string { } } //ファイルがあれば削除 -function safe_unlink ($path): void { +function safe_unlink (?string $path): void { clearstatcache(); if ($path && is_file($path)) { unlink($path); @@ -748,11 +756,8 @@ function safe_unlink ($path): void { } /** * 一連の画像ファイルを削除(元画像、サムネ、動画) - * @param $path - * @param $filename - * @param $ext */ -function delete_files ($imgfile, $time): void { +function delete_files (?string $imgfile, ?string $time): void { $imgfile=basename($imgfile); $time=basename($time); @@ -774,7 +779,7 @@ function delete_res_cache (): void { } //PNG形式またはWebP形式で上書き保存 -function convert2($is_upload_img,$upload_img_mime_type,$fname,$time): void { +function convert2(bool $is_upload_img,?string $upload_img_mime_type,?string $fname,?string $time): void { global $max_kb,$max_file_size_in_png_format_paint,$max_file_size_in_png_format_upload; $upfile=TEMP_DIR.basename($fname); @@ -822,7 +827,7 @@ function convert2($is_upload_img,$upload_img_mime_type,$fname,$time): void { } //Exifをチェックして画像が回転している時は上書き保存 -function check_jpeg_exif($upfile): void { +function check_jpeg_exif(?string $upfile): void { global $max_px; if((exif_imagetype($upfile) !== IMAGETYPE_JPEG ) || !function_exists("imagecreatefromjpeg")){ @@ -886,7 +891,7 @@ function check_jpeg_exif($upfile): void { } //サムネイル作成 -function make_thumbnail($imgfile,$time,$max_w,$max_h): string { +function make_thumbnail(?string $imgfile,?string $time,int $max_w,int $max_h): string { global $use_thumb; $thumbnail=''; if($use_thumb){//スレッドの画像のサムネイルを使う時 @@ -904,8 +909,12 @@ function make_thumbnail($imgfile,$time,$max_w,$max_h): string { return $thumbnail; } -//アップロード画像のファイルサイズが大きすぎる時は削除 -function delete_file_if_sizeexceeds($upfile,$fp,$rp): void { +/** + * アップロード画像のファイルサイズが大きすぎる時は削除 + * @param resource|false $fp + * @param resource|false $rp +*/ +function delete_file_if_sizeexceeds(string $upfile,$fp,$rp): void { global $max_kb,$en; clearstatcache(); if(filesize($upfile) > $max_kb*1024){ @@ -916,7 +925,7 @@ function delete_file_if_sizeexceeds($upfile,$fp,$rp): void { } } -function error($str,$historyback=true): void { +function error(string $str,bool $historyback=true): void { global $boardname,$skindir,$en,$petit_lot; @@ -1016,7 +1025,7 @@ function check_badhost(): void { } //記事の番号かどうかチェック -function check_open_no($no): void { +function check_open_no(?string $no): void { global $en; $no=(string)$no; if(!ctype_digit($no)||$no !== basename($no)){ @@ -1024,7 +1033,7 @@ function check_open_no($no): void { } } -function getId ($userip): string { +function getId (?string $userip): string { session_sta(); return @@ -1035,7 +1044,7 @@ function getId ($userip): string { } //Asyncリクエストの時は処理を中断 -function check_AsyncRequest($upfile=''): void { +function check_AsyncRequest(string $upfile=''): void { //ヘッダーが確認できなかった時の保険 $asyncflag = (bool)filter_input_data('POST','asyncflag',FILTER_VALIDATE_BOOLEAN); $paint_picrep = (bool)filter_input_data('POST','paint_picrep',FILTER_VALIDATE_BOOLEAN); @@ -1192,7 +1201,7 @@ function Reject_if_NGword_exists_in_the_post(): void { } /** * NGワードチェック - * @param $ngwords + * @param array $ngwords * @param string|array $strs * @return bool */ @@ -1280,7 +1289,7 @@ function init(): void { } //ディレクトリ作成 -function check_dir ($path): void { +function check_dir (?string $path): void { $msg=initial_error_message(); @@ -1303,7 +1312,7 @@ function check_dir ($path): void { } // ファイル存在チェック -function check_file ($path): void { +function check_file (?string $path): void { $msg=initial_error_message(); if (!is_file($path)){ @@ -1321,8 +1330,12 @@ function initial_error_message(): array { return $msg; } -// 一括書き込み(上書き) -function writeFile ($fp, $data): void { +/** + * 一括書き込み(上書き) + * @param resource|false $fp + */ + +function writeFile ($fp, string $data): void { global $en; if($data === ''){ closeFile($fp); @@ -1333,7 +1346,11 @@ function writeFile ($fp, $data): void { stream_set_write_buffer($fp, 0); fwrite($fp, $data); } -//fpクローズ + +/** + * fpクローズ + * @param resource|false $fp +*/ function closeFile ($fp): void { if($fp){ fflush($fp); @@ -1342,7 +1359,13 @@ function closeFile ($fp): void { } } -//縮小表示 +/** + *縮小表示 + * @param int|string|null $w + * @param int|string|null $h + * @param int|string|null $max_w + * @param int|string|null $max_h + */ function image_reduction_display($w,$h,$max_w,$max_h): array { if(!ctype_digit((string)$w)||!ctype_digit((string)$h)){ return ['','']; @@ -1360,7 +1383,7 @@ function image_reduction_display($w,$h,$max_w,$max_h): array { } /** * 描画時間を計算 - * @param $psec + * @param int|string $psec * @return array */ function calcPtime ($psec): ?array { @@ -1396,7 +1419,7 @@ function calcPtime ($psec): ?array { * @param $sec * @return string */ -function calc_remaining_time_to_close_thread ($sec): string { +function calc_remaining_time_to_close_thread (int $sec): string { global $en; $D = floor($sec / 86400); @@ -1425,7 +1448,7 @@ function calc_remaining_time_to_close_thread ($sec): string { * @param $filepath * @return string */ -function check_pch_ext ($filepath,$options = []): string { +function check_pch_ext (?string $filepath,array $options = []): string { $exts=[".pch",".tgkr",".chi",".psd"]; @@ -1444,7 +1467,10 @@ function check_pch_ext ($filepath,$options = []): string { return ''; } -// 古いスレッドへの投稿を許可するかどうか +/** +* 古いスレッドへの投稿を許可するかどうか +* @param string|null $postedtime +*/ function check_elapsed_days ($postedtime): bool { global $elapsed_days; if(!$postedtime || !is_numeric($postedtime)){ @@ -1456,7 +1482,7 @@ function check_elapsed_days ($postedtime): bool { : true; // フォームを閉じる日数が未設定なら許可 } // スレッドを閉じるまでの残り時間 -function time_left_to_close_the_thread ($postedtime): string { +function time_left_to_close_the_thread (?string $postedtime): string { global $elapsed_days; if(!$elapsed_days || !$postedtime || !is_numeric($postedtime)){ return ''; @@ -1467,7 +1493,10 @@ function time_left_to_close_the_thread ($postedtime): string { return ($timeleft<(60 * 86400)) ? calc_remaining_time_to_close_thread($timeleft) : ''; } -// マイクロ秒を秒に戻す +/** + * マイクロ秒を秒に戻す + * @param string|null|int $microtime + */ function microtime2time($microtime): int { $microtime=(string)$microtime; $time = (strlen($microtime)>15) ? substr($microtime,0,-6) : substr($microtime,0,-3); @@ -1476,7 +1505,7 @@ function microtime2time($microtime): int { } //POSTされた値をログファイルに格納する書式にフォーマット -function create_formatted_text_from_post($name,$sub,$url,$com): array { +function create_formatted_text_from_post(?string $name,?string $sub,?string $url,?string $com): array { global $en,$name_input_required,$subject_input_required,$comment_input_required; if(!$name||preg_match("/\A\s*\z/u",$name)) $name=""; @@ -1517,14 +1546,17 @@ function create_formatted_text_from_post($name,$sub,$url,$com): array { } //PaintBBS NEOのpchかどうか調べる -function is_neo($src): bool { +function is_neo(?string $src): bool { + if(!$src){ + return false; + } $fp = fopen("$src", "rb"); $is_neo=(fread($fp,3)==="NEO"); fclose($fp); return $is_neo; } //pchデータから幅と高さを取得 -function get_pch_size($src): ?array { +function get_pch_size(?string $src): ?array { if(!$src){ return null; } @@ -1673,7 +1705,10 @@ function getTranslatedLayerName(): string { return "Layer"; } -//flockのラッパー関数 +/** + *flockのラッパー関数 + * @param resource|false $fp + */ function file_lock($fp, int $lock, array $options=[]): void { global $en; $flock=flock($fp, $lock); diff --git a/petitnote/index.php b/petitnote/index.php index 6b48a4b4..b010416f 100644 --- a/petitnote/index.php +++ b/petitnote/index.php @@ -3,8 +3,8 @@ //https://paintbbs.sakura.ne.jp/ //1スレッド1ログファイル形式のスレッド式画像掲示板 -$petit_ver='v1.221.0'; -$petit_lot='lot.20260429'; +$petit_ver='v1.222.1'; +$petit_lot='lot.20260501'; $lang = ($http_langs = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '') ? explode( ',', $http_langs )[0] : ''; @@ -20,25 +20,25 @@ die(__DIR__.'/functions.php'.($en ? ' does not exist.':'がありません。')); } require_once(__DIR__.'/functions.php'); -if(!isset($functions_ver)||$functions_ver<20260228){ +if(!isset($functions_ver)||$functions_ver<20260501){ die($en?'Please update functions.php to the latest version.':'functions.phpを最新版に更新してください。'); } check_file(__DIR__.'/misskey_note.inc.php'); require_once(__DIR__.'/misskey_note.inc.php'); -if(!isset($misskey_note_ver)||$misskey_note_ver<20260228){ +if(!isset($misskey_note_ver)||$misskey_note_ver<20260501){ die($en?'Please update misskey_note.inc.php to the latest version.':'misskey_note.inc.phpを最新版に更新してください。'); } check_file(__DIR__.'/save.inc.php'); require_once(__DIR__.'/save.inc.php'); -if(!isset($save_inc_ver)||$save_inc_ver<20260112){ +if(!isset($save_inc_ver)||$save_inc_ver<20260501){ die($en?'Please update save.inc.php to the latest version.':'save.inc.phpを最新版に更新してください。'); } check_file(__DIR__.'/search.inc.php'); require_once(__DIR__.'/search.inc.php'); -if(!isset($search_inc_ver)||$search_inc_ver<20260223){ +if(!isset($search_inc_ver)||$search_inc_ver<20260501){ die($en?'Please update search.inc.php to the latest version.':'search.inc.phpを最新版に更新してください。'); } @@ -50,13 +50,13 @@ check_file(__DIR__.'/thumbnail_gd.inc.php'); require_once(__DIR__.'/thumbnail_gd.inc.php'); -if(!isset($thumbnail_gd_ver)||$thumbnail_gd_ver<20260113){ +if(!isset($thumbnail_gd_ver)||$thumbnail_gd_ver<20260501){ error($en?'Please update thumbmail_gd.inc.php to the latest version.':'thumbnail_gd.inc.phpを最新版に更新してください。'); } check_file(__DIR__.'/noticemail.inc.php'); require_once(__DIR__.'/noticemail.inc.php'); -if(!isset($noticemail_inc_ver)||$noticemail_inc_ver<20250315){ +if(!isset($noticemail_inc_ver)||$noticemail_inc_ver<20260501){ error($en?'Please update noticemail.inc.php to the latest version.':'noticemail.inc.phpを最新版に更新してください。'); } @@ -406,7 +406,7 @@ function post(): void { $com = $formatted_post['com']; //ファイルアップロード - $up_tempfile = $_FILES['imgfile']['tmp_name'] ?? ''; // 一時ファイル名 + $up_tempfile = (string)($_FILES['imgfile']['tmp_name'] ?? ''); // 一時ファイル名 if(isset($_FILES['imgfile']['error']) && in_array($_FILES['imgfile']['error'],[1,2])){//容量オーバー error($en? "The file is too large." : "ファイルサイズが大きすぎます。"); } @@ -1157,6 +1157,9 @@ function to_continue(): void { //記事は存在するか $flag = false; $resid = ''; + $thumbnail = ''; + $_pchext = ''; + $imgfile = ''; while ($line = fgets($rp)) { if(strpos($line,"\toya")!==false || strpos($line,"\t".$id."\t")!==false){ list($_no,$sub,$name,$verified,$com,$url,$_imgfile,$w,$h,$thumbnail,$painttime,$log_img_hash,$tool,$_pchext,$_time,$first_posted_time,$host,$userid,$hash,$oya)=explode("\t",trim($line)); @@ -1263,6 +1266,7 @@ function download_app_dat(): void { } check_open_no($no); $rp=fopen(LOG_DIR."{$no}.log","r"); + $time=''; while ($line = fgets($rp)) { if(!trim($line)){ continue; @@ -1356,7 +1360,7 @@ function img_replace(): void { $repfind=false; $is_painted_img=false; $hide_animation=false; - + $imgext=''; if(!$is_upload_img){ /*--- テンポラリ捜査 ---*/ $handle = opendir(TEMP_DIR); @@ -1430,7 +1434,21 @@ function img_replace(): void { } $flag=false; - + $_time=''; + $_tool=''; + $_oya=''; + $_imgfile =''; + $_thumbnail=''; + $_painttime=''; + $_no=''; + $_sub=''; + $_name=''; + $_verified=''; + $_com=''; + $_url=''; + $_hash=''; + $_first_posted_time=''; + $i=0; foreach($r_arr as $i => $line){ if(strpos($line,"\t".$id."\t")!==false){ list($_no,$_sub,$_name,$_verified,$_com,$_url,$_imgfile,$_w,$_h,$_thumbnail,$_painttime,$_log_img_hash,$_tool,$_pchext,$_time,$_first_posted_time,$_host,$_userid,$_hash,$_oya)=explode("\t",trim($line)); @@ -1495,7 +1513,7 @@ function img_replace(): void { chmod($upfile,0606); //添付したアップロード画像の元のmime_type - $upload_img_mime_type = $is_upload_img ? mime_content_type($upfile) : ""; + $upload_img_mime_type = (string)($is_upload_img ? mime_content_type($upfile) : ""); if($is_upload_img){ //Exifをチェックして画像が回転している時は上書き保存 @@ -1619,6 +1637,10 @@ function img_replace(): void { $newline = "$_no\t$_sub\t$_name\t$_verified\t$strcut_com\t$_url\t$imgfile\t$w\t$h\t$thumbnail\t$painttime\t$up_img_hash\t$tool\t$pchext\t$time\t$_first_posted_time\t$host\t$userid\t$_hash\toya\n"; $flag=false; + $time_=''; + $no_=''; + $verified_=''; + $hash_=''; foreach($alllog_arr as $i => $val){ if (strpos(trim($val), $no . "\t") === 0) {//全体ログで$noが一致したら list($no_,$sub_,$name_,$verified_,$com_,$url_,$imgfile_,$w_,$h_,$thumbnail_,$painttime_,$log_img_hash_,$tool_,$pchext_,$time_,$first_posted_time_,$host_,$userid_,$hash_,$oya_) = explode("\t",trim($val)); @@ -1687,6 +1709,9 @@ function pchview(): void { $rp=fopen(LOG_DIR."{$no}.log","r"); $flag=false; $resid = ''; + $pchext =''; + $time = ''; + $imgfile = ''; while ($line = fgets($rp)) { if(!trim($line)){ continue; @@ -1729,7 +1754,7 @@ function pchview(): void { } //削除前の確認画面 -function confirmation_before_deletion ($edit_mode=''): void { +function confirmation_before_deletion (): void { global $boardname,$home,$petit_ver,$petit_lot,$skindir,$set_nsfw,$en; global $deny_all_posts; @@ -1775,7 +1800,8 @@ function confirmation_before_deletion ($edit_mode=''): void { error($en?'This operation has failed.':'失敗しました。'); } $find=false; - $resid= ''; + $resid=''; + $first_posted_time=''; foreach($r_arr as $i =>$val){ if(strpos($val,"\t".$id."\t")!==false){ $_line=explode("\t",trim($val)); @@ -1821,7 +1847,7 @@ function confirmation_before_deletion ($edit_mode=''): void { } //編集画面 -function edit_form($id='',$no=''): void { +function edit_form(string $id='',string $no=''): void { global $petit_ver,$petit_lot,$home,$boardname,$skindir,$set_nsfw,$en,$max_kb,$use_upload,$mark_sensitive_image,$use_url_input_field; @@ -1860,6 +1886,8 @@ function edit_form($id='',$no=''): void { $rp=fopen(LOG_DIR."{$no}.log","r"); $flag=false; + $lines=[]; + $com=''; while ($line = fgets($rp)) { if(strpos($line,"\t".$id."\t")!==false){ $lines=explode("\t",trim($line)); @@ -1983,6 +2011,26 @@ function edit(): void { } $flag=false; + $_oya=''; + $_sub=''; + $_imgfile=''; + $_com=''; + $_time=''; + $pchext=''; + $_url=''; + $_host=''; + $res_oya_deleted = false; + $_userid=''; + $_hash=''; + $_verified=''; + $_no=''; + $_w=''; + $_h=''; + $_painttime=''; + $_log_img_hash=''; + $_tool=''; + $_first_posted_time=''; + $i=0; foreach($r_arr as $i => $line){ if(strpos($line,"\t".$id."\t")!==false){ @@ -2161,6 +2209,10 @@ function del(): void { } $find=false; + $oya=''; + $imgfile=''; + $time=''; + $i=0; foreach($r_arr as $i =>$val){ if(strpos($val,"\t".$id."\t")!==false){ list($_no,$sub,$name,$verified,$com,$url,$imgfile,$w,$h,$thumbnail,$painttime,$log_img_hash,$tool,$pchext,$time,$first_posted_time,$host,$userid,$hash,$oya)=explode("\t",trim($val)); @@ -2197,6 +2249,7 @@ function del(): void { error($en?'This operation has failed.':'失敗しました。'); } $flag=false; + $j=0; foreach($alllog_arr as $j =>$_val){//全体ログ if (strpos(trim($_val), $no . "\t") === 0) {//全体ログで$noが一致したら break; @@ -2492,7 +2545,7 @@ function view(): void { } //レス画面に前後のスレッドの画像一覧と次のスレッド前のスレッドのリンクを出す -function res_view_other_works($resno): array +function res_view_other_works(string $resno): array { global $view_other_works; diff --git a/petitnote/misskey_note.inc.php b/petitnote/misskey_note.inc.php index 4c155e6d..88a4164f 100644 --- a/petitnote/misskey_note.inc.php +++ b/petitnote/misskey_note.inc.php @@ -3,7 +3,7 @@ //https://paintbbs.sakura.ne.jp/ //APIを使ってお絵かき掲示板からMisskeyにノート -$misskey_note_ver=20260228; +$misskey_note_ver=20260501; class misskey_note{ //投稿済みの記事をMisskeyにノートするための前処理 @@ -45,6 +45,7 @@ public static function before_misskey_note (): void { } $find=false; $resid=""; + $first_posted_time =""; foreach($r_arr as $i =>$val){ $_line=explode("\t",trim($val)); list($_no,$sub,$name,$verified,$com,$url,$imgfile,$w,$h,$thumbnail,$painttime,$log_hash_img,$tool,$pchext,$time,$first_posted_time,$host,$userid,$hash,$oya)=$_line; @@ -120,6 +121,8 @@ public static function misskey_note_edit_form(): void { $flag=false; $resid=""; + $line=""; + $first_posted_time=""; foreach($r_arr as $val){ $line=explode("\t",trim($val)); diff --git a/petitnote/noticemail.inc.php b/petitnote/noticemail.inc.php index ba3dd8e0..9fdc1d8f 100644 --- a/petitnote/noticemail.inc.php +++ b/petitnote/noticemail.inc.php @@ -93,7 +93,7 @@ class noticemail { - public static function send($data): void + public static function send(array $data): void { mb_language('uni'); diff --git a/petitnote/save.inc.php b/petitnote/save.inc.php index 604118ce..7172096f 100644 --- a/petitnote/save.inc.php +++ b/petitnote/save.inc.php @@ -5,8 +5,21 @@ $save_inc_ver=20260112; class image_save{ - private $security_timer,$imgfile,$en,$count,$errtext,$session_usercode; // プロパティとして宣言 - private $tool,$repcode,$stime,$resto,$timer,$error_type,$hide_animation,$pmax_w,$pmax_h; + private int $security_timer; + private string $imgfile; + private bool $en; + /** @var string|int */ + private $count; + private ?string $session_usercode; // プロパティとして宣言 + private ?string $tool; + private ?string $repcode; + private ?string $stime; + private ?string $resto; + private int $timer; + private ?string $error_type; + private ?string $hide_animation; + private int $pmax_w; + private int $pmax_h; function __construct(){ @@ -33,8 +46,8 @@ function __construct(){ $this->imgfile = time().substr(microtime(),2,6); //画像ファイル名 $this->imgfile = is_file(TEMP_DIR.$this->imgfile.'.png') ? ((time()+1).substr(microtime(),2,6)) : $this->imgfile; - $this->pmax_w= $pmax_w ?? ''; - $this->pmax_h= $pmax_h ?? ''; + $this->pmax_w= $pmax_w ?? 0; + $this->pmax_h= $pmax_h ?? 0; } @@ -197,7 +210,7 @@ private function move_uploaded_image(): void { // list($w,$h)=getimagesize($_FILES['picture']['tmp_name']); - // if($w > $this->pmax_w || $h > $this->pmax_h){//幅と高さ + // if($w && $this->pmax_w && $w > $this->pmax_w || $h && $this->pmax_h && $this->pmax_h > $this->pmax_h){//幅と高さ // //規定サイズ違反を検出しました。画像は保存されません。 // $this->error_msg($this->en ? "The image dimensions are too large." : "画像のサイズが大きすぎます。"); // } @@ -271,7 +284,7 @@ private function move_uploaded_pch(): void { } } - private function error_msg($message): void { + private function error_msg(?string $message): void { switch ($this->error_type){ case "neo": $errtext="error\n"; diff --git a/petitnote/search.inc.php b/petitnote/search.inc.php index 9cc6338d..d57d084d 100644 --- a/petitnote/search.inc.php +++ b/petitnote/search.inc.php @@ -2,7 +2,7 @@ //Petit Note (c)さとぴあ @satopian 2021-2026 MIT License //https://paintbbs.sakura.ne.jp/ -$search_inc_ver = 20260223; +$search_inc_ver = 20260501; class processsearch { @@ -243,7 +243,9 @@ private static function create_search_array(): array if ($imgsearch) { //画像検索の場合 $continue_to_search = (bool)$imgfile; //画像があったら } - + $s_name =""; + $s_sub = ""; + $s_com = ""; if ($continue_to_search) { if ($radio === 1 || $radio === 2 || $radio === 0) { $s_name = self::create_formatted_text_for_search($name); @@ -280,7 +282,7 @@ private static function create_search_array(): array return $arr; } //検索文字列をフォーマット - private static function create_formatted_text_for_search($str): string + private static function create_formatted_text_for_search(?string $str): string { $s_str = mb_convert_kana($str, 'rn', 'UTF-8'); //全角英数を半角に diff --git a/petitnote/template/basic/paint_neo.html b/petitnote/template/basic/paint_neo.html index 5aa748fd..3b39490e 100644 --- a/petitnote/template/basic/paint_neo.html +++ b/petitnote/template/basic/paint_neo.html @@ -30,6 +30,9 @@ } return; } +document.addEventListener('DOMContentLoaded',()=>{ + document.addEventListener('dblclick', (e)=>{ e.preventDefault()}, { passive: false }); +}); diff --git a/petitnote/thumbnail_gd.inc.php b/petitnote/thumbnail_gd.inc.php index 445b315c..b9374c54 100644 --- a/petitnote/thumbnail_gd.inc.php +++ b/petitnote/thumbnail_gd.inc.php @@ -3,11 +3,16 @@ // https://paintbbs.sakura.ne.jp/ // originalscript (C)SakaQ 2005 http://www.punyu.net/php/ -$thumbnail_gd_ver=20260406; +$thumbnail_gd_ver=20260501; defined('PERMISSION_FOR_DEST') or define('PERMISSION_FOR_DEST', 0606); //config.phpで未定義なら0606 class thumbnail_gd { - public static function thumb($path,$fname,$time,$max_w,$max_h,$options=[]): string { +/** + * @param int|string|null $max_w + * @param int|string|null $max_h +*/ + + public static function thumb(?string $path,?string $fname,?string $time,$max_w,$max_h,array $options=[]): string { $path=basename($path).'/'; $fname=basename($fname); $time=basename($time); @@ -122,7 +127,10 @@ private static function gd_check(): bool { return true; } - //GDのイメージを破棄 + /** + * GDのイメージを破棄 + * @param resource|\GdImage|null $gdImage + */ private static function safeImageDestroy($gdImage): void { if(PHP_VERSION_ID < 80000) {//PHP8.0未満の時は imagedestroy($gdImage); @@ -130,7 +138,7 @@ private static function safeImageDestroy($gdImage): void { } // 透明度の処理を行う必要があるかを判断 - private static function isTransparencyEnabled($options, $mime_type): bool { + private static function isTransparencyEnabled(array $options,?string $mime_type): bool { // 透明度を扱うオプションが設定されているか確認 $transparencyOptionsSet = isset($options['toolarge']) || isset($options['webp']) || isset($options['thumbnail_webp']) || isset($options['2webp']) || isset($options['2png']); @@ -142,8 +150,11 @@ private static function isTransparencyEnabled($options, $mime_type): bool { return $transparencyOptionsSet && in_array($mime_type, $transparencySupportedFormats) && $transparencyFunctionsAvailable; } - //各画像フォーマットのリソースを作成 - private static function createImageResource($fname,$mime_type) { + /** + *各画像フォーマットのリソースを作成 + * @param string|bool $mime_type + */ + private static function createImageResource(?string $fname,$mime_type) { switch ($mime_type) { case "image/gif": if(!function_exists("ImageCreateFromGIF")) {//gif @@ -183,8 +194,11 @@ private static function createImageResource($fname,$mime_type) { return $im_in; } - //縮小してPNGで上書き - private static function overwriteResizedImageWithPNG($im_out, $fname): ?string { + /** + * 縮小してPNGで上書き + * @param resource|\GdImage|null $im_out + */ + private static function overwriteResizedImageWithPNG($im_out, ?string $fname): ?string { $outfile=(string)$fname; //本体画像を縮小 if(function_exists("ImagePNG")) { @@ -194,8 +208,11 @@ private static function overwriteResizedImageWithPNG($im_out, $fname): ?string { } return $outfile; } - //サムネイル作成 - private static function createThumbnailImage($im_out, $time, $options): ?string { + /** + * サムネイル作成 + * @param resource|\GdImage|null $im_out + */ + private static function createThumbnailImage($im_out,?string $time,array $options): ?string { if(isset($options['2png'])) { From b05011c9e2bc0e7b3938cb5ac0c1b0ded30d43e9 Mon Sep 17 00:00:00 2001 From: satopian Date: Sat, 2 May 2026 00:20:45 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E5=BE=AE=E8=AA=BF=E6=95=B4=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- petitnote/functions.php | 23 +++++++++++++---------- petitnote/index.php | 10 +++++----- petitnote/noticemail.inc.php | 2 +- petitnote/save.inc.php | 2 +- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/petitnote/functions.php b/petitnote/functions.php index 592222fa..ab4e418f 100644 --- a/petitnote/functions.php +++ b/petitnote/functions.php @@ -735,7 +735,7 @@ function auto_link(?string $str,?string $verified = ""): string { } //mime typeを取得して拡張子を返す -function get_image_type (string $img_file): string { +function get_image_type (?string $img_file): string { $img_type = mime_content_type($img_file); @@ -1044,7 +1044,7 @@ function getId (?string $userip): string { } //Asyncリクエストの時は処理を中断 -function check_AsyncRequest(string $upfile=''): void { +function check_AsyncRequest(?string $upfile=''): void { //ヘッダーが確認できなかった時の保険 $asyncflag = (bool)filter_input_data('POST','asyncflag',FILTER_VALIDATE_BOOLEAN); $paint_picrep = (bool)filter_input_data('POST','paint_picrep',FILTER_VALIDATE_BOOLEAN); @@ -1334,8 +1334,7 @@ function initial_error_message(): array { * 一括書き込み(上書き) * @param resource|false $fp */ - -function writeFile ($fp, string $data): void { +function writeFile ($fp,?string $data): void { global $en; if($data === ''){ closeFile($fp); @@ -1467,11 +1466,11 @@ function check_pch_ext (?string $filepath,array $options = []): string { return ''; } -/** -* 古いスレッドへの投稿を許可するかどうか -* @param string|null $postedtime -*/ -function check_elapsed_days ($postedtime): bool { +/** + * 古いスレッドへの投稿を許可するかどうか + * @param string|null|int $postedtime + */ +function check_elapsed_days (?string $postedtime): bool { global $elapsed_days; if(!$postedtime || !is_numeric($postedtime)){ return true; // 投稿時間が不正な場合は許可 @@ -1481,7 +1480,11 @@ function check_elapsed_days ($postedtime): bool { ? ((time() - (int)$postedtime) <= ((int)$elapsed_days * 86400)) // 指定日数以内なら許可 : true; // フォームを閉じる日数が未設定なら許可 } -// スレッドを閉じるまでの残り時間 + +/** + * スレッドを閉じるまでの残り時間 + * @param string|null|int $postedtime + */ function time_left_to_close_the_thread (?string $postedtime): string { global $elapsed_days; if(!$elapsed_days || !$postedtime || !is_numeric($postedtime)){ diff --git a/petitnote/index.php b/petitnote/index.php index b010416f..0cc40238 100644 --- a/petitnote/index.php +++ b/petitnote/index.php @@ -3,7 +3,7 @@ //https://paintbbs.sakura.ne.jp/ //1スレッド1ログファイル形式のスレッド式画像掲示板 -$petit_ver='v1.222.1'; +$petit_ver='v1.222.2'; $petit_lot='lot.20260501'; $lang = ($http_langs = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '') @@ -51,13 +51,13 @@ check_file(__DIR__.'/thumbnail_gd.inc.php'); require_once(__DIR__.'/thumbnail_gd.inc.php'); if(!isset($thumbnail_gd_ver)||$thumbnail_gd_ver<20260501){ - error($en?'Please update thumbmail_gd.inc.php to the latest version.':'thumbnail_gd.inc.phpを最新版に更新してください。'); + die($en?'Please update thumbmail_gd.inc.php to the latest version.':'thumbnail_gd.inc.phpを最新版に更新してください。'); } check_file(__DIR__.'/noticemail.inc.php'); require_once(__DIR__.'/noticemail.inc.php'); if(!isset($noticemail_inc_ver)||$noticemail_inc_ver<20260501){ - error($en?'Please update noticemail.inc.php to the latest version.':'noticemail.inc.phpを最新版に更新してください。'); + die($en?'Please update noticemail.inc.php to the latest version.':'noticemail.inc.phpを最新版に更新してください。'); } check_file(__DIR__.'/config.php'); @@ -1434,7 +1434,7 @@ function img_replace(): void { } $flag=false; - $_time=''; + $_time=''; $_tool=''; $_oya=''; $_imgfile =''; @@ -1595,7 +1595,7 @@ function img_replace(): void { $aco_dst = IMG_DIR.$time.".aco"; if(is_file($aco_src)){ if(copy($aco_src, $aco_dst)){ - chmod($aco_dst,0606); + chmod($aco_dst,0606); } } } diff --git a/petitnote/noticemail.inc.php b/petitnote/noticemail.inc.php index 9fdc1d8f..b721b2d1 100644 --- a/petitnote/noticemail.inc.php +++ b/petitnote/noticemail.inc.php @@ -1,5 +1,5 @@ Date: Sat, 2 May 2026 18:58:53 +0900 Subject: [PATCH 3/3] =?UTF-8?q?neo=E6=9B=B4=E6=96=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- petitnote/app/neo/neo.js | 78 +++++++++++++++++++++++----------------- petitnote/functions.php | 6 +++- 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/petitnote/app/neo/neo.js b/petitnote/app/neo/neo.js index 7705be64..c9faac96 100644 --- a/petitnote/app/neo/neo.js +++ b/petitnote/app/neo/neo.js @@ -21,7 +21,7 @@ document.addEventListener("DOMContentLoaded", () => { var Neo = function () {}; -Neo.version = "1.6.51"; +Neo.version = "1.6.55"; Neo.painter = null; Neo.fullScreen = false; Neo.uploaded = false; @@ -2023,6 +2023,8 @@ Neo.Painter.prototype.toneTool = null; Neo.Painter.prototype.blurTool = null; Neo.Painter.prototype.dodgeTool = null; Neo.Painter.prototype.burnTool = null; +Neo.Painter.prototype.sliderTool = null; +Neo.Painter.prototype.dummyTool = null; Neo.Painter.prototype.rectTool = null; Neo.Painter.prototype.rectFillTool = null; @@ -2288,8 +2290,9 @@ Neo.Painter.prototype._initCanvas = function (div, width, height) { container.onmouseout = function (e) { ref._rollOutHandler(e); }; + // 先にNeo.Buttonのtouchstart()がトリガーされる container.addEventListener( - "mousedown", + "mousedown", //pointerdownに変更するとここが先にトリガーされ、線幅を保存できなくなる function (e) { ref._mouseDownHandler(e); }, @@ -2475,6 +2478,9 @@ Neo.Painter.prototype._initTools = function () { this.ellipseFillTool = new Neo.EllipseFillTool(); this.blurRectTool = new Neo.BlurRectTool(); this.turnTool = new Neo.TurnTool(); + + this.sliderTool = new Neo.SliderTool(); + this.dummyTool = new Neo.DummyTool(); }; Neo.Painter.prototype.hideInputText = function () { @@ -2655,20 +2661,22 @@ Neo.Painter.prototype._mouseDownHandler = function (e) { if (!this.isUIPaused()) { if (e.target["data-bar"]) { - this.pushTool(new Neo.HandTool()); + this.pushTool(this.handTool); + this.handTool.reverse = false; } else if (this.isSpaceDown && document.activeElement != this.inputText) { - this.pushTool(new Neo.HandTool()); - this.tool.reverse = true; + this.pushTool(this.handTool); + this.handTool.reverse = true; } else if (e.target["data-slider"] != undefined) { - this.pushTool(new Neo.SliderTool()); - this.tool.target = e.target; + this.pushTool(this.sliderTool); + this.sliderTool.target = e.target; + this.sliderTool.alt = false; } else if (e.ctrlKey && e.altKey && !e.shiftKey) { - this.pushTool(new Neo.SliderTool()); - this.tool.target = Neo.sliders[Neo.SLIDERTYPE_SIZE].element; - this.tool.alt = true; + this.pushTool(this.sliderTool); + this.sliderTool.target = Neo.sliders[Neo.SLIDERTYPE_SIZE].element; + this.sliderTool.alt = true; } else if (this.isWidget(e.target)) { this.isMouseDown = false; - this.pushTool(new Neo.DummyTool()); + this.pushTool(this.dummyTool); } } @@ -2770,12 +2778,16 @@ Neo.Painter.prototype._stabilizer = function (e) { if (this.isMouseDown) { // 手ぶれ補正の強さ // 補正なし 0.0 最強 0.99 - const level = Neo.stabiliz_level; + const level = Math.max(0, Math.min(Neo.stabiliz_level, 5)); //手ぶれ補正のレベルを6段階に分けたテーブル //0で補正なし、5で最強 // [0:無効, 1:0.55, 2:0.8, 3:0.85, 4:0.9, 5:0.96] const stabilityTable = [0.0, 0.55, 0.8, 0.85, 0.9, 0.96]; - const stability = stabilityTable[Math.max(0, Math.min(level, 5))]; + const stabilityLebel = stabilityTable[level]; + //ブラシサイズが大きい時と拡大時は補正強度を下げる + const zoomModifier = this.zoom <= 1 ? 1 : 0.88; + const sizeModifier = this.lineWidth <= 8 ? 1 : 0.96; + const stability = stabilityLebel * zoomModifier * sizeModifier; const factor = 1.0 - stability; // stabilizedX が未定義なら現在の位置で初期化 @@ -4804,32 +4816,31 @@ Neo.Painter.prototype.getDestCanvasPosition = function ( }; Neo.Painter.prototype.isWidget = function (element) { - while (1) { - if ( - element == null || - element.id == "neo-canvas" || - element.id == "neo-container" - ) - break; + if (!element || !(element instanceof Element)) return false; - if ( - element.id == "neo-tools" || - element.className == "buttonOn" || - element.className == "buttonOff" || - element.className == "inputText" - ) { - return true; - } - element = element.parentNode; + // #NEO の外側を除外 + const root = element.closest("#NEO"); + if (!root) return false; + + // ツール領域・ボタン類 + if ( + element.closest( + "#neo-tools, .NEO .buttonOn, .NEO .buttonOff, .NEO .inputText", + ) + ) { + return true; } + return false; }; Neo.Painter.prototype.isContainer = function (element) { - while (1) { - if (element == null) break; - if (element.id == "neo-container") return true; - element = element.parentNode; + if (!element || !(element instanceof Element)) return false; + // #NEO の外側を除外 + const root = element.closest("#NEO"); + if (!root) return false; + if (element.closest("#neo-container")) { + return true; } return false; }; @@ -5102,6 +5113,7 @@ Neo.ToolBase.prototype.startX = null; Neo.ToolBase.prototype.startY = null; Neo.ToolBase.prototype.type = null; Neo.ToolBase.prototype.step = 0; +Neo.ToolBase.prototype.reverse = false; Neo.ToolBase.prototype.init = function (oe) {}; Neo.ToolBase.prototype.kill = function (oe) {}; diff --git a/petitnote/functions.php b/petitnote/functions.php index ab4e418f..1989f421 100644 --- a/petitnote/functions.php +++ b/petitnote/functions.php @@ -2,7 +2,7 @@ //Petit Note (c)さとぴあ @satopian 2021-2026 MIT License //https://paintbbs.sakura.ne.jp/ -$functions_ver=20260501; +$functions_ver=20260502; //編集モードログアウト function logout(): void { @@ -737,6 +737,10 @@ function auto_link(?string $str,?string $verified = ""): string { //mime typeを取得して拡張子を返す function get_image_type (?string $img_file): string { + if(!$img_file || !is_file($img_file)){ + return ''; + } + $img_type = mime_content_type($img_file); switch ($img_type) {