<?php
// PukPukiPlus.
// $Id: attach.inc.php,v 1.92.51 2014/01/25 8:38:00 Logue Exp $
// Copyright (C)
//   2010-2014 PukiWiki Advance Developers Team <http://pukiwiki.logue.be/>
//   2005-2009 PukiWiki Plus! Team
//   2003-2007,2009,2011 PukiWiki Developers Team
//   2002-2003 PANDA <panda@arino.jp> http://home.arino.jp/
//   2002      Y.MASUI <masui@hisec.co.jp> http://masui.net/pukiwiki/
//   2001-2002 Originally written by yu-ji
// License: GPL v2 or (at your option) any later version
//

use PukiWiki\Attach;
use PukiWiki\Auth\Auth;
use PukiWiki\Factory;
use PukiWiki\File\AttachFile;
use PukiWiki\File\FileFactory;
use PukiWiki\Listing;
use PukiWiki\Renderer\Header;
use PukiWiki\Renderer\PluginRenderer;
use PukiWiki\Router;
use PukiWiki\Spam\Spam;
use PukiWiki\Utility;
use Zend\Json\Json;

// NOTE (PHP > 4.2.3):
//    This feature is disabled at newer version of PHP.
//    Set this at php.ini if you want.
// Max file size for upload on PHP (PHP default: 2MB)


defined('PLUGIN_ATTACH_ILLEGAL_CHARS_PATTERN')	or define('PLUGIN_ATTACH_ILLEGAL_CHARS_PATTERN', '/[%|=|&|?|#|\r|\n|\0|\@|\t|;|\$|+|\\|\[|\]|\||^|{|}]/');		// default: 4MB

defined('PLUGIN_ATTACH_UPLOAD_MAX_FILESIZE')	or define('PLUGIN_ATTACH_UPLOAD_MAX_FILESIZE', '4M');		// default: 4MB
ini_set('upload_max_filesize', PLUGIN_ATTACH_UPLOAD_MAX_FILESIZE);

// Max file size for upload on script of PukiWikiX_FILESIZE
defined('PLUGIN_ATTACH_MAX_FILESIZE')		or define('PLUGIN_ATTACH_MAX_FILESIZE', (2048 * 1024));		// default: 1MB

// 管理者だけが添付ファイルをアップロードできるようにする
defined('PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY')	or define('PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY', FALSE);		// FALSE or TRUE

// 管理者だけが添付ファイルを削除できるようにする
defined('PLUGIN_ATTACH_DELETE_ADMIN_ONLY')	or define('PLUGIN_ATTACH_DELETE_ADMIN_ONLY', FALSE);		// FALSE or TRUE

// 管理者が添付ファイルを削除するときは、バックアップを作らない
// PLUGIN_ATTACH_DELETE_ADMIN_ONLY=TRUEのとき有効
defined('PLUGIN_ATTACH_DELETE_ADMIN_NOBACKUP')	or define('PLUGIN_ATTACH_DELETE_ADMIN_NOBACKUP', FALSE);	// FALSE or TRUE

// アップロード/削除時にパスワードを要求する(ADMIN_ONLYが優先)
defined('PLUGIN_ATTACH_PASSWORD_REQUIRE')	or define('PLUGIN_ATTACH_PASSWORD_REQUIRE', FALSE);		// FALSE or TRUE

// 添付ファイル名を変更できるようにする
defined('PLUGIN_ATTACH_RENAME_ENABLE')		or define('PLUGIN_ATTACH_RENAME_ENABLE', TRUE);			// FALSE or TRUE

// ファイルのアクセス権
defined('PLUGIN_ATTACH_FILE_MODE')		or define('PLUGIN_ATTACH_FILE_MODE', 0644);
// define('PLUGIN_ATTACH_FILE_MODE', 0604);			// for XREA.COM

// mime-typeを記述したページ
define('PLUGIN_ATTACH_CONFIG_PAGE_MIME', 'plugin/attach/mime-type');

defined('PLUGIN_ATTACH_UNKNOWN_COMPRESS')	or define('PLUGIN_ATTACH_UNKNOWN_COMPRESS', 0);			// 1(compress) or 0(raw)
defined('PLUGIN_ATTACH_COMPRESS_TYPE')		or define('PLUGIN_ATTACH_COMPRESS_TYPE', 'TGZ');		// TGZ, GZ, BZ2 or ZIP

// 添付ファイルキャッシュを使う（ページの表示やページごとの添付ファイル一覧表示は早くなりますが、全ページではむしろ重くなります）
defined('PLUGIN_ATTACH_USE_CACHE')    or define('PLUGIN_ATTACH_USE_CACHE', false);
// 添付ファイルのキャッシュの接頭辞
defined('PLUGIN_ATTACH_CACHE_PREFIX') or define('PLUGIN_ATTACH_CACHE_PREFIX', 'attach-');

// 添付ファイルフォームの名前
defined('PLUGIN_ATTACH_FILE_FIELD_NAME') or define('PLUGIN_ATTACH_FILE_FIELD_NAME', 'attach_file');

function plugin_attach_init()
{
	global $_string;
	$messages = array(
		'_attach_messages' => array(
			'msg_uploaded'	=> T_('Uploaded the file to $1'),
			'msg_deleted'	=> T_('Deleted the file in $1'),
			'msg_freezed'	=> T_('The file has been frozen.'),
			'msg_unfreezed'	=> T_('The file has been unfrozen'),
			'msg_upload'	=> T_('Upload to $1'),
			'msg_info'		=> T_('File information'),
			'msg_confirm'	=> T_('Delete %s.'),
			'msg_list'		=> T_('List of attached file(s)'),
			'msg_listpage'	=> T_('List of attached file(s) in $1'),
			'msg_listall'	=> T_('Attached file list of all pages'),
			'msg_file'		=> T_('Attach file'),
			'msg_maxsize'	=> T_('Maximum file size is %s.'),
			'msg_multiple'	=> T_('File may be specified any number of times.'),
			'msg_count'		=> T_('%s download'),
			'msg_password'	=> T_('password'),
			'msg_adminpass'	=> T_('Administrator password'),
			'msg_delete'	=> T_('Delete file.'),
			'msg_freeze'	=> T_('Freeze file.'),
			'msg_unfreeze'	=> T_('Unfreeze file.'),
			'msg_renamed'	=> T_('The file has been renamed'),
			'msg_isfreeze'	=> T_('File is frozen.'),
			'msg_rename'	=> T_('Rename'),
			'msg_newname'	=> T_('New file name'),
			'msg_require'	=> T_('(require administrator password)'),
			'msg_filesize'	=> T_('size'),
			'msg_type'		=> T_('type'),
			'msg_date'		=> T_('date'),
			'msg_dlcount'	=> T_('access count'),
			'msg_md5hash'	=> T_('MD5 hash'),
			'msg_page'		=> T_('Page'),
			'msg_filename'	=> T_('Stored filename'),
			'msg_thispage'	=> T_('This page'),
			'err_noparm'	=> T_('Cannot upload/delete file in $1'),
			'err_exceed'	=> T_('File size too large to $1'),
			'err_exists'	=> T_('File already exists in $1'),
			'err_notfound'	=> T_('Could not find the file in $1'),
			'err_noexist'	=> T_('File does not exist.'),
			'err_delete'	=> T_('Cannot delete file in  $1'),
			'err_rename'	=> T_('Cannot rename this file'),
			'err_password'	=> $_string['invalidpass'],
			'err_upload'	=> T_('It failed in uploading.'),
			'err_adminpass'	=> T_('Wrong administrator password'),
			'err_ini_size'	=> T_('The value of the upload_max_filesize directive of php.ini is exceeded.'),
			'err_form_size'	=> T_('MAX_FILE_SIZE specified by the HTML form is exceeded.'),
			'err_partial'	=> T_('Only part is uploaded.'),
			'msg_uploaded'  => T_('The file was updaded.'),
			'err_no_file'	=> T_('The file was not uploaded.'),
			'err_no_tmp_dir'=> T_('There is no temporary directory.'),
			'err_cant_write'=> T_('It failed in writing in the disk.'),
			'err_extension'	=> T_('The uploading of the file was stopped by the enhancement module.'),
			'btn_upload'	=> T_('Upload'),
			'btn_info'		=> T_('Information'),
			'btn_submit'	=> T_('Submit'),
			'err_too_long'	=> T_('Query string (page name and/or file name) too long'),
			'err_nopage'	=> T_('No such page'),
			'err_tmp_fail'	=> T_('It failed in the generation of a temporary file.'),
			'err_load_file'	=> T_('The uploaded file cannot be read.'),			// アップロードされたファイルが読めません。
			'err_write_tgz'	=> T_('The compression file cannot be written.'),	// 圧縮ファイルが書けません。
			'err_filename'	=> T_('File name is too long. Please rename more short file name before upoload.')	// ファイル名が長すぎます。アップロードする前に短いファイル名にしてください。
		),
	);
	set_plugin_messages($messages);
}

//-------- convert
function plugin_attach_convert()
{
	global $vars;

	$page = isset($vars['page']) ? $vars['page'] : '';

	$nolist = $noform = FALSE;
	if (func_num_args() > 0) {
		foreach (func_get_args() as $arg) {
			$arg = strtolower($arg);
			$nolist |= ($arg == 'nolist');
			$noform |= ($arg == 'noform');
		}
	}
	
	if (empty($page)) return '<div class="alert alert-warning">#attach(): No page defined.</div>';

	$ret = '';
	if (! $nolist) {
//		$obj  = new Attach($page);
//		$ret .= $obj->toString($page, TRUE);
	}

	if (! $noform) {
		$ret .= attach_form($page);
	}

	return $ret;
}

//-------- action
function plugin_attach_action()
{
	global $vars, $_attach_messages, $_string;

	// Backward compatible
	if (isset($vars['openfile'])) {
		$vars['file'] = $vars['openfile'];
		$vars['pcmd'] = 'open';
	}
	if (isset($vars['delfile'])) {
		$vars['file'] = $vars['delfile'];
		$vars['pcmd'] = 'delete';
	}

	$pcmd  = isset($vars['pcmd'])  ? $vars['pcmd']  : NULL;
	$refer = isset($vars['refer']) ? $vars['refer'] : NULL;
	$pass  = isset($vars['pass'])  ? $vars['pass']  : NULL;
	$page  = isset($vars['page'])  ? $vars['page']  : $refer;
	
	if (!empty($page)){
		$wiki = Factory::Wiki($page);

		if ($wiki->isValied()) {
			// メソッドによってパーミッションを分ける
			if(in_array($pcmd, array('info', 'open', 'list'))) {
				// 読み込み許可
				$wiki->checkReadable();
			} else {
				// 書き込み許可があるか
				$wiki->checkEditable();
			}
		}
	}
	

	if(in_array($pcmd, array('delete', 'freeze', 'unfreeze'))) {
		// if (PKWK_READONLY) die_message('PKWK_READONLY prohibits editing');
		if (Auth::check_role('readonly')) Utility::dieMessage( $_string['error_prohibit'] );
	}

	switch ($pcmd) {
		case 'info'     : return attach_info();
		case 'delete'   : return attach_delete();
		case 'open'     : return attach_open();
		case 'list'     : return attach_list($page);
		case 'freeze'   : return attach_freeze(TRUE);
		case 'unfreeze' : return attach_freeze(FALSE);
		case 'rename'   : return attach_rename();
		default:
		case 'upload'   : return attach_showform();
		case 'form'     : return array('msg'  =>str_replace('$1', $refer, $_attach_messages['msg_upload']), 'body'=>attach_form($refer));
		case 'post'     : return attach_upload($page, $pass);
		case 'progress' : return PluginRenderer::getUploadProgress();
	}
	return (empty($page) || ! $wiki->isValied()) ? attach_list() : attach_showform();
}

//-------- 実体
// ファイルアップロード
// $pass = NULL : パスワードが指定されていない
// $pass = TRUE : アップロード許可
function attach_upload($page, $pass = NULL)
{
	global $_attach_messages, $_string;
	
	// if (PKWK_READONLY) die_message('PKWK_READONLY prohibits editing');
	if (Auth::check_role('readonly')) Utility::dieMessage($_string['error_prohibit']);

	$wiki = Factory::Wiki($page);
	$msgs = array();

	if (empty($page)) Utility::dieMessage('#attach: page name is missing.');
	
	if (! $wiki->isValied()) { Utility::dieMessage($_attach_messages['err_nopage']); }
	
	if ($pass !== TRUE) {
		if (! $wiki->isEditable()){
			return array(
				'result'=>FALSE,
				'msg'=>$_attach_messages['err_noparm']);
		}
	
		if (PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY && Auth::check_role('role_contents_admin') &&  ($pass === NULL || ! pkwk_login($pass))) {
			return array(
				'result'=>FALSE,
				'msg'=>$_attach_messages['err_adminpass']);
		}
	}

	foreach ($_FILES[PLUGIN_ATTACH_FILE_FIELD_NAME]['name'] as $key => $value) {
		$file = $_FILES[PLUGIN_ATTACH_FILE_FIELD_NAME]['name'][$key];

		// 無効な文字が含まれている
		if (preg_match(PLUGIN_ATTACH_ILLEGAL_CHARS_PATTERN, $file)){
			$msgs[$file] = $_string['illegal_chars'];
			continue;
		}

		// 添付ファイルがアップされた時のクエリの長さを取得
		$query = Router::get_cmd_uri('attach', '', '', array(
			'refer'=>$page,
			'pcmd'=>'info',
			'file'=>$file
		));
		// ファイル名が長すぎる
		if (PKWK_QUERY_STRING_MAX && strlen($query) > PKWK_QUERY_STRING_MAX) {
			$msgs[$file] = $_attach_messages['err_too_long'];
			continue;
		}

		// アップロードに失敗
		if ($_FILES[PLUGIN_ATTACH_FILE_FIELD_NAME]['error'][$key] !== UPLOAD_ERR_OK) {
			$msgs[$file] = attach_set_error_message($_FILES[PLUGIN_ATTACH_FILE_FIELD_NAME]['error'][$key]);
			continue;
		}

		// 一時ファイルの生成に失敗
		if (empty($_FILES[PLUGIN_ATTACH_FILE_FIELD_NAME]['tmp_name'][$key]) || ! is_uploaded_file($_FILES[PLUGIN_ATTACH_FILE_FIELD_NAME]['tmp_name'][$key])) {
			$msgs[$file] = $_attach_messages['err_upload'];
			continue;
		}

		// サイズが大きすぎる
		if ($_FILES[PLUGIN_ATTACH_FILE_FIELD_NAME]['size'][$key] > PLUGIN_ATTACH_MAX_FILESIZE) {
			$msgs[$file] = $_attach_messages['err_exceed'];
			continue;
		}

		$ret = attach_doupload($file, $page, $pass, $_FILES[PLUGIN_ATTACH_FILE_FIELD_NAME]['tmp_name'][$key]);
		$msgs[$file] = $ret['msg'];
	}
	$body[] = '<ul>';
	
	foreach ($msgs as $file=>$_result){
		$body[] = '<li>'.$file.': '.$_result.'</li>';
	}
	$body[] = '</ul>';
	
	return array('msg'=> sprintf($_attach_messages['msg_uploaded'], $page), 'body'=>'<ul>'.join("\n", $body).'</ul>', 'result'=>true);
}

function attach_set_error_message($err_no)
{
	global $_attach_messages;

	switch($err_no) {
		case UPLOAD_ERR_INI_SIZE:
			return $_attach_messages['err_ini_size'];
		case UPLOAD_ERR_FORM_SIZE:
			return $_attach_messages['err_form_size'];
		case UPLOAD_ERR_PARTIAL:
			return $_attach_messages['err_partial'];
		case UPLOAD_ERR_NO_FILE:
			return $_attach_messages['err_no_file'];
		case UPLOAD_ERR_NO_TMP_DIR:
			return $_attach_messages['err_no_tmp_dir'];
		case UPLOAD_ERR_CANT_WRITE:
			return $_attach_messages['err_cant_write'];
		case UPLOAD_ERR_EXTENSION:
			return $_attach_messages['err_extension'];
	}
	return $_attach_messages['err_upload'];
}

function attach_gettext($path, $lock=FALSE)
{
	$fp = @fopen($path, 'r');
	if ($fp == FALSE) return FALSE;

	if ($lock) {
		@flock($fp, LOCK_SH);
	}

	// Returns a value
	$result = fread($fp, filesize($path));

	if ($lock) {
		@flock($fp, LOCK_UN);
		@fclose($fp);
	}
	return $result;
}

function attach_doupload($file, $page, $pass=NULL, $temp)
{
	global $_attach_messages, $_string;
	global $notify, $notify_subject, $notify_exclude, $spam;

	$filename = Utility::encode($page).'_'.Utility::encode($file);
	$type = Utility::getMimeInfo($temp);
	$must_compress = (PLUGIN_ATTACH_UNKNOWN_COMPRESS !== 0) ? attach_is_compress($type,PLUGIN_ATTACH_UNKNOWN_COMPRESS) : false;	// 不明なファイルを圧縮するか？
	// ファイル名の長さをチェック
	$filename_length = strlen($filename);
	if ( $filename_length  >= 255 || ($must_compress && $filename_length >= 251 )){
		return array(
			'result'=>FALSE,
			'msg'=>$_attach_messages['err_filename']
		);
	}

	// スパムチェック
	if ($spam !== 0) {
		// ファイルの内容でスパムチェック
		// if attach spam, filtering attach file.
		$vars['uploadname'] = $file['name'];
		$vars['uploadtext'] = attach_gettext($file['tmp_name']);
		if ($vars['uploadtext'] === '' || $vars['uploadtext'] === FALSE) return FALSE;

		if (isset($spam['method']['attach'])) {
			$_method = & $spam['method']['attach'];
		} else if (isset($spam['method']['_default'])) {
			$_method = & $spam['method']['_default'];
		} else {
			$_method = array();
		}
		$exitmode = isset($spam['exitmode']) ? $spam['exitmode'] : '';
		Spam::pkwk_spamfilter('File Attach', $page, $vars, $_method, $exitmode);
	}

	if ($must_compress) {
		// 添付ファイルを圧縮する

		switch (PLUGIN_ATTACH_COMPRESS_TYPE){
			case 'GZ' :
				if (!extension_loaded('zlib')) Utility::dieMessage('#attach: zlib extention has not loaded.');
				$obj = new AttachFile($page, $file . '.gz');
				if ($obj->exist)
					return array('result'=>FALSE,
						'msg'=>$_attach_messages['err_exists']);

				$tp = fopen($file['tmp_name'],'rb') or
					die_message($_attach_messages['err_load_file']);
				$zp = gzopen($obj->filename, 'wb') or
					die_message($_attach_messages['err_write_tgz']);

				while (!feof($tp)) { gzwrite($zp,fread($tp, 8192)); }
				gzclose($zp);
				fclose($tp);
				chmod($obj->filename, PLUGIN_ATTACH_FILE_MODE);
				break;
			case 'ZIP' :
				if (!class_exists('ZipArchive')) Utility::dieMessage('#attach: ZipArchive class has not defined.');
				$obj = new AttachFile($page, $file . '.zip');
				if ($obj->exist)
					return array('result'=>FALSE,
						'msg'=>$_attach_messages['err_exists']);
				$zip = new ZipArchive();

				$zip->addFile($temp,$file);
				// if ($zip->status !== ZIPARCHIVE::ER_OK)
				if ($zip->status !== 0)
					die_message( $_attach_messages['err_upload'].'('.$zip->status.').' );
				$zip->close();
				chmod($obj->filename, PLUGIN_ATTACH_FILE_MODE);
				break;
			case 'BZ2' :
				if (!extension_loaded('bz2')) Utility::dieMessage('#attach: bz2 extention has not loaded.');
				$obj = new AttachFile($page, $file . '.bz2');
				if ($obj->exist)
					return array('result'=>FALSE,
						'msg'=>$_attach_messages['err_exists']);

				$tp = fopen($file['tmp_name'],'rb') or
					die_message($_attach_messages['err_load_file']);
				$zp = bzopen($obj->filename, 'wb') or
					die_message($_attach_messages['err_write_tgz']);

				while (!feof($tp)) { bzwrite($zp,fread($tp, 8192)); }
				bzclose($zp);
				fclose($tp);
				chmod($obj->filename, PLUGIN_ATTACH_FILE_MODE);
				break;
			default:
				//miko
				$obj = new AttachFile($page, $file);
				if ($obj->exist)
					return array('result'=>FALSE,
						'msg'=>$_attach_messages['err_exists']);

				if (move_uploaded_file($temp, $obj->filename))
					chmod($obj->filename, PLUGIN_ATTACH_FILE_MODE);
				break;
		}
	}else{
		// 通常添付
		$obj = new AttachFile($page, $file);
		if (isset($obj->exist) )
			return array('result'=>FALSE,
				'msg'=>$_attach_messages['err_exists']);

		if (move_uploaded_file($temp, $obj->filename))
			chmod($obj->filename, PLUGIN_ATTACH_FILE_MODE);
	}
	
	if (file_exists($temp)){
		unlink($temp);
	}

	// ページのタイムスタンプを更新
	Factory::Wiki($page)->touch();

	$obj->status['pass'] = ($pass !== TRUE && $pass !== NULL) ? md5($pass) : '';

	if ($notify) {
		$notify_exec = TRUE;
		foreach ($notify_exclude as $exclude) {
			$exclude = preg_quote($exclude);
			if (substr($exclude, -1) == '.')
				$exclude = $exclude . '*';
			if (preg_match('/^' . $exclude . '/', get_remoteip())) {
				$notify_exec = FALSE;
				break;
			}
		}
		$footer['ACTION']   = 'File attached';
		$footer['FILENAME'] = $file['name'];
		$footer['FILESIZE'] = $file['size'];
		$footer['PAGE']     = $page;
		$footer['URI'] = get_cmd_uri('attach','',array('refer'=>$page,'pcmd'=>'info','file'=>$file['name']));
		$footer['USER_AGENT']  = TRUE;
		$footer['REMOTE_ADDR'] = TRUE;

		pkwk_mail_notify($notify_subject, "\n", $footer);
	}

	return array(
		'result'=>TRUE,
		'msg'=>$_attach_messages['msg_uploaded']
	);
}

// ファイルタイプによる圧縮添付の判定
function attach_is_compress($type,$compress=1)
{
	if (empty($type)) return $compress;
	list($discrete,$composite_tmp) = explode('/', strtolower($type));
	if (strstr($type,';') === false) {
		$composite = $composite_tmp;
		$parameter = '';
	} else {
		list($composite,$parameter) = explode(';', $composite_tmp);
		$parameter = trim($parameter);
	}
	unset($composite_tmp);

	// type
	static $composite_type = array(
		'application' => array(
			'msword'                => 0, // doc
			'vnd.ms-excel'          => 0, // xls
			'vnd.ms-powerpoint'     => 0, // ppt
			'vnd.visio'             => 0,
			'octet-stream'          => 0, // bin dms lha lzh exe class so dll img iso
			'x-bcpio'               => 0, // bcpio
			'x-bittorrent'          => 0, // torrent
			'x-bzip2'               => 0, // bz2
			'x-compress'            => 0,
			'x-cpio'                => 0, // cpio
			'x-dvi'                 => 0, // dvi
			'x-gtar'                => 0, // gtar
			'x-gzip'                => 0, // gz tgz
			'x-rpm'                 => 0, // rpm
			'x-shockwave-flash'     => 0, // swf
			'zip'                   => 0, // zip
			'x-java-archive'        => 0, // jar
			'x-javascript'          => 1, // js
			'ogg'                   => 0, // ogg
			'pdf'                   => 0, // pdf
		),
	);
	if (isset($composite_type[$discrete][$composite])) {
		return $composite_type[$discrete][$composite];
	}

	// discrete-type
	static $discrete_type = array(
		'text'                          => 1,
		'image'                         => 0,
		'audio'                         => 0,
		'video'                         => 0,
	);
	if (isset($discrete_type[$discrete])) {
		return $discrete_type[$discrete];
	}

	return $compress;
}

// 詳細フォームを表示
function attach_info($err = '')
{
	global $vars, $_attach_messages;

	$age = isset($vars['age']) ? $vars['age'] : 0;

	$obj = new Attach($vars['refer'], $vars['file'], $age);
	return $obj->has($age) ?
		$obj->info($err) :
		array('msg'=>$_attach_messages['err_notfound']);
}

// 削除
function attach_delete()
{
	global $vars, $_attach_messages;

	foreach (array('refer', 'file', 'age', 'pass') as $var)
		${$var} = isset($vars[$var]) ? $vars[$var] : '';

	if (is_freeze($refer) || ! is_editable($refer))
		return array('msg'=>$_attach_messages['err_noparm']);

	$obj = new AttachFile($refer, $file, $age);
	if (! $obj->has())
		return array('msg'=>$_attach_messages['err_notfound']);

	if (PLUGIN_ATTACH_USE_CACHE){
		global $cache;
		$cache['wiki']->removeItem(PLUGIN_ATTACH_CACHE_PREFIX.md5($refer));
	}

	return $obj->delete($pass);
}

// 凍結
function attach_freeze($freeze)
{
	global $vars, $_attach_messages;

	foreach (array('refer', 'file', 'age', 'pass') as $var) {
		${$var} = isset($vars[$var]) ? $vars[$var] : '';
	}

	if (is_freeze($refer) || ! is_editable($refer)) {
		return array('msg'=>$_attach_messages['err_noparm']);
	} else {
		$obj = new Attach($refer, $file, $age);
		return $obj->has() ?
			$obj->freeze($freeze, $pass) :
			array('msg'=>$_attach_messages['err_notfound']);
	}
}

// リネーム
function attach_rename()
{
	global $vars, $_attach_messages;

	foreach (array('refer', 'file', 'age', 'pass', 'newname') as $var) {
		${$var} = isset($vars[$var]) ? $vars[$var] : '';
	}

	if (is_freeze($refer) || ! is_editable($refer)) {
		return array('msg'=>$_attach_messages['err_noparm']);
	}
	$obj = new Attach($refer, $file, $age);
	if (! $obj->has())
		return array('msg'=>$_attach_messages['err_notfound']);

	cache_timestamp_touch('attach');
	return $obj->rename($pass, $newname);
}

// ダウンロード
function attach_open()
{
	global $vars, $_attach_messages;

	foreach (array('refer', 'file', 'age') as $var) {
		${$var} = isset($vars[$var]) ? $vars[$var] : '';
	}
	$age = isset($vars['age']) ? $vars['age'] : 0;
	$obj = new Attach($vars['refer'], $vars['file'], $age);

	return $obj->has() ?
		$obj->render() :
		array('msg'=>$_attach_messages['err_notfound']);
}

// 一覧取得
function attach_list()
{
	global $vars, $_attach_messages, $_string;

	if (Auth::check_role('safemode')) Utility::dieMessage( $_string['prohibit'] );

	$page = isset($vars['page']) ? $vars['page'] : null;
	$refer = isset($vars['refer']) ? $vars['refer'] : $page;
	$type = isset($vars['type']) ? $vars['type'] : null;
	if (! empty($refer)) {
		$wiki = Factory::Wiki($refer);
		$wiki->isReadable();
		$attaches = $wiki->attach();
		
		if ($type === 'json'){
			$headers = Header::getHeaders('application/json');
			Header::writeResponse($headers, 200, Json::encode($attaches));
			exit;
		}
		// ページ別添付ファイル一覧
		$msg = str_replace('$1', Utility::htmlsc($refer), $_attach_messages['msg_listpage']);
		if (count($attaches) === 0){
			return array('msg'=>$msg, 'body'=>'No files uploaded.');
		}
		$ret[] = '<table class="table table-borderd plugin-attach-list" data-pagenate="true" data-sortable="true"><thead>';
		$ret[] = '<thead>';
		$ret[] = '<tr>';
		$ret[] = '<th>' . $_attach_messages['msg_file'] . '</th>';
		$ret[] = '<th>' . $_attach_messages['msg_filesize'] . '</th>';
		$ret[] = '<th>' . $_attach_messages['msg_type'] . '</th>';
		$ret[] = '<th>' . $_attach_messages['msg_date'] . '</th>';
		$ret[] = '</tr>';
		$ret[] = '</thead>';
		$ret[] = '<tbody>';
		foreach($attaches as $name=>$files){
			unset($files['log']);
			foreach ($files as $backup=>$file){
				$attach = new Attach($refer, $name, $backup);
				
				$ret[] = '<tr>';
				if ($backup === 0){
					$ret[] = '<td>' . $attach->toString() . '</td>';
				}else{
					$ret[] = '<td>' . $name . '<em>(Backup no.' . $backup . ')</em></td>';
				}
				$ret[] = '<td>' . $attach->getSize() . '</td>';
				$ret[] = '<td>' . $attach->getMime() . '</td>';
				$ret[] = '<td>' . $attach->getDate() . '</td>';
				$ret[] = '</tr>';
			}
		}
		$ret[] = '</tbody>';
		$ret[] = '</table>';

	}else{
		// 全ページ添付ファイル一覧
		$msg = $_attach_messages['msg_listall'];
		$ret[] = Listing::get('attach', 'attach');
	}
	return array('msg'=>$msg, 'body'=>join("\n",$ret));
}

// アップロードフォームを表示 (action時)
function attach_showform()
{
	global $vars, $_attach_messages, $_string;

	if (Auth::check_role('safemode')) die_message( $_string['prohibit'] );

	$page = isset($vars['page']) ? $vars['page'] : null;

	if (empty($page)) Utility::dieMessage('Page name is not defined');
	
	$isEditable = Factory::Wiki($page)->isEditable();

	$vars['refer'] = $page;

	$html = array();
	if (!IS_AJAX){
		$attach_list = attach_list($page);
		$html[] = '<p><small>[<a href="' . Router::get_cmd_uri('attach', null, null, array('pcmd'=>'list')) . '">'.$_attach_messages['msg_listall'].'</a>]</small></p>';
		if ($isEditable){
			$html[] = '<h2>' . str_replace('$1', $page, $_attach_messages['msg_upload']) . '</h2>'. "\n";
			$html[] = attach_form($page);
		}
		$html[] = '<h2>' . str_replace('$1', $page, $_attach_messages['msg_listpage']) . '</h2>'. "\n";
		$html[] = $attach_list['body'];
	}else{
		$html[] = '<div class="tabs" role="application">';
		$html[] = '<ul role="tablist">';
		if ($isEditable){
			$html[] = '<li role="tab"><a href="' .Router::get_cmd_uri('attach', null, null, array('pcmd'=>'form', 'refer'=>$page)) . '">' . str_replace('$1', $_attach_messages['msg_thispage'], $_attach_messages['msg_upload']) . '</a></li>';
		}
		$html[] = '<li role="tab"><a href="' .Router::get_cmd_uri('attach', null, null, array('pcmd'=>'list', 'refer'=>$page)) . '">' . str_replace('$1', $_attach_messages['msg_thispage'], $_attach_messages['msg_listpage']) . '</a></li>';
		$html[] = '</ul>';
		$html[] = '</div>';
	}

	return array(
		'msg'=>$_attach_messages['msg_upload'],
		'body'=>join("\n",$html)
	);
}



// アップロードフォームの出力
function attach_form($page)
{
	global $_attach_messages;

	if (! ini_get('file_uploads'))	return '<p class="alert alert-warning">#attach(): <code>file_uploads</code> disabled.</p>';
	if (! Factory::Wiki($page)->has())			return '<p class="alert alert-warning">#attach(): No such page.</p>';

	$attach_form[] = '<form enctype="multipart/form-data" action="' . Router::get_script_uri() . '" method="post" class="form-inline plugin-attach-form" data-collision-check="false">';
	$attach_form[] = '<input type="hidden" name="cmd" value="attach" />';
	$attach_form[] = '<input type="hidden" name="pcmd" value="post" />';
	$attach_form[] = '<input type="hidden" name="page" value="'. Utility::htmlsc($page) .'" />';
	$attach_form[] = '<input type="hidden" name="MAX_FILE_SIZE" value="' . PLUGIN_ATTACH_MAX_FILESIZE . '" />';
	$attach_form[] = '<div class="form-group">';
	$attach_form[] = '<label for="_p_attach_file" class="sr-only">' . $_attach_messages['msg_file'] . ':</label>';
	$attach_form[] = '<input type="file" name="' . PLUGIN_ATTACH_FILE_FIELD_NAME . '[]" id="_p_attach_file" class="form-control" multiple="multiple" />';
	$attach_form[] = '</div>';
	if ((PLUGIN_ATTACH_PASSWORD_REQUIRE || PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY) && Auth::check_role('role_contents_admin')){
		$attach_form[] = '<div class="form-group">';
		$attach_form[] = '<input type="password" name="pass" size="8" class="form-control" />';
		$attach_form[] = '</div>';
	}
	$attach_form[] = '<button class="btn btn-primary" type="submit"><span class="fa fa-upload"></span>' . $_attach_messages['btn_upload'] . '</button>';
	$attach_form[] = '</form>';
	$attach_form[] = '<ul class="plugin-attach-ul">';
	$attach_form[] = ( (PLUGIN_ATTACH_PASSWORD_REQUIRE || PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY) && Auth::check_role('role_contents_admin')) ?
						('<li>' . $_attach_messages[PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY ? 'msg_adminpass' : 'msg_password'] . '</li>') : '';
	$attach_form[] = '<li>' . sprintf($_attach_messages['msg_maxsize'], '<var>' . number_format(PLUGIN_ATTACH_MAX_FILESIZE / 1024) . '</var>KB') . '</li>';
	$attach_form[] = '<li>'.$_attach_messages['msg_multiple'].'</li>';
	$attach_form[] = '</ul>';

	return join("\n",$attach_form);
}

/* End of file attach.inc.php */
/* Location: ./wiki-common/plugin/attach.inc.php */