<?php

/**
 * @copyright ICZ Corporation (http://www.icz.co.jp/)
 * @license See the LICENCE file
 * @author <matcha@icz.co.jp>
 * @version $Id$
 */
/**
 * 表示設定クラス
 */
class ViewOptionsController extends AppController
{

    var $name = "ViewOptions";

    var $autoLayout = true;

    var $uses = array(
        'ViewOption'
    );

    var $helpers = array(
        'Html',
        'Form',
        'Ajax',
        'Javascript'
    );
    
    // メイン用
    function index()
    {
        $this->set("main_title", "デザイン設定確認");
        $this->set("title_text", "管理者メニュー");
        // 全オプション取得
        $options = $this->ViewOption->get_option();
        $this->set("options", $options);
    }
    
    // 編集用
    function edit()
    {
        $this->set("main_title", "デザイン設定編集");
        $this->set("title_text", "管理者メニュー");
        $options = $this->ViewOption->get_option();
        $this->set("options", $options);
        
        $errors = $this->ViewOption->invalidFields();
        
        // キャンセルボタンを押された場合、一覧にリダイレクト
        if (isset($this->params['form']['cancel_x'])) {
            $this->redirect("/view_options");
        }
        
        if (isset($this->params['data'])) {
            // トークンチェック
            $this->isCorrectToken($this->data['Security']['token']);
            
            $this->ViewOption->set($this->params['data']);
            if ($this->ViewOption->validates()) {
                if ($this->data['ViewOption']['logo_default']) {
                    $this->data['ViewOption']['logo'] = array(
                        'name' => 'i_logo.jpg',
                        'error' => 0
                    );
                    $result = $this->ViewOption->update_data($this->params['data']);
                    $this->Session->setFlash('設定を保存しました');
                    $this->redirect("/view_options");
                }

                // ファイルのアップロード処理
                if (is_uploaded_file($this->data['ViewOption']['logo']['tmp_name'])) {
                    $logo_data = $this->data['ViewOption']['logo'];

                    // 1) ファイル名の生成
                    $extension = ($logo_data['type'] === 'image/png') ? 'png' : 'jpg';
                    $new_filename = 'logo_' . $this->secureRandomHex(8) . '.' . $extension;
                    $upload_dir = Configure::read('ImgUploadDir');

                    // 2) バリデーションの実行
                    $logo_error = $this->logo_validation($logo_data);

                    // バリデーションが true 以外ならエラーとして処理
                    if ($logo_error !== true) {
                        $this->Session->setFlash($logo_error);
                        $this->redirect("/view_options");
                    }
                    
                    // バリデーション成功時のみ実行
                    // 3-1) 元画像からリソースを作成
                    if ($extension === 'png') {
                        $src_img = @imagecreatefrompng($logo_data['tmp_name']);
                    } else {
                        $src_img = @imagecreatefromjpeg($logo_data['tmp_name']);
                    }

                    if ($src_img) {
                        // 3-2) 透過情報の保持設定(PNGの場合)
                        if ($extension === 'png') {
                            imagealphablending($src_img, false);
                            imagesavealpha($src_img, true);
                        }

                        // 3-3) 新しいファイルとして保存(これにより、メタデータや埋め込みコードが消える)
                        $save_path = $upload_dir . $new_filename;
                        
                        if ($extension === 'png') {
                            $result_save = imagepng($src_img, $save_path, 9); // 圧縮レベル9
                        } else {
                            $result_save = imagejpeg($src_img, $save_path, 90); // クオリティ90
                        }

                        // 3-4) メモリ解放
                        imagedestroy($src_img);

                        if ($result_save) {
                            $this->data['ViewOption']['logo']['name'] = $new_filename;
                            $result = $this->ViewOption->update_data($this->data);
                            $this->Session->setFlash('設定を保存し、画像を最適化しました');
                            $this->redirect("/view_options");
                        } else {
                            $this->Session->setFlash('画像の再生成に失敗しました');
                        }
                    } else {
                        $this->Session->setFlash('画像ファイルが破損しているか、不正な形式です');
                    }
                } else {
                    // エラーコードがUPLOAD_ERR_NO_FILE(ファイルを選択せずに送信ボタンを押す)、またはtmp_nameが空なら画像選択なしと判定
                    if ($this->data['ViewOption']['logo']['error'] == UPLOAD_ERR_NO_FILE || empty($this->data['ViewOption']['logo']['tmp_name'])) {
                        // テキストデータ等のみ保存する
                        $result = $this->ViewOption->update_data($this->params['data']);
                        $this->Session->setFlash('設定を保存しました');
                        $this->redirect("/view_options");
                    } else {
                        // 本当にアップロード処理自体に問題があった場合(サイズオーバー等)
                        $this->Session->setFlash('画像のアップロードに失敗しました');
                        $this->redirect("/view_options");
                    }
                }
            } else {
                $this->set('error', $errors);
            }
        }
    }

    // ロゴ画像のバリデーション
    function logo_validation($logo) {
        // A) ファイルサイズをチェック
        $max_size = Configure::read('ImageSize');
        if ($logo['size'] > $max_size) {
            return '画像サイズは' . ($max_size / 1024 / 1024) . 'MB以下にしてください';
        }

        // B) MIMEタイプ(ブラウザ申告)の予備チェック
        $allowed_types = ['image/jpeg' => 'jpg', 'image/png' => 'png'];
        if (!isset($logo['type']) || !array_key_exists($logo['type'], $allowed_types)) {
            return '画像はJPEGまたはPNG形式でアップロードしてください';
        }

        // C) ファイル実体の解析を行う
        $info = @getimagesize($logo['tmp_name']); // @をつけて警告を抑制
        if (!$info) {
            return '画像ファイルが破損しているか、不正な形式です';
        }

        // D) 解像度制限
        $max_resolution = Configure::read('ImageResolution');
        if ($info[0] > $max_resolution['width'] || $info[1] > $max_resolution['height']) {
            return '画像の解像度は' . $max_resolution['width'] . 'x' . $max_resolution['height'] . '以下にしてください';
        }

        // E) PHPコードの混入防止
        $file_content = file_get_contents($logo['tmp_name']);
        if (preg_match('/<\?php/i', $file_content) || preg_match('/<\?/i', $file_content)) {
            return '不正なデータが含まれているため、アップロードできません';
        }

        // F) 実体のMIMEタイプが許可リストにあるか最終確認
        if (!array_key_exists($info['mime'], $allowed_types)) {
            return '画像はJPEGまたはPNG形式でアップロードしてください';
        }

        return true;
    }

    function secureRandomHex($bytes = 8)
    {
        if (function_exists('random_bytes')) {
            return bin2hex(random_bytes($bytes));
        }

        if (function_exists('openssl_random_pseudo_bytes')) {
            $strong = false;
            $bin = openssl_random_pseudo_bytes($bytes, $strong);
            if ($bin !== false) {
                return bin2hex($bin);
            }
        }

        // 最終フォールバック（PHP5.6向け）
        return sha1(uniqid(mt_rand(), true));
    }

}
