<?php
/*
 * メンバー管理システム
 * Copyright (c) 2023 by Crytus All rights reserved.
 *
 * 【注意】このファイルの修正は充分ご注意ください。
 * 修正する前には、必ずバックアップを保存してください。
 * 動作がおかしくなったら元のファイルに戻してください。
 * このファイルの漢字コードはHTMLと同じにしてください。
 *
 * 新規作成 2023/06/06
 *
 */
// エラー出力の指定
error_reporting (E_ALL & ~E_NOTICE & ~E_WARNING & ~E_STRICT & ~E_DEPRECATED);
//require("mb_setup.php");	// 設定情報
//====================================
// 設定値
$mail_sys = "test@crytus.info";	// 管理者のメールアドレス
$from_name = "システム管理者";	// メール送信者の表示
$from_mail = "info@crytus.info";	// メール送信者のメールアドレス（返信先）
$user_mail = "item2";	// 利用者にメールを送る場合のメールアドレス項目
$user_passwd = "item3";	// 利用者のパスワード項目
$passwd_len = 8;	// パスワード最小桁数
// メッセージ
$title = "メンバー登録";	// システムタイトル

// メール関連
$subject = "ご登録ありがとうございます。\n";	// ユーザー向け件名
$body = "登録内容をお知らせします。
\n";		// ユーザー向け本文・登録時
$subject_sys = "登録がありました。\n";	// 管理者向け件名
$body_sys = "次の登録がありました。\n";		// 管理者向け本文・登録時
$footer = "\n-----------------------
メンバー登録システム";	// 署名
$confirm_message = "この内容でよろしければ、送信してください。";	// 登録確認メッセージ
$complete_message = "ご登録ありがとうございました。
";	// 登録完了メッセージ
//
$passwd_message = "登録したメールアドレスを入力してください。";
$subject_passwd = "パスワードのお知らせ";
$body_passwd = "パスワードをお知らせします。\n\nパスワード：[PASSWORD]\n";
$passwd_end_message = "メールを送信しました。<br><br><a href=\"./member.php?act=userlogin\">ログイン</a>";
$login_success = "ログインしました。";
$login_error = "ログインできませんでした。";
$logout_message = "ログアウトしました。";
$email_error1 = "メールアドレスが入力されていません。";
$email_error2 = "有効なメールアドレスが存在しません。";
$email_error3 = "このメールアドレスは登録済みです。ご利用いただけません。";
$url_error = "このURLは有効ではありません。最初からやり直してください。";
$regist_success = "登録が完了いたしました。ログインしてご利用ください。<br><br><a href=\"./member.php?act=userlogin\">ログイン</a>";
$regist_success2 = "登録が完了いたしました。認証が完了するまでしばらくお待ちください。";	// 管理者認証時
//------------------------------------------------
//====================================
ini_set("short_open_tag", "0");
ini_set("magic_quotes_gpc", "0");
ini_set("mbstring.encoding_translation", "0");

// データベースファイルの場所と名前
$DB_URI = "data/member.sqlite";

// スクリプトの漢字コード（このファイルの漢字コードと一致させてください）
define("SCRIPT_ENCODING", "UTF-8");	// UTF-8の場合先頭の'//'を取ります。

// 一覧の1ページあたりの表示件数
define("PAGE_LIMIT", 10);	// 10件

// データベースの漢字コード
define("DB_ENCODING", "UTF-8");

// メールの漢字コード(UTF-8かJIS)
define("MAIL_ENCODING", "JIS");

// セッションの開始
session_start();

$script_encoding = SCRIPT_ENCODING;

// 1ページの件数
if (!defined("PAGE_LIMIT")) {
	define("PAGE_LIMIT", 10);	// 10件
}

// 動作環境チェック
if (!function_exists("mb_convert_encoding")) {
	error_exit("日本語変換処理が使えません。ご確認をお願い致します。");
}
if (!class_exists("PDO")) {
	error_exit("簡易データベース(SQLite3)が使えません。ご確認をお願い致します。");
} else {
	$ary = PDO::getAvailableDrivers();
	if (!in_array("sqlite", $ary)) {
		error_exit("簡易データベース(SQLite3)が使えません。ご確認をお願い致します。");
	}
}
if (!file_exists($DB_URI)) {
	error_exit("データファイル（{$DB_URI}）がみつかりません。ご確認をお願い致します。");
}
if (!function_exists("ImageCreateFromString")) {
	error_exit("画像処理が組み込まれていません。ご確認をお願い致します。");
}
if (substr(phpversion(), 0, 1) == "4") {
	error_exit("このシステムはPHP5以上が必要です。ご確認をお願い致します。");
}
// 異常終了
function error_exit($msg)
{
	echo '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>';
	echo $msg;
	echo "</body></html>";
	exit;
}
//-------------------------------------------------------------
//define("MAX_REC_SIZE", 4000);	// 1レコードの最大バイト数
// XSS対策
if (is_array($_REQUEST) && (!$_SESSION["LOGIN"])) {
	foreach ($_REQUEST as $k => $v) {
		if (is_array($v)) {
			foreach ($v as $k2 => $v2) {
				$_REQUEST[$k][$k2] = mb_ereg_replace("<.*>", "", $v2);
			}
		} else {
			$_REQUEST[$k] = mb_ereg_replace("<.*>", "", $_REQUEST[$k]);
		}
	}
}
// デモ用
include("demo.php");

$dbh = new PDO("sqlite:" . $DB_URI);

// PHPファイルを実行する
function exec_file($file)
{
	global $setup;
	global $DB_URI;
	global $script_encoding;

	if (file_exists("_files/" . $file)) {
		include_once("_files/" . $file);
	} else {
		$php = load_blob($file);
		if ($php) {
			eval("?>" . $php);
		}
	}
}
// 大きなデータを取り出す
function load_blob($key)
{
	global $dbh;

	$sql = "select seq from file_list where name='{$key}'";
	$ret = $dbh->query($sql);
	$val = $ret->fetchAll();

	if ($val) {
		$val = $val[0];
		$id = $val["seq"];
		$file = load_db_file($id);
		return $file;
	}
	return false;
}
// DBからファイルを取得する
function load_db_file($id)
{
	global $dbh;

	$data = "";
	$sql = "select contents from file_contents where file_num={$id} order by seq";
	$stmt = $dbh->query($sql);
	while ($ret = $stmt->fetch(PDO::FETCH_ASSOC)) {
		$data .= $ret["contents"];
	}
	return $data;
}

$act = htmlspecialchars($_REQUEST["act"]);
if (!$act) {
	$act = "index";
}

// バイナリー処理のファイル
$binary = array(
	"png",
	"jpg",
	"gif",
);
// ファイルの出力
if ($act == "file") {
	$file = htmlspecialchars($_REQUEST["f"]);
	if ($file) {
		if (file_exists($file)) {
			$contents = file_get_contents($file);
		} else if (file_exists("_files/" . $file)) {
			$contents = file_get_contents("_files/" . $file);
		} else {
			$contents = load_blob($file);
			$ary = explode(".", $file);
			if (count($ary) > 1) {	// 拡張子あり？
				if (in_array($ary[count($ary)-1], $binary)) {
					$contents = base64_decode($contents);
				}
			}
		}
	}
	header('Content-Type: ' . get_mime_types($file));
	echo $contents;
	exit;
}
// --------------------------------
// 必要なPHPファイルを読み込む
exec_file("sqlite_db.php");
exec_file("dbaccess.php");
exec_file("cms.php");
exec_file("info.php");
exec_file("info_item.php");
//exec_file("image.php");
exec_file("member.php");
//exec_file("user.php");
exec_file("htmltemplate.php");
exec_file("member_core.php");
//exec_file("markdown.php");
// --------------------------------
$siteinfo = get_setup();
$data["siteinfo"] = $siteinfo;

$data["uri"] = $_SERVER["REQUEST_URI"];

// フォーム登録（認証なし）または、 管理者認証
if ($act == "regist") {
	include("mb_form.php");
	if ($mode == "finish") {
		// 登録完了
		$data["message"] = $regist_success;
		$data["mode"] = "form";
		htmltemplate::t_include("mb_index_.html", $data);
	}
	exit;
}
// ログアウト処理
if ($act == "userlogout") {
	unset($_SESSION["USERLOGIN"]);
	$data["message"] = $logout_message;
	$data["mode"] = "form";
	htmltemplate::t_include("mb_index_.html", $data);
	exit;
}
// ログイン処理
if ($act == "userlogin") {
	if ($_REQUEST["mode"] == "form") {
		$email = htmlspecialchars($_REQUEST["email"]);
		$passwd = htmlspecialchars($_REQUEST["passwd"]);
		$cond[$user_mail] = $email;
		$cond[$user_passwd] = $passwd;
		$cond["status"] = "1";		// 有効
		$ret = Member::findData($cond);
		if ($ret) {
			$data["message"] = $login_success;
			$_SESSION["USERLOGIN"] = $ret[0];
			//
			$upd["last_login"] = date('Y-m-d H:i:s');
			Member::updateData($_SESSION["USERLOGIN"]["member_id"], $upd);
			//
			$data["mode"] = "form";
			htmltemplate::t_include("mb_index_.html", $data);
			exit;
		} else {
			$data["message"] = $login_error;
		}
	}
	$form["email"] = $email;
	$form["passwd"] = $passwd;
	$data["form"] = $form;
	$data["mode"] = "form";
	htmltemplate::t_include("mb_login.html", $data);
	exit;
}
// パスワード問い合わせ
if ($act == "password") {
	$data["message"] = $passwd_message;
	if ($_REQUEST["mode"] == "form") {
		$email = htmlspecialchars($_REQUEST["email"]);
		$cond[$user_mail] = $email;
		$cond["status"] = "1";	// 有効
		$ret = Member::findData($cond);
		if ($ret) {
			$passwd = $ret[0][$user_passwd];
			$body = str_replace("[PASSWORD]", $passwd, $body_passwd) . $footer;
			sendmail("from", $email, $subject_passwd, $body, null, $from_name);
			$data["message"] = $passwd_end_message;
			$data["mode"] = "form";
			htmltemplate::t_include("mb_index_.html", $data);
			exit;
		}
		$data["message"] = $email_error2;
	}
	$form["email"] = $email;
	$data["form"] = $form;
	$data["mode"] = "form";
	htmltemplate::t_include("mb_password.html", $data);
	exit;
}
/*
// 問い合わせ処理
if (($act == "contact")||($act == "contact_reinput")) {
	$id = htmlspecialchars($_REQUEST["id"]);
	$item = get_item($id);
	if ($id && $item) {
		$data["item"] = $item;
		//
		$mode = htmlspecialchars($_REQUEST["mode"]);
		if ($mode == "form") {
			$name = htmlspecialchars($_REQUEST["name"]);
			$email = htmlspecialchars($_REQUEST["email"]);
			$comment = htmlspecialchars($_REQUEST["comment"]);
			$form["name"] = $name;
			$form["email"] = $email;
			$form["comment"] = $comment;
			$data["form"] = $form;
			if ($name && $email && $comment) {
				$data["mode"] = "confirm";
				$data["confirm"] = "1";
				$_SESSION["form"] = $form;
			} else {
				$msg = array();
				if (!$name) {
					$msg[] = $error_msg1;
				}
				if (!$email) {
					$msg[] = $error_msg2;
				}
				if (!$comment) {
					$msg[] = $error_msg3;
				}
				$data["message"] = join("<br/>", $msg);
				$data["mode"] = "form";
			}
		} else if ($mode == "confirm") {
			$form = $_SESSION["form"];
			$body = $mail_body;
			$body = str_replace("{info_id}", $item["info_id"], $body);
			$body = str_replace("{title}", $item["title"], $body);
			$body = str_replace("{name}", $form["name"], $body);
			$body = str_replace("{email}", $form["email"], $body);
			$body = str_replace("{comment}", $form["comment"], $body);
			// メール送信
			$tmp = $pre_admin . "\n" . $body . "\n\n" . $post_admin;
			sendmail2($from_mail, $admin_mail, $subject_admin, $tmp, null, $from_name);
			$tmp = $form["name"] . "{$mail_sama}\n\n{$pre_user}\n{$body}\n\n{$post_user}";
			sendmail2($from_mail, $form["email"], $subject, $tmp, null, $from_name);
		} else {
			$data["mode"] = "form";
		}
		if ($act == "contact_reinput") {
			$data["form"] = $_SESSION["form"];
			$data["mode"] = "form";
		}
		//
		htmltemplate::t_include("contact.html", $data);
		exit;
	}
}
*/
// --------------------------------
// トップページ
if (!file_exists("index_.html")) {
	//include("login.html");
	htmltemplate::t_include("login.html", $data);
} else {
	//include("index_.html");
	htmltemplate::t_include("index_.html", $data);
}
exit;
// --------------------------------
// お知らせ
function get_newinfo($max)
{
	global $DB_URI;

	$sql = "select * from info where open=1 and kind=" . INFO_RSS;
	$inst = DBConnection::getConnection($DB_URI);
	$ret = $inst->search_sql($sql);
	$list = array();
	if ($ret["count"]) {
		foreach ($ret["data"] as $val) {
			$item = get_setup(INFO_RSS, $val["info_id"]);
			$item["id"] = $val["info_id"];
			if ($item["open"]) {
				$item["reg_date"] = $val["date"];
				if ($kind) {
					if ($kind == $item["kind"]) {
						$list[$item["date"]] = $item;
					}
				} else {
					$list[$item["date"]] = $item;
				}
			}
		}
	}
	// 並べ替え
	$rss = array();
	if ($list) {
		$count = 0;
		krsort($list);
		foreach ($list as $val) {
			$val["date"] = substr($val["date"], 0, 4) . "/" . substr($val["date"], 5, 2) . "/" . substr($val["date"], 8, 2);
			$rss[] = $val;
			$count++;
			if ($count >= $max) {
				break;
			}
		}
	}
	return $rss;
}
// --------------------------------
function page_index($cur, $pages)
{
	$page = array();
	$no = 0;
	if ($cur > 1) {
		$page['prev'] = array('no' => $cur - 1, 'name' => 'PREV', 'link' => 1);
	}
	for ($i = 1; $i <= $pages; $i++) {
		if ($i == $cur) {
			$page['list'][$no] = array('no' => $i, 'name' => $i);
		} else {
			$page['list'][$no] = array('no' => $i, 'name' => $i, 'link' => 1);
		}
		$no++;
	}
	if ($cur < ($pages)) {
		$page['next'] = array('no' => $cur + 1, 'name' => 'NEXT', 'link' => 1);
	}
	return $page;
}
// ファイルの拡張子からMIMEタイプを得る
function get_mime_types($file)
{
	$mime_types = array(
		'txt' => 'text/plain',
		'htm' => 'text/html',
		'html' => 'text/html',
		'php' => 'text/html',
		'css' => 'text/css',
		'js' => 'application/javascript',
		'json' => 'application/json',
		'xml' => 'application/xml',
		'swf' => 'application/x-shockwave-flash',
		'flv' => 'video/x-flv',

		// images
		'png' => 'image/png',
		'jpe' => 'image/jpeg',
		'jpeg' => 'image/jpeg',
		'jpg' => 'image/jpeg',
		'gif' => 'image/gif',
		'bmp' => 'image/bmp',
		'ico' => 'image/vnd.microsoft.icon',
		'tiff' => 'image/tiff',
		'tif' => 'image/tiff',
		'svg' => 'image/svg+xml',
		'svgz' => 'image/svg+xml',

		// archives
		'zip' => 'application/zip',
		'rar' => 'application/x-rar-compressed',
		'exe' => 'application/x-msdownload',
		'msi' => 'application/x-msdownload',
		'cab' => 'application/vnd.ms-cab-compressed',

		// audio/video
		'mp3' => 'audio/mpeg',
		'qt' => 'video/quicktime',
		'mov' => 'video/quicktime',

		// adobe
		'pdf' => 'application/pdf',
		'psd' => 'image/vnd.adobe.photoshop',
		'ai' => 'application/postscript',
		'eps' => 'application/postscript',
		'ps' => 'application/postscript',

		// ms office
		'doc' => 'application/msword',
		'rtf' => 'application/rtf',
		'xls' => 'application/vnd.ms-excel',
		'ppt' => 'application/vnd.ms-powerpoint',

		// open office
		'odt' => 'application/vnd.oasis.opendocument.text',
		'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
	);

	$ary = explode(".", $file);
	if (count($ary) > 1) {	// 拡張子あり？
		if ($mime_types[$ary[count($ary)-1]]) {
			return $mime_types[$ary[count($ary)-1]];
		}
	}
	return "application/octet-stream";	// 不明なファイル
}
function get_filetype($file)
{
	if (substr($file["filetype"], 0, 5) == "audio") {
		return "audio";
	}
	if (substr($file["filetype"], 0, 5) == "video") {
		return "video";
	}
	if (substr($file["filetype"], 0, 5) == "image") {
		return "image";
	}
	$ary = explode(".", $file["name"]);
	if (count($ary) > 1) {
		if (($ary[count($ary) - 1] == "vr") || ($ary[count($ary) - 1] == "VR")) {
			return "panorama";
		}
	}
	return "other";
}
/*
 * メール送信処理、本文を変数から
 *
 * 差し込み処理、長いサブジェクトに対応
 */
function sendmail($mail_from, $mail_to, $mail_subject, $body, $attach, $from_name=null)
{
	$mail_from = trim($mail_from);
	$mail_to = trim($mail_to);
	$mail_subject = trim($mail_subject);
	$body = html_entity_decode(trim($body));
	$reply = trim($reply);
	$from_name = trim($from_name);
	// 送信元情報の作成
	if ($from_name) {
		$header = "From: ";
		if (MAIL_ENCODING == "UTF8") {
			$header .= '=?utf-8?B?';
		} else {
			$header .= '=?iso-2022-jp?B?';
		}
		$header .= base64_encode(mb_convert_encoding($from_name, MAIL_ENCODING, SCRIPT_ENCODING)) .
			 '?= <' . $mail_from . ">";
	} else {
		$header = "From: " . $mail_from;
	}
	if ($attach) {	// ファイル添付
		$uniq_id = uniqid('boundary');
		$header .= "\r\nMIME-Version: 1.0";
		$header .= "\r\nContent-Type: multipart/mixed; boundary=\"" . $uniq_id . "\"\r\n";
		// 本文の加工
		$mailMessage = $body;
		$body  = "--" . $uniq_id . "\r\n";
		if (MAIL_ENCODING == "UTF8") {
			$body .= "Content-Type: text/plain; charset=\"UTF-8\"\r\n";
		} else {
			$body .= "Content-Type: text/plain; charset=\"ISO-2022-JP\"\r\n";
		}
		$body .= "\r\n";
		$body .= $mailMessage . "\r\n";

		foreach ($attach as $val) {
			$filename = $val["filename"];
			$filebody = $val["filebody"];
			$filetype = $val["filetype"];

			if (MAIL_ENCODING == "UTF8") {
				$fname = '=?utf-8?B?' . base64_encode(mb_convert_encoding($filename, MAIL_ENCODING, SCRIPT_ENCODING)) . '?=';
			} else {
				$fname = '=?iso-2022-jp?B?' . base64_encode(mb_convert_encoding($filename, MAIL_ENCODING, SCRIPT_ENCODING)) . '?=';
			}

			$body .= "--" . $uniq_id . "\r\n";

			$body .= "Content-Type: $filetype; name=\"$filename\"\r\n";
			$body .= "Content-Transfer-Encoding: base64\r\n";
			$body .= "Content-Disposition: attachment; filename=\"$fname\"\r\n";
			$body .= "\r\n";
			$body .= chunk_split($filebody) . "\r\n";
		}
		$body .= "--" . $uniq_id . "--\r\n";
	} else {
		// 漢字コードの指定
		if (MAIL_ENCODING == "UTF8") {
			$header .= "\r\nContent-Type: text/plain;\r\n\tformat=flowed;\r\n\tcharset=\"utf-8\";\r\n\treply-type=original";
		} else {
			$header .= "\r\nContent-Type: text/plain;\r\n\tcharset=\"iso-2022-jp\"\r\nContent-Transfer-Encoding: 7bit";
		}
	}
	// 返信先指定
	if ($reply) {
		$header .= "\r\nReply-to: <" . $reply . ">";
	}
	// 件名の変換
	$subject_str = '';
	while ($mail_subject) {
		if ($subject_str) {
			$subject_str .= "\r\n\t";
		}
		if (mb_strlen($mail_subject, SCRIPT_ENCODING) < 20) {
			if (MAIL_ENCODING == "UTF8") {
				$subject_str .= '=?utf-8?B?';
			} else {
				$subject_str .= '=?iso-2022-jp?B?';
			}
			$subject_str .= base64_encode(mb_convert_encoding($mail_subject, MAIL_ENCODING, SCRIPT_ENCODING)) . '?=';
			$mail_subject = '';
		} else {
			if (MAIL_ENCODING == "UTF8") {
				$subject_str .= '=?utf-8?B?';
			} else {
				$subject_str .= '=?iso-2022-jp?B?';
			}
			$subject_str .= base64_encode(mb_convert_encoding(mb_substr($mail_subject, 0, 20, SCRIPT_ENCODING), MAIL_ENCODING, SCRIPT_ENCODING)) . '?=';
			$mail_subject = mb_substr($mail_subject, 20, mb_strlen($mail_subject, SCRIPT_ENCODING) - 20, SCRIPT_ENCODING);
		}
	}
	$body = str_replace("\r", "", $body);
	$header = str_replace("\r", "", $header);
	// 送信処理
	return @mail($mail_to, $subject_str, mb_convert_encoding($body, MAIL_ENCODING, SCRIPT_ENCODING), $header);
}
//
function value($key)
{
	if (is_array($_REQUEST[$key])) {
		return join(",", $_REQUEST[$key]);
	}
	return htmlspecialchars($_REQUEST[$key]);
}
if (!function_exists("x_count")) {
	function x_count($item)
	{
		if (is_array($item)) {
			return count($item);
		}
		return 0;
	}
}
// 1文字画像化
function imgch($ch)
{
	$im = imagecreate(20, 20);
	// 文字黒、背景白
	$bg = imagecolorallocate($im, 255, 255, 255);
	$textcolor = imagecolorallocate($im, 0, 0, 0);

	// 文字を描画
	imagestring($im, 10, 3, 3, $ch, $textcolor);

	// 傾き
	$r = mt_rand(-45, 45);
	$im2 = imagerotate($im, $r, 0);

	imagedestroy($im);
	return $im2;
}
// CAPTCHA画像作成
function captcha()
{
	session_start();

	// 出力する4文字を決定
	$ch1 = chr(mt_rand(65, 65 + 25));
	$ch2 = chr(mt_rand(65, 65 + 25));
	$ch3 = chr(mt_rand(65, 65 + 25));
	$ch4 = chr(mt_rand(65, 65 + 25));

	// 確認用にセッションへ保存
	$_SESSION["captcha"] = $ch1 . $ch2 . $ch3 . $ch4;

	$imgCh[] = $ch1;
	$imgCh[] = $ch2;
	$imgCh[] = $ch3;
	$imgCh[] = $ch4;

	$img = imagecreatetruecolor(104, 30);
	imagefill($img, 0, 0, imagecolorallocate($img, 255, 255, 255));

	// 4文字合成
	$px = 3;	// 合成位置
	foreach ($imgCh as $ch) {
 		$img2 = imgch($ch);

 		// 画像のサイズを取得
		$sx = imagesx($img2);
		$sy = imagesy($img2);
		if ($sx < $sy) {
			$sx = $sy;
		} else {
			$sy = $sx;
		}
		imagecopy($img, $img2, $px, 2, 0, 0, $sx - 1, $sy); // 合成する
		$px += $sx;

		imagedestroy($img2);
	}
	$sx = imagesx($img);
	$sy = imagesy($img);

	// 横線を引く
	$color = imagecolorallocate($img, 0, 0, 0);
	imageline($img, 0, 10, $sx - 1, 10, $color);
	imageline($img, 0, 18, $sx - 1, 18, $color);

	// 2倍に拡大
	$img2 = imagecreatetruecolor($sx * 2, $sy * 2);
	imagecopyresized($img2, $img, 0, 0, 0, 0, $sx * 2, $sy * 2, $sx, $sy);

	// 画像出力
	header("Content-type: image/png");
	imagepng($img2);
	//
	imagedestroy($img);
	imagedestroy($img2);
	exit;
}
function hide_pass($pass)
{
	return substr("*******************", 0, strlen($pass));
}
