<?php
/*
 * design/template/recover/Upload.class.php
 * 
 * CopyRight(C) 2010 Shopformer Development Team. All Right Reserved
 * URL: http://sourceforge.jp/projects/shopformer/
 * 
 * 
 * Mail: m_nakashima@users.sourceforge.jp
 * Auther: Masanori Nakashima
 * Last Update: 2010-06-18
 */
require_once( dirname(dirname(dirname(dirname(__FILE__))))
.DIRECTORY_SEPARATOR.'system'
.DIRECTORY_SEPARATOR.'login'
.DIRECTORY_SEPARATOR.'ModuleBase.class.php');
require_once( dirname(dirname(dirname(dirname(__FILE__))))
.DIRECTORY_SEPARATOR.'util'
.DIRECTORY_SEPARATOR.'HttpRequest.class.php');
require_once( dirname(dirname(dirname(__FILE__)))
.DIRECTORY_SEPARATOR.'DaoTemplate.class.php');
/**
 * デザインテンプレートファイルをアップロードして妥当性検査をおこなうモジュール
 * 
 * multipart/form-data形式でPOSTアップロードされたファイルと情報に基づいてデザインテンプレートをアップロードされたファイルから復元・インストールします。
 * 
 * <b>POST入力値</b>
 * <ul>
 * <li><b>file_name</b> ※必須<br />サーバー上に保存するときのテンプレートファイル名を入力。</li>
 * <li><b>view_name</b> ※必須<br />管理パネル上で一覧に表示するテンプレート名を入力。</li>
 * <li><b>install_key_plain</b><br />テンプレートインストールにインストールキーが必要な場合にキーを入力</li>
 * <li><b>override_contents</b><br />サーバー上の同階層に同名の画像やＣＳＳファイルが存在した場合に上書きをするならtまたはtrueを入力</li>
 * <li><b>override_pages</b><br />サーバー上の同階層にに同名のページファイルが存在した場合に上書きをするならtまたはtrueを入力</li>
 * <li><b>template_file</b> ※必須<br />type=fileでデザインテンプレート.fmtファイルを指定。</li>
 * </ul>
 * 
 * <b>spider_HttpRequestにセットする属性キーと値</b>
 * <ul>
 * <li><b>design.template.recover.infoHash</b><br />入力値を格納した連想配列。それぞれ頭にvalidateを付けて妥当性検査結果を格納しています。 array('fileName'=>'','viewName'=>'','installKeyPlain'=>'','overrideContents'=>'','overridePages'=>'')</li>
 * <li><b>design.template.recover.warningMessages</b><br />テンプレートバージョンのズレ等の警告メッセージを配列で格納。</li>
 * </ul>
 * 
 * <b>セッションにセットする属性キーと値</b>
 * <ul>
 * <li><b>design.template.recover.infoHash</b><br />入力値を格納した連想配列 array('fileName'=>'','viewName'=>'','installKeyPlain'=>'','overrideContents'=>'','overridePages'=>'')</li>
 * <li><b>design.template.recover.confirmResult</b><br />POST入力に問題がなければ指定されたキーを格納して文字列「OK」を設定。</li>
 * </ul>
 */
class design_template_recover_Upload extends system_login_ModuleBase {
	function design_template_recover_Upload() {
	}
	function execute( & $request ) {
		// アップロード一時フォルダUri
		$uploadTmpDirUri	= '/desgin/templates/upload';
		// 実行前に古いアップロードファイルがあれば削除
		$uploadTmpDirPath	= system_DataFileWriter::getRealAbsolutePath( $request, $uploadTmpDirUri, DIR_NAME_TMP );
		if( is_dir($uploadTmpDirPath) ) {
			$dsnUpDh	= @opendir( $uploadTmpDirPath );
			if( $dsnUpDh ) {
				while (($fileName = readdir($dsnUpDh)) !== false) {
					if( preg_match('/^\\./',$fileName) == 0 ) {
						$targetUri	= $uploadTmpDirUri.'/'.$fileName;
						$targetPath	= $uploadTmpDirPath.DIRECTORY_SEPARATOR.$fileName;
						if( time() - filemtime($targetPath) > 60 * 60 ) {
							// 1時間以上前のファイルなら削除する
							system_DataFileWriter::delete( $request, $targetUri, DIR_NAME_TMP );
						}
					}
				}
				@closedir($dsnUpDh);
			}
		}
		// 入力値を取得して格納
		$recoverInfoHash	= array();
		$recoverInfoHash['fileName']		= strtolower($request->getParam('file_name','post'));
		$recoverInfoHash['viewName']		= strtolower($request->getParam('view_name','post'));
		$recoverInfoHash['overrideContents']= strtolower($request->getParam('override_contents','post'));
		$recoverInfoHash['overridePages']	= strtolower($request->getParam('override_pages','post'));
		$recoverInfoHash['installKeyPlain']	= strtolower($request->getParam('install_key_plain','post'));
		$recoverInfoHash['authId']			= $request->getParam('auth_id','post');
		$recoverInfoHash['authPassword']	= $request->getParam('auth_password','post');
		// 入力妥当性検査
		$recoverInfoHash['validateFileName']	= 'true';
		if( strlen(trim($recoverInfoHash['fileName'])) == 0 ) {
			$request->addError('テンプレートファイル名を指定してください');
			$recoverInfoHash['validateFileName']	= 'false';
		} else {
			if( preg_match('/\\.fmt$/',$recoverInfoHash['fileName']) == 0 ) {
				$recoverInfoHash['fileName']	.= '.fmt';
			}
			if( preg_match('/^[a-zA-Z][0-9a-zA-Z\\_]*\\.fmt$/',$recoverInfoHash['fileName']) == 0 ) {
				$request->addError('テンプレートファイル名は半角英数字とアンダーバーのみで入力してください。'.$recoverInfoHash['fileName']);
				$recoverInfoHash['validateFileName']	= 'false';
			}
		}
		$recoverInfoHash['validateViewName']	= 'true';
		if( strlen(trim($recoverInfoHash['viewName'])) == 0 ) {
			$request->addError('テンプレート表示名を指定してください');
			$recoverInfoHash['validateViewName']	= 'false';
		}
		// コンテンツファイル上書きの有無
		$recoverInfoHash['validateOverrideContents']	= 'true';
		if( preg_match('/^[tT](|[rR][uU][eE])$/', $recoverInfoHash['overrideContents']) > 0 ) {
			$recoverInfoHash['overrideContents']	= true;
		} else {
			$recoverInfoHash['overrideContents']	= false;
		}
		// ページファイル上書きの有無
		$recoverInfoHash['validateOverridePages']	= 'true';
		if( preg_match('/^[tT](|[rR][uU][eE])$/', $recoverInfoHash['overridePages']) > 0 ) {
			$recoverInfoHash['overridePages']	= true;
		} else {
			$recoverInfoHash['overridePages']	= false;
		}
		
		$recoverInfoHash['validateTemplateFile']	= 'true';
		$recoverInfoHash['validateInstallKeyPlain']	= 'true';
		$recoverInfoHash['validateAuthAccount']		= 'true';
		$warningMessages	= array();
		if( isset($_FILES['template_file'])
		&& is_array($_FILES['template_file']) && strlen($_FILES['template_file']['name']) > 0 ) {
			// ファイルアップロードがあるなら
			$upfile	= $_FILES['template_file'];
			$fileName	= basename($upfile['name']);
			if( preg_match('/^[0-9a-zA-Z\\_\\.]+\\.[0-9a-zA-Z]+$/',$fileName) == 0 ) {
				$request->addError('ファイル名に利用できる文字は英数字とアンダーバー、ドットのみです。');
				$recoverInfoHash['validateTemplateFile']	= 'false';
			} else if( preg_match('/\\.([fF][mM][tT])$/',$fileName) == 0 ) {
				$request->addError('fmtファイル以外アップロードできません。');
				$recoverInfoHash['validateTemplateFile']	= 'false';
			} else if ( defined('UPLOAD_ERR_INI_SIZE') && UPLOAD_ERR_INI_SIZE == $upfile['error'] ) {
				$request->addError('ファイルサイズがサーバーの設定値を超えています。');
				$recoverInfoHash['validateTemplateFile']	= 'false';
			} else if ( defined('UPLOAD_ERR_FORM_SIZE') && UPLOAD_ERR_FORM_SIZE == $upfile['error'] ) {
				$request->addError('ファイルサイズが設定値を超えています。');
				$recoverInfoHash['validateTemplateFile']	= 'false';
			} else if ( defined('UPLOAD_ERR_PARTIAL') && UPLOAD_ERR_PARTIAL == $upfile['error'] ) {
				$request->addError('ファイルが壊れているかアップロード中に壊れました。');
				$recoverInfoHash['validateTemplateFile']	= 'false';
			} else if ( defined('UPLOAD_ERR_NO_FILE') && UPLOAD_ERR_NO_FILE == $upfile['error'] ) {
				$request->addError('ファイルがアップロードされていません。');
				$recoverInfoHash['validateTemplateFile']	= 'false';
			} else if ( defined('UPLOAD_ERR_NO_TMP_DIR') && UPLOAD_ERR_NO_TMP_DIR == $upfile['error'] ) {
				$request->addError('ファイルをサーバーの一時ファイルに保存できませんでした。');
				$recoverInfoHash['validateTemplateFile']	= 'false';
			} else if ( defined('UPLOAD_ERR_OK') && UPLOAD_ERR_OK != $upfile['error'] ) {
				$request->addError('ファイルアップロードに失敗しました。');
				$recoverInfoHash['validateTemplateFile']	= 'false';
			} else {
				// アップロードに問題がないならデザインテンプレートファイル内容の妥当性検査
				$fp	= @fopen($upfile['tmp_name'],'r');
				if( $fp ) {
					// 1行目を取得
					$buffer	= trim(fgets($fp));
					if( 'FORMER-TEMPLATE-VERSION' != $buffer ) {
						$request->addError('アップロードされたファイルはformerデザインテンプレートファイルではありません。');
						$recoverInfoHash['validateTemplateFile']	= 'false';
					} else if(feof($fp)) {
						$request->addError('アップロードされたファイルはformerデザインテンプレートファイルではありません。');
						$recoverInfoHash['validateTemplateFile']	= 'false';
					} else if( DESIGN_VERSION != $dversion = trim(fgets($fp)) ) {
						array_push($warningMessages,'このテンプレートを作成したデザイン管理パッケージのバージョン'
						.$dversion.'は現在インストールのバージョンと異なる為正常に動作しない場合があります。');
						$recoverInfoHash['validateTemplateFile']	= 'false';
					}
					// 'requires.txt'がでてくるまで取得して配列に格納
					$itemArray	= array();
					while (!feof($fp)) {
						$buffer	= trim(fgets($fp));
						if('requires.txt'==$buffer) {
							break;
						} else if(strlen($buffer)>0){
							array_push( $itemArray, $buffer );
						}
					}
					@fclose($fp);
					// 奇数番目をキー偶数番目を値にして連想配列に格納
					$templateHeaders	= array();
					for( $num=0; $num+1<count($itemArray); $num=$num+2 ) {
						$templateHeaders[$itemArray[$num]]	= $itemArray[$num+1];
					}
					// 作成したリリース名の確認
					if( !isset($templateHeaders['FORMER-RELEASE-NAME']) ) {
						array_push($warningMessages,'このテンプレートを作成したformerのプロダクトを確認できません。');
					} else if($templateHeaders['FORMER-RELEASE-NAME'] != RELEASE_NAME ) {
						array_push($warningMessages,'このテンプレートは'.$templateHeaders['FORMER-RELEASE-NAME']
						.'で作成されたテンプレートです。'.RELEASE_NAME.'では正常に動作しない場合があります。');
					}
					// 作成したリリースバージョンの確認
					if( !isset($templateHeaders['FORMER-RELEASE-NAME']) ) {
						array_push($warningMessages,'このテンプレートを作成したformerのプロダクトバージョンを確認できません。');
					} else if($templateHeaders['FORMER-RELEASE-VERSION'] != RELEASE_VERSION ) {
						array_push($warningMessages,'このテンプレートは'.$templateHeaders['FORMER-RELEASE-NAME']
						.' ver'.$templateHeaders['FORMER-RELEASE-VERSION']
						.'で作成されたテンプレートです。ご利用の'.RELEASE_NAME.' ver'.RELEASE_VERSION.'では正常に動作しない場合があります。');
					}
					// インストールキーのチェック
					if( isset($templateHeaders['lisence']) && strlen($templateHeaders['lisence']) > 0 ){
						if( strlen($recoverInfoHash['installKeyPlain']) == 0 ) {
							$request->addError('このテンプレートにはインストールパスワードが必要です。');
							$recoverInfoHash['validateInstallKeyPlain']	= 'false';
						} else if( $templateHeaders['lisence'] != crypt($recoverInfoHash['installKeyPlain'], $templateHeaders['lisence']) ) {
							$request->addError('インストールパスワードの入力が正しくありません。');
							$recoverInfoHash['validateInstallKeyPlain']	= 'false';
						}
					}
					// 認証URLのチェック
					if( strlen( $templateHeaders['FORMER-AUTH-URL'] ) > 0
					&& preg_match('/^http/',$templateHeaders['FORMER-AUTH-URL']) > 0 ) {
						if( strlen($recoverInfoHash['authId']) == 0 || strlen($recoverInfoHash['authPassword']) == 0 ) {
							$request->addError('このテンプレートには認証IDと認証パスワードが必要です。');
							$recoverInfoHash['validateAuthAccount']	= 'false';
						} else {
							// 認証サーバーに問い合わせ
							$headerParams	= array(
								'User-Agent' => RELEASE_NAME.' v'.RELEASE_VERSION.'',
							);
							$httpRequest	= new util_HttpRequest(trim($templateHeaders['FORMER-AUTH-URL']),'post',$headerParams);
							$httpRequest->addPostData('release_name', RELEASE_NAME);
							$httpRequest->addPostData('release_version', RELEASE_VERSION);
							$httpRequest->addPostData('application_url', SPIDER_URL_BASE);
							$httpRequest->addPostData('auth_id', $recoverInfoHash['authId']);
							$httpRequest->addPostData('auth_password', $recoverInfoHash['authPassword']);
							if( $httpRequest->send(null,60) ) {
								$responseCode	= $httpRequest->statusCode;
								$responseBody	= trim($httpRequest->responseBody);
								if( 200 != $responseCode ) {
									$request->addError('認証サーバーが正常な応答を返しませんでした。ステータス'.$responseCode
									.'お手数ですがしばらくたってからやりなおすかデザインテンプレート配布者にお問い合わせください。');
								} else {
									// 本文の解析
									$xmlNodeObject	= simplexml_load_string($responseBody);
									if( false === $xmlNodeObject ) {
										$request->addError('認証サーバーが正常な応答を返しませんでした。'
										.'お手数ですがしばらくたってからやりなおすかデザインテンプレート配布者にお問い合わせください。');
									} else {
										// デザインバージョンとの比較確認
										$attributes = $xmlNodeObject->attributes();
										$verPos		= strpos(DESIGN_VERSION,$attributes['version']);
										if( $verPos === false || $verPos !== 0 ) {
											$request->addError('この認証サーバーの応答は現在のデザイン管理パッケージバージョン'
											.DESIGN_VERSION.'では確認できません。');
										} else if( preg_match('/^[oO][kK]$/',$xmlNodeObject->result) == 0 ){
											$request->addError('認証でエラーが発生しました。');
											foreach($xmlNodeObject->messages as $key => $val ) {
												$request->addError($val);
											}
										} else {
											// 認証OKの場合
										}
									}
								}
							} else {
								$request->addError('認証サーバーが時間内に応答を返しませんでした。'
								.'お手数ですがしばらくたってからやりなおすかデザインテンプレート配布者にお問い合わせください。');
							}
						}
					}
					// アップロード実行
					if( !$request->isError() ){
						// エラーが発生していないならファイルアップロードを実行
						$tmpUri	= $uploadTmpDirUri.'/'.$fileName;
						system_DataFileWriter::import( $request, $tmpUri, $upfile['tmp_name'], DIR_NAME_TMP );
						if( !$request->isError() ){
							$recoverInfoHash['tempUri']	= $tmpUri;
						}
					}
				} else {
					$request->addError('アップロードファイルの内容を確認することができませんでした。');
					$recoverInfoHash['validateTemplateFile']	= 'false';
				}
			}
		} else {
			$request->addError('ファイルをアップロードしてください');
			$recoverInfoHash['validateTemplateFile']	= 'false';
		}
		if( !$request->isError() ){
			$confirmResult	= 'OK';
			$request->setSession('design.template.recover.confirmResult',$confirmResult,SPIDER_SESSION_SCOPE_GLOBAL);
			$request->setSession('design.template.recover.infoHash',$recoverInfoHash,SPIDER_SESSION_SCOPE_GLOBAL);
		}
		$request->setAttribute('design.template.recover.infoHash',$recoverInfoHash );
		$request->setAttribute('design.template.recover.warningMessages',$warningMessages );
	}
}
?>