diff --git a/addons/spam_filter/spam_filter.addon.php b/addons/spam_filter/spam_filter.addon.php new file mode 100644 index 000000000..6582e53ac --- /dev/null +++ b/addons/spam_filter/spam_filter.addon.php @@ -0,0 +1,16 @@ + + * @desc : 스팸필터링 애드온 + **/ + + class spam_filter { + + function proc(&$oModule, $oModuleInfo) { + $oModule->setError(-1); + $oModule->setMessage('error'); + } + + } +?> diff --git a/admin.php b/admin.php new file mode 100644 index 000000000..23dfe47ee --- /dev/null +++ b/admin.php @@ -0,0 +1,62 @@ + + * @desc : 관리자 페이지 + * admin은 ModuleHandler를 이용하지 않는다. + **/ + + // 필요한 설정 파일들을 include + require_once("./config/config.inc.php"); + + // Request Method와 설정값들을 세팅 + $oContext = &Context::getInstance(); + $oContext->init(); + + // 설치가 안되어 있다면 index.php로 이동 + if(!Context::isInstalled()) { + header("location:./index.php"); + exit(); + } + + // sid 검사 + $sid = Context::get('sid'); + if($sid) { + $oModule = module_manager::getAdminModuleObject($sid); + if(!$oModule) { + $sid = null; + Context::set('sid',$sid); + unset($oModule); + } + } + + // 관리자(admin) 모듈 객체 생성 + $oAdmin = getModule('admin'); + $oAdmin->moduleInit(null); + + // act검사 + $act = Context::get('act'); + if(!$sid&&!$oAdmin->isExistsAct($act)) $act = 'dispAdminIndex'; + + // 관리자 모듈의 실행 결과가 있으면 해당 실행결과를 출력 + if($oAdmin->proc($act)) { + + $oModule = &$oAdmin; + + // 관리자 모듈의 실행 결과가 없으면 호출된 다른 모듈의 관리자를 확인 + } else { + $oModule = module_manager::getAdminModuleObject($sid); + if($oModule) { + $oModule->moduleInit(null); + $oModule->proc(); + + // 관리자용 레이아웃으로 변경 + $oModule->setLayoutPath($oAdmin->getLayoutPath()); + $oModule->setLayoutTpl($oAdmin->getLayoutTpl()); + } + } + + // DisplayHandler로 컨텐츠 출력 + $oDisplayHandler = new DisplayHandler(); + $oDisplayHandler->printContent($oModule); +?> diff --git a/classes/addon/AddOnHandler.class.php b/classes/addon/AddOnHandler.class.php new file mode 100644 index 000000000..0afd95235 --- /dev/null +++ b/classes/addon/AddOnHandler.class.php @@ -0,0 +1,51 @@ + + * @desc : addon 실행 + **/ + + class AddOnHandler { + + var $addon_name; + + function callAddOns(&$oModule, $oModuleInfo, $status) { + if(!$oModuleInfo->isAddOnExists($status, ContextHandler::get('act'))) return; + + $addon_list = $oModuleInfo->getAddOnList($status, ContextHandler::get('act')); + $addon_cnt = count($addon_list); + if(!$addon_cnt) return; + for($i=0; $i<$addon_cnt; $i++) { + $addon_name = $addon_list[$i]; + + $oAddOn = new AddOnHandler($addon_name); + $oAddOn->proc($oModule, $oModuleInfo); + } + + } + + function AddOnHandler($addon_name) { + $this->addon_name = $addon_name; + } + + function proc(&$oModule, $oModuleInfo) { + // 해당 모듈을 읽어서 객체를 만듬 + $addon_file = sprintf('./addons/%s/%s.addon.php', $this->addon_name, $this->addon_name); + + // 모듈 파일이 없으면 에러 + if(!file_exists($addon_file)) return; + + // 모듈 파일을 include + require_once($addon_file); + + // 선택된 모듈의 instance는 eval string으로 처리 + $eval_str = sprintf('$oAddOn = new %s();', $this->addon_name); + eval($eval_str); + + // 애드온 실행 + $oAddOn->proc($oModule, $oModuleInfo); + } + + } + +?> diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php new file mode 100644 index 000000000..f650f426d --- /dev/null +++ b/classes/context/Context.class.php @@ -0,0 +1,547 @@ + + * @desc : Request Argument/Module Config/ Layout-AddOn-Plugin과 + * 결과물까지 모두 처리 + **/ + + class Context { + + // GET/POST/XMLRPC 중 어떤 방식으로 요청이 왔는지에 대한 값이 세팅 + var $request_method = 'GET'; + + // request parameter 를 정리하여 담을 변수 + var $context = NULL; + + // DB 정보 + var $db_info = NULL; + + // js file + var $js_files = array(); + + // css file + var $css_files = array(); + + // html header 정보 + var $html_header = NULL; + + // 언어정보 + var $lang_type = 'ko'; + var $lang = NULL; + var $loaded_lang_files = array(); + + // 현 사이트의 title + var $site_title = ''; + + // 현재 요청 들어온 $_GET을 별도로 정리/보관 ( set method에 의해 값 변경 적용) + var $get_vars = NULL; + + // 업로드 유무 체크 + var $is_uploaded = false; + + /** + * Context 객체 생성 및 초기화 + **/ + // public object getInstance()/*{{{*/ + // Context는 어디서든 객체 선언없이 사용하기 위해서 static 하게 사용 + function &getInstance() { + if(!$GLOBALS['__ContextInstance__']) $GLOBALS['__ContextInstance__'] = new Context(); + return $GLOBALS['__ContextInstance__']; + }/*}}}*/ + + // public void init()/*{{{*/ + // DB정보, Request Argument등을 세팅 + function init() { + // context 변수를 $GLOBALS의 변수로 지정 + $this->context = &$GLOBALS['__Context__']; + $this->context->lang = &$GLOBALS['lang']; + + // 인증관련 데이터를 Context에 설정 + $oMember = getModule('member'); + if($oMember->isLogged()) { + $this->_set('is_logged', true); + $this->_set('logged_info', $_SESSION['logged_info']); + } + + // 기본적인 DB정보 세팅 + $this->_loadDBInfo(); + + // 기본 언어파일 로드 + $this->lang = &$GLOBALS['lang']; + $this->_loadLang("./common/lang/"); + + // Request Method 설정 + $this->_setRequestMethod(); + + // Request Argument 설정 + $this->_setXmlRpcArgument(); + $this->_setRequestArgument(); + $this->_setUploadedArgument(); + }/*}}}*/ + + /** + * DB 정보를 설정하고 DB Type과 DB 정보를 return + **/ + // private void _loadDBInfo()/*{{{*/ + // 설정파일을 통해 DB정보를 로드 + function _loadDBInfo() { + if(!$this->isInstalled()) return; + + // db 정보 설정 + $db_config_file = $this->getConfigFile(); + if(file_exists($db_config_file)) { + include $db_config_file; + } + $this->_setDBInfo($db_info); + }/*}}}*/ + + // public string getDBType()/*{{{*/ + // DB의 db_type을 return + function getDBType() { + $oContext = &Context::getInstance(); + return $oContext->_getDBType(); + }/*}}}*/ + + // private string _getDBType()/*{{{*/ + function _getDBType() { + return $this->db_info->db_type; + }/*}}}*/ + + // public object setDBInfo($db_info) /*{{{*/ + // DB 정보가 담긴 object를 return + function setDBInfo($db_info) { + $oContext = &Context::getInstance(); + $oContext->_setDBInfo($db_info); + }/*}}}*/ + + // private string _setDBInfo($db_info)/*{{{*/ + function _setDBInfo($db_info) { + $this->db_info = $db_info; + }/*}}}*/ + + // public object getDBInfo() /*{{{*/ + // DB 정보가 담긴 object를 return + function getDBInfo() { + $oContext = &Context::getInstance(); + return $oContext->_getDBInfo(); + }/*}}}*/ + + // private string _getDBInfo()/*{{{*/ + function _getDBInfo() { + return $this->db_info; + }/*}}}*/ + + /** + * 사이트 title + **/ + // public void setBrowserTitle($site_title)/*{{{*/ + function setBrowserTitle($site_title) { + $oContext = &Context::getInstance(); + $oContext->_setBrowserTitle($site_title); + }/*}}}*/ + + // private void _setBrowserTitle($site_title)/*{{{*/ + function _setBrowserTitle($site_title) { + $this->site_title = $site_title; + }/*}}}*/ + + // public string getBrowserTitle()/*{{{*/ + function getBrowserTitle() { + $oContext = &Context::getInstance(); + return $oContext->_getBrowserTitle(); + }/*}}}*/ + + // private string _getBrowserTitle() /*{{{*/ + function _getBrowserTitle() { + return $this->site_title; + }/*}}}*/ + + /** + * 언어관련 + **/ + // public void loadLang($path)/*{{{*/ + // 지정된 언어파일 로드 + function loadLang($path) { + $oContext = &Context::getInstance(); + $oContext->_loadLang($path); + }/*}}}*/ + + // private void _loadLang($path)/*{{{*/ + // 지정된 언어파일 로드 + function _loadLang($path) { + global $lang; + if(substr($path,-1)!='/') $path .= '/'; + $filename = sprintf('%s%s.lang.php', $path, $this->lang_type); + if(!file_exists($filename)) $filename = sprintf('%slang/%s.lang.php', $path, $this->lang_type); + if(!file_exists($filename)) return; + if(in_array($filename, $this->loaded_lang_files)) return; + $this->loaded_lang_files[] = $filename; + include ($filename); + }/*}}}*/ + + // public void setLangType($lang_type = 'ko')/*{{{*/ + function setLangType($lang_type = 'ko') { + $oContext = &Context::getInstance(); + $oContext->_setLangType($lang); + }/*}}}*/ + + // private void _setLangType($lang_type = 'ko')/*{{{*/ + function _setLangType($lang_type = 'ko') { + $this->lang_type = $lang_type; + }/*}}}*/ + + // public string getLangType()/*{{{*/ + function getLangType() { + $oContext = &Context::getInstance(); + return $oContext->_getLangType(); + }/*}}}*/ + + // private string _getLangType()/*{{{*/ + function _getLangType() { + return $this->lang_type; + }/*}}}*/ + + // public string getLang($code)/*{{{*/ + function getLang($code) { + if($GLOBALS['lang']->{$code}) return $GLOBALS['lang']->{$code}; + return $code; + }/*}}}*/ + + // public string setLang($code, $val)/*{{{*/ + function setLang($code, $val) { + $GLOBALS['lang']->{$code} = $val; + }/*}}}*/ + + // public obj convertEncoding($obj) + // obj내의 문자들을 utf8로 변경 + function convertEncoding($source_obj) {/*{{{*/ + $charset_list = array( + 'UTF-8', 'EUC-KR', 'CP949', 'ISO-8859-1', 'EUC-JP', 'SHIFT_JIS', 'CP932', + 'EUC-CN', 'HZ', 'GBK', 'GB18030', 'EUC-TW', 'BIG5', 'CP950', 'BIG5-HKSCS', + 'ISO-2022-CN', 'ISO-2022-CN-EXT', 'ISO-2022-JP', 'ISO-2022-JP-2', 'ISO-2022-JP-1', + 'ISO-8859-6', 'ISO-8859-8', 'JOHAB', 'ISO-2022-KR', 'CP1255', 'CP1256', 'CP862', + 'ASCII', 'ISO-8859-1', 'ISO-8850-2', 'ISO-8850-3', 'ISO-8850-4', 'ISO-8850-5', + 'ISO-8850-7', 'ISO-8850-9', 'ISO-8850-10', 'ISO-8850-13', 'ISO-8850-14', + 'ISO-8850-15', 'ISO-8850-16', 'CP1250', 'CP1251', 'CP1252', 'CP1253', 'CP1254', + 'CP1257', 'CP850', 'CP866', + ); + + $obj = clone($source_obj); + + for($i=0;$i$val) { + if(!$val) continue; + if($val && !iconv($charset,'UTF-8',$val)) $flag = false; + } + + if($flag == true) { + foreach($obj as $key => $val) $obj->{$key} = iconv($charset,'UTF-8',$val); + return $obj; + } + } + }/*}}}*/ + + /** + * Request Method 및 Argument의 설정 및 return + **/ + // private void _setRequestMethod()/*{{{*/ + // request method가 어떤것인지 판단하여 저장 (GET/POST/XMLRPC) + function _setRequestMethod() { + if($GLOBALS['HTTP_RAW_POST_DATA']) $this->request_method = "XMLRPC"; + else $this->request_method = $_SERVER['REQUEST_METHOD']; + }/*}}}*/ + + // private void _setRequestArgument();/*{{{*/ + // GET/POST방식일 경우 처리 + function _setRequestArgument() { + if($this->_getRequestMethod() == 'XMLRPC') return; + if(!count($_REQUEST)) return; + foreach($_REQUEST as $key => $val) { + if(is_array($val)) { + for($i=0;$i_getRequestMethod()=='GET'&&$_GET[$key]) $set_to_vars = true; + elseif($this->_getRequestMethod()=='POST'&&$_POST[$key]) $set_to_vars = true; + else $set_to_vars = false; + $this->_set($key, $val, $set_to_vars); + } + }/*}}}*/ + + // private void _setXmlRpcArgument()/*{{{*/ + // XML RPC일때역시 + function _setXmlRpcArgument() { + if($this->_getRequestMethod() != 'XMLRPC') return; + $oXml = new XmlParser(); + $xml_obj = $oXml->parse(); + + $method_name = $xml_obj->methodcall->methodname->body; + $params = $xml_obj->methodcall->params; + unset($params->node_name); + + unset($params->attrs); + if(!count($params)) return; + foreach($params as $key => $obj) { + $val = trim($obj->body); + $this->_set($key, $val, true); + } + }/*}}}*/ + + // public boolean isUploaded() /*{{{*/ + // 업로드 되었을 경우 return true + function isUploaded() { + $oContext = &Context::getInstance(); + return $oContext->_isUploaded(); + }/*}}}*/ + + // private boolean isUploaded() /*{{{*/ + // 업로드 되었을 경우 return true + function _isUploaded() { + return $this->is_uploaded; + }/*}}}*/ + + // private void _setUploadedArgument()/*{{{*/ + // 업로드된 파일이 있을 경우도 역시 context에 통합 처리 (단 정상적인 업로드인지 체크) + function _setUploadedArgument() { + if($this->_getRequestMethod() != 'POST') return; + if(!eregi("^multipart\/form-data", $_SERVER['CONTENT_TYPE'])) return; + if(!$_FILES) return; + + foreach($_FILES as $key => $val) { + $tmp_name = $val['tmp_name']; + if(!$tmp_name || !is_uploaded_file($tmp_name)) continue; + $this->_set($key, $val, true); + $this->is_uploaded = true; + } + }/*}}}*/ + + // public string getRequestMethod()/*{{{*/ + // Request Method값을 return (GET/POST/XMLRPC); + function getRequestMethod() { + $oContext = &Context::getInstance(); + return $oContext->_getRequestMethod(); + }/*}}}*/ + + // private string _getRequestMethod()/*{{{*/ + function _getRequestMethod() { + return $this->request_method; + }/*}}}*/ + + // public string getUrl($num_args, $args_list)/*{{{*/ + // 요청받은 url에 args_list를 적용하여 return + function getUrl($num_args, $args_list) { + $oContext = &Context::getInstance(); + return $oContext->_getUrl($num_args, $args_list); + }/*}}}*/ + + // private string _getUrl($num_args, $args_list)/*{{{*/ + // 요청받은 url에 args_list를 적용하여 return + function _getUrl($num_args, $args_list) { + if(!is_object($this->get_vars)) $get_vars = null; + else $get_vars = clone($this->get_vars); + for($i=0;$i<$num_args;$i=$i+2) { + $key = $args_list[$i]; + $val = $args_list[$i+1]; + $get_vars->{$key} = trim($val); + } + + $var_count = count(get_object_vars($get_vars)); + if(!$var_count) return; + foreach($get_vars as $key => $val) { + if(!$val) continue; + $url_list[] = sprintf("%s=%s",$key, $val); + } + + preg_match("/([a-zA-Z\_]+)\.php/i", $_SERVER['PHP_SELF'], $match); + $filename = $match[0]; + if($filename == 'index.php') $filename = ''; + + return './'.$filename.'?'.htmlspecialchars(implode('&', $url_list)); + }/*}}}*/ + + // public string getRequestUri() /*{{{*/ + function getRequestUri() { + $hostname = $_SERVER['SERVER_NAME']; + $port = $_SERVER['SERVER_PORT']; + if($port!=80) $hostname .= ":{$port}"; + $path = $_SERVER['REDIRECT_URL']; + $path = $_SERVER['REDIRECT_URL']?$_SERVER['REDIRECT_URL']:preg_replace('/([a-zA-Z0-9\_]+).php/i','',$_SERVER['PHP_SELF']); + return sprintf("http://%s%s",$hostname,$path); + }/*}}}*/ + + /** + * Request Argument외의 데이터 set/get + **/ + // public void set($key, $val, $set_to_get_vars = false)/*{{{*/ + // key/val 로 데이터 세팅 + function set($key, $val, $set_to_get_vars = false) { + $oContext = &Context::getInstance(); + $oContext->_set($key, $val, $set_to_get_vars); + }/*}}}*/ + + // private void _set($key, $val, $set_to_get_vars = false)/*{{{*/ + function _set($key, $val, $set_to_get_vars = false) { + $this->context->{$key} = $val; + if($set_to_get_vars || $this->get_vars->{$key}) $this->get_vars->{$key} = $val; + }/*}}}*/ + + // public object get($key)/*{{{*/ + // key값에 해당하는 값을 return + function get($key) { + $oContext = &Context::getInstance(); + return $oContext->_get($key); + }/*}}}*/ + + // private object _get($key)/*{{{*/ + function _get($key) { + return $this->context->{$key}; + }/*}}}*/ + + // public object gets(void)/*{{{*/ + // 받고자 하는 변수만 object에 입력하여 받음 + function gets() { + $num_args = func_num_args(); + if($num_args<1) return; + $args_list = func_get_args(); + + $oContext = &Context::getInstance(); + return $oContext->_gets($num_args, $args_list); + }/*}}}*/ + + // private object _gets($args_list)/*{{{*/ + function _gets($num_args, $args_list) { + for($i=0;$i<$num_args;$i++) { + $args = $args_list[$i]; + $output->{$args} = $this->_get($args); + } + return $output; + }/*}}}*/ + + // public object getAll()/*{{{*/ + // 모든 데이터를 return + function getAll() { + $oContext = &Context::getInstance(); + return $oContext->_getAll(); + }/*}}}*/ + + // private object _getAll()/*{{{*/ + function _getAll() { + return $this->context; + }/*}}}*/ + + // public object getRequestVars()/*{{{*/ + // GET/POST/XMLRPC에서 넘어온 변수값을 return + function getRequestVars() { + $oContext = &Context::getInstance(); + return $oContext->_getRequestVars(); + }/*}}}*/ + + // private object _getRequestVars()/*{{{*/ + function _getRequestVars() { + return clone($this->get_vars); + }/*}}}*/ + + /** + * CSS/JS/HeaderText 등 html을 출력할때 사용할 값들 + **/ + // public void addJsFile($file)/*{{{*/ + // js file 추가 + function addJsFile($file) { + $oContext = &Context::getInstance(); + return $oContext->_addJsFile($file); + }/*}}}*/ + + // private void _addJsFile($file)/*{{{*/ + function _addJsFile($file) { + if(in_array($file, $this->js_files)) return; + $this->js_files[] = $file; + }/*}}}*/ + + // public array getJsFile()/*{{{*/ + function getJsFile() { + $oContext = &Context::getInstance(); + return $oContext->_getJsFile(); + }/*}}}*/ + + // private array _getJsFile()/*{{{*/ + function _getJsFile() { + return $this->js_files; + }/*}}}*/ + + // public void addCSSFile($file)/*{{{*/ + // CSS file 추가 + function addCSSFile($file) { + $oContext = &Context::getInstance(); + return $oContext->_addCSSFile($file); + }/*}}}*/ + + // private void _addCSSFile($file)/*{{{*/ + function _addCSSFile($file) { + if(in_array($file, $this->css_files)) return; + $this->css_files[] = $file; + }/*}}}*/ + + // public array getCSSFile()/*{{{*/ + // CSS file 추가 + function getCSSFile() { + $oContext = &Context::getInstance(); + return $oContext->_getCSSFile(); + }/*}}}*/ + + // private array _getCSSFile()/*{{{*/ + function _getCSSFile() { + return $this->css_files; + }/*}}}*/ + + // public void addHtmlHeader($file)/*{{{*/ + // HtmlHeader 추가 + function addHtmlHeader($file) { + $oContext = &Context::getInstance(); + return $oContext->_addHtmlHeader($file); + }/*}}}*/ + + // private void _addHtmlHeader($file)/*{{{*/ + function _addHtmlHeader($file) { + $this->HtmlHeader .= ($this->HtmlHeader?"\n":"").$file; + }/*}}}*/ + + // public string getHtmlHeader()/*{{{*/ + // HtmlHeader 추가 + function getHtmlHeader() { + $oContext = &Context::getInstance(); + return $oContext->_getHtmlHeader(); + }/*}}}*/ + + // private string _getHtmlHeader()/*{{{*/ + function _getHtmlHeader() { + return $this->HtmlHeader; + }/*}}}*/ + + /** + * 인스톨 관련 + **/ + // public String getConfigFile()/*{{{*/ + // db설정내용이 저장되어 있는 config file의 path를 return + function getConfigFile() { + return "./files/config/db.config.php"; + }/*}}}*/ + + // public boolean isInstalled()/*{{{*/ + // 설치가 되어 있는지에 대한 체크 + function isInstalled() { + return file_exists(Context::getConfigFile()); + }/*}}}*/ + + } +?> diff --git a/classes/db/DB.class.php b/classes/db/DB.class.php new file mode 100644 index 000000000..59dffa7b9 --- /dev/null +++ b/classes/db/DB.class.php @@ -0,0 +1,237 @@ + + * @desc : DB*의 상위 클래스 + **/ + + class DB { + + // connector resource or file description + var $fd = NULL; + + // result + var $result = NULL; + + // errno, errstr + var $errno = 0; + var $errstr = ''; + var $query = ''; + + // isconnected + var $is_connected = false; + + // 지원하는 DB의 종류 + var $supported_list = array(); + + // public Object &getInstance($db_type)/*{{{*/ + // DB를 상속받는 특정 db type의 instance를 생성 후 return + function &getInstance($db_type = NULL) { + if(!$db_type) $db_type = Context::getDBType(); + if(!$db_type) return new Output(-1, 'msg_db_not_setted'); + + if(!$GLOBALS['__DB__']) { + $class_name = sprintf("DB%s%s", strtoupper(substr($db_type,0,1)), strtolower(substr($db_type,1))); + $class_file = sprintf("./classes/db/%s.class.php", $class_name); + if(!file_exists($class_file)) new Output(-1, 'msg_db_not_setted'); + + require_once($class_file); + $eval_str = sprintf('$GLOBALS[\'__DB__\'] = new %s();', $class_name); + eval($eval_str); + } + + return $GLOBALS['__DB__']; + }/*}}}*/ + + /** + * 지원 가능한 DB 목록을 return + **/ + // public array getSupportedList()/*{{{*/ + // 지원하는 DB의 종류 return + function getSupportedList() { + $oDB = new DB(); + return $oDB->_getSupportedList(); + }/*}}}*/ + + // private array _getSupportedList()/*{{{*/ + function _getSupportedList() { + if(!count($this->supported_list)) { + $db_classes_path = "./classes/db/"; + $filter = "/^DB([^\.]+)\.class\.php/i"; + $this->supported_list = FileHandler::readDir($db_classes_path, $filter, true); + } + return $this->supported_list; + }/*}}}*/ + + // public boolean isSupported($db_type) /*{{{*/ + // 지원하는 DB인지에 대한 check + function isSupported($db_type) { + $supported_list = DB::getSupportedList(); + return in_array($db_type, $supported_list); + }/*}}}*/ + + /** + * 에러 남기기 + **/ + // public void setError($errno, $errstr) /*{{{*/ + function setError($errno, $errstr) { + $this->errno = $errno; + $this->errstr = $errstr; + + if(__DEBUG__ && $this->errno!=0) debugPrint(sprintf("Query Fail\t#%05d : %s - %s\n\t\t%s", $GLOBALS['__dbcnt'], $errno, $errstr, $this->query)); + }/*}}}*/ + + /** + * 각종 bool 값 return + **/ + // public boolean isConnected()/*{{{*/ + // 접속되었는지 return + function isConnected() { + return $this->is_connected; + }/*}}}*/ + + // public boolean isError()/*{{{*/ + // 오류가 발생하였는지 return + function isError() { + return $error===0?true:false; + }/*}}}*/ + + // public object getError()/*{{{*/ + function getError() { + return new Output($this->errno, $this->errstr); + }/*}}}*/ + + /** + * query execute + **/ + // public object executeQuery($query_id, $args = NULL)/*{{{*/ + // query_id = module.queryname + // query_id에 해당하는 xml문(or 캐싱파일)을 찾아서 실행 + function executeQuery($query_id, $args = NULL) { + if(!$query_id) return new Output(-1, 'msg_invalid_queryid'); + + list($module, $id) = explode('.',$query_id); + if(!$module||!$id) return new Output(-1, 'msg_invalid_queryid'); + + $xml_file = sprintf('./modules/%s/queries/%s.xml', $module, $id); + if(!file_exists($xml_file)) { + $xml_file = sprintf('./files/modules/%s/queries/%s.xml', $module, $id); + if(!file_exists($xml_file)) return new Output(-1, 'msg_invalid_queryid'); + } + + // 일단 cache 파일을 찾아본다 + $cache_file = sprintf('./files/queries/%s.cache.php', $query_id); + + // 없으면 원본 쿼리 xml파일을 찾아서 파싱을 한다 + if(!file_exists($cache_file)||filectime($cache_file)parse($query_id, $xml_file, $cache_file); + } + + // 쿼리를 실행한다 + return $this->_executeQuery($cache_file, $args, $query_id); + }/*}}}*/ + + // private object _executeQuery($cache_file, $args)/*{{{*/ + // 쿼리문을 실행하고 결과를 return한다 + function _executeQuery($cache_file, $source_args, $query_id) { + global $lang; + + if(!file_exists($cache_file)) return new Output(-1, 'msg_invalid_queryid'); + + if(__DEBUG__) $query_start = getMicroTime(); + + if($source_args) $args = clone($source_args); + $output = include($cache_file); + + if( (is_a($output, 'Output')||is_subclass_of($output,'Output'))&&!$output->toBool()) return $output; + + // action값에 따라서 쿼리 생성으로 돌입 + switch($action) { + case 'insert' : + $output = $this->_executeInsertAct($tables, $column, $pass_quotes); + break; + case 'update' : + $output = $this->_executeUpdateAct($tables, $column, $condition, $pass_quotes); + break; + case 'delete' : + $output = $this->_executeDeleteAct($tables, $condition, $pass_quotes); + break; + case 'select' : + $output = $this->_executeSelectAct($tables, $column, $invert_columns, $condition, $navigation, $group_script, $pass_quotes); + break; + } + + if(__DEBUG__) { + $query_end = getMicroTime(); + $elapsed_time = $query_end - $query_start; + $GLOBALS['__db_elapsed_time__'] += $elapsed_time; + $GLOBALS['__db_queries__'] .= sprintf("\t%02d. %s (%0.4f sec)\n\t %s\n", ++$GLOBALS['__dbcnt'], $query_id, $elapsed_time, $this->query); + } + + if($this->errno!=0) return new Output($this->errno, $this->errstr); + if(is_a($output, 'Output') || is_subclass_of($output, 'Output')) return $output; + return new Output(); + }/*}}}*/ + + // private object _checkFilter($key, $val, $filter_type, $minlength, $maxlength) /*{{{*/ + // $val을 $filter_type으로 검사 + function _checkFilter($key, $val, $filter_type, $minlength, $maxlength) { + global $lang; + + $length = strlen($val); + if($minlength && $length < $minlength) return new Output(-1, sprintf($lang->filter->outofrange, $lang->{$key}?$lang->{$key}:$key)); + if($maxlength && $length > $maxlength) return new Output(-1, sprintf($lang->filter->outofrange, $lang->{$key}?$lang->{$key}:$key)); + + switch($filter_type) { + case 'email' : + case 'email_adderss' : + if(!eregi('^[_0-9a-z-]+(\.[_0-9a-z-]+)*@[0-9a-z-]+(\.[0-9a-z-]+)*$', $val)) return new Output(-1, sprintf($lang->filter->invalid_email, $lang->{$key}?$lang->{$key}:$key)); + break; + case 'homepage' : + if(!eregi('^(http|https)+(:\/\/)+[0-9a-z_-]+\.[^ ]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_homepage, $lang->{$key}?$lang->{$key}:$key)); + break; + case 'userid' : + case 'user_id' : + if(!eregi('^[a-zA-Z]+([_0-9a-zA-Z]+)*$', $val)) return new Output(-1, sprintf($lang->filter->invalid_userid, $lang->{$key}?$lang->{$key}:$key)); + break; + case 'number' : + if(!eregi('^[0-9]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_number, $lang->{$key}?$lang->{$key}:$key)); + break; + case 'alpha' : + if(!eregi('^[a-z]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_alpha, $lang->{$key}?$lang->{$key}:$key)); + break; + case 'alpha_number' : + if(!eregi('^[0-9a-z]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_alpha_number, $lang->{$key}?$lang->{$key}:$key)); + break; + } + + return new Output(); + }/*}}}*/ + + // private string _combineCondition($cond_group, $group_pipe) /*{{{*/ + function _combineCondition($cond_group, $group_pipe) { + if(!is_array($cond_group)) return; + $cond_query = ''; + foreach($cond_group as $group_idx => $group) { + if(!is_array($group)) continue; + + $buff = ''; + foreach($group as $key => $val) { + $pipe = key($val); + $cond = array_pop($val); + if($buff) $buff .= $pipe.' '.$cond; + else $buff = $cond; + } + + $g_pipe = $group_pipe[$group_idx]; + if(!$g_pipe) $g_pipe = 'and'; + if($cond_query) $cond_query .= sprintf(' %s ( %s )', $g_pipe, $buff); + else $cond_query = '('.$buff.')'; + } + return $cond_query; + }/*}}}*/ + + } +?> diff --git a/classes/db/DBMysql.class.php b/classes/db/DBMysql.class.php new file mode 100644 index 000000000..bac4ae71a --- /dev/null +++ b/classes/db/DBMysql.class.php @@ -0,0 +1,375 @@ + + * @desc : db(mysql, cubrid, sqlite..)를 이용하기 위한 db class의 abstract class + **/ + + class DBMysql extends DB { + + // db info + var $hostname = '127.0.0.1'; + var $userid = NULL; + var $password = NULL; + var $database = NULL; + var $prefix = 'zb'; + + // mysql에서 사용될 column type + var $column_type = array( + 'number' => 'int', + 'varchar' => 'varchar', + 'char' => 'char', + 'text' => 'text', + 'date' => 'varchar(14)', + ); + + // public void DBMysql()/*{{{*/ + function DBMysql() { + $this->_setDBInfo(); + $this->_connect(); + }/*}}}*/ + + /** + * DB정보 설정 및 connect/ close + **/ + // public boolean _setDBInfo()/*{{{*/ + function _setDBInfo() { + $db_info = Context::getDBInfo(); + $this->hostname = $db_info->db_hostname; + $this->userid = $db_info->db_userid; + $this->password = $db_info->db_password; + $this->database = $db_info->db_database; + $this->prefix = $db_info->db_table_prefix; + if(!substr($this->prefix,-1)!='_') $this->prefix .= '_'; + }/*}}}*/ + + // public boolean _connect()/*{{{*/ + function _connect() { + // db 정보가 없으면 무시 + if(!$this->hostname || !$this->userid || !$this->password || !$this->database) return; + + // 접속시도 + $this->fd = @mysql_connect($this->hostname, $this->userid, $this->password); + if(mysql_error()) { + $this->setError(mysql_errno(), mysql_error()); + return; + } + + // db 선택 + @mysql_select_db($this->database, $this->fd); + if(mysql_error()) { + $this->setError(mysql_errno(), mysql_error()); + return; + } + + // 접속체크 + $this->is_connected = true; + + // mysql의 경우 utf8임을 지정 + $this->_query("SET NAMES 'utf8'"); + }/*}}}*/ + + // public boolean close()/*{{{*/ + function close() { + if(!$this->isConnected()) return; + @mysql_close($this->fd); + }/*}}}*/ + + /** + * add quotation + **/ + // public string addQuotes(string $string)/*{{{*/ + function addQuotes($string) { + if(get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string)); + if(!is_numeric($string)) $string = @mysql_escape_string($string); + return $string; + }/*}}}*/ + + /** + * query : query문 실행하고 result return + * fetch : reutrn 된 값이 없으면 NULL + * rows이면 array object + * row이면 object + * return + * getNextSequence : 1씩 증가되는 sequence값을 return (mysql의 auto_increment는 sequence테이블에서만 사용) + */ + // private object _query(string $query) /*{{{*/ + function _query($query) { + if(!$this->isConnected()) return; + $this->query = $query; + + $this->setError(0,'success'); + + $result = @mysql_query($query, $this->fd); + + if(mysql_error()) { + $this->setError(mysql_errno(), mysql_error()); + return; + } + + return $result; + }/*}}}*/ + + // private object _fetch($result) /*{{{*/ + function _fetch($result) { + if($this->errno!=0 || !$result) return; + while($tmp = mysql_fetch_object($result)) { + $output[] = $tmp; + } + if(count($output)==1) return $output[0]; + return $output; + }/*}}}*/ + + // public int getNextSequence() /*{{{*/ + // sequence값을 받음 + function getNextSequence() { + $query = sprintf("insert into `%ssequence` (seq) values ('')", $this->prefix); + $this->_query($query); + return mysql_insert_id(); + }/*}}}*/ + + /** + * Table의 Create/Drop/Alter/Rename/Truncate/Dump... + **/ + // public boolean isTableExists(string $table_name)/*{{{*/ + function isTableExists($target_name) { + $query = sprintf("show tables like '%s%s'", $this->prefix, $this->addQuotes($target_name)); + $result = $this->_query($query); + $tmp = $this->_fetch($result); + if(!$tmp) return false; + return true; + }/*}}}*/ + + // public boolean createTableByXml($xml) /*{{{*/ + // xml 을 받아서 테이블을 생성 + function createTableByXml($xml_doc) { + return $this->_createTable($xml_doc); + }/*}}}*/ + + // public boolean createTableByXmlFile($file_name) /*{{{*/ + // xml 을 받아서 테이블을 생성 + function createTableByXmlFile($file_name) { + if(!file_exists($file_name)) return; + // xml 파일을 읽음 + $buff = FileHandler::readFile($file_name); + return $this->_createTable($buff); + }/*}}}*/ + + // private boolean _createTable($xml)/*{{{*/ + // type : number, varchar, text, char, date, + // opt : notnull, default, size + // index : primary key, index, unique + function _createTable($xml_doc) { + // xml parsing + $oXml = new XmlParser(); + $xml_obj = $oXml->parse($xml_doc); + + // 테이블 생성 schema 작성 + $table_name = $xml_obj->table->attrs->name; + if($this->isTableExists($table_name)) return; + $table_name = $this->prefix.$table_name; + + if(!is_array($xml_obj->table->column)) $columns[] = $xml_obj->table->column; + else $columns = $xml_obj->table->column; + foreach($columns as $column) { + $name = $column->attrs->name; + $type = $column->attrs->type; + $size = $column->attrs->size; + $notnull = $column->attrs->notnull; + $primary_key = $column->attrs->primary_key; + $index = $column->attrs->index; + $unique = $column->attrs->unique; + $default = $column->attrs->default; + $auto_increment = $column->attrs->auto_increment; + + $column_schema[] = sprintf('`%s` %s%s %s %s %s', + $name, + $this->column_type[$type], + $size?'('.$size.')':'', + $default?"default '".$default."'":'', + $notnull?'not null':'', + $auto_increment?'auto_increment':'' + ); + + if($primary_key) $primary_list[] = $name; + else if($unique) $unique_list[$unique][] = $name; + else if($index) $index_list[$index][] = $name; + } + + if(count($primary_list)) { + $column_schema[] = sprintf("primary key (%s)", '`'.implode($primary_list,'`,`').'`'); + } + + if(count($unique_list)) { + foreach($unique_list as $key => $val) { + $column_schema[] = sprintf("unique %s (%s)", $key, '`'.implode($val,'`,`').'`'); + } + } + + if(count($index_list)) { + foreach($index_list as $key => $val) { + $column_schema[] = sprintf("index %s (%s)", $key, '`'.implode($val,'`,`').'`'); + } + } + + $schema = sprintf('create table `%s` (%s%s);', $this->addQuotes($table_name), "\n", implode($column_schema,",\n")); + $output = $this->_query($schema); + if(!$output) return false; + }/*}}}*/ + + // public boolean dropTable($target_name) /*{{{*/ + // 테이블 삭제 + function dropTable($target_name) { + $query = sprintf('drop table `%s%s`;', $this->prefix, $this->addQuotes($target_name)); + $this->_query($query); + }/*}}}*/ + + // public boolean renameTable($source_name, $targe_name) /*{{{*/ + // 테이블의 이름 변경 + function renameTable($source_name, $targe_name) { + $query = sprintf("alter table `%s%s` rename `%s%s`;", $this->prefix, $this->addQuotes($source_name), $this->prefix, $this->addQuotes($targe_name)); + $this->_query($query); + }/*}}}*/ + + // public boolean truncateTable($target_name) /*{{{*/ + // 테이블을 비움 + function truncateTable($target_name) { + $query = sprintf("truncate table `%s%s`;", $this->prefix, $this->addQuotes($target_name)); + $this->_query($query); + }/*}}}*/ + + // public boolean dumpTable($target_name) 미완성 /*{{{*/ + // 테이블 데이터 Dump + function dumpTable($target_name) { + }/*}}}*/ + + /** + * insert/update/delete/select 구현 + **/ + // private string _executeInsertAct($tables, $column, $pass_quotes)/*{{{*/ + function _executeInsertAct($tables, $column, $pass_quotes) { + $table = array_pop($tables); + + foreach($column as $key => $val) { + $key_list[] = $key; + if(in_array($key, $pass_quotes)) $val_list[] = $this->addQuotes($val); + else $val_list[] = '\''.$this->addQuotes($val).'\''; + } + + $query = sprintf("insert into `%s%s` (%s) values (%s);", $this->prefix, $table, '`'.implode('`,`',$key_list).'`', implode(',', $val_list)); + return $this->_query($query); + }/*}}}*/ + + // private string _executeUpdateAct($tables, $column, $condition, $pass_quotes)/*{{{*/ + function _executeUpdateAct($tables, $column, $condition, $pass_quotes) { + $table = array_pop($tables); + + foreach($column as $key => $val) { + if(in_array($key, $pass_quotes)) $update_list[] = sprintf('`%s` = %s', $key, $this->addQuotes($val)); + else $update_list[] = sprintf('`%s` = \'%s\'', $key, $this->addQuotes($val)); + } + if(!count($update_list)) return; + $update_query = implode(',',$update_list); + + if($condition) $condition = ' where '.$condition; + + $query = sprintf("update `%s%s` set %s %s;", $this->prefix, $table, $update_query, $condition); + return $this->_query($query); + }/*}}}*/ + + // private string _executeDeleteAct($tables, $condition, $pass_quotes)/*{{{*/ + function _executeDeleteAct($tables, $condition, $pass_quotes) { + $table = array_pop($tables); + + if($condition) $condition = ' where '.$condition; + + $query = sprintf("delete from `%s%s` %s;", $this->prefix, $table, $condition); + return $this->_query($query); + }/*}}}*/ + + // private string _executeSelectAct($tables, $column, $invert_columns, $condition, $navigation, $pass_quotes)/*{{{*/ + // 네비게이션 변수 정리를 해야함 + function _executeSelectAct($tables, $column, $invert_columns, $condition, $navigation, $group_script, $pass_quotes) { + if(!count($tables)) $table = $this->prefix.array_pop($tables); + else { + foreach($tables as $key => $val) $table_list[] = sprintf('%s%s as %s', $this->prefix, $key, $val); + } + $table = implode(',',$table_list); + + if(!$column) $columns = '*'; + else { + foreach($invert_columns as $key => $val) { + $column_list[] = sprintf('%s as %s',$val, $key); + } + $columns = implode(',', $column_list); + } + + if($condition) $condition = ' where '.$condition; + + if($navigation->list_count) return $this->_getNavigationData($table, $columns, $condition, $navigation); + + $query = sprintf("select %s from %s %s", $columns, $table, $condition); + + $query .= ' '.$group_script; + + if($navigation->index) { + foreach($navigation->index as $index_obj) { + $index_list[] = sprintf('%s %s', $index_obj[0], $index_obj[1]); + } + if(count($index_list)) $query .= ' order by '.implode(',',$index_list); + } + + + $result = $this->_query($query); + if($this->errno!=0) return; + $data = $this->_fetch($result); + + $buff = new Output(); + $buff->data = $data; + return $buff; + }/*}}}*/ + + // private function _getNavigationData($query)/*{{{*/ + // query xml에 navigation 정보가 있을 경우 페이징 관련 작업을 처리한다 + // 그닥 좋지는 않은 구조이지만 편리하다.. -_-; + function _getNavigationData($table, $columns, $condition, $navigation) { + // 전체 개수를 구함 + $count_query = sprintf("select count(*) as count from %s %s", $table, $condition); + $result = $this->_query($count_query); + $count_output = $this->_fetch($result); + $total_count = (int)$count_output->count; + + // 전체 페이지를 구함 + $total_page = (int)(($total_count-1)/$navigation->list_count) +1; + + // 페이지 변수를 체크 + if($navigation->page > $total_page) $page = $navigation->page; + else $page = $navigation->page; + $start_count = ($page-1)*$navigation->list_count; + + foreach($navigation->index as $index_obj) { + $index_list[] = sprintf('%s %s', $index_obj[0], $index_obj[1]); + } + + $index = implode(',',$index_list); + $query = sprintf('select %s from %s %s order by %s limit %d, %d', $columns, $table, $condition, $index, $start_count, $navigation->list_count); + $result = $this->_query($query); + if($this->errno!=0) return; + + $virtual_no = $total_count - ($page-1)*$navigation->list_count; + while($tmp = mysql_fetch_object($result)) { + $data[$virtual_no--] = $tmp; + } + + $buff = new Output(); + $buff->total_count = $total_count; + $buff->total_page = $total_page; + $buff->page = $page; + $buff->data = $data; + + require_once('./classes/page/PageHandler.class.php'); + $buff->page_navigation = new PageHandler($total_count, $total_page, $page, $navigation->page_count); + return $buff; + }/*}}}*/ + } +?> diff --git a/classes/display/DisplayHandler.class.php b/classes/display/DisplayHandler.class.php new file mode 100644 index 000000000..22080644e --- /dev/null +++ b/classes/display/DisplayHandler.class.php @@ -0,0 +1,154 @@ + + * @desc : display 객체 + * Request Method에 따라서 html or xml 출력방법을 결정한다 + * xml : oModule의 variables를 simple xml 로 출력 + * html : oModule의 template/variables로 html을 만들고 contents_html로 처리 + * plugin이나 layout의 html과 연동하여 출력 + * + **/ + + class DisplayHandler { + + // 출력하는 컨텐츠의 사이즈 + var $content_size = 0; + + // public void printContent() /*{{{*/ + function printContent($oModule) { + // header 출력 + $this->_printHeader(); + + // request method에 따른 처리 + $content = $this->getContent($oModule); + + // 요청방식에 따라 출력을 별도로 + if(Context::getRequestMethod()!="XMLRPC") { + Context::set('content', $content); + + // content 래핑 (common/tpl/default.html) + require_once("./classes/template/TemplateHandler.class.php"); + $oTemplate = new TemplateHandler(); + $output = $oTemplate->compile($oModule->layout_path, $oModule->layout_tpl); + } else { + $output = $content; + } + + $this->content_size = strlen($output); + print $output; + + // 디버깅 데이터 출력 + $this->_debugOutput(); + }/*}}}*/ + + // public void getContent() /*{{{*/ + function getContent($oModule) { + // request method에 따른 처리 + return $this->_toDoc($oModule); + }/*}}}*/ + + /** + * 문서 출력 + **/ + // private string _toDoc($oModule) /*{{{*/ + function _toDoc($oModule) { + if(Context::getRequestMethod() == 'XMLRPC') $content = $this->_toXmlDoc($oModule); + else $content = $this->_toHTMLDoc($oModule); + return $content; + }/*}}}*/ + + // private string _toXmlDoc($oModule) /*{{{*/ + function _toXmlDoc($oModule) { + $xmlDoc = "\n"; + $xmlDoc .= sprintf("%s\n",$oModule->getError()); + $xmlDoc .= sprintf("%s\n",$oModule->getMessage()); + + $variables = $oModule->getVariables(); + if(count($variables)) { + foreach($variables as $key => $val) { + if(is_string($val)) $val = ''; + $xmlDoc .= "<{$key}>{$val}\n"; + } + } + + $xmlDoc .= ""; + + return $xmlDoc; + }/*}}}*/ + + // private string _toHTMLDoc($oModule) /*{{{*/ + function _toHTMLDoc($oModule) { + // template handler 객체 생성 + require_once("./classes/template/TemplateHandler.class.php"); + $oTemplate = new TemplateHandler(); + + // module tpl 변환 + $template_path = $oModule->getTemplatePath(); + $tpl_file = $oModule->getTemplateFile(); + return $oTemplate->compile($template_path, $tpl_file); + }/*}}}*/ + + // public int getContentSize() /*{{{*/ + function getContentSize() { + return $this->content_size; + }/*}}}*/ + + // private void _debugOutput()/*{{{*/ + // __DEBUG__가 true일 경우 각 부분의 실행시간등을 debugPrint 함수를 이용해서 출력 + // 개발시나 테스트시에 config/config.inc.php의 __DEBUG__를 true로 세팅하고 + // tail -f ./files/_debug_message.php로 하여 console로 확인하면 편리함 + function _debugOutput() { + if(!__DEBUG__) return; + $end = getMicroTime(); + + $buff = "\n\n** Debug at ".date('Y-m-d H:i:s')." ************************************************************\n"; + $buff .= "\n- Request/ Response info\n"; + $buff .= sprintf("\tRequest URI \t\t\t: %s:%s%s%s%s\n", $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['PHP_SELF'], $_SERVER['QUERY_STRING']?'?':'', $_SERVER['QUERY_STRING']); + $buff .= sprintf("\tRequest method \t\t\t: %s\n", $_SERVER['REQUEST_METHOD']); + $buff .= sprintf("\tResponse contents size\t\t: %d byte\n", $this->getContentSize()); + if($GLOBALS['__db_queries__']) { + $buff .= "\n- DB Queries\n"; + $buff .= $GLOBALS['__db_queries__']; + } + $buff .= "\n- Elapsed time\n"; + + if($GLOBALS['__db_elapsed_time__']) $buff .= sprintf("\tDB queries elapsed time\t\t: %0.5f sec\n", $GLOBALS['__db_elapsed_time__']); + $buff .= sprintf("\tclass file load elapsed time \t: %0.5f sec\n", __RequireClassEndTime__-__RequireClassStartTime__); + $buff .= sprintf("\tTemplate compile elapsed time\t: %0.5f sec\n", $GLOBALS['__template_elapsed__']); + $buff .= sprintf("\tPHP elapsed time \t\t: %0.5f sec\n", $end-__StartTime__-$GLOBALS['__template_elapsed__']-$GLOBALS['__db_elapsed_time__']-(__RequireClassEndTime__-__RequireClassStartTime__)); + $buff .= sprintf("\tTotal elapsed time \t\t: %0.5f sec", $end-__StartTime__); + + debugPrint($buff, false); + }/*}}}*/ + + /** + * 헤더 출력 + ***/ + // private void _printHeader()/*{{{*/ + function _printHeader() { + if(Context::getRequestMethod() == 'XMLRPC') return $this->_printXMLHeader(); + else return $this->_printHTMLHeader(); + }/*}}}*/ + + // private void _printXMLHeader()/*{{{*/ + function _printXMLHeader() { + header("Content-Type: text/xml; charset=UTF-8"); + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header("Cache-Control: no-store, no-cache, must-revalidate"); + header("Cache-Control: post-check=0, pre-check=0", false); + header("Pragma: no-cache"); + }/*}}}*/ + + // private void _printHTMLHeader()/*{{{*/ + function _printHTMLHeader() { + header("Content-Type: text/html; charset=UTF-8"); + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header("Cache-Control: no-store, no-cache, must-revalidate"); + header("Cache-Control: post-check=0, pre-check=0", false); + header("Pragma: no-cache"); + }/*}}}*/ + } +?> diff --git a/classes/file/FileHandler.class.php b/classes/file/FileHandler.class.php new file mode 100644 index 000000000..bbec5b2bb --- /dev/null +++ b/classes/file/FileHandler.class.php @@ -0,0 +1,94 @@ + + * @desc : 파일 시스템 관련 라이브러리 + **/ + + class FileHandler { + + // public String readFile()/*{{{*/ + function readFile($file_name) { + if(!file_exists($file_name)) return; + if(filesize($file_name)<1) return; + $fp = fopen($file_name, "r"); + $buff = fread($fp, filesize($file_name)); + fclose($fp); + return trim($buff); + }/*}}}*/ + + // public String writeFile($file_name, $buff, $mode = "w")/*{{{*/ + function writeFile($file_name, $buff, $mode = "w") { + $mode = strtolower($mode); + if($mode != "a") $mode = "w"; + if(@!$fp = fopen($file_name,$mode)) return; + fwrite($fp, $buff); + fclose($fp); + }/*}}}*/ + + // public array readDir($path, $filter = '', $to_lower = flase)/*{{{*/ + // $path내의 파일들을 return ('.', '..', '.로 시작하는' 파일들은 제외) + function readDir($path, $filter = '', $to_lower = false, $concat_prefix = false) { + if(substr($path,-1)!='/') $path .= '/'; + if(!is_dir($path)) return array(); + $oDir = dir($path); + while($file = $oDir->read()) { + if(substr($file,0,1)=='.') continue; + if($filter && !preg_match($filter, $file)) continue; + if($to_lower) $file = strtolower($file); + if($filter) $file = preg_replace($filter, '$1', $file); + else $file = $file; + + if($concat_prefix) $file = $path.$file; + $output[] = $file; + } + if(!$output) return array(); + return $output; + }/*}}}*/ + + // public boolean makeDir($path) {/*{{{*/ + // 디렉토리 생성 + function makeDir($path_string) { + $path_list = explode('/', $path_string); + + for($i=0;$iread()) { + if ($entry != "." && $entry != "..") { + if (is_dir($path."/".$entry)) { + FileHandler::removeDir($path."/".$entry); + } else { + @unlink($path."/".$entry); + } + } + } + $directory->close(); + @rmdir($path); + }/*}}}*/ + + // public string filesize($size) /*{{{*/ + // byte단위의 파일크기를 적절하게 변환해서 return + function filesize($size) { + if(!$size) return "0Byte"; + if($size<1024) return ($size."Byte"); + if($size >1024 && $size< 1024 *1024) return sprintf("%0.1fKB",$size / 1024); + return sprintf("%0.2fMB",$size / (1024*1024)); + }/*}}}*/ + + + } +?> diff --git a/classes/layout/LayoutHandler.class.php b/classes/layout/LayoutHandler.class.php new file mode 100644 index 000000000..2f14d7f1e --- /dev/null +++ b/classes/layout/LayoutHandler.class.php @@ -0,0 +1,45 @@ + + * @desc : layout 실행 + **/ + + class LayoutHandler { + + var $layout_info; + var $layout_name; + + function callLayout(&$oModule, $oModuleInfo) { + if($oModule->getActType() != 'disp') return; + if(!$oModuleInfo->isLayoutExists()) return; + + $oLayout = new LayoutHandler(); + $oLayout->proc($oModule, $oModuleInfo); + } + + function proc(&$oModule, $oModuleInfo) { + $this->layout_info = $oModuleInfo->getLayout(); + $this->layout_name = $this->layout_info->layout_name; + $this->layout_name = 'test'; + + // 해당 모듈을 읽어서 객체를 만듬 + $layout_file = sprintf('./layouts/%s/%s.layout.php', $this->layout_name, $this->layout_name); + + // 모듈 파일이 없으면 에러 + if(!file_exists($layout_file)) return; + + // 모듈 파일을 include + require_once($layout_file); + + // 선택된 모듈의 instance는 eval string으로 처리 + $eval_str = sprintf('$oLayout = new %s();', $this->layout_name); + eval($eval_str); + + // 애드온 실행 + $oLayout->proc($oModule, $oModuleInfo); + } + + + } +?> diff --git a/classes/module/Module.class.php b/classes/module/Module.class.php new file mode 100644 index 000000000..42eaf89aa --- /dev/null +++ b/classes/module/Module.class.php @@ -0,0 +1,132 @@ + + * @desc : modules의 abstract class + **/ + + // abstract class Module + class Module extends Output { + + // 현재 모듈의 실행 위치 + var $module_path = NULL; + + // skin 설정 (없을 경우도 있음) + var $skin = 'default'; + + // 현재 모듈 생성시 주어진 설정 정보들 + var $module_srl = NULL; + var $module_info = NULL; + + // 모듈의 action을 정의하는 변수 설정 + var $act = NULL; + var $act_type = 'disp'; + + // 레이아웃 path, tpl + var $layout_path = "./common/tpl/"; + var $layout_tpl = "default_layout"; + + // public void moduleInit($module_info)/*{{{*/ + // 모듈의 정보 세팅 + function moduleInit($module_info) { + // 브라우저 타이틀 지정 + Context::setBrowserTitle($module_info->browser_title?$module_info->browser_title:$module_info->mid); + + // 기본 변수 설정 + $this->module_info = $module_info; + context::set('module_info', &$this->module_info); + + $this->module_srl = $module_info->module_srl; + + // skin 설정 (기본으로는 default) + if($this->module_info->skin) $this->skin = $this->module_info->skin; + else $this->skin = 'default'; + + // 템플릿 위치 설정 + if(!$this->template_path) { + $template_path = $this->module_path.'skins/'.$this->skin; + $this->setTemplatePath($template_path); + } + }/*}}}*/ + + // public boolean isExistsAct($act)/*{{{*/ + // 현재 모듈에 $act에 해당하는 method가 있는지 체크 + function isExistsAct($act) { + return method_exists($this, $act); + }/*}}}*/ + + // public String getActType()/*{{{*/ + // 현재 acT_type의 return (disp/proc) + function getActType() { + return $this->act_type; + }/*}}}*/ + + // public void setModulePath($path)/*{{{*/ + // 현재 모듈의 path를 지정 + function setModulePath($path) { + if(substr($path,-1)!='/') $path.='/'; + $this->module_path = $path; + }/*}}}*/ + + // public boolean doError($msg_code) /*{{{*/ + function doError($msg_code) { + $this->setError(-1); + if(!Context::getLang($msg_code)) $this->setMessage($msg_code); + else $this->setMessage(Context::getLang($msg_code)); + return false; + }/*}}}*/ + + // public void setLayoutPath($path)/*{{{*/ + function setLayoutPath($path) { + $this->layout_path = $path; + }/*}}}*/ + + // public void setLayoutTpl($tpl)/*{{{*/ + function setLayoutTpl($tpl) { + $this->layout_tpl = $tpl; + }/*}}}*/ + + // public void proc($act = null)/*{{{*/ + //모듈의 각 action을 실행하는 부분 + //$act값에 의해서 $action_list에 선언된 것들을 실행한다 + function proc($act = null) { + + // 별도로 요청한 act가 없으면 주어진 act를 이용 + if($act) $this->act = $act; + else $this->act = Context::get('act'); + + // act의 종류가 disp/proc인지에 대한 확인 + if($this->act&&strtolower(substr($this->act,0,4)) != 'disp') $this->act_type = 'proc'; + + // act값이 없거나 존재하지 않는 method를 호출시에 default_act를 지정 + if(!$this->act || !$this->isExistsAct($this->act)) $this->act = $this->default_act; + + // module의 *init 호출 (기본 init과 proc/disp init 2가지 있음) + if($this->act_type == 'proc') { + $output = $this->procInit(); + if((is_a($output, 'Output') || is_subclass_of($output, 'Output')) && !$output->toBool() ) { + $this->setError($output->getError()); + $this->setMessage($output->getMessage()); + return; + } elseif(!$output) { + $this->setError(-1); + $this->setMessage('fail'); + return; + } + } else $this->dispInit(); + + // 기본 act조차 없으면 return + if(!$this->isExistsAct($this->act)) return false; + + // act값으로 method 실행 + $output = call_user_method($this->act, $this); + + if(is_a($output, 'Output') || is_subclass_of($output, 'Output')) { + $this->setError($output->getError()); + $this->setMessage($output->getMessage()); + } + + return true; + }/*}}}*/ + } +?> diff --git a/classes/module/ModuleHandler.class.php b/classes/module/ModuleHandler.class.php new file mode 100644 index 000000000..908a33b6b --- /dev/null +++ b/classes/module/ModuleHandler.class.php @@ -0,0 +1,87 @@ + + * @desc : mid의 값으로 모듈을 찾고 관련 정보들을 세팅 + **/ + + class ModuleHandler { + + // mid와 해당 mid의 설정 값 + var $mid = NULL; + var $module_info = NULL; + + // 모듈과 해당 모듈의 instance + var $module = NULL; + var $oModule = NULL; + + // public void ModuleHandler()/*{{{*/ + function ModuleHandler() { + + // 설치가 안되어 있다면 설치를 위한 준비 + if(!Context::isInstalled()) return $this->_prepareInstall(); + + // 설치가 되어 있다면 요청받은 mid에 해당하는 모듈 instance 생성 + // mid가 없이 document_srl만 있다면 document_srl로 mid를 찾음 + $mid = Context::get('mid'); + $document_srl = Context::get('document_srl'); + + // document_srl만 있다면 mid를 구해옴 + if(!$mid && $document_srl) { + $module_info = module_manager::getModuleInfoByDocument($document_srl); + if($module_info) $mid = $module_info->mid; + } + + // mid 값에 대한 모듈 정보를 추출 + if(!$module_info) $module_info = module_manager::getModuleInfo($mid); + + // 모듈 정보에서 module 이름을 구해움 + $module = $module_info->module; + + $this->mid = $module_info->mid; + $this->module_info = $module_info; + + Context::set('module', $module); + Context::set('mid', $this->mid, true); + Context::set('module_srl', $this->module_info->module_srl, true); + + // 만약 모듈이 없다면 오류 출력 + if(!$module) return $this->_moduleIsNotExists(); + + $this->oModule = getModule($module); + $this->module = $module; + }/*}}}*/ + + // private void _prepareInstall()/*{{{*/ + // 설치를 하기 위해서 mid, module등을 강제 지정 + function _prepareInstall() { + // module로 install 모듈을 지정 + $this->module = 'install'; + Context::set('mid', NULL); + Context::set('module', $this->module); + + // module_manager 호출 + $this->oModule = getModule($this->module); + }/*}}}*/ + + // private void _moduleIsNotExists()/*{{{*/ + // 아무런 설정이 되어 있지 않다면 오류 표시 + function _moduleIsNotExists() { + $this->module = 'message'; + Context::set('mid', NULL); + Context::set('module', $this->module); + + $this->oModule = getModule($this->module); + + Context::set('error', -1); + Context::set('message', Context::getLang('msg_mid_not_exists')); + }/*}}}*/ + + // public object proc()/*{{{*/ + function proc() { + $this->oModule->moduleInit($this->module_info); + $this->oModule->proc(); + return $this->oModule; + }/*}}}*/ + } +?> diff --git a/classes/output/Output.class.php b/classes/output/Output.class.php new file mode 100644 index 000000000..9f0fb3563 --- /dev/null +++ b/classes/output/Output.class.php @@ -0,0 +1,110 @@ + + * @desc : result 객체 + * request method에 따라서 error+message+variables[]를 xml문서로 + * 또는 html 출력을 + * 또는 사용법에 따라 error로 결과를 리턴한다 + * error != 0 이면 에러가 발생하였다는 것으로 정의 + **/ + + class Output { + + // template path 지정 + var $template_path = NULL; + var $template_file = NULL; + + // 기본 에러와 메세지 + var $error = 0; + var $message = 'success'; + + // 추가 변수 + var $variables = array(); + + // public void Output($error = 0, $message = 'success')/*{{{*/ + // error 코드를 지정 + function Output($error = 0, $message = 'success') { + $this->error = $error; + $this->message = $message; + }/*}}}*/ + + // public void setError($error)/*{{{*/ + // error 코드를 지정 + function setError($error = 0) { + $this->error = $error; + }/*}}}*/ + + // public string getError()/*{{{*/ + function getError() { + return $this->error; + }/*}}}*/ + + // public void setMessage($message)/*{{{*/ + // 메세지 지정 + function setMessage($message = 'success') { + if(Context::getLang($message)) $message = Context::getLang($message); + $this->message = $message; + return true; + }/*}}}*/ + + // public string getMessage()/*{{{*/ + // 메세지 지정 + function getMessage() { + return $this->message; + }/*}}}*/ + + // public void add($key, $val)/*{{{*/ + // xml문서를 작성시 필요한 key, val 추가 + function add($key, $val) { + $this->variables[$key] = $val; + }/*}}}*/ + + // public string get($key)/*{{{*/ + // 추가된 변수의 key에 해당하는 값을 return + function get($key) { + return $this->variables[$key]; + }/*}}}*/ + + // public array getVariables()/*{{{*/ + // 설정된 variables를 return + function getVariables() { + return $this->variables; + }/*}}}*/ + + // public boolean toBool()/*{{{*/ + // error값이 0이 아니면 오류 + function toBool() { + return $this->error==0?true:false; + }/*}}}*/ + + // public boolean toBoolean()/*{{{*/ + // error값이 0이 아니면 오류 + function toBoolean() { + return $this->toBool(); + }/*}}}*/ + + // public void setTemplatePath($path)/*{{{*/ + // 현재 모듈의 tpl 파일을 저장 + function setTemplatePath($path) { + if(!substr($path,-1)!='/') $path .= '/'; + $this->template_path = $path; + }/*}}}*/ + + // public string getTemplatePath()/*{{{*/ + // 설정된 template path를 return + function getTemplatePath() { + return $this->template_path; + }/*}}}*/ + + // public void setTemplateFile($filename)/*{{{*/ + function setTemplateFile($filename) { + $this->template_file = $filename; + }/*}}}*/ + + // public string getTemplateFile()/*{{{*/ + function getTemplateFile() { + return $this->template_file; + }/*}}}*/ + } +?> diff --git a/classes/page/PageHandler.class.php b/classes/page/PageHandler.class.php new file mode 100644 index 000000000..d68549200 --- /dev/null +++ b/classes/page/PageHandler.class.php @@ -0,0 +1,42 @@ + + * @desc : 페이지 처리 + **/ + + class PageHandler { + + var $total_count = 0; + var $total_page = 0; + var $cur_page = 0; + var $page_count = 10; + var $first_page = 1; + var $last_page = 1; + var $point = 0; + + function PageHandler($total_count, $total_page, $cur_page, $page_count = 10) { + $this->total_count = $total_count; + $this->total_page = $total_page; + $this->cur_page = $cur_page; + $this->page_count = $page_count; + $this->point = 0; + + $first_page = $cur_page-(int)($page_count/2); + if($first_page<1) $first_page = 1; + $last_page = $first_page+$page_count-1; + if($last_page>$total_page) $last_page = $total_page; + + $this->first_page = $first_page; + $this->last_page = $last_page; + } + + function getNextPage() { + $page = $this->first_page+$this->point++; + if($page > $this->last_page) $page = 0; + return $page; + } + + } + +?> diff --git a/classes/template/TemplateHandler.class.php b/classes/template/TemplateHandler.class.php new file mode 100644 index 000000000..6b8ab2c70 --- /dev/null +++ b/classes/template/TemplateHandler.class.php @@ -0,0 +1,286 @@ + + * @desc : 템플릿 컴파일 + **/ + + class TemplateHandler { + + var $compiled_path = './files/template_compiled/'; + + var $tpl_path = ''; + var $tpl_file = ''; + + // public string compile($tpl_path, $tpl_filename)/*{{{*/ + function compile($tpl_path, $tpl_filename) { + $this->tpl_path = $tpl_path; + + // 디버그를 위한 컴파일 시작 시간 저장 + if(__DEBUG__) $start = getMicroTime(); + + // 변수 체크 + if(substr($tpl_path,-1)!='/') $tpl_path .= '/'; + if(substr($tpl_filename,-5)!='.html') $tpl_filename .= '.html'; + + // tpl_file 변수 생성 + $tpl_file = $tpl_path.$tpl_filename; + + // tpl_file이 비어 있거나 해당 파일이 없으면 return + if(!$tpl_file || !file_exists($tpl_file)) return; + + $this->tpl_file = $tpl_file; + + // compiled된(or 될) 파일이름을 구함 + $compiled_tpl_file = $this->_getCompiledFileName($tpl_file); + + // 일단 컴파일 + $buff = $this->_compile($tpl_file, $compiled_tpl_file); + + if(__DEBUG__) { + $template_elapsed = getMicroTime() - $start; + $GLOBALS['__template_elapsed__'] += $template_elapsed; + } + + // Context와 compiled_tpl_file로 컨텐츠 생성 + $output = $this->_fetch($compiled_tpl_file, $buff); + + // 컴파일된 파일을 실행 + return $output; + }/*}}}*/ + + // private void _compile($tpl_file, $compiled_tpl_file)/*{{{*/ + // tpl_file이 컴파일이 되어 있는 것이 있는지 체크 + function _compile($tpl_file, $compiled_tpl_file) { + if(!file_exists($compiled_tpl_file)) return $this->_compileTplFile($tpl_file, $compiled_tpl_file); + + $source_ftime = filectime($tpl_file); + $target_ftime = filectime($compiled_tpl_file); + if($source_ftime>$target_ftime) return $this->_compileTplFile($tpl_file, $compiled_tpl_file); + }/*}}}*/ + + // private void _compileTplFile($tpl_file, $compiled_tpl_file)/*{{{*/ + // tpl_file을 compile + function _compileTplFile($tpl_file, $compiled_tpl_file) { + + // tpl 파일을 읽음 + $buff = FileHandler::readFile($tpl_file); + if(!$buff) return; + + // 변수를 변경 + $buff = preg_replace_callback('/\{[^@^ ]([^\}]+)\}/i', array($this, '_compileVarToContext'), $buff); + + // 이미지 태그 img의 src의 값이 ./ 로 시작하면 {$tpl_path}로 변경 + $buff = preg_replace_callback('!src=[\'"]{1}(.*?)[\'"]{1}!is', array($this, '_compileImgPath'), $buff); + + // 함수를 변경 + $buff = preg_replace_callback('/\{\@([^\}]+)\}/i', array($this, '_compileVarToFunc'), $buff); + + // 의 변경 + $buff = preg_replace_callback('!<\!--@(.*?)-->!is', array($this, '_compileFuncToCode'), $buff); + + // include 변경 + $buff = preg_replace_callback('!<\!--#include\(([^\)]*?)\)-->!is', array($this, '_compileIncludeToCode'), $buff); + + // import xml filter/ css/ js + $buff = preg_replace_callback('!<\!--%import\(\"([^\"]*?)\"\)-->!is', array($this, '_compileImportCode'), $buff); + + // 파일에 쓰기 전에 직접 호출되는 것을 방지 + $buff = sprintf('%s%s%s','',"\n",$buff); + + // 컴파일된 코드를 파일에 저장 + FileHandler::writeFile($compiled_tpl_file, $buff); + + return $buff; + }/*}}}*/ + + // private string _compileVarToContext($matches)/*{{{*/ + // {$와 } 안의 $... 변수를 Context::get(...) 으로 변경 + function _compileVarToContext($matches) { + $str = trim(substr($matches[0],1,strlen($matches[0])-2)); + return ']+)/i','$__Context->\\1', $str).');?>'; + }/*}}}*/ + + // private string _compileImgPath($matches)/*{{{*/ + // {$와 } 안의 $... 변수를 Context::get(...) 으로 변경 + function _compileImgPath($matches) { + $str1 = $matches[0]; + $str2 = $matches[1]; + $path = $str2; + if(!eregi("^\.\/(images|img)",$path)) return $str1; + + $path = 'tpl_path?>'.substr($path,2); + return str_replace($str2, $path, $str1); + }/*}}}*/ + + // private string _compileVarToFunc($matches)/*{{{*/ + // {@와 } 안의 @... 함수를 print func(..)로 변경 + function _compileVarToFunc($matches) { + return ']+)/i','$__Context->\\1', trim($matches[1])).');?>'; + }/*}}}*/ + + // private string _compileFuncToCode($matches)/*{{{*/ + // 사이의 구문을 php코드로 변경 + function _compileFuncToCode($matches) { + $code = trim($matches[1]); + if(!$code) return; + switch(strtolower($code)) { + case 'else' : + $output = '}else{'; + break; + case 'end' : + case 'endif' : + case 'endfor' : + case 'endforeach' : + $output = '}'; + break; + default : + if(substr($code,0,4)=='else') { + $code = '}'.$code; + } elseif(substr($code,0,7)=='foreach') { + $tmp_str = substr($code,8); + $tmp_arr = explode(' ', $tmp_str); + $var_name = $tmp_arr[0]; + if(substr($var_name,0,1)=='$') $prefix = sprintf('if(is_array($__Context->%s)) ', substr($var_name,1)); + else $prefix = sprintf('if(is_array(%s)) ', $var_name); + } + $output = preg_replace('/\$([a-zA-Z0-9\_\-]+)/i','$__Context->\\1', $code).'{'; + break; + } + + return sprintf('', $prefix, $output); + }/*}}}*/ + + // private string _compileIncludeToCode($matches)/*{{{*/ + // 를 변환 + function _compileIncludeToCode($matches) { + // include하려는 대상문자열에 변수가 있으면 변수 처리 + $arg = str_replace(array('"','\''), '', $matches[1]); + if(!$arg) return; + + $tmp_arr = explode("/", $arg); + for($i=0;$itpl_file), $arg); + + // 2단계로 root로부터 경로를 체크 + if(!file_exists($filename)) $filename = './'.$arg; + if(!file_exists($filename)) return; + + // path, filename으로 분리 + $tmp_arr = explode('/', $filename); + $filename = array_pop($tmp_arr); + $path = implode('/', $tmp_arr).'/'; + + // include 시도 + $output = sprintf( + 'compile(\'%s\',\'%s\');%s'. + '?>%s', + "\n", + "\n", + $path, + $filename, + "\n", + "\n" + ); + return $output; + }/*}}}*/ + + // private string _compileImportCode($matches)/*{{{*/ + // 의 확장자를 봐서 js filter/ css/ js 파일을 include하도록 수정 + function _compileImportCode($matches) { + // 현재 tpl 파일의 위치를 구해서 $base_path에 저장하여 적용하려는 xml file을 찾음 + $base_path = dirname($this->tpl_file).'/'; + $given_file = trim($matches[1]); + if(!$given_file) return; + $filename = sprintf("%s%s",$base_path, $given_file); + + // path와 파일이름을 구함 + $tmp_arr = explode("/",$filename); + $filename = array_pop($tmp_arr); + + $base_path = implode("/",$tmp_arr)."/"; + + // 확장자를 구함 + $tmp_arr = explode(".",$filename); + $ext = strtolower(array_pop($tmp_arr)); + + // 확장자에 따라서 파일 import를 별도로 + switch($ext) { + // xml js filter + case 'xml' : + // XmlJSFilter 클래스의 객체 생성후 js파일을 만들고 Context::addJsFile처리 + $output = sprintf( + 'compile();%s'. + '?>%s', + "\n", + "\n", + $base_path, + $filename, + "\n", + "\n", + "\n" + ); + break; + // css file + case 'css' : + $output = sprintf('', $base_path, $filename); + break; + // js file + case 'js' : + $output = sprintf('', $base_path, $filename); + break; + } + + return $output; + }/*}}}*/ + + // private string _getComliedFileName($tpl_file) /*{{{*/ + // $tpl_file로 compiled_tpl_file이름을 return + function _getCompiledFileName($tpl_file) { + return sprintf('%s%s.compiled.php',$this->compiled_path, md5($tpl_file)); + }/*}}}*/ + + // private string _fetch($compiled_tpl_file)/*{{{*/ + // ob_* 함수를 이용하여 fetch... + function _fetch($compiled_tpl_file, $buff = NULL) { + $__Context = &$GLOBALS['__Context__']; + + if($_SESSION['is_logged']) $__Context->logged_info->$_SESSION['logged_info']; + + // ob_start를 시킨후 컴파일된 tpl파일을 include하고 결과를 return + ob_start(); + // tpl파일을 compile하지 못할 경우 $buff로 넘어온 값을 eval시킴 (미설치시에나..) + if($buff) { + $eval_str = "?>".$buff; + eval($eval_str); + } else { + @include $compiled_tpl_file; + } + $output = ob_get_contents(); + ob_end_clean(); + + return $output; + }/*}}}*/ + + } +?> diff --git a/classes/xml/XmlJsFilter.class.php b/classes/xml/XmlJsFilter.class.php new file mode 100644 index 000000000..7a2e92f4b --- /dev/null +++ b/classes/xml/XmlJsFilter.class.php @@ -0,0 +1,158 @@ + + * @desc : filter xml문서를 해석하여 js파일로 만듬 + * filter xml은 tpl 파일과 같은 위치에 있어야 함 + * + * <-- 폼 항목의 체크 + * + * + * <-- 폼 항목을 조합하여 key=val 의 js array로 return, act는 필수 + * + * + * <-- 서버에 ajax로 전송하여 받을 결과값 + * <-- error이름의 결과값을 받겠다는 것 + * + * + * + * - field + * target = 폼 element의 이름 + * required = true/ false 꼭 있어야 하는지에 대한 체크 + * minlength, maxlength = 최소/최대 길이 + * filter = javascript로 체크하기 위한 체크 필터 + * email : email의 형식 ( aaa.aaa@aaa.com) + * userid : 영문+숫자+_, 첫 글자는 영문, 소문자 + * alpha : 영문값만 허용 + * number : 숫자만 허용 + * equalto = target , 현재 폼과 지정 target의 값이 동일해야 함 + * - parameter + * param = key : key를 이름으로 가지고 value의 값을 가지는 array 값 생성 + * value = target : target form element의 값을 가져옴 + * concat = str1,str2,target2... : 값들의 string 또는 form element value를 연결 + * - response + * name = key : return받을 결과값의 변수명 + **/ + + class XmlJsFilter { + var $compiled_path = './files/js_filter_compiled/'; + var $xml_file = NULL; + var $js_file = NULL; + + // public void XmlJsFilter($path, $xml_file)/*{{{*/ + function XmlJsFilter($path, $xml_file) { + $this->xml_file = sprintf("%s%s",$path, $xml_file); + $this->js_file = $this->_getCompiledFileName($this->xml_file); + }/*}}}*/ + + // public void compile()/*{{{*/ + // 원 xml파일과 compiled된js파일의 시간 비교 및 유무 비교등을 처리 + function compile() { + if(!file_exists($this->xml_file)) return; + if(!file_exists($this->js_file)) $this->_compile(); + if(filectime($this->xml_file)>filectime($this->js_file)) $this->_compile(); + $this->_compile(); + Context::addJsFile($this->js_file); + }/*}}}*/ + + // private void _compile()/*{{{*/ + // 실제 xml_file을 컴파일하여 js_file을 생성 + function _compile() { + global $lang; + + // xml 파일을 읽음 + $buff = FileHandler::readFile($this->xml_file); + + // xml parsing + $oXml = new XmlParser(); + $xml_obj = $oXml->parse($buff); + + // XmlJsFilter는 filter_id, field, parameter 3개의 데이터를 핸들링 + $filter_id = $xml_obj->filter->attrs->id; + $confirm_msg_code = $xml_obj->filter->attrs->confirm_msg_code; + $field_item = $xml_obj->filter->field->item; + $parameter_item = $xml_obj->filter->parameter->item; + $response_item = $xml_obj->filter->response->item; + + // 언어 입력을 위한 사용되는 필드 조사 + $target_list = array(); + + // js function 을 만들기 시작 + $js_doc = sprintf("function %s(fo_obj, callback_user_func) {\n", $filter_id); + $js_doc .= "\tvar oFilter = new XmlJsFilter(fo_obj, callback_user_func);\n"; + + // field, 즉 체크항목의 script 생성 + $field_cnt = count($field_item); + if($field_cnt) { + foreach($field_item as $key =>$field_obj) { + $attrs = $field_obj->attrs; + $target = trim($attrs->target); + if(!$target) continue; + $required = $attrs->required=='true'?'true':'false'; + $minlength = $attrs->minlength>0?$attrs->minlength:'0'; + $maxlength = $attrs->maxlength>0?$attrs->maxlength:'0'; + $equalto = trim($attrs->equalto); + $filter = $attrs->filter; + + $js_doc .= sprintf( + "\toFilter.addFieldItem(\"%s\",%s,%s,%s,\"%s\",\"%s\");\n", + $target, $required, $minlength, $maxlength, $equalto, $filter + ); + + if(!in_array($target, $target_list)) $target_list[] = $target; + } + } + + // 데이터를 만들기 위한 parameter script 생성 + $parameter_cnt = count($parameter_item); + if($parameter_cnt) { + foreach($parameter_item as $key =>$parameter_obj) { + $attrs = $parameter_obj->attrs; + $param = trim($attrs->param); + $target = trim($attrs->target); + if(!$param || !$target) continue; + $target = htmlentities($target,ENT_QUOTES); + $js_doc .= sprintf( + "\toFilter.addParameterItem(\"%s\",\"%s\");\n", + $param, $target + ); + if(!in_array($param, $target_list)) $target_list[] = $param; + } + } + + // response script 생성 + $response_cnt = count($response_item); + for($i=0;$i<$response_cnt;$i++) { + $attrs = $response_item[$i]->attrs; + $name = $attrs->name; + $js_doc .= sprintf("\toFilter.addResponseItem(\"%s\");\n", $name); + } + + if($confirm_msg_code) $js_doc .= sprintf("\treturn oFilter.proc(\"%s\");\n",str_replace('"','\"',$lang->{$confirm_msg_code})); + else $js_doc .= sprintf("\treturn oFilter.proc();\n"); + $js_doc .= "}\n"; + + // form 필드 lang 값을 기록 + $target_cnt = count($target_list); + for($i=0;$i<$target_cnt;$i++) { + $target = $target_list[$i]; + $js_doc .= sprintf("alertMsg[\"%s\"] = \"%s\"\n", $target, str_replace("\"","\\\"",$lang->{$target})); + } + + // 에러 메세지를 기록 + foreach($lang->filter as $key => $val) { + $js_doc .= sprintf("alertMsg[\"%s\"] = \"%s\";\n", $key, str_replace("\"","\\\"",$val)); + } + + // js파일 생성 + FileHandler::writeFile($this->js_file, $js_doc); + }/*}}}*/ + + // private string _getCompiledFileName($xml_file) /*{{{*/ + // $xml_file로 compiled_xml_file이름을 return + function _getCompiledFileName($xml_file) { + return sprintf('%s%s.%s.compiled.js',$this->compiled_path, md5($xml_file),Context::getLangType()); + }/*}}}*/ + } +?> diff --git a/classes/xml/XmlParser.class.php b/classes/xml/XmlParser.class.php new file mode 100644 index 000000000..cc95a3f00 --- /dev/null +++ b/classes/xml/XmlParser.class.php @@ -0,0 +1,111 @@ + + * @desc : xmlrpc를 해석하여 object로 return 하는 simple xml parser + **/ + + class XmlParser { + + var $oParser = NULL; + + var $input = NULL; + var $output = array(); + + var $lang = "en"; + + // public object loadXmlFile($filename)/*{{{*/ + function loadXmlFile($filename) { + if(!file_exists($filename)) return; + + $buff = FileHandler::readFile($filename); + + $oXmlParser = new XmlParser(); + return $oXmlParser->parse($buff); + }/*}}}*/ + + // public void parse($input)/*{{{*/ + function parse($input = '') { + $this->lang = Context::getLangType(); + + $this->input = $input?$input:$GLOBALS['HTTP_RAW_POST_DATA']; + + // 지원언어 종류를 뽑음 + preg_match_all("/xml:lang=\"([^\"].+)\"/i", $this->input, $matches); + + // xml:lang이 쓰였을 경우 지원하는 언어종류를 뽑음 + if(count($matches[1]) && $supported_lang = array_unique($matches[1])) { + // supported_lang에 현재 접속자의 lang이 없으면 en이 있는지 확인하여 en이 있으면 en을 기본, 아니면 첫번째것을.. + if(!in_array($this->lang, $supported_lang)) { + if(in_array('en', $supported_lang)) { + $this->lang = 'en'; + } else { + $this->lang = array_shift($supported_lang); + } + } + // 특별한 언어가 지정되지 않았다면 언어체크를 하지 않음 + } else { + unset($this->lang); + } + + + $this->oParser = xml_parser_create(); + + xml_set_object($this->oParser, $this); + xml_set_element_handler($this->oParser, "_tagOpen", "_tagClosed"); + xml_set_character_data_handler($this->oParser, "_tagBody"); + + xml_parse($this->oParser, $this->input); + xml_parser_free($this->oParser); + + if(!count($this->output)) return; + return array_shift($this->output); + }/*}}}*/ + + // private void _tagOpen($parser, $node_name, $attrs)/*{{{*/ + function _tagOpen($parser, $node_name, $attrs) { + $obj->node_name = strtolower($node_name); + $obj->attrs = $this->_arrToObj($attrs); + + array_push($this->output, $obj); + }/*}}}*/ + + // private void _tagBody($parser, $body)/*{{{*/ + function _tagBody($parser, $body) { + if(!trim($body)) return; + $this->output[count($this->output)-1]->body .= $body; + }/*}}}*/ + + // private void _tagClosed($parser, $node_name)/*{{{*/ + function _tagClosed($parser, $node_name) { + $node_name = strtolower($node_name); + $cur_obj = array_pop($this->output); + $parent_obj = &$this->output[count($this->output)-1]; + if($this->lang&&$cur_obj->attrs->{'xml:lang'}&&$cur_obj->attrs->{'xml:lang'}!=$this->lang) return; + if($this->lang&&$parent_obj->{$node_name}->attrs->{'xml:lang'}&&$parent_obj->{$node_name}->attrs->{'xml:lang'}!=$this->lang) return; + + if($parent_obj->{$node_name}) { + $tmp_obj = $parent_obj->{$node_name}; + if(is_array($tmp_obj)) { + array_push($parent_obj->{$node_name}, $cur_obj); + } else { + $parent_obj->{$node_name} = array(); + array_push($parent_obj->{$node_name}, $tmp_obj); + array_push($parent_obj->{$node_name}, $cur_obj); + } + } else { + $parent_obj->{$node_name} = $cur_obj; + } + }/*}}}*/ + + // private void _arrToObj($arr)/*{{{*/ + function _arrToObj($arr) { + if(!count($arr)) return; + foreach($arr as $key => $val) { + $key = strtolower($key); + $output->{$key} = $val; + } + return $output; + }/*}}}*/ + } +?> diff --git a/classes/xml/XmlQueryParser.class.php b/classes/xml/XmlQueryParser.class.php new file mode 100644 index 000000000..5fc01051f --- /dev/null +++ b/classes/xml/XmlQueryParser.class.php @@ -0,0 +1,340 @@ + + * @desc : query xml을 파싱하여 결과를 return + **/ + + class XmlQueryParser { + + // 조건문에서 조건을 등호로 표시하는 변수 + var $cond_operation = array( + 'equal' => '=', + 'more' => '>=', + 'excess' => '>', + 'less' => '<=', + 'below' => '<', + 'notequal' => '!=', + 'notnull' => 'is not null', + 'null' => 'is null', + ); + + // private string parse($query_id, $xml_file, $cache_file)/*{{{*/ + // 쿼리 파일을 찾아서 파싱하고 cacheing한다 + function parse($query_id, $xml_file, $cache_file) { + // query xml 파일을 찾아서 파싱, 결과가 없으면 return + $buff = FileHandler::readFile($xml_file); + $oXml = new XmlParser(); + $xml_obj = $oXml->parse($buff); + if(!$xml_obj) return; + + // 쿼리 스크립트를 만들때 필요한 변수들 + $filter_script = $notnull_script = $column_script = $default_script = ''; + + // insert, update, delete, select등의 action + $action = strtolower($xml_obj->query->attrs->action); + if(!$action) return; + + // 테이블 정리 (배열코드로 변환) + $tables = $this->_getTablesScript($xml_obj); + + // 컬럼 정리 + $column_script = $this->_getColumnsScript($xml_obj, $default_script, $notnull_script, $filter_script, $action); + + // 조건절 정리 + $condition_script = $this->_getConditionScript($xml_obj, $default_script, $notnull_script, $filter_script); + + // group 정리 + $group_script = $this->_getGroupScript($xml_obj); + + // 네비게이션 정리 + $navigation_script = $this->_getNavigationScript($xml_obj); + + // 캐쉬 내용 작성 + $buff = + sprintf( + '', + $query_id, + $action, + $tables, + $default_script, + $column_script, + $notnull_script, + $filter_script, + $condition_script, + $navigation_script, + $group_script + ); + + // 저장 + FileHandler::writeFile($cache_file, $buff); + }/*}}}*/ + + // private string _getDefaultCode($name, $value)/*{{{*/ + function _getDefaultCode($name, $value) { + if(!$value) return; + if(substr($value, -1)!=')') return sprintf('if(!$args->%s) $args->%s = \'%s\';'."\n", $name, $name, $value); + + $str_pos = strpos($value, '('); + $func_name = substr($value, 0, $str_pos); + $args = substr($value, $str_pos+1, strlen($value)-1); + + switch($func_name) { + case 'ipaddress' : + $val = '\''.$_SERVER['REMOTE_ADDR'].'\''; + break; + case 'unixtime' : + $val = 'time()'; + break; + case 'curdate' : + $val = 'date("YmdHis")'; + break; + case 'sequence' : + $val = '$this->getNextSequence()'; + break; + case 'plus' : + $args = abs($args); + $val = sprintf('\'%s+%d\'', $name, $args); + $pass_quotes = true; + break; + case 'minus' : + $args = abs($args); + $val = sprintf('\'%s-%d\'', $name, $args); + $pass_quotes = true; + break; + } + + $output = sprintf('if(!$args->%s) $args->%s = %s;'."\n", $name, $name, $val); + if($pass_quotes) $output .= sprintf('$pass_quotes[] = \'%s\';'."\n",$name); + return $output; + }/*}}}*/ + + // private string _getFilterCode($key, $type, $minlength, $maxlength, $var='column')/*{{{*/ + function _getFilterCode($key, $type, $minlength, $maxlength, $var='column', $notnull='') { + if(!$type||!$minlength||!$maxlength) return; + if(!$notnull) $notnull_code = sprintf('if($%s->%s) ', $var, $key); + return + sprintf('unset($output); %s$output = $this->_checkFilter(\'%s\', $%s->%s, \'%s\', \'%d\', \'%d\'); if(!$output->toBool()) return $output;'."\n", + $notnull_code, + $key, + $var, + $key, + $type, + (int)$minlength, + (int)$maxlength + ); + }/*}}}*/ + + // private string _getNotNullCode($name)/*{{{*/ + function _getNotNullCode($name, $var='column') { + return + sprintf('if(!$%s->%s) return new Output(-1, sprintf($lang->filter->isnull, $lang->%s?$lang->%s:\'%s\'));'."\n", + $var, + $name, + $name, + $name, + $name + ); + }/*}}}*/ + + // private string _getTablesScript($xml_obj) /*{{{*/ + function _getTablesScript($xml_obj) { + $obj_tables = $xml_obj->query->tables->table; + if(!is_array($obj_tables)) $obj_tables = array('', $obj_tables); + + foreach($obj_tables as $table_info) { + $name = trim($table_info->attrs->name); + if(!$name) continue; + $alias = trim($table_info->attrs->alias); + if(!$alias) $alias = $name; + $table_list[] = sprintf('\'%s\'=>\'%s\'', $name, $alias); + } + return implode(",",$table_list); + }/*}}}*/ + + // private string _getColumnsScript($xml_obj, &$default_script, &$notnull_script, &$filter_script, $action)/*{{{*/ + function _getColumnsScript($xml_obj, &$default_script, &$notnull_script, &$filter_script, $action) { + $obj_columns = $xml_obj->query->columns->column; + if(!is_array($obj_columns)) $obj_columns = array('', $obj_columns); + + foreach($obj_columns as $column_info) { + $name = trim($column_info->attrs->name); + if(!$name || $name == '*') continue; + + $var = trim($column_info->attrs->var); + $alias = trim($column_info->attrs->alias); + if(!$alias) $alias = $name; + $default = trim($column_info->attrs->default); + $notnull = trim($column_info->attrs->notnull); + + $filter_type = trim($column_info->attrs->filter); + $minlength = (int)trim($column_info->attrs->minlength); + $maxlength = (int)trim($column_info->attrs->maxlength); + + $column_script .= sprintf('$column->%s = $args->%s;'."\n", $alias, $var?$var:$alias); + $invert_columns[] = sprintf('\'%s\'=>\'%s\'', $alias, $name); + + $default_script .= $this->_getDefaultCode($alias, $default); + if($action != 'select') { + if($filter_type) $filter_script .= $this->_getFilterCode($alias, $filter_type, $minlength, $maxlength, 'column', $notnull); + if($notnull) $notnull_script .= $this->_getNotNullCode($alias); + } + } + if(is_array($invert_columns)) $column_script .= sprintf('$invert_columns = array(%s);'."\n", implode(',',$invert_columns)); + return $column_script; + }/*}}}*/ + + // private string _getConditionScript($xml_obj, &$default_script, &$notnull_script, &$filter_script)/*{{{*/ + function _getConditionScript($xml_obj, &$default_script, &$notnull_script, &$filter_script) { + $cond_idx = 0; + + $obj_conditions = $xml_obj->query->conditions->condition; + + $condition_script = $condition = $this->_getConditionQuery($cond_idx++, $obj_conditions, NULL, $notnull_script, $filter_script); + + $obj_groups = $xml_obj->query->conditions->group; + if(!is_array($obj_groups)) $obj_groups = array('', $obj_groups); + + foreach($obj_groups as $obj_group) { + $group_pipe = $obj_group->attrs->pipe; + if(!$group_pipe) continue; + $buff = $this->_getConditionQuery($cond_idx++, $obj_group->condition, $group_pipe, $notnull_script, $filter_script); + $condition_script .= $buff; + } + + $condition_script .= '$condition = $this->_combineCondition($cond_group, $group_pipe);'."\n"; + return $condition_script; + }/*}}}*/ + + // private string _getConditionQuery($cond_idx, $obj, $group_pipe, &$notnull_script, &$filter_script) /*{{{*/ + // 조건문의 쿼리를 만들어 줌 + function _getConditionQuery($cond_idx, $obj, $group_pipe, &$notnull_script, &$filter_script) { + if(!is_array($obj)) $obj = array('', $obj); + + $idx = 0; + foreach($obj as $obj_cond) { + $operation = $obj_cond->attrs->operation; + if(!$operation) continue; + + $column = $obj_cond->attrs->column; + $var = $obj_cond->attrs->var; + $filter = $obj_cond->attrs->filter; + $notnull = $obj_cond->attrs->notnull; + $pipe = $obj_cond->attrs->pipe; + if(!$pipe) $pipe = 'and'; + $default = $obj_cond->attrs->default; + + // 비교 대상이 다른 혹은 같은 테이블의 column일 경우 + if(eregi("\.", $var)) { + switch($operation) { + case 'in' : + $buff = sprintf('%s in (%s)', $column, $var); + break; + default : + $operation = $this->cond_operation[$operation]; + if(!$operation) $operation = 'and'; + $buff = sprintf('%s %s %s', $column, $operation, $var); + break; + } + $condition_script .= sprintf('$cond_group[%d][][\'%s\'] = \'%s\';'."\n",$cond_idx, $pipe, $buff); + + // 입력받을 변수일 경우 + } else { + switch($operation) { + case 'like' : + $buff = sprintf('sprintf("%s like \'%%%%%%s%%%%\' ", $this->addQuotes($args->%s))', $column, $var); + break; + case 'like_prefix' : + $buff = sprintf('sprintf("%s like \'%%s%%%%\' ", $this->addQuotes($args->%s))', $column, $var); + break; + case 'in' : + $buff = sprintf('sprintf("%s in (%%s) ", $this->addQuotes($args->%s))', $column, $var); + break; + case 'notnull' : + case 'null' : + $operation = $this->cond_operation[$operation]; + unset($var); + $buff = sprintf('"%s %s "', $column, $operation); + break; + default : + $operation = $this->cond_operation[$operation]; + if($default) $buff = sprintf('sprintf("%s %s \'%%s\' ", $args->%s?$this->addQuotes($args->%s):\'%s\')', $column, $operation, $var?$var:$column, $var?$var:$column, $default); + else $buff = sprintf('sprintf("%s %s \'%%s\' ", $this->addQuotes($args->%s))', $column, $operation, $var?$var:$column); + break; + } + $buff = sprintf('$cond_group[%d][][\'%s\'] = %s;'."\n",$cond_idx, $pipe, $buff); + + if(!$notnull && $var) $buff = sprintf('if($args->%s) ', $var).$buff; + $condition_script .= $buff; + if($notnull) $notnull_script .= $this->_getNotNullCode($var?$var:$column, 'args'); + if($filter) $filter_script .= $this->_getFilterCode($var, $filter, 0, 0, 'args', $notnull); + } + } + $condition_script .= sprintf('$group_pipe[%d] = \'%s\';'."\n", $cond_idx, $group_pipe); + return $condition_script; + }/*}}}*/ + + // private string _getGroupScript($xml_obj)/*{{{*/ + function _getGroupScript($xml_obj) { + $group_list = $xml_obj->query->groups->group; + if(!$group_list) return; + if(!is_array($group_list)) $group_list = array($group_list); + for($i=0;$iattrs->column); + if(!$column) continue; + $group_column_list[] = $column; + } + if(count($group_column_list)) { + return ' group by '.implode(" , ", $group_column_list); + } + }/*}}}*/ + + // private string _getNavigationScript($xml_obj) /*{{{*/ + function _getNavigationScript($xml_obj) { + $obj_navigation = $xml_obj->query->navigation; + if(!$obj_navigation) return; + + $obj_index = $obj_navigation->index->attrs; + $index_list = array(); + if(!is_array($obj_index)) $obj_index = array('', $obj_index); + foreach($obj_index as $index_info) { + $var = trim($index_info->var); + if(!$var) continue; + $default = trim($index_info->default); + $order = trim($index_info->order); + if(!$order) $order = 'asc'; + + $navigation_script .= sprintf('$navigation->index[] = array($args->%s?$args->%s:\'%s\', \'%s\');'."\n", $var, $var, $default, $order); + } + + $obj_list_count = $obj_navigation->list_count->attrs; + $count_var = $obj_list_count->var; + $count_default = $obj_list_count->default; + if($count_var) $navigation_script .= sprintf('$navigation->list_count = $args->%s?$args->%s%s;'."\n", $count_var, $count_var, $count_default?':'.$count_default:''); + + $obj_page_count = $obj_navigation->page_count->attrs; + $count_var = $obj_page_count->var; + $count_default = $obj_page_count->default; + if($count_var) $navigation_script .= sprintf('$navigation->page_count = $args->%s?$args->%s%s;'."\n", $count_var, $count_var, $count_default?':'.$count_default:''); + + $obj_page = $obj_navigation->page->attrs; + $page_var = $obj_page->var; + $page_default = $obj_page->default; + if($page_var) $navigation_script .= sprintf('$navigation->page = $args->%s?$args->%s%s;'."\n", $page_var, $page_var, $page_default?':'.$page_default:''); + return $navigation_script; + }/*}}}*/ + } +?> diff --git a/common/css/default.css b/common/css/default.css new file mode 100644 index 000000000..0273c3871 --- /dev/null +++ b/common/css/default.css @@ -0,0 +1,42 @@ +#waitingforserverresponse { + display:inline; + border:2px solid #444444; + background-color:#FFFFFF; + padding:15px 20px 13px 20px; + font-weight:bold; + font-size:9pt; + color:#444444; + top:40px; + left:40px; + position:absolute; + z-index:100; + visibility:hidden; +} + +A.bold { + font-weight:bold; +} + +A.editor_blue_text:link { color: #17B1B7; text-decoration:none; border-bottom:2px solid #17B1B7;} +A.editor_blue_text:visited { color: #17B1B7; text-decoration:none; border-bottom:2px solid #17B1B7;} +A.editor_blue_text:active { color: #17B1B7; text-decoration:none; border-bottom:2px solid #17B1B7;} +A.editor_blue_text:hover { color: #17B1B7; text-decoration:none; border-bottom:2px solid #17B1B7;} + +A.editor_red_text:link { color: #B71717; text-decoration:none; border-bottom:2px solid #B71717; } +A.editor_red_text:visited { color: #B71717; text-decoration:none; border-bottom:2px solid #B71717;} +A.editor_red_text:active { color: #B71717; text-decoration:none; border-bottom:2px solid #B71717;} +A.editor_red_text:hover { color: #B71717; text-decoration:none; border-bottom:2px solid #B71717;} + +A.editor_yellow_text:link { color: #6A8308; text-decoration:none; border-bottom:2px solid #6A8308; } +A.editor_yellow_text:visited { color: #6A8308; text-decoration:none; border-bottom:2px solid #6A8308;} +A.editor_yellow_text:active { color: #6A8308; text-decoration:none; border-bottom:2px solid #6A8308;} +A.editor_yellow_text:hover { color: #6A8308; text-decoration:none; border-bottom:2px solid #6A8308;} + +A.editor_green_text:link { color: #08830B; text-decoration:none; border-bottom:2px solid #08830B;} +A.editor_green_text:visited { color: #08830B; text-decoration:none; border-bottom:2px solid #08830B;} +A.editor_green_text:active { color: #08830B; text-decoration:none; border-bottom:2px solid #08830B;} +A.editor_green_text:hover { color: #08830B; text-decoration:none; border-bottom:2px solid #08830B;} + +.folder_opener { display: block; } +.folder_closer { display: none; } +.folder_area { display: none; } diff --git a/common/js/common.js b/common/js/common.js new file mode 100644 index 000000000..495fececb --- /dev/null +++ b/common/js/common.js @@ -0,0 +1,122 @@ +/** + * 몇가지 유용한 & 기본적으로 자주 사용되는 자바스크립트 함수들 모음 + **/ + +// string prototype으로 trim 함수 추가 +String.prototype.trim = function() {/*{{{*/ + return this.replace(/(^\s*)|(\s*$)/g, ""); +}/*}}}*/ + +// 주어진 인자가 하나라도 defined되어 있지 않으면 false return +function isDef() {/*{{{*/ + for(var i=0; i"+ + "document.writeln(\""+ + ""+ + ""+ + ""+ + ""+ + "<\/object>"+ + "\");"+ + ""; + break; + default : + html = ""+ + ""; + break; + } + + return html; +}/*}}}*/ + +// 화면내에서 이미지 리사이즈 및 클릭할 수 있도록 +function resizeImageContents() {/*{{{*/ + var objs = xGetElementsByTagName('img'); + for(var i in objs) { + var obj = objs[i]; + var parent = xParent(obj); + if(!obj||!parent) continue; + + var parent_width = xWidth(parent); + var obj_width = xWidth(obj); + if(parent_width>=obj_width) continue; + + obj.style.cursor = 'pointer'; + obj.source_width = obj_width; + obj.source_height = xHeight(obj); + xWidth(obj, xWidth(parent)-1); + + xAddEventListener(obj,'click', resizeImagePopup); + } +}/*}}}*/ +xAddEventListener(window, 'load', resizeImageContents); + +function resizeImagePopup(evt) {/*{{{*/ + var e = new xEvent(evt); + if(!e.target.src) return; + var obj = e.target; + var scrollbars = "no"; + var resizable = "no"; + + var width = obj.source_width; + if(width>screen.availWidth) { + width = screen.availWidth-50; + scrollbars = "yes"; + resizable = "yes"; + } + var height = obj.source_height; + if(height>screen.availHeight) { + height = screen.availHeight-50; + scrollbars = "yes"; + resizable = "yes"; + } + var popup = window.open(e.target.src,"_imagePopup","width="+width+",height="+height+",top=1,left=1,resizable="+resizable+",toolbars=no,scrollbars="+resizable); + if(popup) popup.focus(); +}/*}}}*/ + +// 에디터에서 사용하는 내용 여닫는 코드 (고정) +function svc_folder_open(id) {/*{{{*/ + var open_text_obj = xGetElementById("_folder_open_"+id); + var close_text_obj = xGetElementById("_folder_close_"+id); + var folder_obj = xGetElementById("_folder_"+id); + open_text_obj.style.display = "none"; + close_text_obj.style.display = "block"; + folder_obj.style.display = "block"; +}/*}}}*/ + +function svc_folder_close(id) {/*{{{*/ + var open_text_obj = xGetElementById("_folder_open_"+id); + var close_text_obj = xGetElementById("_folder_close_"+id); + var folder_obj = xGetElementById("_folder_"+id); + open_text_obj.style.display = "block"; + close_text_obj.style.display = "none"; + folder_obj.style.display = "none"; +}/*}}}*/ diff --git a/common/js/x.js b/common/js/x.js new file mode 100644 index 000000000..fbc5ae13a --- /dev/null +++ b/common/js/x.js @@ -0,0 +1,633 @@ +/* x.js compiled from X 4.0 with XC 0.27b. + * Distributed by GNU LGPL. For copyrights, license, documentation and more visit Cross-Browser.com + * Copyright 2001-2005 Michael Foster (Cross-Browser.com) + */ + +var xOp7Up,xOp6Dn,xIE4Up,xIE4,xIE5,xIE6,xNN4,xUA=navigator.userAgent.toLowerCase(); +if(window.opera){ + var i=xUA.indexOf('opera'); + if(i!=-1){ + var v=parseInt(xUA.charAt(i+6)); + xOp7Up=v>=7; + xOp6Dn=v<7; + } +} +else if(navigator.vendor!='KDE' && document.all && xUA.indexOf('msie')!=-1){ + xIE4Up=parseFloat(navigator.appVersion)>=4; + xIE4=xUA.indexOf('msie 4')!=-1; + xIE5=xUA.indexOf('msie 5')!=-1; + xIE6=xUA.indexOf('msie 6')!=-1; +} +else if(document.layers){xNN4=true;} +xMac=xUA.indexOf('mac')!=-1; + +// (element, event(without 'on'), event listener(function name)[, caption]) +function xAddEventListener(e,eT,eL,cap) +{ + if(!(e=xGetElementById(e))) return; + eT=eT.toLowerCase(); + if((!xIE4Up && !xOp7Up) && e==window) { + if(eT=='resize') { window.xPCW=xClientWidth(); window.xPCH=xClientHeight(); window.xREL=eL; xResizeEvent(); return; } + if(eT=='scroll') { window.xPSL=xScrollLeft(); window.xPST=xScrollTop(); window.xSEL=eL; xScrollEvent(); return; } + } + var eh='e.on'+eT+'=eL'; + if(e.addEventListener) e.addEventListener(eT,eL,cap); + else if(e.attachEvent) e.attachEvent('on'+eT,eL); + else eval(eh); +} +// called only from the above +function xResizeEvent() +{ + if (window.xREL) setTimeout('xResizeEvent()', 250); + var cw = xClientWidth(), ch = xClientHeight(); + if (window.xPCW != cw || window.xPCH != ch) { window.xPCW = cw; window.xPCH = ch; if (window.xREL) window.xREL(); } +} + +function xScrollEvent() +{ + if (window.xSEL) setTimeout('xScrollEvent()', 250); + var sl = xScrollLeft(), st = xScrollTop(); + if (window.xPSL != sl || window.xPST != st) { window.xPSL = sl; window.xPST = st; if (window.xSEL) window.xSEL(); } +} + +function xAppendChild(oParent, oChild) +{ + if (oParent.appendChild) return oParent.appendChild(oChild); + else return null; +} + +function xClientHeight() +{ + var h=0; + if(xOp6Dn) h=window.innerHeight; + else if(document.compatMode == 'CSS1Compat' && !window.opera && document.documentElement && document.documentElement.clientHeight) + h=document.documentElement.clientHeight; + else if(document.body && document.body.clientHeight) + h=document.body.clientHeight; + else if(xDef(window.innerWidth,window.innerHeight,document.width)) { + h=window.innerHeight; + if(document.width>window.innerWidth) h-=16; + } + return h; +} + +function xClientWidth() +{ + var w=0; + if(xOp6Dn) w=window.innerWidth; + else if(document.compatMode == 'CSS1Compat' && !window.opera && document.documentElement && document.documentElement.clientWidth) + w=document.documentElement.clientWidth; + else if(document.body && document.body.clientWidth) + w=document.body.clientWidth; + else if(xDef(window.innerWidth,window.innerHeight,document.height)) { + w=window.innerWidth; + if(document.height>window.innerHeight) w-=16; + } + return w; +} + +function xCreateElement(sTag) +{ + if (document.createElement) return document.createElement(sTag); + else return null; +} + +function xDef() +{ + for(var i=0; i 0) { + var offset = document.cookie.indexOf(search); + if (offset != -1) { + offset += search.length; + var end = document.cookie.indexOf(";", offset); + if (end == -1) end = document.cookie.length; + value = unescape(document.cookie.substring(offset, end)); + } + } + return value; +} + +function xGetElementById(e) +{ + if(typeof(e)!='string') return e; + if(document.getElementById) e=document.getElementById(e); + else if(document.all) e=document.all[e]; + else e=null; + return e; +} + +function xGetElementsByAttribute(sTag, sAtt, sRE, fn) +{ + var a, list, found = new Array(), re = new RegExp(sRE, 'i'); + list = xGetElementsByTagName(sTag); + for (var i = 0; i < list.length; ++i) { + a = list[i].getAttribute(sAtt); + if (!a) {a = list[i][sAtt];} + if (typeof(a)=='string' && a.search(re) != -1) { + found[found.length] = list[i]; + if (fn) fn(list[i]); + } + } + return found; +} + +function xGetElementsByClassName(c,p,t,f) +{ + var found = new Array(); + var re = new RegExp('\\b'+c+'\\b', 'i'); + var list = xGetElementsByTagName(t, p); + for (var i = 0; i < list.length; ++i) { + if (list[i].className && list[i].className.search(re) != -1) { + found[found.length] = list[i]; + if (f) f(list[i]); + } + } + return found; +} + +function xGetElementsByTagName(t,p) +{ + var list = null; + t = t || '*'; + p = p || document; + if (xIE4 || xIE5) { + if (t == '*') list = p.all; + else list = p.all.tags(t); + } + else if (p.getElementsByTagName) list = p.getElementsByTagName(t); + return list || new Array(); +} + +function xGetURLArguments() +{ + var idx = location.href.indexOf('?'); + var params = new Array(); + if (idx != -1) { + var pairs = location.href.substring(idx+1, location.href.length).split('&'); + for (var i=0; i=0) { + var pt=0,pb=0,bt=0,bb=0; + if (document.compatMode=='CSS1Compat') { + var gcs = xGetComputedStyle; + pt=gcs(e,'padding-top',1); + if (pt !== null) { + pb=gcs(e,'padding-bottom',1); + bt=gcs(e,'border-top-width',1); + bb=gcs(e,'border-bottom-width',1); + } + // Should we try this as a last resort? + // At this point getComputedStyle and currentStyle do not exist. + else if(xDef(e.offsetHeight,e.style.height)){ + e.style.height=h+'px'; + pt=e.offsetHeight-h; + } + } + h-=(pt+pb+bt+bb); + if(isNaN(h)||h<0) return; + else e.style.height=h+'px'; + } + h=e.offsetHeight; + } + else if(css && xDef(e.style.pixelHeight)) { + if(h>=0) e.style.pixelHeight=h; + h=e.style.pixelHeight; + } + return h; +} + +function xHex(n, digits, prefix) +{ + var p = '', n = Math.ceil(n); + if (prefix) p = prefix; + n = n.toString(16); + for (var i=0; i < digits - n.length; ++i) { + p += '0'; + } + return p + n; +} + +function xHide(e){return xVisibility(e,0);} + +function xInnerHtml(e,h) +{ + if(!(e=xGetElementById(e)) || !xStr(e.innerHTML)) return null; + var s = e.innerHTML; + if (xStr(h)) {e.innerHTML = h;} + return s; +} + +function xLeft(e, iX) +{ + if(!(e=xGetElementById(e))) return 0; + var css=xDef(e.style); + if (css && xStr(e.style.left)) { + if(xNum(iX)) e.style.left=iX+'px'; + else { + iX=parseInt(e.style.left); + if(isNaN(iX)) iX=0; + } + } + else if(css && xDef(e.style.pixelLeft)) { + if(xNum(iX)) e.style.pixelLeft=iX; + else iX=e.style.pixelLeft; + } + return iX; +} + +function xMoveTo(e,x,y) +{ + xLeft(e,x); + xTop(e,y); +} + +function xName(e) +{ + if (!e) return e; + else if (e.id && e.id != "") return e.id; + else if (e.name && e.name != "") return e.name; + else if (e.nodeName && e.nodeName != "") return e.nodeName; + else if (e.tagName && e.tagName != "") return e.tagName; + else return e; +} + +function xNextSib(e,t) +{ + var s = e ? e.nextSibling : null; + if (t) while (s && s.nodeName != t) { s = s.nextSibling; } + else while (s && s.nodeType != 1) { s = s.nextSibling; } + return s; +} + +function xNum() +{ + for(var i=0; i=0) { + var pl=0,pr=0,bl=0,br=0; + if (document.compatMode=='CSS1Compat') { + var gcs = xGetComputedStyle; + pl=gcs(e,'padding-left',1); + if (pl !== null) { + pr=gcs(e,'padding-right',1); + bl=gcs(e,'border-left-width',1); + br=gcs(e,'border-right-width',1); + } + // Should we try this as a last resort? + // At this point getComputedStyle and currentStyle do not exist. + else if(xDef(e.offsetWidth,e.style.width)){ + e.style.width=w+'px'; + pl=e.offsetWidth-w; + } + } + w-=(pl+pr+bl+br); + if(isNaN(w)||w<0) return; + else e.style.width=w+'px'; + } + w=e.offsetWidth; + } + else if(css && xDef(e.style.pixelWidth)) { + if(w>=0) e.style.pixelWidth=w; + w=e.style.pixelWidth; + } + return w; +} + +function xZIndex(e,uZ) +{ + if(!(e=xGetElementById(e))) return 0; + if(e.style && xDef(e.style.zIndex)) { + if(xNum(uZ)) e.style.zIndex=uZ; + uZ=parseInt(e.style.zIndex); + } + return uZ; +} + +function xStopPropagation(evt) +{ + if (evt && evt.stopPropagation) evt.stopPropagation(); + else if (window.event) window.event.cancelBubble = true; +} + diff --git a/common/js/xml_handler.js b/common/js/xml_handler.js new file mode 100644 index 000000000..668765c5e --- /dev/null +++ b/common/js/xml_handler.js @@ -0,0 +1,136 @@ +/** + * @file : common/js/xml_handler.js + * @author : zero + * @desc : ajax 사용을 위한 기본 js + **/ + +// xml handler을 이용하는 user function +function exec_xml(method_name, act, params, callback_func, response_tags, callback_func_arg) { + var oXml = new xml_handler(); + oXml.reset(); + oXml.setMethod(method_name); + oXml.addParam('act', act); + for(var key in params) { + var val = params[key]; + oXml.addParam(key, val); + } + + var waiting_obj = document.getElementById('waitingforserverresponse'); + waiting_obj.style.visibility = 'visible'; + oXml.request(xml_response_filter, oXml, callback_func, response_tags, callback_func_arg); +} + +// 결과 처리 후 callback_func에 넘겨줌 +function xml_response_filter(oXml, callback_func, response_tags, callback_func_arg) { + var xmlDoc = oXml.getResponseXml(); + if(!xmlDoc) return; + + var waiting_obj = document.getElementById('waitingforserverresponse'); + waiting_obj.style.visibility = 'hidden'; + var ret_obj = oXml.toZMsgObject(xmlDoc, response_tags); + if(ret_obj['error']!=0) { + alert(ret_obj['message']); + return; + } + + callback_func(ret_obj, response_tags, callback_func_arg); +} + +// xml handler +function xml_handler() { + this.obj_xmlHttp = null; + this.method_name = null; + if(location.href.indexOf('admin.php')>0) this.xml_path = "./admin.php"; + else this.xml_path = "./index.php"; + + this.params = new Array(); + + this.reset = xml_handlerReset; + this.getXmlHttp = zGetXmlHttp; + this.request = xml_handlerRequest; + this.setPath = xml_handlerSetPath; + this.setMethod = xml_handlerSetMethod; + this.addParam = xml_handlerAddParam; + this.getResponseXml = xml_handlerGetResponseXML; + this.toZMsgObject = xml_handlerToZMsgObject; + + this.obj_xmlHttp = this.getXmlHttp(); +} + +function zGetXmlHttp() { + if (window.XMLHttpRequest) return new XMLHttpRequest(); + else if (window.ActiveXObject) { + try { + return new ActiveXObject("Msxml2.XMLHTTP"); + } catch (e) { + return new ActiveXObject("Microsoft.XMLHTTP"); + } + } + return null; +} + +function xml_handlerRequest(callBackFunc, xmlObj, callBackFunc2, response_tags, callback_func_arg) { + + var rd = ""; + rd += "\n" + + "\n" + + ""+this.method_name+"\n" + + "\n" + + for (var key in this.params) { + var val = this.params[key]; + rd += "<"+key+">\n"; + } + + rd += "\n" + + "\n"; + if(this.obj_xmlHttp.readyState!=0) { + this.obj_xmlHttp.abort(); + this.obj_xmlHttp = this.getXmlHttp(); + } + this.obj_xmlHttp.onreadystatechange = function () {callBackFunc(xmlObj, callBackFunc2, response_tags, callback_func_arg)}; + this.obj_xmlHttp.open('POST', this.xml_path, true); + this.obj_xmlHttp.send(rd); +} + +function xml_handlerSetPath(path) { + this.xml_path = "./"+path; +} + +function xml_handlerSetMethod(method_name) { + this.method_name = method_name; +} + +function xml_handlerReset() { + this.obj_xmlHttp = this.getXmlHttp(); + this.params = new Array(); +} + +function xml_handlerAddParam(key, val) { + this.params[key] = val; +} + +function xml_handlerGetResponseXML() { + if(this.obj_xmlHttp && this.obj_xmlHttp.readyState == 4 && isDef(this.obj_xmlHttp.responseXML)) { + var xmlDoc = this.obj_xmlHttp.responseXML; + this.reset(); + return xmlDoc; + } + return null; +} + +function xml_handlerToZMsgObject(xmlDoc, tags) { + if(!xmlDoc) return null; + if(!tags) { + tags = new Array('error','message'); + } + var obj_ret = new Array(); + for(var i=0; i + * @desc : xml filter에서 사용될 js + **/ + +var alertMsg = new Array(); + +// filtering +function XmlJsFilter(form_object, callback_user_func) { + + this.fo_obj = null; + this.user_func = null; + this.field = new Array(); + this.parameter = new Array(); + this.response = new Array(); + + this.fo_obj = form_object; + this.user_func = callback_user_func; + + this.addFieldItem = XmlJsFilterAddFieldItem; + this.addParameterItem = XmlJsFilterAddParameterItem; + this.addResponseItem = XmlJsFilterAddResponseItem; + this.getValue = XmlJsFilterGetValue; + this.executeFilter = XmlJsFilterExecuteFilter; + this.checkFieldItem = XmlJsFilterCheckFieldItem; + this.getParameterParam = XmlJsFilterGetParameterParam; + this.alertMsg = XmlJsFilterAlertMsg; + this.proc = XmlJsFilterProc; +} + +function XmlJsFilterAddFieldItem(target, required, minlength, maxlength, equalto, filter) { + var obj = new Array(target, required, minlength, maxlength, equalto, filter); + this.field[this.field.length] = obj; +} + +function XmlJsFilterAddParameterItem(param, target) { + var obj = new Array(param, target); + this.parameter[this.parameter.length] = obj; +} + +function XmlJsFilterAddResponseItem(name) { + this.response[this.response.length] = name; +} + +function XmlJsFilterGetValue(target_name) { + var obj = this.fo_obj[target_name]; + if(typeof(obj)=='undefined') return ''; + var value = ''; + var length = obj.length; + var type = obj.type; + + if(length) type = obj[0].type; + + switch(type) { + case 'checkbox' : + if(typeof(length)!='undefined') { + value_list = new Array(); + for(var i=0;i=0) msg = alertMsg[msg_code].replace('%s',target_msg); + else msg = target_msg+alertMsg[msg_code]; + } else { + msg = msg_code; + } + + if(typeof(minlength)!='undefined' && typeof(maxlength)!='undefined') msg += "("+minlength+"~"+maxlength+")"; + + alert(msg); + try { + this.fo_obj[target].focus(); + } catch(e) { + } + return false; +} + +function XmlJsFilterCheckFieldItem() { + for(var i=0; i0 && maxlength>0 && (value.length < minlength || value.length > maxlength)) return this.alertMsg(target, 'outofrange', minlength, maxlength); + + if(equalto) { + var equalto_value = this.getValue(equalto); + if(equalto_value != value) return this.alertMsg(target, 'equalto'); + } + + if(filter.length && filter[0]) { + for(var j=0;j + * @desc : 한국어 언어팩 (기본적인 내용만 수록) + **/ + + // 기본적으로 사용되는 action 언어 + $lang->cmd_write = '쓰기'; + $lang->cmd_reply = '답글'; + $lang->cmd_delete = '삭제'; + $lang->cmd_modify = '수정'; + $lang->cmd_list = '목록'; + $lang->cmd_prev = '이전'; + $lang->cmd_next = '다음'; + $lang->cmd_send_trackback = '엮인글발송'; + $lang->cmd_registration = '등록'; + $lang->cmd_save = '저장'; + $lang->cmd_input = '입력'; + $lang->cmd_search = '검색'; + $lang->cmd_cancel = '취소'; + $lang->cmd_back = '돌아가기'; + $lang->cmd_vote= '추천'; + $lang->cmd_login = '로그인'; + $lang->cmd_logout = '로그아웃'; + $lang->cmd_signup = '가입'; + $lang->cmd_leave = '탈퇴'; + $lang->cmd_move = '이동'; + $lang->cmd_move_up = '위로'; + $lang->cmd_move_down = '아래로'; + $lang->cmd_management = '관리'; + $lang->cmd_make = "생성"; + $lang->cmd_select_all = "모두선택"; + $lang->cmd_unselect_all = "모두해제"; + + $lang->enable = '가능'; + $lang->disable = '불가능'; + + // 기본 단어 + $lang->no = '번호'; + $lang->notice = '공지'; + $lang->secret = '비밀'; + $lang->category = '분류'; + $lang->document_srl = '문서번호'; + $lang->user_id = '아이디'; + $lang->author = '작성자'; + $lang->password = '비밀번호'; + $lang->password1 = '비밀번호'; + $lang->password2 = '비밀번호 확인'; + $lang->admin_id = '관리자ID'; + $lang->user_name = '이름'; + $lang->nick_name = '닉네임'; + $lang->email_address = '이메일 주소'; + $lang->homepage = '홈페이지'; + $lang->browser_title = '브라우저 제목'; + $lang->title = '제목'; + $lang->title_content = '제목+내용'; + $lang->content = '내용'; + $lang->document = '게시물'; + $lang->comment = '댓글'; + $lang->description = '설명'; + $lang->trackback = '엮인글'; + $lang->tag = '태그'; + $lang->about_tag = '태그 입력시 , (쉼표)를 이용하시면 복수 등록이 가능합니다'; + $lang->allow_comment = '댓글허용'; + $lang->lock_comment = '댓글잠금'; + $lang->allow_trackback = '엮인글허용'; + $lang->uploaded_file = '첨부파일'; + $lang->grant = "권한"; + $lang->target = "대상"; + + $lang->document_url = '게시글 주소'; + $lang->trackback_url = '엮인글 주소'; + $lang->blog_name = '블로그이름'; + $lang->excerpt = '발췌'; + + $lang->document_count = '글수'; + $lang->page_count = '페이지수'; + $lang->readed_count = '조회수'; + $lang->voted_count = '추천수'; + $lang->member_count = '회원수'; + $lang->date = '날짜'; + $lang->regdate = '등록일'; + $lang->last_update = '최근수정일'; + $lang->last_login = '최종로그인'; + $lang->first_page = '첫페이지'; + $lang->last_page = '끝페이지'; + $lang->search_target = '검색대상'; + $lang->keyword = '검색어'; + $lang->is_default = "기본"; + + $lang->use = "사용"; + $lang->notuse = "미사용"; + + // xml filter에서 사용되는 javascript용 alert msg + $lang->filter->isnull = '%s의 값을 입력해주세요'; + $lang->filter->outofrange = '%s의 글자 길이를 맞추어 주세요.'; + $lang->filter->equalto = '%s의 값이 잘못 되었습니다.'; + $lang->filter->invalid_email = '%s의 형식이 잘못되었습니다. (예: zb5@zeroboard.com)'; + $lang->filter->invalid_user_id = $lang->filter->invalid_userid = "%s의 형식이 잘못되었습니다.\\n영문,숫자와 _로 만드실 수 있으며 제일 앞은 영문이어야 합니다"; + $lang->filter->invalid_homepage = '%s의 형식이 잘못되었습니다. (예: http://www.zeroboard.com)'; + $lang->filter->invalid_korean = '%s의 형식이 잘못되었습니다. 한글로만 입력해주셔야 합니다'; + $lang->filter->invalid_korean_number = '%s의 형식이 잘못되었습니다. 한글과 숫자로만 입력해주셔야 합니다'; + $lang->filter->invalid_alpha = '%s의 형식이 잘못되었습니다. 영문으로만 입력해주셔야 합니다'; + $lang->filter->invalid_alpha_number = '%s의 형식이 잘못되었습니다. 영문과 숫자로만 입력해주셔야 합니다'; + $lang->filter->invalid_number = '%s의 형식이 잘못되었습니다. 숫자로만 입력해주셔야 합니다'; + + // 메세지 관련 + $lang->msg_call_server = '서버에 요청중입니다. 잠시만 기다려주세요.'; + $lang->msg_db_not_setted = 'DB설정이 되어 있지 않습니다'; + $lang->msg_mid_not_exists = '설정이 되어 있지 않습니다. 관리자 페이지에서 기본 설정을 해주시기 바랍니다.'; + $lang->msg_invalid_queryid = 'Query ID값이 잘못 지정되었습니다'; + $lang->msg_not_permitted = '권한이 없습니다'; + $lang->msg_input_password = '비밀번호를 입력하여 주세요'; + $lang->msg_invalid_document = '잘못된 문서번호입니다'; + $lang->msg_invalid_request = '잘못된 요청입니다'; + $lang->msg_invalid_password = '비밀번호가 올바르지 않습니다'; + $lang->msg_error_occured = '오류가 발생하였습니다'; + $lang->msg_not_founded = '대상을 찾을 수 없습니다'; + + $lang->success_registed = '등록되었습니다'; + $lang->success_updated = '수정되었습니다'; + $lang->success_deleted = '삭제되었습니다'; + $lang->success_voted = '추천되었습니다'; + $lang->success_moved = '이동되었습니다'; + + $lang->failed_voted = '추천하실 수 없습니다'; + $lang->fail_to_delete_have_children = '답글이 있어서 삭제할 수 없습니다'; + + $lang->confirm_submit = '등록하시겠습니까?'; + $lang->confirm_logout = '로그아웃하시겠습니까?'; + $lang->confirm_vote = '추천하시겠습니까?'; + $lang->confirm_delete = '삭제하시겠습니까?'; + +?> diff --git a/common/tpl/common_footer.html b/common/tpl/common_footer.html new file mode 100644 index 000000000..d254cb43e --- /dev/null +++ b/common/tpl/common_footer.html @@ -0,0 +1,3 @@ +
{$lang->msg_call_server}
+ + diff --git a/common/tpl/common_header.html b/common/tpl/common_header.html new file mode 100644 index 000000000..51846c504 --- /dev/null +++ b/common/tpl/common_header.html @@ -0,0 +1,19 @@ + + + + +{Context::getBrowserTitle()} + + + + + + + + + + + +{Context::getHtmlHeader()} + + diff --git a/common/tpl/default_layout.html b/common/tpl/default_layout.html new file mode 100644 index 000000000..d1da8601d --- /dev/null +++ b/common/tpl/default_layout.html @@ -0,0 +1,3 @@ + +{$content} + diff --git a/config/config.inc.php b/config/config.inc.php new file mode 100644 index 000000000..5b9493f8c --- /dev/null +++ b/config/config.inc.php @@ -0,0 +1,37 @@ + + * @desc : 기본적으로 사용하는 class파일의 include 및 환경 설정을 함 + **/ + + // 기본적인 상수 선언 + // 웹에서 직접 호출되는 것을 막기 위해 체크하는 상수 선언 + define('__ZB5__', true); + + // 기본 함수 라이브러리 파일 + require_once("./config/func.inc.php"); + + // debug mode = true 일때 files/_debug_message.php 에 디버그 내용이 쌓임 + define('__DEBUG__', true); + if(__DEBUG__) define('__StartTime__', getMicroTime()); + + // 세션 설정 + @session_cache_limiter('no-cache, must-revalidate'); + @session_start(); + + // 기본적인 class 파일 include + if(__DEBUG__) define('__RequireClassStartTime__', getMicroTime()); + require_once("./classes/xml/XmlParser.class.php"); + require_once("./classes/context/Context.class.php"); + require_once("./classes/db/DB.class.php"); + require_once("./classes/file/FileHandler.class.php"); + require_once("./classes/output/Output.class.php"); + require_once("./classes/module/Module.class.php"); + require_once("./classes/display/DisplayHandler.class.php"); + require_once("./classes/module/ModuleHandler.class.php"); + require_once('./modules/module_manager/module_manager.module.php'); + //require_once("./classes/addon/AddOnHandler.class.php"); + //require_once("./classes/layout/LayoutHandler.class.php"); + if(__DEBUG__) define('__RequireClassEndTime__', getMicroTime()); +?> diff --git a/config/func.inc.php b/config/func.inc.php new file mode 100644 index 000000000..c6ffa9637 --- /dev/null +++ b/config/func.inc.php @@ -0,0 +1,84 @@ + + * @desc : 편의 목적으로 만든 함수라이브러리 파일 + **/ + + // php5에 대비하여 clone 정의/*{{{*/ + if (version_compare(phpversion(), '5.0') < 0) { + eval(' + function clone($object) { + return $object; + } + '); + }/*}}}*/ + + // function object getModule($module_name, $is_admin=false)/*{{{*/ + // module_manager::getModuleObject($module_name)을 쓰기 쉽게 함수로 선언 + function getModule($module_name, $is_admin=false) { + if($is_admin) return module_manager::getAdminModuleObject($module_name); + return module_manager::getModuleObject($module_name); + }/*}}}*/ + + // function string getUrl($args_list)/*{{{*/ + // Context::getUrl($args_list)를 쓰기 쉽게 함수로 선언 + function getUrl() { + $num_args = func_num_args(); + $args_list = func_get_args(); + + if(!$num_args) return Context::getRequestUri(); + + return Context::getUrl($num_args, $args_list); + }/*}}}*/ + + // function string cut_str($string, $cut_size, $tail = '...')/*{{{*/ + // microtime + function cut_str($string, $cut_size, $tail='...') { + if(!$string || !$cut_size) return $string; + $unicode_str = iconv("UTF-8","UCS-2",$string); + if(strlen($unicode_str) < $cut_size*2) return $string; + + $output = substr($unicode_str, 0, $cut_size*2); + return iconv("UCS-2","UTF-8",$output_str).$tail; + }/*}}}*/ + + // function string zdate($str, $format = "Y-m-d H:i:s")/*{{{*/ + // 시간 출력 + function zdate($str, $format = "Y-m-d H:i:s") { + return date($format, mktime(substr($str,8,2), substr($str,10,2), substr($str,12,2), substr($str,4,2), substr($str,6,2), substr($str,0,4))); + }/*}}}*/ + + // function void debugPrint($buff)/*{{{*/ + // 간단한 console debugging용 함수 + function debugPrint($buff, $display_line = true) { + $debug_file = "./files/_debug_message.php"; + $buff = sprintf("%s\n",print_r($buff,true)); + + if($display_line) $buff = "\n====================================\n".$buff."------------------------------------\n"; + + if(@!$fp = fopen($debug_file,"a")) return; + fwrite($fp, $buff); + fclose($fp); + }/*}}}*/ + + // function float getMicroTime()/*{{{*/ + // microtime + function getMicroTime() { + list($time1, $time2) = explode(' ', microtime()); + return (float)$time1+(float)$time2; + }/*}}}*/ + + // function string delObjectVars($target_obj, $del_obj)/*{{{*/ + // 첫번째 인자로 오는 object var에서 2번째 object의 var들을 빼낸다 + function delObjectVars($target_obj, $del_obj) { + if(count(get_object_vars($target_obj))<1) return; + if(count(get_object_vars($del_obj))<1) clone($target_obj); + + if(is_object($target_var)) $var = clone($target_var); + foreach($del_obj as $key => $val) { + unset($var->{$var_name}); + } + return $var; + }/*}}}*/ +?> diff --git a/editor/default/editor.css b/editor/default/editor.css new file mode 100644 index 000000000..2b70a4461 --- /dev/null +++ b/editor/default/editor.css @@ -0,0 +1,176 @@ +div.editor_content { + margin:3px; +} + +div.editor_fontbox { + margin : 3px 3px 3px 0px; + float:left; +} + +div.editor_fontbox select { + width:70px; + height:18px; +} + +div.editor_iconbox { + margin : 3px 3px 3px 0px; + white-space:nowrap; + font-size:1pt; + float:left; +} + +div.editor_iconbox img { + width : 16px; + height : 16px; + border : 1px solid #EEEEEE; + background-color : #FFFFFF; + padding:1px; + cursor : pointer; + margin-right:1px; +} + +div.editor_parabox { + margin : 3px 3px 3px 0px; + font-size:9pt; + text-align:right; + display:none; + float:right; +} + +div.editor_iframe_box { + clear:left; + border:1px solid #EFEFEF; + margin:3px 0px 0px 0px; +} + +div.editor_drag_down_area { + width:100%; + height:15px; + background:url(./images/icon_drag_down.gif) no-repeat center; + background-color:#EFEFEF; + cursor:s-resize; + position:relative; + margin-top:10px; +} + +.editor_pop_body { + padding:4px 4px 4px 4px; + margin:0px; + border:0px; + background-color:#FFFFFF; +} + +.editor_window { + background-color : #EFEFEF; +} + +textarea.editor_small_textarea { + font-family:tahoma; + border : 1px solid #CCCCCC; + background-color : #FFFFFF; + font-size : 8pt; + width:99%; + height:100px; +} + +textarea.editor_textarea { + font-family:tahoma; + border : 1px solid #CCCCCC; + background-color : #FFFFFF; + font-size : 8pt; + width:100%; + height:450px; +} + +input.editor_submit { + border : 1px solid #555555; + background-color : #AAAAAA; + color : #000000; + font-weight:bold; + font-family:verdana; + width : 100%; + height : 20px; + font-size : 8pt; +} + +div.quotation_box { + font-size:8pt; + font-family:tahoma; + margin-bottom:8px; + padding-bottom:5px; + border-bottom:1px dotted #AAAAAA; +} + +#quotation th { width:80px; font-size:8pt; font-family:tahoma; } + +img.color_icon { + width:15px; + height:15px; + border:1px solid #FFFFFF; +} + +img.color_icon_over { + width:15px; + height:15px; + border:1px solid #000000; + cursor:pointer; +} + +td.editor_field { + font-family:tahoma; + font-size:8pt; + font-weight:bold; + background-color : #CCCCCC; + text-align : center; +} + +input.editor_input { + font-family:tahoma; + border : 1px solid #CCCCCC; + background-color : #FFFFFF; + width : 330px; + height : 18px; + padding : 1px; + font-size : 8pt; +} + +.editor_uploader_box { + margin:0px; + border:0px; + padding:0px; +} + +.editor_uploader_box table { + border:0px; + margin:0px; + padding:2px; + table-layout:fixed; + width:100%; +} + +.uploaded_file_preview_box { + border:1px solid #EEEEEE; + width:120px; + height:120px; +} + +.uploaded_file_list { + width:100%; + height:120px; +} + +.editor_align_icon { + margin:0px 0px 6px 5px; + font-size:9pt; +} + +.editor_align_icon img { + vertical-align:middle; + cursor:pointer; +} + +img.editor_multimedia { + background:url(./images/multimedia_icon.gif) no-repeat center; + background-color:#FFFFFF; + border:2px dotted #B7AD10; +} diff --git a/editor/default/editor.html b/editor/default/editor.html new file mode 100644 index 000000000..262f94020 --- /dev/null +++ b/editor/default/editor.html @@ -0,0 +1,59 @@ + + + + + + + +
+
+ + +
+
+ {$lang->edit->help_fontcolor} + {$lang->edit->help_fontbgcolor} + {$lang->edit->help_bold} + {$lang->edit->help_italic} + {$lang->edit->help_underline} + {$lang->edit->help_strike} + {$lang->edit->help_add_url} + {$lang->edit->help_add_image} + {$lang->edit->help_add_multimedia} + {$lang->edit->help_add_emoticon} + {$lang->edit->help_add_quotation} + {$lang->edit->help_add_html} +
+ +
+ + +
+ +
+
diff --git a/editor/default/editor.js b/editor/default/editor.js new file mode 100755 index 000000000..7f7c42370 --- /dev/null +++ b/editor/default/editor.js @@ -0,0 +1,706 @@ +/** + * richtext 에디터 관련 + **/ +// iframe의 id prefix +var iframe_id = 'editor_iframe_'; + +// srl값에 해당하는 iframe의 object를 return +function editorGetIFrame(document_srl) {/*{{{*/ + var obj_id = iframe_id+document_srl; + return xGetElementById(obj_id); +}/*}}}*/ + +// editor 초기화를 onload이벤트 후에 시작시킴 +function editorInit(document_srl) {/*{{{*/ + var start_func = function _editorStart() { editorStart(document_srl); } + var init_func = function _editorInit() { setTimeout(start_func, 300); } + xAddEventListener(window, 'load', init_func); +}/*}}}*/ + +// editor 초기화 (document_srl로 iframe객체를 얻어서 쓰기 모드로 전환) +function editorStart(document_srl) {/*{{{*/ + // iframe obj를 찾음 + var iframe_obj = editorGetIFrame(document_srl); + if(!iframe_obj) return; + + // 현 에디터를 감싸고 있는 form문을 찾아서 content object를 찾아서 내용 sync + var fo_obj = iframe_obj.parentNode; + while(fo_obj.nodeName != 'FORM') { fo_obj = fo_obj.parentNode; } + + var content = fo_obj.content.value; + + // 기본 폰트를 가져옴 + var default_font = xGetElementById('editor_font_'+document_srl).options[1].value; + + // iframe내의 document object + var contentDocument = iframe_obj.contentWindow.document; + + // editing가능하도록 설정 + + + // 기본 내용 작성 + var contentHtml = ''+ + ''+ + ''; + + /********* 오페라에서 stylesheet를 못 가져와서 일단 주석 처리하고 수동 처리 + for(var i in document.styleSheets) { + var tmp_obj = document.styleSheets[i]; + if(typeof(tmp_obj.href)=='undefined'||tmp_obj.href.lastIndexOf(".css")<0) continue; + contentHtml += ""; + } + **********/ + contentHtml += ""; + contentHtml += ""; + contentHtml += ""+ + ""+ + content+ + ""; + + contentDocument.designMode = 'on'; + contentDocument.open("text/html","replace"); + contentDocument.write(contentHtml); + contentDocument.close(); + + // 작성시 필요한 이벤트 체크 + if(xIE4Up) xAddEventListener(contentDocument, 'keydown',editorKeyPress); + else xAddEventListener(contentDocument, 'keypress',editorKeyPress); + xAddEventListener(contentDocument,'mousedown',editorHideObject); + + //xAddEventListener(document,'keypress',editorKeyPress); + xAddEventListener(document,'mouseup',editorEventCheck); + xAddEventListener(document,'mousedown',editorHideObject); + + // 문단작성기능 on/off + if(xIE4Up) { + xDisplay('editor_paragraph_'+document_srl, 'none'); + xDisplay('editor_use_paragraph_box_'+document_srl, 'inline'); + } else { + xDisplay('editor_paragraph_'+document_srl, 'block'); + xDisplay('editor_use_paragraph_box_'+document_srl, 'none'); + } + + // 에디터의 내용을 지속적으로 fo_obj.content.value에 입력 + editorSyncContent(fo_obj.content, document_srl); +}/*}}}*/ + +var _editorSyncList = new Array(); /*{{{*/ +function editorSyncContent(obj, document_srl) { + _editorSyncList[_editorSyncList.length] = {field:obj, document_srl:document_srl} +}/*}}}*/ + +function _editorSync() {/*{{{*/ + for(var i=0;i<_editorSyncList.length;i++) { + var field = _editorSyncList[i].field; + var document_srl = _editorSyncList[i].document_srl; + var content = editorGetContent(document_srl); + if(typeof(content)=='undefined'||!content) continue; + field.value = content; + } + setTimeout(_editorSync, 1000); +}/*}}}*/ +xAddEventListener(window, 'load', _editorSync); + +// 문단기능 toggle +function editorUseParagraph(obj, document_srl) { /*{{{*/ + toggleDisplay('editor_paragraph_'+document_srl); +}/*}}}*/ + +// 에디터의 내용 return +function editorGetContent(document_srl) {/*{{{*/ + var iframe_obj = editorGetIFrame(document_srl); + if(!iframe_obj) return; + var html = ''; + html = xInnerHtml(iframe_obj.contentWindow.document.body); + if(!html) return; + return html.trim(); +}/*}}}*/ + +// 에디터 내의 선택된 부분의 html 코드를 return +function editorGetSelectedHtml(document_srl) {/*{{{*/ + var iframe_obj = editorGetIFrame(document_srl); + if(xIE4Up) { + var range = iframe_obj.contentWindow.document.selection.createRange(); + var html = range.htmlText; + range.select(); + return html; + } else { + var range = iframe_obj.contentWindow.getSelection().getRangeAt(0); + var dummy = xCreateElement('div'); + dummy.appendChild(range.cloneContents()); + var html = xInnerHtml(dummy); + return html; + } +}/*}}}*/ + +// 에디터 내의 선택된 부분의 html코드를 변경 +function editorReplaceHTML(iframe_obj, html) {/*{{{*/ + iframe_obj.contentWindow.focus(); + if(xIE4Up) { + var range = iframe_obj.contentWindow.document.selection.createRange(); + range.pasteHTML(html); + } else { + var range = iframe_obj.contentWindow.getSelection().getRangeAt(0); + range.deleteContents(); + range.insertNode(range.createContextualFragment(html)); + } +}/*}}}*/ + +// 입력 키에 대한 이벤트 체크 +function editorKeyPress(evt) {/*{{{*/ + var e = new xEvent(evt); + if (e.keyCode == 13) { + if(xIE4Up && e.shiftKey == false && !xGetElementById("use_paragraph").checked ) { + if(e.target.parentElement.document.designMode!="On") return; + var obj = e.target.parentElement.document.selection.createRange(); + obj.pasteHTML('
'); + obj.select(); + evt.cancelBubble = true; + evt.returnValue = false; + return; + } + } + + if (e.ctrlKey) { + switch(e.keyCode) { + case 98 : // b + editorDo('Bold',null,e.target); + xPreventDefault(evt); + xStopPropagation(evt); + break; + case 105 : // i + editorDo('Italic',null,e.target); + xPreventDefault(evt); + xStopPropagation(evt); + break; + case 117 : // u + editorDo('Underline',null,e.target); + xPreventDefault(evt); + xStopPropagation(evt); + break; + case 83 : // s + case 115 : // s + editorDo('StrikeThrough',null,e.target); + xPreventDefault(evt); + xStopPropagation(evt); + break; + } + } +}/*}}}*/ + +// 에디터 상단의 버튼 클릭시 action 처리 +var editorPrevObj = null;/*{{{*/ +var editorPrevSrl = null; +function editorEventCheck(evt) { + var e = new xEvent(evt); + var target_id = e.target.id; + if(target_id.indexOf('editor_')!=-1) { + var tmp_str = target_id.split('_'); + var method_name = tmp_str[1]; + var document_srl = tmp_str[2]; + switch(method_name) { + case 'Bold' : + case 'Italic' : + case 'Underline' : + case 'StrikeThrough' : + case 'justifyleft' : + case 'justifycenter' : + case 'justifyright' : + case 'indent' : + case 'outdent' : + case 'insertorderedlist' : + case 'insertunorderedlist' : + editorDo(method_name, '', document_srl); + break; + default : + editorPrevSrl = document_srl; + switch(method_name) { + case "addemoticon" : + var x = (screen.availWidth - 225)/2; + var y = (screen.availHeight - 150)/2; + var editor_popup = window.open(editor_path+"popup/add_emoticon.php","_editorPopup","top="+y+",left="+x+",width=225,height=150,resizable=no,toolbars=no,scrollbars=no"); + if(editor_popup) editor_popup.focus(); + return; + break; + case "quotation" : + var x = (screen.availWidth - 400)/2; + var y = (screen.availHeight - 400)/2; + var editor_popup = window.open(editor_path+"popup/add_quotation.php","_editorPopup","top="+y+",left="+x+",width=400,height=400,resizable=no,toolbars=no,scrollbars=no"); + if(editor_popup) editor_popup.focus(); + return; + break; + case "addurl" : + var x = (screen.availWidth - 400)/2; + var y = (screen.availHeight - 220)/2; + var editor_popup = window.open(editor_path+"popup/add_url.php","_editorPopup","top="+y+",left="+x+",width=400,height=220,resizable=no,toolbars=no,scrollbars=no"); + if(editor_popup) editor_popup.focus(); + return; + break; + case "addimage" : + var x = (screen.availWidth - 420)/2; + var y = (screen.availHeight - 80)/2; + var editor_popup = window.open(editor_path+"popup/add_image.php","_editorPopup","top="+y+",left="+x+",width=420,height=80,resizable=no,toolbars=no,scrollbars=no"); + if(editor_popup) editor_popup.focus(); + return; + break; + case "addmultimedia" : + var x = (screen.availWidth - 400)/2; + var y = (screen.availHeight - 220)/2; + var editor_popup = window.open(editor_path+"popup/add_multi.php","_editorPopup","top="+y+",left="+x+",width=420,height=110,resizable=no,toolbars=no,scrollbars=no"); + if(editor_popup) editor_popup.focus(); + return; + break; + case "addhtml" : + var x = (screen.availWidth - 400)/2; + var y = (screen.availHeight - 500)/2; + var editor_popup = window.open(editor_path+"popup/add_html.php","_editorPopup","top="+y+",left="+x+",width=400,height=500,resizable=no,toolbars=no,scrollbars=no"); + if(editor_popup) editor_popup.focus(); + return; + break; + case "ForeColor" : + case "BackColor" : + var x = (screen.availWidth - 145)/2; + var y = (screen.availHeight - 95)/2; + var editor_popup = window.open(editor_path+"popup/color_box.php?mode="+method_name,"_editorPopup","top="+y+",left="+x+",width=145,height=95,resizable=no,toolbars=no,scrollbars=no"); + if(editor_popup) editor_popup.focus(); + return; + } + break; + } + } + return; +}/*}}}*/ + +// focus +function editorFocus(document_srl) {/*{{{*/ + var iframe_obj = editorGetIFrame(document_srl); + iframe_obj.contentWindow.focus(); +} +/*}}}*/ + +// 편집 기능 실행 +function editorDo(name, value, target) {/*{{{*/ + if(typeof(target)=='object') _editorDoObject(name, value, target); + else _editorDoSrl(name, value, target); +}/*}}}*/ + +function _editorDoSrl(name, value, document_srl) {/*{{{*/ + var iframe_obj = editorGetIFrame(document_srl); + editorFocus(document_srl); + if(xIE4Up) iframe_obj.contentWindow.document.execCommand(name, false, value); + else iframe_obj.contentWindow.document.execCommand(name, false, value); + editorFocus(document_srl); +}/*}}}*/ + +function _editorDoObject(name, value, obj) {/*{{{*/ + if(xIE4Up) { + obj.parentElement.document.execCommand(name, false, value); + } else { + obj.parentNode.execCommand(name, false, value); + } +}/*}}}*/ + +function editorHideObject(evt) {/*{{{*/ + if(!editorPrevObj) return; + var e = new xEvent(evt); + var tobj = e.target; + while(tobj) { + if(tobj.id == editorPrevObj.id) { + return; + } + tobj = xParent(tobj); + } + editorPrevObj.style.visibility = 'hidden'; + editorPrevObj = null; + return; +}/*}}}*/ + +function editorChangeFontName(obj,srl) {/*{{{*/ + var value = obj.options[obj.selectedIndex].value; + if(!value) return; + editorDo('FontName',value,srl); + obj.selectedIndex = 0; +}/*}}}*/ + +function editorChangeFontSize(obj,srl) {/*{{{*/ + var value = obj.options[obj.selectedIndex].value; + if(!value) return; + editorDo('FontSize',value,srl); + obj.selectedIndex = 0; +}/*}}}*/ + +function editorSetForeColor(color_code) {/*{{{*/ + editorDo("ForeColor",color_code,editorPrevSrl); + editorPrevObj.style.visibility = 'hidden'; + editorFocus(editorPrevSrl); +}/*}}}*/ + +function editorSetBackColor(color_code) {/*{{{*/ + if(xIE4Up) editorDo("BackColor",color_code,editorPrevSrl); + else editorDo("hilitecolor",color_code,editorPrevSrl); + editorFocus(editorPrevSrl); +}/*}}}*/ + +function editorInsertEmoticon(obj) {/*{{{*/ + editorFocus(editorPrevSrl); + editorDo("InsertImage",obj.src,editorPrevSrl); + editorFocus(editorPrevSrl); +}/*}}}*/ + +function editorDoInsertUrl(link, document_srl) {/*{{{*/ + editorFocus(document_srl); + var iframe_obj = editorGetIFrame(srl); + editorReplaceHTML(iframe_obj, link); +}/*}}}*/ + +function editorInsertUrl(text, url, link_type) {/*{{{*/ + if(!text || !url) return; + //if(!/^(http|ftp)/i.test(url)) url = 'http://'+url; + + var link = ''; + if(!link_type) link = ""+text+""; + else link = ""+text+""; + + editorFocus(editorPrevSrl); + var obj = editorGetIFrame(editorPrevSrl) + editorReplaceHTML(obj, link); +}/*}}}*/ + +function editorInsertImage(url, src_align) {/*{{{*/ + if(!url) return; + //if(!/^(http|ftp)/i.test(url)) url = 'http://'+url; + + editorFocus(editorPrevSrl); + + var html = "\"i\"
"; + return html; +}/*}}}*/ + +function editorInsertMultimedia(url, width, height) {/*{{{*/ + if(url) { + var html = editorGetMultimediaHtml(url, width, height); + editorFocus(editorPrevSrl); + var obj = editorGetIFrame(editorPrevSrl) + editorReplaceHTML(obj, html); + editorFocus(editorPrevSrl); + } +}/*}}}*/ + +function editorInsertHTML(html) {/*{{{*/ + if(!html) return; + + editorFocus(editorPrevSrl); + var obj = editorGetIFrame(editorPrevSrl) + editorReplaceHTML(obj, html); + editorFocus(editorPrevSrl); +}/*}}}*/ + +function editorInsertQuotation(html) {/*{{{*/ + if(!html) return; + + if(!xIE4Up) html += "
"; + editorFocus(editorPrevSrl); + var obj = editorGetIFrame(editorPrevSrl) + editorReplaceHTML(obj, html); + editorFocus(editorPrevSrl); +}/*}}}*/ + +function editorHighlight(ret_obj, response_tags, obj) {/*{{{*/ + var html = ret_obj['html']; + html = "
"+html+"
"; + if(!xIE4Up) html += "
"; + editorReplaceHTML(obj, html); +}/*}}}*/ + +/** + * iframe 드래그 관련 + **/ +var editorIsDrag = false; +var editorDragY = 0; +var editorDragObj = null; +var editorDragID = ''; +xAddEventListener(document, 'mousedown', editorDragStart); +xAddEventListener(document, 'mouseup', editorDragStop); +function editorDragStart(evt) {/*{{{*/ + var e = new xEvent(evt); + var obj = e.target; + if(typeof(obj.id)=='undefined'||!obj.id) return; + var id = obj.id; + if(id.indexOf('editor_drag_bar_')!=0) return; + + editorIsDrag = true; + editorDragObj = e.target; + editorDragY = e.pageY; + editorDragID = id.substr('editor_drag_bar_'.length); + xAddEventListener(document, 'mousemove', editorDragMove); + xAddEventListener(editorDragObj, 'mouseout', editorDragMove); + + var iframe_obj = editorGetIFrame(editorDragID); + xAddEventListener(iframe_obj, 'mousemove', editorDragMove); +}/*}}}*/ + +function editorDragStop(evt) {/*{{{*/ + var iframe_obj = editorGetIFrame(editorDragID); + xRemoveEventListener(document, 'mousemove', editorDragMove); + xRemoveEventListener(iframe_obj, 'mousemove', editorDragMove); + + editorIsDrag = false; + editorDragY = 0; + editorDragObj = null; + editorDragID = ''; +}/*}}}*/ + +function editorDragMove(evt) {/*{{{*/ + if(typeof(editorIsDrag)=='undefined'||!editorIsDrag) return; + var e = new xEvent(evt); + var iframe_obj = editorGetIFrame(editorDragID); + + var y = e.pageY; + var yy = y - editorDragY; + if(yy<0) return; + editorDragY = y; + + var editorHeight = xHeight(iframe_obj); + xHeight(iframe_obj, editorHeight+yy); +}/*}}}*/ + +/** + * 파일 업로드 관련 + **/ +var uploading_file = false; +var uploaded_files = new Array(); + +// 업로드를 하기 위한 준비 시작 +function editor_upload_init(document_srl) {/*{{{*/ + xAddEventListener(window,'load',function _change_form_target() {editor_upload_form_set(document_srl);} ); +}/*}}}*/ + +// document_srl에 해당하는 form의 action을 iframe으로 변경 +function editor_upload_form_set(document_srl) {/*{{{*/ + // 업로드용 iframe을 생성 + if(!xGetElementById('tmp_upload_iframe')) { + if(xIE4Up) { + window.document.body.insertAdjacentHTML("afterEnd", ""); + } else { + var obj_iframe = xCreateElement('IFRAME'); + obj_iframe.name = obj_iframe.id = 'tmp_upload_iframe'; + obj_iframe.style.display = 'none'; + obj_iframe.style.width = '1px'; + obj_iframe.style.height = '1px'; + obj_iframe.style.position = 'absolute'; + obj_iframe.style.top = '-10px'; + obj_iframe.style.left = '-10px'; + window.document.body.appendChild(obj_iframe); + } + } + + // form의 action 을 변경 + var field_obj = xGetElementById("uploaded_file_list_"+document_srl); + if(!field_obj) return; + var fo_obj = field_obj.parentNode; + while(fo_obj.nodeName != 'FORM') { fo_obj = fo_obj.parentNode; } + fo_obj.target = 'tmp_upload_iframe'; + + // document_srl에 해당하는 첨부파일 목록을 로드 + var mid = fo_obj.mid.value; + var document_srl = fo_obj.document_srl.value; + var url = "./?mid="+mid+"&act=procDeleteFile&document_srl="+document_srl; + + // iframe에 url을 보내버림 + var iframe_obj = xGetElementById('tmp_upload_iframe'); + if(!iframe_obj) return; + + iframe_obj.contentWindow.document.location.href=url; +}/*}}}*/ + +// 파일 업로드 +function editor_file_upload(field_obj, document_srl) {/*{{{*/ + if(uploading_file) return; + + var fo_obj = field_obj.parentNode; + while(fo_obj.nodeName != 'FORM') { fo_obj = fo_obj.parentNode; } + + uploading_file = true; + fo_obj.submit(); + uploading_file = false; + + var sel_obj = xGetElementById('uploaded_file_list_'+document_srl); + var string = 'wait for uploading...'; + var opt_obj = new Option(string, '', true, true); + sel_obj.options[sel_obj.options.length] = opt_obj; +}/*}}}*/ + +// 업로드된 파일 목록을 삭제 +function editor_upload_clear_list(document_srl) {/*{{{*/ + var obj = xGetElementById('uploaded_file_list_'+document_srl); + while(obj.options.length) { + obj.remove(0); + } + var preview_obj = xGetElementById('uploaded_file_preview_box_'+document_srl); + xInnerHtml(preview_obj,'') +}/*}}}*/ + +// 업로드된 파일 정보를 목록에 추가 +function editor_insert_uploaded_file(document_srl, file_srl, filename, file_size, disp_file_size, uploaded_filename, sid) {/*{{{*/ + var obj = xGetElementById('uploaded_file_list_'+document_srl); + var string = filename+' ('+disp_file_size+')'; + var opt_obj = new Option(string, file_srl, true, true); + obj.options[obj.options.length] = opt_obj; + + var file_obj = {file_srl:file_srl, filename:filename, file_size:file_size, uploaded_filename:uploaded_filename, sid:sid} + uploaded_files[file_srl] = file_obj; + + editor_preview(obj, document_srl); +}/*}}}*/ + +// 파일 목록창에서 클릭 되었을 경우 미리 보기 +function editor_preview(sel_obj, document_srl) {/*{{{*/ + if(sel_obj.options.length<1) return; + var file_srl = sel_obj.options[sel_obj.selectedIndex].value; + var obj = uploaded_files[file_srl]; + if(typeof(obj)=='undefined'||!obj) return; + var uploaded_filename = obj.uploaded_filename; + var preview_obj = xGetElementById('uploaded_file_preview_box_'+document_srl); + + if(!uploaded_filename) { + xInnerHtml(preview_obj, ''); + return; + } + + var html = ""; + + // 플래쉬 동영상의 경우 + if(/\.flv$/i.test(uploaded_filename)) { + html = ""; + // 플래쉬 파일의 경우 + } else if(/\.swf$/i.test(uploaded_filename)) { + html = ""; + // wmv, avi, mpg, mpeg등의 동영상 파일의 경우 + } else if(/\.(wmv|avi|mpg|mpeg|asx|asf|mp3)$/i.test(uploaded_filename)) { + html = ""; + // 이미지 파일의 경우 + } else if(/\.(jpg|jpeg|png|gif)$/i.test(uploaded_filename)) { + html = ""; + } + xInnerHtml(preview_obj, html); +}/*}}}*/ + +// 업로드된 파일 삭제 +function editor_remove_file(document_srl) {/*{{{*/ + var obj = xGetElementById('uploaded_file_list_'+document_srl); + if(obj.options.length<1) return; + var file_srl = obj.options[obj.selectedIndex].value; + if(!file_srl) return; + + // 삭제하려는 파일의 정보를 챙김;; + var fo_obj = obj; + while(fo_obj.nodeName != 'FORM') { fo_obj = fo_obj.parentNode; } + var mid = fo_obj.mid.value; + var document_srl = fo_obj.document_srl.value; + var url = "./?mid="+mid+"&act=procDeleteFile&document_srl="+document_srl+"&file_srl="+file_srl; + + // iframe에 url을 보내버림 + var iframe_obj = xGetElementById('tmp_upload_iframe'); + if(!iframe_obj) return; + + iframe_obj.contentWindow.document.location.href=url; +}/*}}}*/ + +// 업로드 목록의 선택된 파일을 내용에 추가 +function editor_insert_file(document_srl, align) {/*{{{*/ + var obj = xGetElementById('uploaded_file_list_'+document_srl); + if(obj.options.length<1) return; + var file_srl = obj.options[obj.selectedIndex].value; + if(!file_srl) return; + var file_obj = uploaded_files[file_srl]; + var filename = file_obj.filename; + var sid = file_obj.sid; + var uploaded_filename = file_obj.uploaded_filename; + editorPrevSrl = document_srl; + + // 바로 링크 가능한 파일의 경우 (이미지, 플래쉬, 동영상 등..) + if(uploaded_filename && typeof(align)!='undefined') { + + var type = ""; + + // 이미지 파일의 경우 + if(/\.(jpg|jpeg|png|gif)$/i.test(uploaded_filename)) { + + editorFocus(editorPrevSrl); + + var html = "\""+filename+"\""; + + var iframe_obj = editorGetIFrame(editorPrevSrl); + editorReplaceHTML(iframe_obj, html); + } + + // binary파일의 경우 다운로드 링크를 추가 + } else { + var fo_obj = obj; + while(fo_obj.nodeName != 'FORM') { fo_obj = fo_obj.parentNode; } + var mid = fo_obj.mid.value; + var document_srl = fo_obj.document_srl.value; + var url = "./?mid="+mid+"&act=procDownload&document_srl="+document_srl+"&file_srl="+file_srl+"&sid="+sid; + + var x = (screen.availWidth - 400)/2; + var y = (screen.availHeight - 220)/2; + var editor_popup = window.open(editor_path+"popup/add_url.php?title="+escape(filename)+"&url="+escape(url),"_editorPopup","top="+y+",left="+x+",width=400,height=220,resizable=no,toolbars=no,scrollbars=no"); + if(editor_popup) editor_popup.focus(); + } + +}/*}}}*/ + +/** + * 글을 쓰다가 페이지 이동시 첨부파일에 대한 정리 + **/ +function editorRemoveAttachFiles(mid, document_srl) {/*{{{*/ + var obj = xGetElementById('uploaded_file_list_'+document_srl); + if(obj.options.length<1) return; + + var params = new Array(); + params['document_srl'] = document_srl; + exec_xml(mid, 'procClearFile', params, null, null, null); +}/*}}}*/ diff --git a/editor/default/editor_uploader.html b/editor/default/editor_uploader.html new file mode 100644 index 000000000..d12fcc7b3 --- /dev/null +++ b/editor/default/editor_uploader.html @@ -0,0 +1,44 @@ + + + +
+ + + + + + + + + + + +
+
+ {$lang->edit->icon_align_article} + {$lang->edit->icon_align_article} +
+
+ {$lang->edit->icon_align_left} + {$lang->edit->icon_align_left} +
+
+ {$lang->edit->icon_align_middle} + {$lang->edit->icon_align_middle} +
+
+ {$lang->edit->icon_align_right} + {$lang->edit->icon_align_right} +
+
+ + + + + +
+
+ diff --git a/editor/default/flvplayer/flvplayer.swf b/editor/default/flvplayer/flvplayer.swf new file mode 100644 index 000000000..5b5412a52 Binary files /dev/null and b/editor/default/flvplayer/flvplayer.swf differ diff --git a/editor/default/images/add_image.gif b/editor/default/images/add_image.gif new file mode 100644 index 000000000..a376c161f Binary files /dev/null and b/editor/default/images/add_image.gif differ diff --git a/editor/default/images/add_indent.gif b/editor/default/images/add_indent.gif new file mode 100644 index 000000000..a092d8c2a Binary files /dev/null and b/editor/default/images/add_indent.gif differ diff --git a/editor/default/images/add_multi.gif b/editor/default/images/add_multi.gif new file mode 100644 index 000000000..5762257f4 Binary files /dev/null and b/editor/default/images/add_multi.gif differ diff --git a/editor/default/images/add_url.gif b/editor/default/images/add_url.gif new file mode 100644 index 000000000..d923ff083 Binary files /dev/null and b/editor/default/images/add_url.gif differ diff --git a/editor/default/images/align_center.gif b/editor/default/images/align_center.gif new file mode 100644 index 000000000..389da4164 Binary files /dev/null and b/editor/default/images/align_center.gif differ diff --git a/editor/default/images/align_left.gif b/editor/default/images/align_left.gif new file mode 100644 index 000000000..8cf629b38 Binary files /dev/null and b/editor/default/images/align_left.gif differ diff --git a/editor/default/images/align_right.gif b/editor/default/images/align_right.gif new file mode 100644 index 000000000..64034efb9 Binary files /dev/null and b/editor/default/images/align_right.gif differ diff --git a/editor/default/images/blank.gif b/editor/default/images/blank.gif new file mode 100644 index 000000000..35d42e808 Binary files /dev/null and b/editor/default/images/blank.gif differ diff --git a/editor/default/images/bold.gif b/editor/default/images/bold.gif new file mode 100644 index 000000000..db1da7d03 Binary files /dev/null and b/editor/default/images/bold.gif differ diff --git a/editor/default/images/color_block.gif b/editor/default/images/color_block.gif new file mode 100644 index 000000000..099c95f3c Binary files /dev/null and b/editor/default/images/color_block.gif differ diff --git a/editor/default/images/emoticon.gif b/editor/default/images/emoticon.gif new file mode 100644 index 000000000..cd9fc0fba Binary files /dev/null and b/editor/default/images/emoticon.gif differ diff --git a/editor/default/images/emoticon/msn001.gif b/editor/default/images/emoticon/msn001.gif new file mode 100644 index 000000000..cdbd99eab Binary files /dev/null and b/editor/default/images/emoticon/msn001.gif differ diff --git a/editor/default/images/emoticon/msn002.gif b/editor/default/images/emoticon/msn002.gif new file mode 100644 index 000000000..1cb28dfa5 Binary files /dev/null and b/editor/default/images/emoticon/msn002.gif differ diff --git a/editor/default/images/emoticon/msn003.gif b/editor/default/images/emoticon/msn003.gif new file mode 100644 index 000000000..92498b893 Binary files /dev/null and b/editor/default/images/emoticon/msn003.gif differ diff --git a/editor/default/images/emoticon/msn004.gif b/editor/default/images/emoticon/msn004.gif new file mode 100644 index 000000000..4d28cddb7 Binary files /dev/null and b/editor/default/images/emoticon/msn004.gif differ diff --git a/editor/default/images/emoticon/msn005.gif b/editor/default/images/emoticon/msn005.gif new file mode 100644 index 000000000..261ff6f1e Binary files /dev/null and b/editor/default/images/emoticon/msn005.gif differ diff --git a/editor/default/images/emoticon/msn006.gif b/editor/default/images/emoticon/msn006.gif new file mode 100644 index 000000000..4147ae7fc Binary files /dev/null and b/editor/default/images/emoticon/msn006.gif differ diff --git a/editor/default/images/emoticon/msn007.gif b/editor/default/images/emoticon/msn007.gif new file mode 100644 index 000000000..0e7756bfd Binary files /dev/null and b/editor/default/images/emoticon/msn007.gif differ diff --git a/editor/default/images/emoticon/msn008.gif b/editor/default/images/emoticon/msn008.gif new file mode 100644 index 000000000..c20b32598 Binary files /dev/null and b/editor/default/images/emoticon/msn008.gif differ diff --git a/editor/default/images/emoticon/msn009.gif b/editor/default/images/emoticon/msn009.gif new file mode 100644 index 000000000..0b843dd1e Binary files /dev/null and b/editor/default/images/emoticon/msn009.gif differ diff --git a/editor/default/images/emoticon/msn010.gif b/editor/default/images/emoticon/msn010.gif new file mode 100644 index 000000000..0188685b9 Binary files /dev/null and b/editor/default/images/emoticon/msn010.gif differ diff --git a/editor/default/images/emoticon/msn011.gif b/editor/default/images/emoticon/msn011.gif new file mode 100644 index 000000000..e3548aeb1 Binary files /dev/null and b/editor/default/images/emoticon/msn011.gif differ diff --git a/editor/default/images/emoticon/msn012.gif b/editor/default/images/emoticon/msn012.gif new file mode 100644 index 000000000..96c29eea4 Binary files /dev/null and b/editor/default/images/emoticon/msn012.gif differ diff --git a/editor/default/images/emoticon/msn013.gif b/editor/default/images/emoticon/msn013.gif new file mode 100644 index 000000000..baf46d258 Binary files /dev/null and b/editor/default/images/emoticon/msn013.gif differ diff --git a/editor/default/images/emoticon/msn014.gif b/editor/default/images/emoticon/msn014.gif new file mode 100644 index 000000000..eee013eda Binary files /dev/null and b/editor/default/images/emoticon/msn014.gif differ diff --git a/editor/default/images/emoticon/msn015.gif b/editor/default/images/emoticon/msn015.gif new file mode 100644 index 000000000..0813a4f2b Binary files /dev/null and b/editor/default/images/emoticon/msn015.gif differ diff --git a/editor/default/images/emoticon/msn016.gif b/editor/default/images/emoticon/msn016.gif new file mode 100644 index 000000000..f187c63dd Binary files /dev/null and b/editor/default/images/emoticon/msn016.gif differ diff --git a/editor/default/images/emoticon/msn017.gif b/editor/default/images/emoticon/msn017.gif new file mode 100644 index 000000000..ccbb0758a Binary files /dev/null and b/editor/default/images/emoticon/msn017.gif differ diff --git a/editor/default/images/emoticon/msn018.gif b/editor/default/images/emoticon/msn018.gif new file mode 100644 index 000000000..b08d174ed Binary files /dev/null and b/editor/default/images/emoticon/msn018.gif differ diff --git a/editor/default/images/emoticon/msn019.gif b/editor/default/images/emoticon/msn019.gif new file mode 100644 index 000000000..7ba69aed3 Binary files /dev/null and b/editor/default/images/emoticon/msn019.gif differ diff --git a/editor/default/images/emoticon/msn020.gif b/editor/default/images/emoticon/msn020.gif new file mode 100644 index 000000000..4808bb4c0 Binary files /dev/null and b/editor/default/images/emoticon/msn020.gif differ diff --git a/editor/default/images/emoticon/msn021.gif b/editor/default/images/emoticon/msn021.gif new file mode 100644 index 000000000..02bcedb4e Binary files /dev/null and b/editor/default/images/emoticon/msn021.gif differ diff --git a/editor/default/images/emoticon/msn022.gif b/editor/default/images/emoticon/msn022.gif new file mode 100644 index 000000000..834ca31d3 Binary files /dev/null and b/editor/default/images/emoticon/msn022.gif differ diff --git a/editor/default/images/emoticon/msn023.gif b/editor/default/images/emoticon/msn023.gif new file mode 100644 index 000000000..1c75a640a Binary files /dev/null and b/editor/default/images/emoticon/msn023.gif differ diff --git a/editor/default/images/emoticon/msn024.gif b/editor/default/images/emoticon/msn024.gif new file mode 100644 index 000000000..33c108eca Binary files /dev/null and b/editor/default/images/emoticon/msn024.gif differ diff --git a/editor/default/images/emoticon/msn025.gif b/editor/default/images/emoticon/msn025.gif new file mode 100644 index 000000000..0da3b10f5 Binary files /dev/null and b/editor/default/images/emoticon/msn025.gif differ diff --git a/editor/default/images/emoticon/msn026.gif b/editor/default/images/emoticon/msn026.gif new file mode 100644 index 000000000..160f6a22f Binary files /dev/null and b/editor/default/images/emoticon/msn026.gif differ diff --git a/editor/default/images/emoticon/msn027.gif b/editor/default/images/emoticon/msn027.gif new file mode 100644 index 000000000..1e911fb26 Binary files /dev/null and b/editor/default/images/emoticon/msn027.gif differ diff --git a/editor/default/images/emoticon/msn028.gif b/editor/default/images/emoticon/msn028.gif new file mode 100644 index 000000000..5439d0075 Binary files /dev/null and b/editor/default/images/emoticon/msn028.gif differ diff --git a/editor/default/images/emoticon/msn029.gif b/editor/default/images/emoticon/msn029.gif new file mode 100644 index 000000000..cc4cec40a Binary files /dev/null and b/editor/default/images/emoticon/msn029.gif differ diff --git a/editor/default/images/emoticon/msn030.gif b/editor/default/images/emoticon/msn030.gif new file mode 100644 index 000000000..4beeeb88c Binary files /dev/null and b/editor/default/images/emoticon/msn030.gif differ diff --git a/editor/default/images/emoticon/msn031.gif b/editor/default/images/emoticon/msn031.gif new file mode 100644 index 000000000..c3bc29863 Binary files /dev/null and b/editor/default/images/emoticon/msn031.gif differ diff --git a/editor/default/images/emoticon/msn032.gif b/editor/default/images/emoticon/msn032.gif new file mode 100644 index 000000000..6a8a26e9c Binary files /dev/null and b/editor/default/images/emoticon/msn032.gif differ diff --git a/editor/default/images/emoticon/msn033.gif b/editor/default/images/emoticon/msn033.gif new file mode 100644 index 000000000..f0dc4bf2d Binary files /dev/null and b/editor/default/images/emoticon/msn033.gif differ diff --git a/editor/default/images/emoticon/msn034.gif b/editor/default/images/emoticon/msn034.gif new file mode 100644 index 000000000..9283363c5 Binary files /dev/null and b/editor/default/images/emoticon/msn034.gif differ diff --git a/editor/default/images/emoticon/msn035.gif b/editor/default/images/emoticon/msn035.gif new file mode 100644 index 000000000..6e2ecd3d3 Binary files /dev/null and b/editor/default/images/emoticon/msn035.gif differ diff --git a/editor/default/images/emoticon/msn036.gif b/editor/default/images/emoticon/msn036.gif new file mode 100644 index 000000000..ddb0aa040 Binary files /dev/null and b/editor/default/images/emoticon/msn036.gif differ diff --git a/editor/default/images/emoticon/msn037.gif b/editor/default/images/emoticon/msn037.gif new file mode 100644 index 000000000..cfca21644 Binary files /dev/null and b/editor/default/images/emoticon/msn037.gif differ diff --git a/editor/default/images/emoticon/msn038.gif b/editor/default/images/emoticon/msn038.gif new file mode 100644 index 000000000..14a163612 Binary files /dev/null and b/editor/default/images/emoticon/msn038.gif differ diff --git a/editor/default/images/emoticon/msn039.gif b/editor/default/images/emoticon/msn039.gif new file mode 100644 index 000000000..f6c0d7f4e Binary files /dev/null and b/editor/default/images/emoticon/msn039.gif differ diff --git a/editor/default/images/emoticon/msn040.gif b/editor/default/images/emoticon/msn040.gif new file mode 100644 index 000000000..d379bd702 Binary files /dev/null and b/editor/default/images/emoticon/msn040.gif differ diff --git a/editor/default/images/font_bg_color.gif b/editor/default/images/font_bg_color.gif new file mode 100644 index 000000000..e1f4a8fe9 Binary files /dev/null and b/editor/default/images/font_bg_color.gif differ diff --git a/editor/default/images/font_color.gif b/editor/default/images/font_color.gif new file mode 100644 index 000000000..92e6ca4f7 Binary files /dev/null and b/editor/default/images/font_color.gif differ diff --git a/editor/default/images/html_add.gif b/editor/default/images/html_add.gif new file mode 100644 index 000000000..fc9382d86 Binary files /dev/null and b/editor/default/images/html_add.gif differ diff --git a/editor/default/images/icon_align_article.gif b/editor/default/images/icon_align_article.gif new file mode 100644 index 000000000..f16697d91 Binary files /dev/null and b/editor/default/images/icon_align_article.gif differ diff --git a/editor/default/images/icon_align_left.gif b/editor/default/images/icon_align_left.gif new file mode 100644 index 000000000..247324f22 Binary files /dev/null and b/editor/default/images/icon_align_left.gif differ diff --git a/editor/default/images/icon_align_middle.gif b/editor/default/images/icon_align_middle.gif new file mode 100644 index 000000000..5e9a00d35 Binary files /dev/null and b/editor/default/images/icon_align_middle.gif differ diff --git a/editor/default/images/icon_align_right.gif b/editor/default/images/icon_align_right.gif new file mode 100644 index 000000000..0ac97aa0b Binary files /dev/null and b/editor/default/images/icon_align_right.gif differ diff --git a/editor/default/images/icon_drag_down.gif b/editor/default/images/icon_drag_down.gif new file mode 100644 index 000000000..101b5a398 Binary files /dev/null and b/editor/default/images/icon_drag_down.gif differ diff --git a/editor/default/images/italic.gif b/editor/default/images/italic.gif new file mode 100644 index 000000000..f69a12c0d Binary files /dev/null and b/editor/default/images/italic.gif differ diff --git a/editor/default/images/list_bullet.gif b/editor/default/images/list_bullet.gif new file mode 100644 index 000000000..029a2cfba Binary files /dev/null and b/editor/default/images/list_bullet.gif differ diff --git a/editor/default/images/list_number.gif b/editor/default/images/list_number.gif new file mode 100644 index 000000000..81aeab4b1 Binary files /dev/null and b/editor/default/images/list_number.gif differ diff --git a/editor/default/images/multimedia_icon.gif b/editor/default/images/multimedia_icon.gif new file mode 100644 index 000000000..d5309d362 Binary files /dev/null and b/editor/default/images/multimedia_icon.gif differ diff --git a/editor/default/images/php_highlight.gif b/editor/default/images/php_highlight.gif new file mode 100644 index 000000000..ab7f45995 Binary files /dev/null and b/editor/default/images/php_highlight.gif differ diff --git a/editor/default/images/quotation.gif b/editor/default/images/quotation.gif new file mode 100644 index 000000000..e4664db83 Binary files /dev/null and b/editor/default/images/quotation.gif differ diff --git a/editor/default/images/remove_indent.gif b/editor/default/images/remove_indent.gif new file mode 100644 index 000000000..f3178ae25 Binary files /dev/null and b/editor/default/images/remove_indent.gif differ diff --git a/editor/default/images/strike.gif b/editor/default/images/strike.gif new file mode 100644 index 000000000..c6b4aca23 Binary files /dev/null and b/editor/default/images/strike.gif differ diff --git a/editor/default/images/underline.gif b/editor/default/images/underline.gif new file mode 100644 index 000000000..7a44f82e7 Binary files /dev/null and b/editor/default/images/underline.gif differ diff --git a/editor/default/lang/ko.lang.php b/editor/default/lang/ko.lang.php new file mode 100644 index 000000000..238925b51 --- /dev/null +++ b/editor/default/lang/ko.lang.php @@ -0,0 +1,60 @@ + + * @desc : 한국어 언어팩 (기본적인 내용만 수록) + **/ + + $lang->edit->fontname = '폰트'; + $lang->edit->fontsize = '크기'; + $lang->edit->use_paragraph = '문단기능'; + $lang->edit->fontlist = array( + "굴림", + "돋움", + "바탕", + "궁서", + "times", + "Courier", + "Tahoma", + "Arial", + ); + + $lang->edit->image_url = '이미지 경로'; + + $lang->edit->multimedia_url = '멀티미디어 경로'; + $lang->edit->multimedia_width = '가로크기'; + $lang->edit->multimedia_height = '세로크기'; + + $lang->edit->submit = '확인'; + + $lang->edit->help_fontcolor = "글자의 색상을 지정합니다"; + $lang->edit->help_fontbgcolor = "글자의 배경색상을 지정합니다"; + $lang->edit->help_bold = "글자를 진하게 합니다"; + $lang->edit->help_italic = "글자를 기울이게 합니다"; + $lang->edit->help_underline = "밑줄을 긋습니다"; + $lang->edit->help_strike = "취소선을 긋습니다"; + $lang->edit->help_add_url= "link를 만듭니다"; + $lang->edit->help_add_image = "이미지를 추가합니다"; + $lang->edit->help_add_multimedia = "동영상/플래쉬등을 추가합니다"; + $lang->edit->help_add_emoticon = "이모티콘을 추가합니다"; + $lang->edit->help_add_quotation = "글박스를 만들거나 글숨김 기능을 추가합니다"; + $lang->edit->help_add_html = "html 코드를 직접 입력합니다"; + $lang->edit->help_add_html = "html 코드를 직접 입력합니다"; + $lang->edit->help_align_left = "왼쪽 정렬을 합니다"; + $lang->edit->help_align_center = "가운데 정렬을 합니다"; + $lang->edit->help_align_right = "오른쪽 정렬을 합니다"; + $lang->edit->help_add_indent = "들여쓰기를 합니다"; + $lang->edit->help_remove_indent = "들여쓰기를 제거합니다"; + $lang->edit->help_use_paragrapth = "정렬, 들여쓰기등의 문단 꾸미기 기능을 사용합니다.\n문단구분자로 P태그가 적용됩니다.\nShift+엔터를 이용하시면 + BR태그가 적용됩니다."; + + $lang->edit->upload = '첨부'; + $lang->edit->link_selected = '다운로드 링크 추가'; + $lang->edit->delete_selected = '선택파일 삭제'; + + $lang->edit->icon_align_article = '한 문단을 차지'; + $lang->edit->icon_align_left = '글의 왼쪽으로'; + $lang->edit->icon_align_middle = '가운데 정렬'; + $lang->edit->icon_align_right = '글의 우측으로'; + +?> diff --git a/editor/default/popup/add_emoticon.php b/editor/default/popup/add_emoticon.php new file mode 100644 index 000000000..0c300ea6d --- /dev/null +++ b/editor/default/popup/add_emoticon.php @@ -0,0 +1,35 @@ + + + + + add Emoticon + + + + + + + + + diff --git a/editor/default/popup/add_html.php b/editor/default/popup/add_html.php new file mode 100755 index 000000000..c108206cb --- /dev/null +++ b/editor/default/popup/add_html.php @@ -0,0 +1,39 @@ + + + + + Edit Html + + + + + + +
+
+
+
+
+
+ + + diff --git a/editor/default/popup/add_image.php b/editor/default/popup/add_image.php new file mode 100644 index 000000000..30dfb8a3d --- /dev/null +++ b/editor/default/popup/add_image.php @@ -0,0 +1,55 @@ + + + + + add Image + + + + + + +
+
+ + + + + + + + + + + + + + +
url'/>
type + +
+ +
+
+
+ + + diff --git a/editor/default/popup/add_multi.php b/editor/default/popup/add_multi.php new file mode 100644 index 000000000..85dab24b5 --- /dev/null +++ b/editor/default/popup/add_multi.php @@ -0,0 +1,51 @@ + + + + + add Multimedia + + + + + + +
+
+ + + + + + + + + + + + + + + + + + +
url
width
height
+
+
+ + + diff --git a/editor/default/popup/add_quotation.php b/editor/default/popup/add_quotation.php new file mode 100644 index 000000000..066a31631 --- /dev/null +++ b/editor/default/popup/add_quotation.php @@ -0,0 +1,216 @@ + + + + + add Quotation + + + + + + +
+
+
+ quotation + fold +
+ +
+ + + + + + + + + + + + + + + +
bg color
border type + +
border color
+
+ +
+
+ + + + + + + +
+ + + + + + + +
+ +
+
+
+
+ + + diff --git a/editor/default/popup/add_url.php b/editor/default/popup/add_url.php new file mode 100644 index 000000000..9705bceb0 --- /dev/null +++ b/editor/default/popup/add_url.php @@ -0,0 +1,75 @@ + + + + + add Url + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + +
text
url"/>
bold
type + +
+ +
+
+
+ + + diff --git a/editor/default/popup/color_box.php b/editor/default/popup/color_box.php new file mode 100644 index 000000000..82df6f561 --- /dev/null +++ b/editor/default/popup/color_box.php @@ -0,0 +1,39 @@ + + + + + change Color + + + + + + + + + diff --git a/index.php b/index.php new file mode 100644 index 000000000..98d941df2 --- /dev/null +++ b/index.php @@ -0,0 +1,23 @@ + + * @desc : 모든 요청(request)의 관문으로 main() 역할을 함 + * Main class의 instance를 생성하여 constructor 실행하는 역할만 수행 + **/ + + // 필요한 설정 파일들을 include + require_once("./config/config.inc.php"); + + // Request Method와 설정값들을 세팅 + $oContext = &Context::getInstance(); + $oContext->init(); + + // ModuleHandler 호출하여 content 출력 + $oModuleHandler = new ModuleHandler(); + $oModule = $oModuleHandler->proc(); + + // DisplayHandler로 컨텐츠 출력 + $oDisplayHandler = new DisplayHandler(); + $oDisplayHandler->printContent($oModule); +?> diff --git a/layouts/test/test.layout.php b/layouts/test/test.layout.php new file mode 100644 index 000000000..7b898228d --- /dev/null +++ b/layouts/test/test.layout.php @@ -0,0 +1,13 @@ + + * @desc : test 레이아웃 + **/ + + class test { + function proc(&$oModule, $oModuleInfo) { + $oModule->setHtml('레이아웃'); + } + } diff --git a/modules/admin/admin.module.php b/modules/admin/admin.module.php new file mode 100644 index 000000000..3c9eb1523 --- /dev/null +++ b/modules/admin/admin.module.php @@ -0,0 +1,148 @@ + + * @desc : 기본 모듈중의 하나인 admin module + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class admin extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = ''; + + // 모듈에서 사용할 변수들 + var $skin = "default"; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/admin/"; + **/ + + // 초기화 + function init() {/*{{{*/ + // admin 모듈의 언어 로드 + Context::loadLang($this->module_path.'lang'); + + // 관리자 모듈 목록을 세팅 + $module_list = module_manager::getAdminModuleList(); + Context::set('module_list', $module_list); + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + // 접속 사용자에 대한 체크 + $oMember = getModule('member'); + $logged_info = $oMember->getLoggedInfo(); + + // 로그인 하지 않았다면 로그인 폼 출력 + if(!$oMember->isLogged()) return $this->act = 'dispLogin'; + + // 로그인되었는데 관리자(member->is_admin!=1)가 아니면 오류 표시 + if($logged_info->is_admin != 'Y') { + Context::set('msg_code', 'msg_is_not_administrator'); + return $this->act = 'dispError'; + } + + // 관리자용 레이아웃으로 변경 + $this->setLayoutPath($this->getLayoutPath()); + $this->setLayoutTpl($this->getLayoutTpl()); + + return true; + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + // 로그인/로그아웃 act의 경우는 패스~ + if(in_array($this->act, array('procLogin', 'procLogout'))) return true; + + // 접속 사용자에 대한 체크 + $oMember = getModule('member'); + $logged_info = $oMember->getLoggedInfo(); + + // 로그인되었는데 관리자(member->is_admin!=1)가 아니면 오류 표시 + if($logged_info->is_admin != 'Y') { + $this->setError(-1); + $this->setMessage('msg_is_not_administrator'); + return false; + } + + return true; + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 error, message가 지정되어야 한다 + * + * 변수의 사용은 Context::get('이름')으로 얻어오면 된다 + **/ + + // 출력부분 + function dispAdminIndex() {/*{{{*/ + $this->setTemplateFile('index'); + }/*}}}*/ + + function dispLogin() {/*{{{*/ + if(Context::get('is_logged')) return $this->dispAdminIndex(); + $this->setTemplateFile('login_form'); + }/*}}}*/ + + function dispLogout() {/*{{{*/ + if(!Context::get('is_logged')) return $this->dispAdminIndex(); + $this->setTemplateFile('logout'); + }/*}}}*/ + + function dispError() {/*{{{*/ + Context::set('error_msg', Context::getLang( Context::get('msg_code') ) ); + $this->setTemplateFile('error'); + }/*}}}*/ + + // 실행부분 + function procLogin() {/*{{{*/ + // 아이디, 비밀번호를 받음 + $user_id = Context::get('user_id'); + $password = Context::get('password'); + // member모듈 객체 생성 + $oMember = getModule('member'); + return $oMember->doLogin($user_id, $password); + }/*}}}*/ + + function procLogout() {/*{{{*/ + // member모듈 객체 생성 + $oMember = getModule('member'); + return $oMember->doLogout(); + }/*}}}*/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + + function getLayoutPath() {/*{{{*/ + return $this->template_path; + }/*}}}*/ + + function getLayoutTpl() {/*{{{*/ + return "layout.html"; + }/*}}}*/ + } +?> diff --git a/modules/admin/lang/ko.lang.php b/modules/admin/lang/ko.lang.php new file mode 100644 index 000000000..c257e9fe9 --- /dev/null +++ b/modules/admin/lang/ko.lang.php @@ -0,0 +1,9 @@ + + * @desc : 한국어 언어팩 (기본적인 내용만 수록) + **/ + + $lang->msg_is_not_administrator = '관리자만 접속이 가능합니다'; +?> diff --git a/modules/admin/module.xml b/modules/admin/module.xml new file mode 100644 index 000000000..4a62a35d3 --- /dev/null +++ b/modules/admin/module.xml @@ -0,0 +1,11 @@ + + + 관리자 툴 + Admin tool + + 제로 + zero + 모듈 관리 툴 + Admin tool + + diff --git a/modules/admin/skins/default/css/admin.css b/modules/admin/skins/default/css/admin.css new file mode 100644 index 000000000..e1bd94a38 --- /dev/null +++ b/modules/admin/skins/default/css/admin.css @@ -0,0 +1,22 @@ +#admin_title { + font-weight:bold; + float:left; + height:30px; +} + +#admin_info { + float:right; + height:30px; +} + +#admin_module_list { + clear:both; + float:left; +} + +#admin_module_content { + position:relative; + margin-left:150px; + left:0px; + top:30px; +} diff --git a/modules/admin/skins/default/error.html b/modules/admin/skins/default/error.html new file mode 100644 index 000000000..fbdcbcd39 --- /dev/null +++ b/modules/admin/skins/default/error.html @@ -0,0 +1 @@ +{$error_msg} diff --git a/modules/admin/skins/default/filter/filter.login.xml b/modules/admin/skins/default/filter/filter.login.xml new file mode 100644 index 000000000..26ec5aab1 --- /dev/null +++ b/modules/admin/skins/default/filter/filter.login.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/modules/admin/skins/default/filter/filter.logout.xml b/modules/admin/skins/default/filter/filter.logout.xml new file mode 100644 index 000000000..3c1f3a9f1 --- /dev/null +++ b/modules/admin/skins/default/filter/filter.logout.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/modules/admin/skins/default/index.html b/modules/admin/skins/default/index.html new file mode 100644 index 000000000..5ad28e227 --- /dev/null +++ b/modules/admin/skins/default/index.html @@ -0,0 +1 @@ +haha diff --git a/modules/admin/skins/default/js/admin.js b/modules/admin/skins/default/js/admin.js new file mode 100644 index 000000000..109f9c9e7 --- /dev/null +++ b/modules/admin/skins/default/js/admin.js @@ -0,0 +1,27 @@ +/** + * @file : modules/admin/js/admin.js + * @author : zero + * @desc : admin 모듈의 javascript + **/ + +// 현재 페이지 reload +function procReload(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + + location.href = location.href; +} + +// 로그아웃 +function procLogout(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + + location.href = "./admin.php"; +} + +// 로그인폼에서 아이디 포커스 +function procAdminLoginFocus() { + var fo = xGetElementById('user_id'); + if(fo) fo.focus(); +} diff --git a/modules/admin/skins/default/layout.html b/modules/admin/skins/default/layout.html new file mode 100644 index 000000000..b58a6776c --- /dev/null +++ b/modules/admin/skins/default/layout.html @@ -0,0 +1,21 @@ + + + + + + + +
+ +
style="font-weight:bold;"> + {$module_title} +
+ +
+
+ {$content} +
+ + diff --git a/modules/admin/skins/default/login_form.html b/modules/admin/skins/default/login_form.html new file mode 100644 index 000000000..fe228544b --- /dev/null +++ b/modules/admin/skins/default/login_form.html @@ -0,0 +1,30 @@ + + + +
+ + + + + + + + + + + + + + + + +
{$lang->user_id}
{$lang->password}
+ + +
+ +
+ + diff --git a/modules/admin/skins/default/logout.html b/modules/admin/skins/default/logout.html new file mode 100644 index 000000000..9c271b427 --- /dev/null +++ b/modules/admin/skins/default/logout.html @@ -0,0 +1,21 @@ + + + +
+ + + + + + + + + + + +
{$lang->cmd_logout}
{$lang->confirm_logout}
+ + +
+ +
diff --git a/modules/board/admin/category_list.html b/modules/board/admin/category_list.html new file mode 100644 index 000000000..837a4e4f3 --- /dev/null +++ b/modules/board/admin/category_list.html @@ -0,0 +1,57 @@ + + + + + + +
+ + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->category_title}{$lang->document_count}{$lang->last_update}{$lang->cmd_modify}{$lang->cmd_move}{$lang->cmd_delete}
{$lang->msg_category_is_null}
{$category_info->title}{number_format($category_info->document_count)}{zdate($category_info->last_update,"Y-m-d H:i:s")}{$lang->cmd_modify}{$lang->cmd_move_up}{$lang->cmd_move_down}{$lang->cmd_delete}
+
+ + +
+ + + + + + +
+ {$lang->category_title} : + + +
+ +
diff --git a/modules/board/admin/category_update_form.html b/modules/board/admin/category_update_form.html new file mode 100644 index 000000000..0c45b09fb --- /dev/null +++ b/modules/board/admin/category_update_form.html @@ -0,0 +1,21 @@ + + + + + + +
+ + + + + +
+ {$lang->category_title} : + + + +
+ +
+ diff --git a/modules/board/admin/delete_form.html b/modules/board/admin/delete_form.html new file mode 100644 index 000000000..02136ac7c --- /dev/null +++ b/modules/board/admin/delete_form.html @@ -0,0 +1,34 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
{$lang->confirm_delete}
{$lang->module_name}{$module_info->mid}
{$lang->module}{$module_info->module}
{$lang->document_count}{$module_info->document_count}
+ + +
+ +
+ diff --git a/modules/board/admin/filter/filter.delete_module.xml b/modules/board/admin/filter/filter.delete_module.xml new file mode 100644 index 000000000..ce7bba07c --- /dev/null +++ b/modules/board/admin/filter/filter.delete_module.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/modules/board/admin/filter/filter.insert.xml b/modules/board/admin/filter/filter.insert.xml new file mode 100644 index 000000000..6152deb8d --- /dev/null +++ b/modules/board/admin/filter/filter.insert.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/modules/board/admin/filter/filter.insert_category.xml b/modules/board/admin/filter/filter.insert_category.xml new file mode 100644 index 000000000..2f67d5148 --- /dev/null +++ b/modules/board/admin/filter/filter.insert_category.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/modules/board/admin/filter/filter.insert_grant.xml b/modules/board/admin/filter/filter.insert_grant.xml new file mode 100644 index 000000000..7b1abcf77 --- /dev/null +++ b/modules/board/admin/filter/filter.insert_grant.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/modules/board/admin/filter/filter.update_category.xml b/modules/board/admin/filter/filter.update_category.xml new file mode 100644 index 000000000..ed18f9b9d --- /dev/null +++ b/modules/board/admin/filter/filter.update_category.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/modules/board/admin/grant_list.html b/modules/board/admin/grant_list.html new file mode 100644 index 000000000..ee9990736 --- /dev/null +++ b/modules/board/admin/grant_list.html @@ -0,0 +1,45 @@ + + + +
+ + + + + +
+ {$lang->about_grant} +
+ + + + + + + + + + + + + + + +
{$lang->grant}{$lang->target}
{$lang->grant_title[$val]} +
+ + + grant)&&in_array($v->group_srl,$module_info->grant[$val]))-->checked="true"/> + + + +
+
+ + +
+
+ +
+ +
diff --git a/modules/board/admin/header.html b/modules/board/admin/header.html new file mode 100644 index 000000000..8c64bd215 --- /dev/null +++ b/modules/board/admin/header.html @@ -0,0 +1,14 @@ + + +
+ [{$lang->cmd_list}] + style="font-weight:bold">[{$lang->cmd_view_info}] + style="font-weight:bold">[{$lang->cmd_manage_category}] + style="font-weight:bold">[{$lang->cmd_manage_grant}] + style="font-weight:bold">[{$lang->cmd_manage_skin}] +
+
+ {$lang->mid} : {$module_info->mid} + ({$lang->cmd_move}) + [{$lang->is_default}] +
diff --git a/modules/board/admin/info.html b/modules/board/admin/info.html new file mode 100644 index 000000000..6cdb08b7c --- /dev/null +++ b/modules/board/admin/info.html @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->skin}{$module_info->skin}
{$lang->use_category}{$lang->use}{$lang->notuse}
{$lang->browser_title}{$module_info->browser_title}
{$lang->description}{nl2br($module_info->description)}
{$lang->header_text}{$module_info->header_text}
{$lang->footer_text}{$module_info->footer_text}
{$lang->admin_id}{$module_info->admin_id}
+ +
diff --git a/modules/board/admin/insert_form.html b/modules/board/admin/insert_form.html new file mode 100644 index 000000000..d9ddb0ce3 --- /dev/null +++ b/modules/board/admin/insert_form.html @@ -0,0 +1,99 @@ + + + +
+ + {$lang->msg_new_module} + + {$lang->msg_update_module} + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->mid}
{$lang->about_mid}
{$lang->skin} + +
{$lang->about_skin}
{$lang->use_category}use_category=='Y')-->checked="true" />
{$lang->about_use_category}
{$lang->browser_title}
{$lang->about_browser_title}
{$lang->is_default}is_default=='Y')-->checked="true"/>
{$lang->about_default}
{$lang->description}
{$lang->about_description}
{$lang->header_text}
{$lang->about_header_text}
{$lang->footer_text}
{$lang->about_footer_text}
{$lang->admin_id}
{$lang->about_admin_id}
+ + +
+
diff --git a/modules/board/admin/js/admin.js b/modules/board/admin/js/admin.js new file mode 100644 index 000000000..6a53ad5ca --- /dev/null +++ b/modules/board/admin/js/admin.js @@ -0,0 +1,95 @@ +/** + * @file : modules/board/js/admin.js + * @author : zero + * @desc : board 모듈의 관리자용 javascript + **/ + +/* 모듈 생성 후 */ +function procInsert(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var sid = ret_obj['sid']; + var act = ret_obj['act']; + var page = ret_obj['page']; + var module_srl = ret_obj['module_srl']; + alert(message); + + url = "./admin.php?sid="+sid+"&module_srl="+module_srl+"&page="+page+"&act="+act; + location.href = url; +} + +/* 모듈 삭제 후 */ +function procDelete(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var sid = ret_obj['sid']; + var act = ret_obj['act']; + var page = ret_obj['page']; + alert(message); + + url = "./admin.php?sid="+sid+"&page="+page+"&act="+act; + location.href = url; +} + +/* 카테고리 관련 작업들 */ +function doUpdateCategory(category_srl, mode, message) { + if(typeof(message)!='undefined'&&!confirm(message)) return; + + var fo_obj = xGetElementById('fo_category_info'); + fo_obj.category_srl.value = category_srl; + fo_obj.mode.value = mode; + + procFormFilter(fo_obj, update_category, procReload); +} + +/* 카테고리 정보 수정 후 */ +function procUpdateCategory(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var module_srl = ret_obj['module_srl']; + alert(message); + + var url = "./admin.php?sid=board&module_srl="+module_srl+"&act=dispCategoryInfo"; + location.href = url; +} + +/* 메세지 출력후 현페이지 리로드 */ +function procReload(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + if(message) alert(message); + location.href = location.href; +} + +/* 권한 관련 */ +function procSelectAll(obj, key) { + var fo_obj = obj.parentNode; + while(fo_obj.nodeName != 'FORM') { fo_obj = fo_obj.parentNode; } + for(var i=0;i + + +
+ {number_format($total_count)}, + {$lang->page_count} : {number_format($page)} / {number_format($total_page)} +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->no}{$lang->mid}{$lang->browser_title}{$lang->is_default}{$lang->skin}{$lang->admin_id}{$lang->regdate}{$lang->cmd_move}{$lang->cmd_delete}
{$no}{$val->mid}{$val->browser_title}{$val->is_default}{$val->skin}{$val->admin_id}{zdate($val->regdate,"Y-m-d")}{$lang->cmd_move}{$lang->cmd_delete}
+
+ + + + + +
+ [{$lang->first_page}] + + + + {$page_no} + + [{$page_no}] + + + + [{$lang->last_page}] +
diff --git a/modules/board/admin/skin_info.html b/modules/board/admin/skin_info.html new file mode 100644 index 000000000..eeadada40 --- /dev/null +++ b/modules/board/admin/skin_info.html @@ -0,0 +1,119 @@ + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->skin_default_info}
{$lang->skin}{$skin_info->title}
{$lang->skin_maker}{$skin_info->maker->name} ({$skin_info->maker->email_address})
{$lang->skin_maker_homepage}{$skin_info->maker->homepage}
{$lang->date}{$skin_info->maker->date}
{$lang->description}{nl2br($skin_info->maker->description)}
{$lang->colorset} + +
+ + {$val->title} + + colorset==$val->name)-->checked="true"/> + +
+ +
+
+ + +
+ + + + + + + + + + + + + + + + + +
{$lang->extra_vars}
description)-->rowspan="2">{$val->title} + + + + + + + + + + + + + value))-->checked="true"/> + + + + + + + + value)-->checked="true"/> + + + + + + +
+
+ + +
+ + + + +
{nl2br($val->description)}
+
+ + +
+ +
+ +
diff --git a/modules/board/board.admin.php b/modules/board/board.admin.php new file mode 100644 index 000000000..69ea95820 --- /dev/null +++ b/modules/board/board.admin.php @@ -0,0 +1,403 @@ + + * @desc : board의 관리자 파일 + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class board_admin extends Module { + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = 'dispContent'; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/system_install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + // 기본 정보를 읽음 + Context::loadLang($this->module_path.'lang'); + + // 스킨의 종류를 읽음 + $oModule = getModule('module_manager'); + $skins = $oModule->getSkins($this->module_path); + Context::set('skins', $skins); + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + // module_srl이 있으면 미리 체크하여 존재하는 모듈이면 module_info 세팅 + $module_srl = Context::get('module_srl'); + if($module_srl) { + $oModule = getModule('module_manager'); + $module_info = $oModule->getModuleInfoByModuleSrl($module_srl); + if(!$module_info) { + Context::set('module_srl',''); + $this->act = 'dispContent'; + } else Context::set('module_info',$module_info); + } + + return true; + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + return true; + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 error, message가 지정되어야 한다 + **/ + + // 출력 부분 + function dispContent() {/*{{{*/ + + // 등록된 board 모듈을 불러와 세팅 + $oDB = &DB::getInstance(); + $args->sort_index = "module_srl"; + $args->page = Context::get('page'); + $args->list_count = 40; + $args->page_count = 10; + $output = $oDB->executeQuery('board.getBoardList', $args); + + // 템플릿에 쓰기 위해서 context::set + Context::set('total_count', $output->total_count); + Context::set('total_page', $output->total_page); + Context::set('page', $output->page); + Context::set('board_list', $output->data); + Context::set('page_navigation', $output->page_navigation); + + // 템플릿 파일 지정 + $this->setTemplateFile('list'); + }/*}}}*/ + + function dispInfo() {/*{{{*/ + if(!Context::get('module_srl')) return $this->dispContent(); + + // 템플릿 파일 지정 + $this->setTemplateFile('info'); + }/*}}}*/ + + function dispCategoryInfo() {/*{{{*/ + $module_srl = Context::get('module_srl'); + + // 카테고리의 목록을 구해옴 + $oDocument = getModule('document'); + $category_list = $oDocument->getCategoryList($module_srl); + Context::set('category_list', $category_list); + + // 수정하려는 카테고리가 있다면해당 카테고리의 정보를 가져옴 + $category_srl = Context::get('category_srl'); + if($category_srl) { + $selected_category = $oDocument->getCategory($category_srl); + if(!$selected_category) Context::set('category_srl',''); + else Context::set('selected_category',$selected_category); + $this->setTemplateFile('category_update_form'); + } else { + $this->setTemplateFile('category_list'); + } + }/*}}}*/ + + function dispGrantInfo() {/*{{{*/ + $module_srl = Context::get('module_srl'); + + // 현 모듈의 권한 목록을 가져옴 + $oBoard = getModule('board'); + $grant_list = $oBoard->grant_list; + + // 권한 목록 세팅 + Context::set('grant_list', $grant_list); + + // 권한 그룹의 목록을 가져온다 + $oMember = getModule('member'); + $group_list = $oMember->getGroups(); + Context::set('group_list', $group_list); + + $this->setTemplateFile('grant_list'); + }/*}}}*/ + + function dispSkinInfo() {/*{{{*/ + // 현재 선택된 모듈의 스킨의 정보 xml 파일을 읽음 + $module_info = Context::get('module_info'); + $skin = $module_info->skin; + + $oModule = getModule('module_manager'); + $skin_info = $oModule->loadSkinInfo($this->module_path, $skin); + + // skin_info에 extra_vars 값을 지정 + if(count($skin_info->extra_vars)) { + foreach($skin_info->extra_vars as $key => $val) { + $name = $val->name; + $type = $val->type; + $value = $module_info->{$name}; + if($type=="checkbox"&&!$value) $value = array(); + $skin_info->extra_vars[$key]->value= $value; + } + } + + Context::set('skin_info', $skin_info); + $this->setTemplateFile('skin_info'); + }/*}}}*/ + + function dispInsert() {/*{{{*/ + // 템플릿 파일 지정 + $this->setTemplateFile('insert_form'); + }/*}}}*/ + + function dispDeleteForm() {/*{{{*/ + if(!Context::get('module_srl')) return $this->dispContent(); + + $module_info = Context::get('module_info'); + + $oDocument = getModule('document'); + $document_count = $oDocument->getDocumentCount($module_info->module_srl); + $module_info->document_count = $document_count; + + Context::set('module_info',$module_info); + + // 템플릿 파일 지정 + $this->setTemplateFile('delete_form'); + }/*}}}*/ + + // 실행 부분 + function procInsert() {/*{{{*/ + // 일단 입력된 값들을 모두 받아서 db 입력항목과 그외 것으로 분리 + $args = Context::gets('module_srl','mid','skin','use_category','browser_title','description','is_default','header_text','footer_text','admin_id'); + $args->module = 'board'; + if($args->is_default!='Y') $args->is_default = 'N'; + if($args->use_category!='Y') $args->use_category = 'N'; + + // 기본 값외의 것들을 정리 + $extra_var = delObjectVars(Context::getRequestVars(), $args); + unset($extra_var->sid); + unset($extra_var->act); + unset($extra_var->page); + + // module_srl이 있으면 원본을 구해온다 + $oModule = getModule('module_manager'); + + // module_srl이 넘어오면 원 모듈이 있는지 확인 + if($args->module_srl) { + $module_info = $oModule->getModuleInfoByModuleSrl($args->module_srl); + // 만약 원래 모듈이 없으면 새로 입력하기 위한 처리 + if($module_info->module_srl != $args->module_srl) unset($args->module_srl); + } + + // $extra_var를 serialize + $args->extra_var = serialize($extra_var); + + // is_default=='Y' 이면 + if($args->is_default=='Y') $oModule->clearDefaultModule(); + + // module_srl의 값에 따라 insert/update + if(!$args->module_srl) { + $output = $oModule->insertModule($args); + $msg_code = 'success_registed'; + } else { + $output = $oModule->updateModule($args); + $msg_code = 'success_updated'; + } + + if(!$output->toBool()) return $output; + + $this->add('sid','board'); + $this->add('act','dispInfo'); + $this->add('page',Context::get('page')); + $this->add('module_srl',$output->get('module_srl')); + $this->setMessage($msg_code); + }/*}}}*/ + + function procDelete() {/*{{{*/ + $module_srl = Context::get('module_srl'); + + // 원본을 구해온다 + $oModule = getModule('module_manager'); + $output = $oModule->deleteModule($module_srl); + if(!$output->toBool()) return $output; + + $this->add('sid','board'); + $this->add('act','dispContent'); + $this->add('page',Context::get('page')); + $this->setMessage('success_deleted'); + }/*}}}*/ + + function procInsertCategory() {/*{{{*/ + // 일단 입력된 값들을 모두 받아서 db 입력항목과 그외 것으로 분리 + $module_srl = Context::get('module_srl'); + $category_title = Context::get('category_title'); + + // module_srl이 있으면 원본을 구해온다 + $oDocument = getModule('document'); + $output = $oDocument->insertCategory($module_srl, $category_title); + if(!$output->toBool()) return $output; + + $this->add('sid','board'); + $this->add('act','dispCategoryInfo'); + $this->add('page',Context::get('page')); + $this->add('module_srl',$module_srl); + $this->setMessage('success_registed'); + }/*}}}*/ + + function procUpdateCategory() {/*{{{*/ + $category_srl = Context::get('category_srl'); + $mode = Context::get('mode'); + + $oDocument = getModule('document'); + + switch($mode) { + case 'up' : + $output = $oDocument->moveCategoryUp($category_srl); + $msg_code = 'success_moved'; + break; + case 'down' : + $output = $oDocument->moveCategoryDown($category_srl); + $msg_code = 'success_moved'; + break; + case 'delete' : + $output = $oDocument->deleteCategory($category_srl); + $msg_code = 'success_deleted'; + break; + case 'update' : + $selected_category = $oDocument->getCategory($category_srl); + $args->category_srl = $selected_category->category_srl; + $args->title = Context::get('category_title'); + $args->list_order = $selected_category->list_order; + $output = $oDocument->updateCategory($args); + $msg_code = 'success_updated'; + break; + } + if(!$output->toBool()) return $output; + $this->add('module_srl', $selected_category->module_srl); + $this->setMessage($msg_code); + }/*}}}*/ + + function procUpdateSkinInfo() {/*{{{*/ + // module_srl에 해당하는 정보들을 가져오기 + $module_srl = Context::get('module_srl'); + $oModule = getModule('module_manager'); + $module_info = $oModule->getModuleInfoByModuleSrl($module_srl); + $skin = $module_info->skin; + + // 스킨의 정볼르 구해옴 (extra_vars를 체크하기 위해서) + $oModule = getModule('module_manager'); + $skin_info = $oModule->loadSkinInfo($this->module_path, $skin); + + // 입력받은 변수들을 체크 (sid, act, module_srl, page등 기본적인 변수들 없앰) + $obj = Context::getRequestVars(); + unset($obj->sid); + unset($obj->act); + unset($obj->module_srl); + unset($obj->page); + + // 원 skin_info에서 extra_vars의 type이 image일 경우 별도 처리를 해줌 + if($skin_info->extra_vars) { + foreach($skin_info->extra_vars as $vars) { + if($vars->type!='image') continue; + + $image_obj = $obj->{$vars->name}; + + // 삭제 요청에 대한 변수를 구함 + $del_var = $obj->{"del_".$vars->name}; + unset($obj->{"del_".$vars->name}); + if($del_var == 'Y') { + @unlink($module_info->{$vars->name}); + continue; + } + + // 업로드 되지 않았다면 이전 데이터를 그대로 사용 + if(!$image_obj['tmp_name']) { + $obj->{$vars->name} = $module_info->{$vars->name}; + continue; + } + + // 정상적으로 업로드된 파일이 아니면 무시 + if(!is_uploaded_file($image_obj['tmp_name'])) { + unset($obj->{$vars->name}); + continue; + } + + // 이미지 파일이 아니어도 무시 + if(!eregi("\.(jpg|jpeg|gif|png)$", $image_obj['name'])) { + unset($obj->{$vars->name}); + continue; + } + + // 경로를 정해서 업로드 + $path = sprintf("./files/attach/images/%s/", $module_srl); + + // 디렉토리 생성 + if(!FileHandler::makeDir($path)) return false; + + $filename = $path.$image_obj['name']; + + // 파일 이동 + if(!move_uploaded_file($image_obj['tmp_name'], $filename)) { + unset($obj->{$vars->name}); + continue; + } + + // 변수를 바꿈 + unset($obj->{$vars->name}); + $obj->{$vars->name} = $filename; + } + } + + // serialize하여 저장 + $extra_vars = serialize($obj); + + $oModule = getModule('module_manager'); + $oModule->updateModuleExtraVars($module_srl, $extra_vars); + + $url = sprintf("./admin.php?sid=%s&module_srl=%s&act=dispSkinInfo&page=%s", 'board', $module_srl, Context::get('page')); + print ""; + exit(); + }/*}}}*/ + + function procInsertGrant() {/*{{{*/ + $module_srl = Context::get('module_srl'); + + // 현 모듈의 권한 목록을 가져옴 + $oBoard = getModule('board'); + $grant_list = $oBoard->grant_list; + + if(count($grant_list)) { + foreach($grant_list as $grant) { + $arr_grant[$grant] = explode(',',Context::get($grant)); + } + $grant = serialize($arr_grant); + } + + $oModule = getModule('module_manager'); + $oModule->updateModuleGrant($module_srl, $grant); + + $this->add('sid','board'); + $this->add('act','dispGrantInfo'); + $this->add('page',Context::get('page')); + $this->add('module_srl',Context::get('module_srl')); + $this->setMessage('success_registed'); + }/*}}}*/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + } +?> diff --git a/modules/board/board.module.php b/modules/board/board.module.php new file mode 100644 index 000000000..059ea10c0 --- /dev/null +++ b/modules/board/board.module.php @@ -0,0 +1,667 @@ + + * @desc : 기본 모듈중의 하나인 board module + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class board extends Module { + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = 'dispContent'; + + // 검색 옵션 + var $search_option = array('title','content','title_content','user_name'); + + // 모듈에서 사용할 변수들 + var $skin = "default"; + var $list_count = 3; + var $page_count = 10; + var $category_list = NULL; + + // 권한의 종류를 미리 설정 + var $grant_list = array( + 'list', + 'view', + 'write_document', + 'write_comment', + 'fileupload', + 'management', + ); + + // 에디터 + var $editor = 'default'; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/system_install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + // lang + Context::loadLang($this->template_path.'lang/'); + + // 카테고리를 사용한다면 카테고리 목록을 구해옴 + if($this->module_info->use_category=='Y') { + $oDocument = getModule('document'); + $this->category_list = $oDocument->getCategoryList($this->module_srl); + Context::set('category_list', $this->category_list); + } + + // 에디터 세팅 + Context::set('editor', $this->editor); + $editor_path = sprintf("./editor/%s/", $this->editor); + Context::set('editor_path', $editor_path); + Context::loadLang($editor_path); + + return true; + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + // lang + Context::loadLang($this->template_path.'lang/'); + + // 파일 업로드일 경우 $act값을 procUploadFile() 로 변경 + if(Context::isUploaded()) $this->act = 'procUploadFile'; + + return true; + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 error, message가 지정되어야 한다 + **/ + + // 출력 부분 + function dispContent() {/*{{{*/ + // 목록 구현에 필요한 변수들을 가져온다 + $document_srl = Context::get('document_srl'); + $page = Context::get('page'); + + // document 객체를 생성. 기본 데이터 구조의 경우 document모듈만 쓰면 만사 해결.. -_-; + $oDocument = getModule('document'); + + // document_srl이 있다면 해당 글을 구해오자 + if($document_srl) { + $document = $oDocument->getDocument($document_srl); + + // 글이 찾아지지 않으면 무효화 + if(!$document) { + Context::set('document_srl',''); + $document_srl = NULL; + unset($document); + } + } + + // 글이 찾아지면 조회수 업데이트 및 기타 등등 + if($document) { + + // 비밀글이고 권한이 없을 경우 인증페이지로 + if($document->is_secret=='Y' && !$document->is_granted) return $this->setTemplateFile('input_password_form'); + + // 조회수 업데이트 + if($oDocument->updateReadedCount($document_srl)) $document->readed_count++; + + // 댓글 가져오기 + if($document->comment_count && $document->allow_comment == 'Y') { + $oComment = getModule('comment'); + $comment_list = $oComment->getCommentList($document_srl); + Context::set('comment_list', $comment_list); + } + + // 트랙백 가져오기 + if($document->trackback_count && $document->allow_trackback == 'Y') { + $oTrackback = getModule('trackback'); + $trackback_list = $oTrackback->getTrackbackList($document_srl); + Context::set('trackback_list', $trackback_list); + } + + // 첨부파일 가져오기 + if($document->uploaded_count) { + $file_list = $oDocument->getFiles($document_srl); + $document->uploaded_list = $file_list; + } + + Context::set('document', $document); + } + + // 만약 document_srl은 있는데 page가 없다면 글만 호출된 경우, + // 그럼 page를 구해서 세팅해주자.. + if($document_srl && !$page) { + $page = $oDocument->getDocumentPage($document_srl, $this->module_srl, $this->list_count); + Context::set('page', $page); + } + + // 검색옵션 + $search_target = Context::get('search_target'); + $keyword = Context::get('keyword'); + if($search_target && $keyword) { + $keyword = str_replace(' ','%',$keyword); + switch($search_target) { + case 'title' : + $search_obj->s_title = $keyword; + break; + case 'content' : + $search_obj->s_content = $keyword; + break; + case 'title_content' : + $search_obj->s_title = $keyword; + $search_obj->s_content = $keyword; + break; + case 'user_name' : + $search_obj->s_user_name = $keyword; + break; + } + } + + // 카테고리 + $category = Context::get('category'); + if($category) $search_obj->category_srl = $category; + + // 목록의 경우 document->getDocumentList 에서 걍 알아서 다 해버리는 구조이다... (아.. 이거 나쁜 버릇인데.. ㅡ.ㅜ 어쩔수 없다) + $output = $oDocument->getDocumentList($this->module_srl, 'list_order', $page, $this->list_count, $this->page_count, $search_obj); + + // 템플릿에 쓰기 위해서 context::set + Context::set('total_count', $output->total_count); + Context::set('total_page', $output->total_page); + Context::set('page', $output->page); + Context::set('document_list', $output->data); + Context::set('page_navigation', $output->page_navigation); + + // 템플릿에서 사용할 검색옵션 세팅 + $count_search_option = count($this->search_option); + for($i=0;$i<$count_search_option;$i++) { + $search_option[$this->search_option[$i]] = Context::getLang($this->search_option[$i]); + } + Context::set('search_option', $search_option); + + $this->setTemplateFile('list'); + }/*}}}*/ + + function dispWriteForm() {/*{{{*/ + // 목록 구현에 필요한 변수들을 가져온다 + $document_srl = Context::get('document_srl'); + + // document 모듈 객체 생성 + $oDocument = getModule('document'); + + // 지정된 글이 없다면 (신규) 새로운 번호를 만든다 + if(!$document_srl) { + $oDB = &DB::getInstance(); + $document_srl = $oDB->getNextSequence(); + + // 글의 수정일 경우 원본 글을 가져와서 확인을 한다 + } else { + $document = $oDocument->getDocument($document_srl); + if(!$document) { + $oDB = &DB::getInstance(); + $document_srl = $oDB->getNextSequence(); + } + } + + // 글을 수정하려고 할 경우 권한이 없는 경우 비밀번호 입력화면으로 + if($document&&!$document->is_granted) return $this->setTemplateFile('input_password_form'); + + Context::set('document_srl',$document_srl); + Context::set('document', $document); + + $this->setTemplateFile('write_form'); + }/*}}}*/ + + function dispDeleteForm() {/*{{{*/ + // 삭제할 문서번호를 가져온다 + $document_srl = Context::get('document_srl'); + + // 지정된 글이 있는지 확인 + if($document_srl) { + $oDocument = getModule('document'); + $document = $oDocument->getDocument($document_srl); + } + + // 삭제하려는 글이 없으면 에러 + if(!$document) return $this->dispContent(); + + // 권한이 없는 경우 비밀번호 입력화면으로 + if($document&&!$document->is_granted) return $this->setTemplateFile('input_password_form'); + + Context::set('document',$document); + + $this->setTemplateFile('delete_form'); + }/*}}}*/ + + function dispCommentModifyForm() {/*{{{*/ + // 목록 구현에 필요한 변수들을 가져온다 + $document_srl = Context::get('document_srl'); + $comment_srl = Context::get('comment_srl'); + + // 지정된 댓글이 없다면 오류 + if(!$comment_srl) return new Output(-1, 'msg_invalid_request'); + + // 해당 댓글를 찾아본다 + $oComment = getModule('comment'); + $comment = $oComment->getComment($comment_srl); + + // 댓글이 없다면 오류 + if(!$comment) return new Output(-1, 'msg_invalid_request'); + + // 글을 수정하려고 할 경우 권한이 없는 경우 비밀번호 입력화면으로 + if($comment_srl&&$comment&&!$_SESSION['own_comment'][$comment_srl]) return $this->setTemplateFile('input_password_form'); + + // 필요한 정보들 세팅 + Context::set('document_srl',$document_srl); + Context::set('comment_srl',$comment_srl); + Context::set('comment', $comment); + + $this->setTemplateFile('comment_form'); + }/*}}}*/ + + function dispCommentDeleteForm() {/*{{{*/ + // 삭제할 댓글번호를 가져온다 + $comment_srl = Context::get('comment_srl'); + + // 삭제하려는 댓글가 있는지 확인 + if($comment_srl) { + $oComment = getModule('comment'); + $comment = $oComment->getComment($comment_srl); + } + + // 삭제하려는 글이 없으면 에러 + if(!$comment) return $this->dispContent(); + + // 권한이 없는 경우 비밀번호 입력화면으로 + if($comment_srl&&$comment&&!$_SESSION['own_comment'][$comment_srl]) return $this->setTemplateFile('input_password_form'); + + Context::set('comment',$comment); + + $this->setTemplateFile('delete_comment_form'); + }/*}}}*/ + + function dispCommentReplyForm() {/*{{{*/ + // 목록 구현에 필요한 변수들을 가져온다 + $document_srl = Context::get('document_srl'); + $parent_srl = Context::get('comment_srl'); + + // 지정된 원 댓글이 없다면 오류 + if(!$parent_srl) return new Output(-1, 'msg_invalid_request'); + + // 해당 댓글를 찾아본다 + $oComment = getModule('comment'); + $source_comment = $oComment->getComment($parent_srl); + + // 댓글이 없다면 오류 + if(!$source_comment) return new Output(-1, 'msg_invalid_request'); + + // 필요한 정보들 세팅 + Context::set('document_srl',$document_srl); + Context::set('parent_srl',$parent_srl); + Context::set('comment_srl',NULL); + Context::set('source_comment',$source_comment); + + $this->setTemplateFile('comment_form'); + }/*}}}*/ + + function dispTrackbackDeleteForm() {/*{{{*/ + // 삭제할 댓글번호를 가져온다 + $trackback_srl = Context::get('trackback_srl'); + + // 삭제하려는 댓글가 있는지 확인 + $oTrackback = getModule('trackback'); + $output = $oTrackback->getTrackback($trackback_srl); + $trackback = $output->data; + + // 삭제하려는 글이 없으면 에러 + if(!$trackback) return $this->dispContent(); + + Context::set('trackback',$trackback); + + $this->setTemplateFile('delete_trackback_form'); + }/*}}}*/ + + function dispLogin() {/*{{{*/ + if(Context::get('is_logged')) return $this->dispContent(); + $this->setTemplateFile('login_form'); + }/*}}}*/ + + function dispLogout() {/*{{{*/ + if(!Context::get('is_logged')) return $this->dispContent(); + $this->setTemplateFile('logout'); + }/*}}}*/ + + function dispError() {/*{{{*/ + }/*}}}*/ + + function dispRss() {/*{{{*/ + $page = Context::get('page'); + + // rss 제목 및 정보등을 추출 + $info->title = Context::getBrowserTitle(); + $info->description = $this->module_info->description; + $info->language = Context::getLangType(); + $info->date = gmdate("D, d M Y H:i:s"); + $info->link = sprintf("%s?mid=%s", Context::getRequestUri(), Context::get('mid')); + + // 컨텐츠 추출 + $oDocument = getModule('document'); + $output = $oDocument->getDocumentList($this->module_srl, 'update_order', $page, 20, 20, NULL); + $document_list = $output->data; + + // 출력하고 끝내기 + $oRss = getModule('rss'); + $oRss->printRssDocument($info, $document_list); + exit(); + }/*}}}*/ + + function dispAdminIndex() {/*{{{*/ + $this->setTemplateFile('module_list'); + }/*}}}*/ + + // 실행 부분 + function procInsertDocument() {/*{{{*/ + // 글작성시 필요한 변수를 가져옴 + $obj = Context::getRequestVars(); + //$obj = Context::gets('document_srl','user_name','email_address','homepage','tags','title','content','password','allow_comment','lock_comment','allow_trackback','category_srl','is_notice','is_secret'); + $obj->module_srl = $this->module_srl; + if($obj->is_notice!='Y') $obj->is_notice = 'N'; + if($obj->is_secret!='Y') $obj->is_secret = 'N'; + if($obj->allow_comment!='Y') $obj->allow_comment = 'N'; + if($obj->lock_comment!='Y') $obj->lock_comment = 'N'; + if($obj->allow_trackback!='Y') $obj->allow_trackback = 'N'; + + // document module 객체 생성 + $oDocument = getModule('document'); + + // 첨부 파일의 갯수를 구함 + $obj->uploaded_count = $oDocument->getFilesCount($obj->document_srl); + + // 이미 존재하는 글인지 체크 + $document = $oDocument->getDocument($obj->document_srl); + + // 이미 존재하는 경우 수정 + if($document->document_srl == $obj->document_srl) { + $output = $oDocument->updateDocument($document, $obj); + $msg_code = 'success_updated'; + + // 그렇지 않으면 신규 등록 + } else { + $output = $oDocument->insertDocument($obj); + $msg_code = 'success_registed'; + $obj->document_srl = $output->get('document_srl'); + } + + // 트랙백 발송 + $trackback_url = Context::get('trackback_url'); + $trackback_charset = Context::get('trackback_charset'); + if($trackback_url) { + $oTrackback = getModule('trackback'); + $oTrackback->sendTrackback($obj, $trackback_url, $trackback_charset); + } + + if(!$output->toBool()) return $output; + $this->setMessage($msg_code); + $this->add('mid', Context::get('mid')); + $this->add('document_srl', $output->get('document_srl')); + }/*}}}*/ + + function procDeleteDocument() {/*{{{*/ + // 문서 번호 확인 + $document_srl = Context::get('document_srl'); + if(!$document_srl) return $this->doError('msg_invalid_document'); + + // 문서 있는지 확인 + $oDocument = getModule('document'); + $document = $oDocument->getDocument($document_srl); + if($document->document_srl!=$document_srl) return $this->doError('msg_invalid_document'); + + // 글 삭제 + $output = $oDocument->deleteDocument($document); + if(!$output->toBool()) return $output; + + $this->add('mid', Context::get('mid')); + $this->add('page', $output->get('page')); + $this->setMessage('success_deleted'); + }/*}}}*/ + + function procVoteDocument() {/*{{{*/ + $oDocument = getModule('document'); + $document_srl = Context::get('document_srl'); + return $oDocument->updateVotedCount($document_srl); + }/*}}}*/ + + function procInsertComment() {/*{{{*/ + // 댓글 입력에 필요한 데이터 추출 + $obj = Context::gets('document_srl','comment_srl','parent_srl','content','password','nick_name','user_name','member_srl','email_address','homepage'); + $obj->module_srl = $this->module_srl; + + // comment 객체 생성 + $oComment = getModule('comment'); + + // comment_srl이 없을 경우 신규 입력 + if(!$obj->comment_srl) { + // parent_srl이 있으면 답변으로 + if($obj->parent_srl) { + $comment = $oComment->getComment($obj->parent_srl); + if(!$comment) return new Output(-1, 'msg_invalid_request'); + $output = $oComment->insertComment($obj); + $comment_srl = $output->get('comment_srl'); + // 없으면 신규 + } else { + $output = $oComment->insertComment($obj); + } + + // comment_srl이 있으면 수정으로 + } else { + $comment = $oComment->getComment($obj->comment_srl); + if(!$comment) return new Output(-1, 'msg_invalid_request'); + + $obj->parent_srl = $comment->parent_srl; + $output = $oComment->updateComment($obj); + $comment_srl = $obj->comment_srl; + } + + if(!$output->toBool()) return $output; + $this->setMessage('success_registed'); + $this->add('mid', Context::get('mid')); + $this->add('document_srl', $obj->document_srl); + $this->add('comment_srl', $comment_srl); + }/*}}}*/ + + function procDeleteComment() {/*{{{*/ + // 댓글 번호 확인 + $comment_srl = Context::get('comment_srl'); + if(!$comment_srl) return $this->doError('msg_invalid_request'); + + // 삭제 + $oComment = getModule('comment'); + $output = $oComment->deleteComment($comment_srl); + if(!$output->toBool()) return $output; + + $this->add('mid', Context::get('mid')); + $this->add('page', Context::get('page')); + $this->add('document_srl', $output->get('document_srl')); + $this->setMessage('success_deleted'); + }/*}}}*/ + + function procReceiveTrackback() {/*{{{*/ + $obj = Context::gets('document_srl','url','title','excerpt'); + $oTrackback = getModule('trackback'); + $oTrackback->insertTrackback($obj); + }/*}}}*/ + + function procDeleteTrackback() {/*{{{*/ + $trackback_srl = Context::get('trackback_srl'); + $oTrackback = getModule('trackback'); + $output = $oTrackback->deleteTrackback($trackback_srl); + + $this->add('mid', Context::get('mid')); + $this->add('page', Context::get('page')); + $this->add('document_srl', $output->get('document_srl')); + $this->setMessage('success_deleted'); + }/*}}}*/ + + function procLogin() {/*{{{*/ + // 아이디, 비밀번호를 받음 + $user_id = Context::get('user_id'); + $password = Context::get('password'); + + // member모듈 객체 생성 + $oMember = getModule('member'); + return $oMember->doLogin($user_id, $password); + }/*}}}*/ + + function procLogout() {/*{{{*/ + // member모듈 객체 생성 + $oMember = getModule('member'); + return $oMember->doLogout(); + }/*}}}*/ + + function procVerificationPassword() {/*{{{*/ + // 비밀번호와 문서 번호를 받음 + $password = md5(Context::get('password')); + $document_srl = Context::get('document_srl'); + $comment_srl = Context::get('comment_srl'); + + // comment_srl이 있을 경우 댓글이 대상 + if($comment_srl) { + // 문서번호에 해당하는 글이 있는지 확인 + $oComment = getModule('comment'); + $data = $oComment->getComment($comment_srl); + // comment_srl이 없으면 문서가 대상 + } else { + // 문서번호에 해당하는 글이 있는지 확인 + $oDocument = getModule('document'); + $data = $oDocument->getDocument($document_srl); + } + + // 글이 없을 경우 에러 + if(!$data) return $this->doError('msg_invalid_request'); + + // 문서의 비밀번호와 입력한 비밀번호의 비교 + if($data->password != $password) return $this->doError('msg_invalid_password'); + + // 해당 글에 대한 권한 부여 + if($comment_srl) $_SESSION['own_comment'][$comment_srl] = true; + else $_SESSION['own_document'][$document_srl] = true; + }/*}}}*/ + + function procUploadFile() {/*{{{*/ + // 기본적으로 필요한 변수인 document_srl, module_srl을 설정 + $document_srl = Context::get('document_srl'); + $module_srl = $this->module_srl; + + // document모듈 객체 생성후 걍 넘겨버림 + $oDocument = getModule('document'); + $output = $oDocument->insertFile($module_srl, $document_srl); + print $this->printUploadedFileList($document_srl); + exit(); + }/*}}}*/ + + function procDeleteFile() {/*{{{*/ + // 기본적으로 필요한 변수인 document_srl, module_srl을 설정 + $document_srl = Context::get('document_srl'); + $module_srl = $this->module_srl; + $file_srl = Context::get('file_srl'); + + // document모듈 객체 생성후 걍 넘겨버림 + $oDocument = getModule('document'); + $output = $oDocument->deleteFile($file_srl); + print $this->printUploadedFileList($document_srl); + exit(); + }/*}}}*/ + + function procDownload() {/*{{{*/ + // 다운로드에 필요한 변수 체크 + $file_srl = Context::get('file_srl'); + $sid = Context::get('sid'); + + // document module 객체 생성후 해당 파일의 정보를 체크 + $oDocument = getModule('document'); + $file_obj = $oDocument->getFile($file_srl); + if($file_obj->file_srl!=$file_srl||$file_obj->sid!=$sid) exit(); + + // 이상이 없으면 download_count 증가 + $args->file_srl = $file_srl; + $oDB = &DB::getInstance(); + $oDB->executeQuery('document.updateFileDownloadCount', $args); + + // 파일 출력 + $filename = $file_obj->source_filename; + + if(strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { + $filename = urlencode($filename); + $filename = preg_replace('/\./', '%2e', $filename, substr_count($filename, '.') - 1); + } + + $uploaded_filename = $file_obj->uploaded_filename; + if(!file_exists($uploaded_filename)) exit(); + + $fp = fopen($uploaded_filename, 'rb'); + if(!$fp) exit(); + + header("Cache-Control: "); + header("Pragma: "); + header("Content-Type: application/octet-stream"); + + header("Content-Length: " .(string)($file_obj->file_size)); + header('Content-Disposition: attachment; filename="'.$filename.'"'); + header("Content-Transfer-Encoding: binary\n"); + + fpassthru($fp); + exit(); + }/*}}}*/ + + function procClearFile() {/*{{{*/ + $document_srl = Context::get('document_srl'); + + // document_srl의 글이 등록되어 있다면 pass + $oDocument = getModule('document'); + $data = $oDocument->getDocument($document_srl); + if($data) exit(); + + // 등록되어 있지 않다면 첨부파일 삭제 + $oDocument->deleteFiles($this->module_srl, $document_srl); + }/*}}}*/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + function printUploadedFileList($document_srl) {/*{{{*/ + // 첨부파일들의 정보를 취합해서 return + $oDocument = getModule('document'); + $file_list = $oDocument->getFiles($document_srl); + $file_count = count($file_list); + $buff = ""; + for($i=0;$i<$file_count;$i++) { + $file_info = $file_list[$i]; + if(!$file_info->file_srl) continue; + + $buff .= sprintf("parent.editor_insert_uploaded_file(\"%d\", \"%d\",\"%s\", \"%d\", \"%s\", \"%s\", \"%s\");\n", $document_srl, $file_info->file_srl, $file_info->source_filename, $file_info->file_size, FileHandler::filesize($file_info->file_size), $file_info->direct_download=='Y'?$file_info->uploaded_filename:'', $file_info->sid); + } + + $buff = sprintf("", $document_srl, $buff); + return $buff; + }/*}}}*/ + } + +?> diff --git a/modules/board/lang/ko.lang.php b/modules/board/lang/ko.lang.php new file mode 100644 index 000000000..59221ce43 --- /dev/null +++ b/modules/board/lang/ko.lang.php @@ -0,0 +1,56 @@ + + * @desc : 게시판(board) 모듈의 기본 언어팩 + **/ + + // 버튼에 사용되는 언어 + $lang->cmd_view_info = "모듈정보"; + $lang->cmd_manage_category = "분류관리"; + $lang->cmd_manage_grant = "권한관리"; + $lang->cmd_manage_skin = "스킨관리"; + + // 항목 + $lang->mid = "모듈이름"; + $lang->header_text = "상단 내용"; + $lang->footer_text = "하단 내용"; + $lang->skin = "스킨"; + $lang->use_category = "분류 사용"; + $lang->category_title = "분류명"; + $lang->module = "모듈"; + + $lang->skin_default_info = "기본정보"; + $lang->skin_maker = "스킨제작자"; + $lang->skin_maker_homepage = "홈페이지"; + + $lang->colorset = "컬러셋"; + $lang->extra_vars = "확장변수"; + + // 권한의 명칭 + $lang->grant_title = array( + 'list' => "목록 접근 권한", + 'view' => "내용 접근 권한", + 'write_document' => "게시물 작성 권한", + 'write_comment' => "코멘트 작성 권한", + 'fileupload' => "파일첨부 권한", + 'management' => "관리 권한", + ); + + // 주절 주절.. + $lang->about_mid = "모듈이름은 http://주소/?mid=모듈이름 처럼 직접 호출할 수 있는 값입니다. (영문+숫자만 가능)"; + $lang->about_browser_title = "브라우저의 제목에 나타나는 값입니다. RSS/Trackback에서도 사용됩니다."; + $lang->about_description= "관리용으로 사용되는 설명입니다"; + $lang->about_default = "선택하시면 사이트에 mid값 없이 접속하였을 경우 기본으로 보여줍니다"; + $lang->about_header_text = "모듈의 상단에 표시되는 내용입니다 (html 태그 사용 가능)"; + $lang->about_footer_text = "모듈의 하단에 표시되는 내용입니다 (html 태그 사용 가능)"; + $lang->about_skin = "모듈의 스킨을 선택하실 수 있습니다"; + $lang->about_use_category = "선택하시면 분류기능을 사용할 수 있습니다"; + $lang->about_admin_id = "해당 모듈에 대해 최고 권한을 가지는 관리자를 지정할 수 있습니다. ,(콤마)로 다수 아이디 지정이 가능합니다. (관리자페이지 접근은 불가능)"; + $lang->about_grant = "특정 권한의 대상을 모두 해제하시면 로그인하지 않은 회원까지 권한을 가질 수 있습니다"; + + $lang->msg_new_module = "모듈 생성"; + $lang->msg_update_module = "모듈 수정"; + $lang->msg_category_is_null = "등록된 분류가 없습니다"; + $lang->msg_grant_is_null = "등록된 권한 대상이 없습니다"; +?> diff --git a/modules/board/module.xml b/modules/board/module.xml new file mode 100644 index 000000000..59d96c871 --- /dev/null +++ b/modules/board/module.xml @@ -0,0 +1,11 @@ + + + 게시판 + BBS + + 제로 + zero + 게시판 모듈 + board + + diff --git a/modules/board/queries/getBoardList.xml b/modules/board/queries/getBoardList.xml new file mode 100644 index 000000000..2a8ad6131 --- /dev/null +++ b/modules/board/queries/getBoardList.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/comment.html b/modules/board/skins/default/comment.html new file mode 100644 index 000000000..bd706044e --- /dev/null +++ b/modules/board/skins/default/comment.html @@ -0,0 +1,53 @@ + + + +
+ {$lang->comment} : {count($comment_list)} +
+ + +
+ + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + +
{$lang->date}{zdate($val->regdate, "Y-m-d H:i:s")}
{$lang->user_name}{$val->user_name}
{$lang->content}{nl2br($val->content)}
ipaddress{$val->ipaddress}
+ [{$lang->cmd_modify}] + [{$lang->cmd_reply}] + [{$lang->cmd_delete}] +
+ + + + + + + + + + + diff --git a/modules/board/skins/default/comment_form.html b/modules/board/skins/default/comment_form.html new file mode 100644 index 000000000..ef9a742e5 --- /dev/null +++ b/modules/board/skins/default/comment_form.html @@ -0,0 +1,77 @@ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
{$lang->date}{$source_comment->regdate}
{$lang->user_name}{$source_comment->user_name}
{$lang->readed_count}{$source_comment->readed_count}
{$lang->voted_count}{$source_comment->voted_count}
{$lang->content}{nl2br($source_comment->content)}
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->user_name}
{$lang->password}
{$lang->email_address}
{$lang->homepage}
{$lang->content}
+ + + + + + + +
+
diff --git a/modules/board/skins/default/delete_comment_form.html b/modules/board/skins/default/delete_comment_form.html new file mode 100644 index 000000000..c08d194fa --- /dev/null +++ b/modules/board/skins/default/delete_comment_form.html @@ -0,0 +1,23 @@ + + + +
+ + + + + + + + + + + + +
{$lang->confirm_delete}
+ + +
+ +
+ diff --git a/modules/board/skins/default/delete_form.html b/modules/board/skins/default/delete_form.html new file mode 100644 index 000000000..02d2fa595 --- /dev/null +++ b/modules/board/skins/default/delete_form.html @@ -0,0 +1,26 @@ + + + +
+ + + + + + + + + + + + + + + +
{$lang->confirm_delete}
{$lang->title}{$document->title}
+ + +
+ +
+ diff --git a/modules/board/skins/default/delete_trackback_form.html b/modules/board/skins/default/delete_trackback_form.html new file mode 100644 index 000000000..5ad48f1ec --- /dev/null +++ b/modules/board/skins/default/delete_trackback_form.html @@ -0,0 +1,23 @@ + + + +
+ + + + + + + + + + + + +
{$lang->confirm_delete}
+ + +
+ +
+ diff --git a/modules/board/skins/default/filter/filter.delete_comment.xml b/modules/board/skins/default/filter/filter.delete_comment.xml new file mode 100644 index 000000000..7e24cf910 --- /dev/null +++ b/modules/board/skins/default/filter/filter.delete_comment.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/filter/filter.delete_document.xml b/modules/board/skins/default/filter/filter.delete_document.xml new file mode 100644 index 000000000..06e6d36a9 --- /dev/null +++ b/modules/board/skins/default/filter/filter.delete_document.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/filter/filter.delete_trackback.xml b/modules/board/skins/default/filter/filter.delete_trackback.xml new file mode 100644 index 000000000..dd7336ef1 --- /dev/null +++ b/modules/board/skins/default/filter/filter.delete_trackback.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/filter/filter.input_password.xml b/modules/board/skins/default/filter/filter.input_password.xml new file mode 100644 index 000000000..39603f2e3 --- /dev/null +++ b/modules/board/skins/default/filter/filter.input_password.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/filter/filter.insert.xml b/modules/board/skins/default/filter/filter.insert.xml new file mode 100644 index 000000000..bef2f2e83 --- /dev/null +++ b/modules/board/skins/default/filter/filter.insert.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/filter/filter.insert_comment.xml b/modules/board/skins/default/filter/filter.insert_comment.xml new file mode 100644 index 000000000..1c60d5057 --- /dev/null +++ b/modules/board/skins/default/filter/filter.insert_comment.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/filter/filter.login.xml b/modules/board/skins/default/filter/filter.login.xml new file mode 100644 index 000000000..d6e559d75 --- /dev/null +++ b/modules/board/skins/default/filter/filter.login.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/filter/filter.logout.xml b/modules/board/skins/default/filter/filter.logout.xml new file mode 100644 index 000000000..d8d0344d5 --- /dev/null +++ b/modules/board/skins/default/filter/filter.logout.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/filter/filter.search.xml b/modules/board/skins/default/filter/filter.search.xml new file mode 100644 index 000000000..be1d9757f --- /dev/null +++ b/modules/board/skins/default/filter/filter.search.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/filter/filter.vote.xml b/modules/board/skins/default/filter/filter.vote.xml new file mode 100644 index 000000000..bfda2105f --- /dev/null +++ b/modules/board/skins/default/filter/filter.vote.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/modules/board/skins/default/header.html b/modules/board/skins/default/header.html new file mode 100644 index 000000000..93ce4dd87 --- /dev/null +++ b/modules/board/skins/default/header.html @@ -0,0 +1 @@ + diff --git a/modules/board/skins/default/input_password_form.html b/modules/board/skins/default/input_password_form.html new file mode 100644 index 000000000..8971d1e28 --- /dev/null +++ b/modules/board/skins/default/input_password_form.html @@ -0,0 +1,26 @@ + + + +
+ + + + + + + + + + + + + + + + +
{$lang->msg_input_password}
{$lang->password}
+ + +
+ +
diff --git a/modules/board/skins/default/js/admin.js b/modules/board/skins/default/js/admin.js new file mode 100644 index 000000000..899158ccb --- /dev/null +++ b/modules/board/skins/default/js/admin.js @@ -0,0 +1,39 @@ +/** + * @file : modules/board/js/admin.js + * @author : zero + * @desc : board 모듈의 관리자용 javascript + **/ + +/* 모듈 생성 후 */ +function procInsertModule(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var sid = ret_obj['sid']; + var act = ret_obj['act']; + var page = ret_obj['page']; + var module_srl = ret_obj['module_srl']; + alert(message); + + url = "./admin.php?sid="+sid+"&module_srl="+module_srl+"&page="+page+"&act="+act; + location.href = url; +} + +/* 카테고리 관련 작업들 */ +function doUpdateCategory(category_srl, mode, message) { + if(typeof(message)!='undefined'&&!confirm(message)) return; + + var fo_obj = xGetElementById('fo_module_category_info'); + fo_obj.category_srl.value = category_srl; + fo_obj.mode.value = mode; + + procFormFilter(fo_obj, update_category_info, procReload); +} + +/* 메세지 출력후 현페이지 리로드 */ +function procReload(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + if(message) alert(message); + + location.href = location.href; +} diff --git a/modules/board/skins/default/js/board.js b/modules/board/skins/default/js/board.js new file mode 100644 index 000000000..658b77803 --- /dev/null +++ b/modules/board/skins/default/js/board.js @@ -0,0 +1,107 @@ +/** + * @file : modules/board/js/board.js + * @author : zero + * @desc : board 모듈의 javascript + **/ + +/* 글쓰기 작성후 */ +function procInsert(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var mid = ret_obj['mid']; + var document_srl = ret_obj['document_srl']; + var category_srl = ret_obj['category_srl']; + alert(message); + url = "./?mid="+mid+"&document_srl="+document_srl; + if(category_srl) url += '&category='+category_srl; + location.href = url; +} + +/* 글 삭제 */ +function procDeleteDocument(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var mid = ret_obj['mid']; + var page = ret_obj['page']; + var url = "./?mid="+mid; + if(page) url += "&page="+page; + alert(message); + location.href = url; +} + +/* 검색 실행 */ +function procSearch(fo_obj, args) { + fo_obj.submit(); +} + +/* 추천, 추천은 별도의 폼입력이 필요 없어 직접 필터 사용 */ +function doVote() { + var fo_obj = document.getElementById('fo_document_info'); + procFormFilter(fo_obj, vote, procVote) +} + +function procVote(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + alert(message); + + location.href = location.href; +} + +// 현재 페이지 reload +function procReload(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + + location.href = location.href; +} + +/* 댓글 글쓰기 작성후 */ +function procInsertComment(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var mid = ret_obj['mid']; + var document_srl = ret_obj['document_srl']; + var comment_srl = ret_obj['comment_srl']; + var url = "./?mid="+mid+"&document_srl="+document_srl; + if(comment_srl) url += "#comment_"+comment_srl; + + alert(message); + + location.href = url; +} + +/* 댓글 삭제 */ +function procDeleteComment(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var mid = ret_obj['mid']; + var document_srl = ret_obj['document_srl']; + var page = ret_obj['page']; + var url = "./?mid="+mid+'&document_srl='+document_srl; + if(page) url += "&page="+page; + alert(message); + + location.href = url; +} + +/* 트랙백 삭제 */ +function procDeleteTrackback(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var mid = ret_obj['mid']; + var document_srl = ret_obj['document_srl']; + var page = ret_obj['page']; + var url = "./?mid="+mid+'&document_srl='+document_srl; + if(page) url += "&page="+page; + alert(message); + + location.href = url; +} + +/* 카테고리 이동 */ +function procChangeCategory(sel_obj, url) { + var category_srl = sel_obj.options[sel_obj.selectedIndex].value; + if(!category_srl) location.href=url; + else location.href=url+'&category='+category_srl; +} diff --git a/modules/board/skins/default/list.html b/modules/board/skins/default/list.html new file mode 100644 index 000000000..8a4ee5a1f --- /dev/null +++ b/modules/board/skins/default/list.html @@ -0,0 +1,124 @@ + + + +{$module_info->header_text} + + + +
+ + + + + + + + + +
{$module_info->title}
{nl2br($module_info->desc)}
+
+ + + +
+ {$lang->document_count} : {number_format($total_count)}, + {$lang->page_count} : {number_format($page)} / {number_format($total_page)} + rss + + [{$lang->cmd_logout}] + + [{$lang->cmd_login}] + + + [{$lang->cmd_management}] + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->no} +
+ +
+
{$lang->title}{$lang->user_name}{$lang->readed_count}{$lang->voted_count}{$lang->date}
{$no}{$category_list[$val->category_srl]->title} + {$val->title} + + [{$val->comment_count}] + + + [{$val->trackback_count}] + + {$val->user_name}{$val->readed_count}{$val->voted_count}{zdate($val->regdate,"Y-m-d")}
+
+ + + + + +
+
+ + + + + +
+
+ + +
+ [{$lang->first_page}] + + + + {$page_no} + + [{$page_no}] + + + + [{$lang->last_page}] +
+ +{$module_info->footer_text} diff --git a/modules/board/skins/default/login_form.html b/modules/board/skins/default/login_form.html new file mode 100644 index 000000000..efb60da06 --- /dev/null +++ b/modules/board/skins/default/login_form.html @@ -0,0 +1,26 @@ + + + +
+ + + + + + + + + + + + + + + + +
{$lang->user_id}
{$lang->password}
+ + +
+ +
diff --git a/modules/board/skins/default/logout.html b/modules/board/skins/default/logout.html new file mode 100644 index 000000000..0ba1c5ec5 --- /dev/null +++ b/modules/board/skins/default/logout.html @@ -0,0 +1,22 @@ + + + +
+ + + + + + + + + + + + +
{$lang->cmd_logout}
{$lang->confirm_logout}
+ + +
+ +
diff --git a/modules/board/skins/default/skin.xml b/modules/board/skins/default/skin.xml new file mode 100644 index 000000000..d751f33c9 --- /dev/null +++ b/modules/board/skins/default/skin.xml @@ -0,0 +1,67 @@ + + + 게시판 기본 스킨 + BBS default skin + + 제로 + zero + board모듈의 default스킨 + default skin of the board module + + + + 기본 + normal + + + 이상한거 + deep + + + + + 제목 + title + 그냥 테스트용입니다 + just for test.. + + + 제목 2 + title 2 + haha + + + 내용 + memo + 내용의 기본값 + default value of memo + + + 선택1 + select 1 + 1 + 2 + 3 + 4 + 5 + + + 다중선택 + multi select + a + b + c + + + 하나선택 + one select + A + B + C + + + 로고이미지 + logo image + + + diff --git a/modules/board/skins/default/trackback.html b/modules/board/skins/default/trackback.html new file mode 100644 index 000000000..1af1d6107 --- /dev/null +++ b/modules/board/skins/default/trackback.html @@ -0,0 +1,50 @@ + + + +
+ {$lang->trackback} : {count($trackback_list)} +
+ + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->title}{$val->title}
{$lang->date}{zdate($val->regdate, "Y-m-d H:i:s")}
{$lang->blog_name}{$val->blog_name}
{$lang->excerpt}{nl2br($val->excerpt)}
ipaddress{$val->ipaddress}
+ [{$lang->cmd_delete}] +
+
+ + + + +
diff --git a/modules/board/skins/default/view_document.html b/modules/board/skins/default/view_document.html new file mode 100644 index 000000000..1ed3d9942 --- /dev/null +++ b/modules/board/skins/default/view_document.html @@ -0,0 +1,108 @@ + + + + +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->category}{$category_list[$document->category_srl]->title}
{$lang->title}{$document->title}
{$lang->date}{zdate($document->regdate,"Y-m-d H:i:s")}
{$lang->user_name}{$document->user_name}
{$lang->readed_count}{$document->readed_count}
{$lang->voted_count}{$document->voted_count}
{$lang->content}{Document::transContent($document->content)}
+ {$lang->document_url} : {getUrl()}?document_srl={$document->document_srl} + +
+ {$lang->trackback_url} : {getUrl()}trackback.php?document_srl={$document->document_srl} + +
{$lang->tag}{$document->tags}
{$lang->uploaded_file} + + + +
ipaddress{$document->ipaddress}
+ + {$lang->allow_comment} + + + {$lang->lock_comment} + + + {$lang->allow_trackback} + +
+
+ + + + + + + + + + + + + + diff --git a/modules/board/skins/default/write_form.html b/modules/board/skins/default/write_form.html new file mode 100644 index 000000000..88fb36614 --- /dev/null +++ b/modules/board/skins/default/write_form.html @@ -0,0 +1,100 @@ + + + +
fileupload)-->enctype="multipart/form-data"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->category} + +
{$lang->user_name}
{$lang->password}
{$lang->email_address}
{$lang->homepage}
{$lang->title}
  + is_notice== "Y")-->checked="true" id="is_notice" /> + + + is_secret== "Y")-->checked="true" id="is_secret" /> + + + allow_comment != "N")-->checked="true" id="allow_comment" /> + + + lock_comment == "Y")-->checked="true" id="lock_comment" /> + + + allow_trackback != "N")-->checked="true" id="allow_trackback" /> + +
{$lang->content} + + +
{$lang->cmd_send_trackback} + + +
{$lang->tag} +
+ {$lang->about_tag} +
+ + +
+ +
diff --git a/modules/comment/comment.module.php b/modules/comment/comment.module.php new file mode 100644 index 000000000..bd427f839 --- /dev/null +++ b/modules/comment/comment.module.php @@ -0,0 +1,267 @@ + + * @desc : 기본 모듈중의 하나인 comment module + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class comment extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = ''; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + //Context::loadLang($this->module_path.'lang'); + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 comment, comment가 지정되어야 한다 + **/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + + // 코멘트의 권한 부여 + // 세션값으로 현 접속상태에서만 사용 가능 + // public void addGrant($comment_srl) {/*{{{*/ + function addGrant($comment_srl) { + $_SESSION['own_comment'][$comment_srl] = true; + }/*}}}*/ + + // public void isGranted($comment_srl) {/*{{{*/ + function isGranted($comment_srl) { + return $_SESSION['own_comment'][$comment_srl]; + }/*}}}*/ + + // 코멘트 + // public boolean insertComment($obj)/*{{{*/ + // 댓글 입력 + function insertComment($obj) { + // document_srl에 해당하는 글이 있는지 확인 + $document_srl = $obj->document_srl; + if(!$document_srl) return new Output(-1,'msg_invalid_document'); + $oDocument = getModule('document'); + $document = $oDocument->getDocument($document_srl); + if(!$document_srl) return new Output(-1,'msg_invalid_document'); + if($document->lock_comment=='Y') return new Output(-1,'msg_invalid_request'); + + // 댓글를 입력 + $oDB = &DB::getInstance(); + $obj->comment_srl = $oDB->getNextSequence(); + $obj->list_order = $obj->comment_srl * -1; + if($obj->password) $obj->password = md5($obj->password); + $output = $oDB->executeQuery('comment.insertComment', $obj); + + // 입력에 이상이 없으면 해당 글의 댓글 수를 올림 + if(!$output->toBool()) return $output; + + // 해당 글의 전체 댓글 수를 구해옴 + $comment_count = $this->getCommentCount($document_srl); + + // 해당글의 댓글 수를 업데이트 + $output = $oDocument->updateCommentCount($document_srl, $comment_count); + + // 댓글의 권한을 부여 + $this->addGrant($obj->comment_srl); + $output->add('comment_srl', $obj->comment_srl); + return $output; + }/*}}}*/ + + // public boolean updateComment($obj)/*{{{*/ + // 댓글 수정 + function updateComment($obj) { + // 권한이 있는지 확인 + if(!$this->isGranted($obj->comment_srl)) return new Output(-1, 'msg_not_permitted'); + + // 업데이트 + $oDB = &DB::getInstance(); + if($obj->password) $obj->password = md5($obj->password); + $output = $oDB->executeQuery('comment.updateComment', $obj); + $output->add('comment_srl', $obj->comment_srl); + return $output; + }/*}}}*/ + + // public boolean deleteComment($comment_srl)/*{{{*/ + // 댓글 삭제 + function deleteComment($comment_srl) { + // 기존 댓글이 있는지 확인 + $comment = $this->getComment($comment_srl); + if($comment->comment_srl != $comment_srl) return new Output(-1, 'msg_invalid_request'); + $document_srl = $comment->document_srl; + + // 해당 댓글에 child가 있는지 확인 + $child_count = $this->getChildCommentCount($comment_srl); + if($child_count>0) return new Output(-1, 'fail_to_delete_have_children'); + + // 권한이 있는지 확인 + if(!$this->isGranted($comment_srl)) return new Output(-1, 'msg_not_permitted'); + + // 삭제 + $oDB = &DB::getInstance(); + $args->comment_srl = $comment_srl; + $output = $oDB->executeQuery('comment.deleteComment', $args); + if(!$output->toBool()) return new Output(-1, 'msg_error_occured'); + + // 댓글 수를 구해서 업데이트 + $comment_count = $this->getCommentCount($document_srl); + + // 해당글의 댓글 수를 업데이트 + $oDocument = getModule('document'); + $output = $oDocument->updateCommentCount($document_srl, $comment_count); + $output->add('document_srl', $document_srl); + return $output; + }/*}}}*/ + + // public boolean deleteComments($document_srl)/*{{{*/ + // 특정 글의 모든 댓글 삭제 + function deleteComments($document_srl) { + // 권한이 있는지 확인 + if(!$this->isGranted($document_srl)) return new Output(-1, 'msg_not_permitted'); + + // 삭제 + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('comment.deleteComments', $args); + return $output; + }/*}}}*/ + + // public boolean deleteMoudleComments($module_srl)/*{{{*/ + // 특정 모듈의 모든 댓글 삭제 + function deleteModuleComments($module_srl) { + // 삭제 + $oDB = &DB::getInstance(); + $args->module_srl = $module_srl; + $output = $oDB->executeQuery('comment.deleteModuleComments', $args); + return $output; + }/*}}}*/ + + // public int getChildCommentCount($comment_srl)/*{{{*/ + // 자식 답글의 갯수 리턴 + function getChildCommentCount($comment_srl) { + $oDB = &DB::getInstance(); + $args->comment_srl = $comment_srl; + $output = $oDB->executeQuery('comment.getChildCommentCount', $args); + return (int)$output->data->count; + }/*}}}*/ + + // public boolean getComment($comment_srl)/*{{{*/ + // 댓글 가져오기 + function getComment($comment_srl) { + $oDB = &DB::getInstance(); + $args->comment_srl = $comment_srl; + $output = $oDB->executeQuery('comment.getComment', $args); + return $output->data; + }/*}}}*/ + + // public boolean getComments($comment_srl_list)/*{{{*/ + // 여러개의 댓글들을 가져옴 (페이징 아님) + function getComments($comment_srl_list) { + if(is_array($comment_srl_list)) $comment_srls = implode(',',$comment_srl_list); + + $oDB = &DB::getInstance(); + $args->comment_srls = $comment_srls; + $output = $oDB->executeQuery('comment.getComments', $args); + return $output->data; + }/*}}}*/ + + // public number getCommentCount($module_srl, $search_obj = NULL)/*{{{*/ + // document_srl 에 해당하는 댓글의 전체 갯수를 가져옴 + function getCommentCount($document_srl) { + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('comment.getCommentCount', $args); + $total_count = $output->data->count; + return (int)$total_count; + }/*}}}*/ + + // public boolean getCommentList($document_srl)/*{{{*/ + // module_srl값을 가지는 댓글의 목록을 가져옴 + function getCommentList($document_srl) { + // 댓글 목록을 가져옴 + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $args->list_order = 'list_order'; + $output = $oDB->executeQuery('comment.getCommentList', $args); + if(!$output->toBool()) return $output; + $source_list= $output->data; + if(!is_array($source_list)) $source_list = array($source_list); + + // 댓글를 계층형 구조로 정렬 + $comment_count = count($source_list); + + $root = NULL; + $list = NULL; + for($i=$comment_count-1;$i>=0;$i--) { + $comment_srl = $source_list[$i]->comment_srl; + $parent_srl = $source_list[$i]->parent_srl; + if(!$comment_srl) continue; + + $list[$comment_srl] = $source_list[$i]; + + if($parent_srl) { + $list[$parent_srl]->child[] = &$list[$comment_srl]; + } else { + $root->child[] = &$list[$comment_srl]; + } + + } + $this->_arrangeComment($comment_list, $root->child, 0); + return $comment_list; + }/*}}}*/ + + // private object _arrangeComment(&$comment_list, $list, $depth)/*{{{*/ + // 댓글를 계층형으로 재배치 + function _arrangeComment(&$comment_list, $list, $depth) { + if(!count($list)) return; + foreach($list as $key => $val) { + if($val->child) { + $tmp = $val; + $tmp->depth = $depth; + $comment_list[$tmp->comment_srl] = $tmp; + $this->_arrangeComment($comment_list,$val->child,$depth+1); + } + else { + $val->depth = $depth; + $comment_list[$val->comment_srl] = $val; + } + } + }/*}}}*/ + } +?> diff --git a/modules/comment/module.xml b/modules/comment/module.xml new file mode 100644 index 000000000..b71ff20bb --- /dev/null +++ b/modules/comment/module.xml @@ -0,0 +1,11 @@ + + + 댓글 + comment + + 제로 + zero + 댓글 모듈 + comment + + diff --git a/modules/comment/queries/deleteComment.xml b/modules/comment/queries/deleteComment.xml new file mode 100644 index 000000000..ce4b80e1f --- /dev/null +++ b/modules/comment/queries/deleteComment.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/modules/comment/queries/deleteComments.xml b/modules/comment/queries/deleteComments.xml new file mode 100644 index 000000000..30894de97 --- /dev/null +++ b/modules/comment/queries/deleteComments.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/comment/queries/deleteModuleComments.xml b/modules/comment/queries/deleteModuleComments.xml new file mode 100644 index 000000000..98858b815 --- /dev/null +++ b/modules/comment/queries/deleteModuleComments.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/comment/queries/getChildCommentCount.xml b/modules/comment/queries/getChildCommentCount.xml new file mode 100644 index 000000000..4686c279c --- /dev/null +++ b/modules/comment/queries/getChildCommentCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/comment/queries/getComment.xml b/modules/comment/queries/getComment.xml new file mode 100644 index 000000000..17e595ad4 --- /dev/null +++ b/modules/comment/queries/getComment.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/comment/queries/getCommentCount.xml b/modules/comment/queries/getCommentCount.xml new file mode 100644 index 000000000..6cdc97a29 --- /dev/null +++ b/modules/comment/queries/getCommentCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/comment/queries/getCommentList.xml b/modules/comment/queries/getCommentList.xml new file mode 100644 index 000000000..2599b286b --- /dev/null +++ b/modules/comment/queries/getCommentList.xml @@ -0,0 +1,14 @@ + + +
+ + + + + + + + + + + diff --git a/modules/comment/queries/getComments.xml b/modules/comment/queries/getComments.xml new file mode 100644 index 000000000..171fff6a0 --- /dev/null +++ b/modules/comment/queries/getComments.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/comment/queries/insertComment.xml b/modules/comment/queries/insertComment.xml new file mode 100644 index 000000000..7ecaa5c4d --- /dev/null +++ b/modules/comment/queries/insertComment.xml @@ -0,0 +1,21 @@ + + +
+ + + + + + + + + + + + + + + + + + diff --git a/modules/comment/queries/updateComment.xml b/modules/comment/queries/updateComment.xml new file mode 100644 index 000000000..e263590ac --- /dev/null +++ b/modules/comment/queries/updateComment.xml @@ -0,0 +1,20 @@ + + +
+ + + + + + + + + + + + + + + + + diff --git a/modules/comment/schemas/comments.xml b/modules/comment/schemas/comments.xml new file mode 100644 index 000000000..46222f3d4 --- /dev/null +++ b/modules/comment/schemas/comments.xml @@ -0,0 +1,18 @@ +
+ + + + + + + + + + + + + + + + +
diff --git a/modules/document/document.module.php b/modules/document/document.module.php new file mode 100644 index 000000000..0e58ab999 --- /dev/null +++ b/modules/document/document.module.php @@ -0,0 +1,702 @@ + + * @desc : 기본 모듈중의 하나인 document module + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class document extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + // 공지사항의 고정된 list_order + var $notice_list_order = -1000000000; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = ''; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + //Context::loadLang($this->module_path.'lang'); + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 document, document가 지정되어야 한다 + **/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + + // 문서의 권한 부여 + // 세션값으로 현 접속상태에서만 사용 가능 + // public void addGrant($document_srl) {/*{{{*/ + function addGrant($document_srl) { + $_SESSION['own_document'][$document_srl] = true; + }/*}}}*/ + + // public void isGranted($document_srl) {/*{{{*/ + function isGranted($document_srl) { + return $_SESSION['own_document'][$document_srl]; + }/*}}}*/ + + // 문서 + // public object insertDocument($obj)/*{{{*/ + // 문서 입력 + function insertDocument($obj) { + // 입력 + $oDB = &DB::getInstance(); + + // 카테고리가 있나 검사하여 없는 카테고리면 0으로 세팅 + if($obj->category_srl) { + $category_list = $this->getCategoryList($obj->module_srl); + if(!$category_list[$obj->category_srl]) $obj->category_srl = 0; + } + + // 태그 처리 + $oTag = getModule('tag'); + $obj->tags = $oTag->insertTag($obj->module_srl, $obj->document_srl, $obj->tags); + + // 글 입력 + $obj->readed_count = 0; + $obj->update_order = $obj->list_order = $obj->document_srl * -1; + if($obj->password) $obj->password = md5($obj->password); + + // 공지사항일 경우 list_order에 무지막지한 값;;을 입력 + if($obj->is_notice=='Y') $obj->list_order = $this->notice_list_order; + + // DB에 입력 + $output = $oDB->executeQuery('document.insertDocument', $obj); + + if(!$output->toBool()) return $output; + + // 성공하였을 경우 category_srl이 있으면 카테고리 update + if($obj->category_srl) $this->updateCategoryCount($obj->category_srl); + + // return + $this->addGrant($obj->document_srl); + $output->add('document_srl',$obj->document_srl); + $output->add('category_srl',$obj->category_srl); + return $output; + }/*}}}*/ + + // public object updateDocument($source_obj, $obj)/*{{{*/ + // 문서 수정 + function updateDocument($source_obj, $obj) { + // 카테고리가 변경되었으면 검사후 없는 카테고리면 0으로 세팅 + if($source_obj->category_srl!=$obj->category_srl) { + $category_list = $this->getCategoryList($obj->module_srl); + if(!$category_list[$obj->category_srl]) $obj->category_srl = 0; + } + + // 태그 처리 + $oTag = getModule('tag'); + $obj->tags = $oTag->insertTag($obj->module_srl, $obj->document_srl, $obj->tags); + + // 수정 + $oDB = &DB::getInstance(); + $obj->update_order = $oDB->getNextSequence() * -1; + + // 공지사항일 경우 list_order에 무지막지한 값을, 그렇지 않으면 document_srl*-1값을 + if($obj->is_notice=='Y') $obj->list_order = $this->notice_list_order; + else $obj->list_order = $obj->document_srl*-1; + + if($obj->password) $obj->password = md5($obj->password); + + // DB에 입력 + $output = $oDB->executeQuery('document.updateDocument', $obj); + + if(!$output->toBool()) return $output; + + // 성공하였을 경우 category_srl이 있으면 카테고리 update + if($source_obj->category_srl!=$obj->category_srl) { + if($source_obj->category_srl) $this->updateCategoryCount($source_obj->category_srl); + if($obj->category_srl) $this->updateCategoryCount($obj->category_srl); + } + + $output->add('document_srl',$obj->document_srl); + return $output; + }/*}}}*/ + + // public object deleteDocument($obj)/*{{{*/ + // 문서 삭제 + function deleteDocument($obj) { + // 변수 세팅 + $document_srl = $obj->document_srl; + $category_srl = $obj->category_srl; + + // 기존 문서가 있는지 확인 + $document = $this->getDocument($document_srl); + if($document->document_srl != $document_srl) return false; + + // 권한이 있는지 확인 + if(!$document->is_granted) return new Output(-1, 'msg_not_permitted'); + + // 글 삭제 + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('document.deleteDocument', $args); + if(!$output->toBool()) return $output; + + // 댓글 삭제 + $oComment = getModule('comment'); + $output = $oComment->deleteComments($document_srl); + + // 엮인글 삭제 + $oTrackback = getModule('trackback'); + $output = $oTrackback->deleteTrackbacks($document_srl); + + // 태그 삭제 + $oTag = getModule('tag'); + $oTag->deleteTag($document_srl); + + // 첨부 파일 삭제 + if($document->uploaded_count) $this->deleteFiles($document->module_srl, $document_srl); + + // 카테고리가 있으면 카테고리 정보 변경 + if($document->category_srl) $this->updateCategoryCount($document->category_srl); + + return $output; + }/*}}}*/ + + // public object deleteModuleDocument($module_srl) /*{{{*/ + function deleteModuleDocument($module_srl) { + $args->module_srl = $module_srl; + $oDB = &DB::getInstance(); + $output = $oDB->executeQuery('document.deleteModuleDocument', $args); + return $output; + }/*}}}*/ + + // public object getDocument($document_srl)/*{{{*/ + // 문서 가져오기 + function getDocument($document_srl) { + // DB에서 가져옴 + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('document.getDocument', $args); + $document = $output->data; + + // 이 문서에 대한 권한이 있는지 확인 + if($this->isGranted($document->document_srl)) { + $document->is_granted = true; + } elseif($document->member_srl) { + $oMember = getModule('member'); + $member_srl = $oMember->getMemberSrl(); + if($member_srl && $member_srl ==$document->member_srl) $document->is_granted = true; + } + return $document; + }/*}}}*/ + + // public object getDocuments($document_srl_list)/*{{{*/ + // 여러개의 문서들을 가져옴 (페이징 아님) + function getDocuments($document_srl_list) { + if(is_array($document_srl_list)) $document_srls = implode(',',$document_srl_list); + + // DB에서 가져옴 + $oDB = &DB::getInstance(); + $args->document_srls = $document_srls; + $output = $oDB->executeQuery('document.getDocuments', $args); + $document_list = $output->data; + if(!$document_list) return; + + // 권한 체크 + $oMember = getModule('member'); + $member_srl = $oMember->getMemberSrl(); + + $document_count = count($document_list); + for($i=0;$i<$document_count;$i++) { + $document = $document_list[$i]; + + $is_granted = false; + if($this->isGranted($document->document_srl)) { + $is_granted = true; + } elseif($member_srl && $member_srl == $document->member_srl) { + $is_granted = true; + } + $document_list[$i]->is_granted = $is_granted; + } + return $document_list; + }/*}}}*/ + + // public object getDocumentCount($module_srl, $search_obj = NULL)/*{{{*/ + // module_srl에 해당하는 문서의 전체 갯수를 가져옴 + function getDocumentCount($module_srl, $search_obj = NULL) { + $oDB = &DB::getInstance(); + + $args->module_srl = $module_srl; + $args->s_title = $search_obj->s_title; + $args->s_content = $search_obj->s_content; + $args->s_user_name = $search_obj->s_user_name; + $args->s_member_srl = $search_obj->s_member_srl; + $args->s_ipaddress = $search_obj->s_ipaddress; + $args->s_regdate = $search_obj->s_regdate; + $output = $oDB->executeQuery('document.getDocumentCount', $args); + $total_count = $output->data->count; + return (int)$total_count; + }/*}}}*/ + + // public object getDocumentList($module_srl, $sort_index='list_order', $page=1, $list_order=20, $page_count=10, $search_obj = NULL)/*{{{*/ + // module_srl값을 가지는 문서의 목록을 가져옴 + function getDocumentList($module_srl, $sort_index = 'list_order', $page = 1, $list_count = 20, $page_count = 10, $search_obj = NULL) { + $args->module_srl = $module_srl; + $args->s_title = $search_obj->s_title; + $args->s_content = $search_obj->s_content; + $args->s_user_name = $search_obj->s_user_name; + $args->s_member_srl = $search_obj->s_member_srl; + $args->s_ipaddress = $search_obj->s_ipaddress; + $args->s_regdate = $search_obj->s_regdate; + $args->category_srl = $search_obj->category_srl; + + $args->sort_index = $sort_index; + $args->page = $page; + $args->list_count = $list_count; + $args->page_count = $page_count; + $oDB = &DB::getInstance(); + $output = $oDB->executeQuery('document.getDocumentList', $args); + + if(!count($output->data)) return $output; + + // 권한 체크 + $oMember = getModule('member'); + $member_srl = $oMember->getMemberSrl(); + + foreach($output->data as $key => $document) { + $is_granted = false; + if($this->isGranted($document->document_srl)) $is_granted = true; + elseif($member_srl && $member_srl == $document->member_srl) $is_granted = true; + $output->data[$key]->is_granted = $is_granted; + } + return $output; + }/*}}}*/ + + // public object getDocumentPage($document_srl, $module_srl, $list_count)/*{{{*/ + // 해당 document의 page 가져오기, module_srl이 없으면 전체에서.. + function getDocumentPage($document_srl, $module_srl=0, $list_count) { + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $args->module_srl = $module_srl; + $output = $oDB->executeQuery('document.getDocumentPage', $args); + $count = $output->data->count; + $page = (int)(($count-1)/$list_count)+1; + return $page; + }/*}}}*/ + + // public object updateReadedCount($document_srl)/*{{{*/ + // 해당 document의 조회수 증가 + function updateReadedCount($document_srl) { + if($_SESSION['readed_document'][$document_srl]) return false; + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('document.updateReadedCount', $args); + return $_SESSION['readed_document'][$document_srl] = true; + }/*}}}*/ + + // public object updateVotedCount($document_srl)/*{{{*/ + // 해당 document의 추천수 증가 + function updateVotedCount($document_srl) { + if($_SESSION['voted_document'][$document_srl]) return new Output(-1, 'failed_voted'); + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('document.updateVotedCount', $args); + $_SESSION['voted_document'][$document_srl] = true; + return new Output(0, 'success_voted'); + }/*}}}*/ + + // public object updateCommentCount($document_srl, $comment_count)/*{{{*/ + // 해당 document의 댓글 수 증가 + function updateCommentCount($document_srl, $comment_count) { + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $args->comment_count = $comment_count; + $output = $oDB->executeQuery('document.updateCommentCount', $args); + return new Output(); + }/*}}}*/ + + // public object updateTrackbackCount($document_srl, $trackback_count)/*{{{*/ + // 해당 document의 엮인글 수증가 + function updateTrackbackCount($document_srl, $trackback_count) { + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $args->trackback_count = $trackback_count; + $output = $oDB->executeQuery('document.updateTrackbackCount', $args); + return new Output(); + }/*}}}*/ + + // 카테고리 관리 + // public object getCategory($category_srl) /*{{{*/ + function getCategory($category_srl) { + $args->category_srl = $category_srl; + $oDB = &DB::getInstance(); + $output = $oDB->executeQuery('document.getCategory', $args); + return $output->data; + }/*}}}*/ + + // public object getCategoryList($module_srl) /*{{{*/ + function getCategoryList($module_srl) { + $args->module_srl = $module_srl; + $args->sort_index = 'list_order'; + $oDB = &DB::getInstance(); + $output = $oDB->executeQuery('document.getCategoryList', $args); + $category_list = $output->data; + if(!$category_list) return NULL; + if(!is_array($category_list)) $category_list = array($category_list); + $category_count = count($category_list); + for($i=0;$i<$category_count;$i++) { + $category_srl = $category_list[$i]->category_srl; + $list[$category_srl] = $category_list[$i]; + } + return $list; + }/*}}}*/ + + // public object insertCategory($module_srl, $title) /*{{{*/ + function insertCategory($module_srl, $title) { + $oDB = &DB::getInstance(); + $args->list_order = $args->category_srl = $oDB->getNextSequence(); + $args->module_srl = $module_srl; + $args->title = $title; + $args->document_count = 0; + return $oDB->executeQuery('document.insertCategory', $args); + }/*}}}*/ + + // public object updateCategory($args) /*{{{*/ + function updateCategory($args) { + $oDB = &DB::getInstance(); + return $oDB->executeQuery('document.updateCategory', $args); + }/*}}}*/ + + // public object updateCategoryCount($category_srl, $document_count = 0) /*{{{*/ + function updateCategoryCount($category_srl, $document_count = 0) { + if(!$document_count) $document_count = $this->getCategoryDocumentCount($category_srl); + $args->category_srl = $category_srl; + $args->document_count = $document_count; + $oDB = &DB::getInstance(); + return $oDB->executeQuery('document.updateCategoryCount', $args); + }/*}}}*/ + + // public int getCategoryDocumentCount($category_srl) /*{{{*/ + function getCategoryDocumentCount($category_srl) { + $args->category_srl = $category_srl; + $oDB = &DB::getInstance(); + $output = $oDB->executeQuery('document.getCategoryDocumentCount', $args); + return (int)$output->data->count; + }/*}}}*/ + + // public object deleteCategory($category_srl) /*{{{*/ + function deleteCategory($category_srl) { + $args->category_srl = $category_srl; + $oDB = &DB::getInstance(); + + // 카테고리 정보를 삭제 + $output = $oDB->executeQuery('document.deleteCategory', $args); + if(!$output->toBool()) return $output; + + // 현 카테고리 값을 가지는 문서들의 category_srl을 0 으로 세팅 + unset($args); + $args->target_category_srl = 0; + $args->source_category_srl = $category_srl; + $output = $oDB->executeQuery('document.updateDocumentCategory', $args); + return $output; + }/*}}}*/ + + // public object deleteModuleCategory($module_srl) /*{{{*/ + function deleteModuleCategory($module_srl) { + $args->module_srl = $module_srl; + $oDB = &DB::getInstance(); + $output = $oDB->executeQuery('document.deleteModuleCategory', $args); + return $output; + }/*}}}*/ + + // public object moveCategoryUp($category_srl) /*{{{*/ + function moveCategoryUp($category_srl) { + // 선택된 카테고리의 정보를 구한다 + $oDB = &DB::getInstance(); + $args->category_srl = $category_srl; + $output = $oDB->executeQuery('document.getCategory', $args); + $category = $output->data; + $list_order = $category->list_order; + $module_srl = $category->module_srl; + + // 전체 카테고리 목록을 구한다 + $category_list = $this->getCategoryList($module_srl); + $category_srl_list = array_keys($category_list); + if(count($category_srl_list)<2) return new Output(); + + $prev_category = NULL; + foreach($category_list as $key => $val) { + if($key==$category_srl) break; + $prev_category = $val; + } + + // 이전 카테고리가 없으면 그냥 return + if(!$prev_category) return new Output(-1,Context::getLang('msg_category_not_moved')); + + // 선택한 카테고리가 가장 위의 카테고리이면 그냥 return + if($category_srl_list[0]==$category_srl) return new Output(-1,Context::getLang('msg_category_not_moved')); + + // 선택한 카테고리의 정보 + $cur_args->category_srl = $category_srl; + $cur_args->list_order = $prev_category->list_order; + $cur_args->title = $category->title; + $this->updateCategory($cur_args); + + // 대상 카테고리의 정보 + $prev_args->category_srl = $prev_category->category_srl; + $prev_args->list_order = $list_order; + $prev_args->title = $prev_category->title; + $this->updateCategory($prev_args); + + return new Output(); + }/*}}}*/ + + // public object moveCategoryDown($category_srl) /*{{{*/ + function moveCategoryDown($category_srl) { + // 선택된 카테고리의 정보를 구한다 + $oDB = &DB::getInstance(); + $args->category_srl = $category_srl; + $output = $oDB->executeQuery('document.getCategory', $args); + $category = $output->data; + $list_order = $category->list_order; + $module_srl = $category->module_srl; + + // 전체 카테고리 목록을 구한다 + $category_list = $this->getCategoryList($module_srl); + $category_srl_list = array_keys($category_list); + if(count($category_srl_list)<2) return new Output(); + + for($i=0;$icategory_srl = $category_srl; + $cur_args->list_order = $next_category->list_order; + $cur_args->title = $category->title; + $this->updateCategory($cur_args); + + // 대상 카테고리의 정보 + $next_args->category_srl = $next_category->category_srl; + $next_args->list_order = $list_order; + $next_args->title = $next_category->title; + $this->updateCategory($next_args); + + return new Output(); + }/*}}}*/ + + // 파일 관리 + // public int getFilesCount($document_srl) /*{{{*/ + function getFilesCount($document_srl) { + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('document.getFilesCount', $args); + return (int)$output->data->count; + }/*}}}*/ + + // public object getFile($file_srl) /*{{{*/ + function getFile($file_srl) { + $oDB = &DB::getInstance(); + $args->file_srl = $file_srl; + $output = $oDB->executeQuery('document.getFile', $args); + return $output->data; + }/*}}}*/ + + // public object getFiles($document_srl) /*{{{*/ + function getFiles($document_srl) { + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $args->sort_index = 'file_srl'; + $output = $oDB->executeQuery('document.getFiles', $args); + $file_list = $output->data; + if($file_list && !is_array($file_list)) $file_list = array($file_list); + for($i=0;$idirect_download; + if($direct_download!='Y') continue; + $uploaded_filename = Context::getRequestUri().substr($file_list[$i]->uploaded_filename,2); + $file_list[$i]->uploaded_filename = $uploaded_filename; + } + return $file_list; + }/*}}}*/ + + // public object insertFile($module_srl, $document_sr) /*{{{*/ + function insertFile($module_srl, $document_srl) { + $oDB = &DB::getInstance(); + + $file_info = Context::get('file'); + + // 정상적으로 업로드된 파일이 아니면 오류 출력 + if(!is_uploaded_file($file_info['tmp_name'])) return false; + + // 이미지인지 기타 파일인지 체크하여 upload path 지정 + if(eregi("\.(jpg|jpeg|gif|png|wmv|mpg|mpeg|avi|swf|flv|mp3|asaf|wav|asx|midi)$", $file_info['name'])) { + $path = sprintf("./files/attach/images/%s/%s/", $module_srl,$document_srl); + $filename = $path.$file_info['name']; + $direct_download = 'Y'; + } else { + $path = sprintf("./files/attach/binaries/%s/%s/", $module_srl, $document_srl); + $filename = $path.md5(crypt(rand(1000000,900000), rand(0,100))); + $direct_download = 'N'; + } + + // 디렉토리 생성 + if(!FileHandler::makeDir($path)) return false; + + // 파일 이동 + if(!move_uploaded_file($file_info['tmp_name'], $filename)) return false; + + // 사용자 정보를 구함 + $oMember = getModule('member'); + $member_srl = $oMember->getMemberSrl(); + + // 파일 정보를 정리 + $oDB = &DB::getInstance(); + $args->file_srl = $oDB->getNextSequence(); + $args->document_srl = $document_srl; + $args->module_srl = $module_srl; + $args->direct_download = $direct_download; + $args->source_filename = $file_info['name']; + $args->uploaded_filename = $filename; + $args->file_size = filesize($filename); + $args->comment = NULL; + $args->member_srl = $member_srl; + $args->sid = md5($args->source_filename); + + $output = $oDB->executeQuery('document.insertFile', $args); + if(!$output->toBool()) return $output; + $output->add('file_srl', $args->file_srl); + $output->add('file_size', $args->file_size); + $output->add('source_filename', $args->source_filename); + return $output; + }/*}}}*/ + + // public object deleteFile($file_srl) /*{{{*/ + function deleteFile($file_srl) { + $oDB = &DB::getInstance(); + + // 파일 정보를 가져옴 + $args->file_srl = $file_srl; + $output = $oDB->executeQuery('document.getFile', $args); + if(!$output->toBool()) return $output; + $file_info = $output->data; + if(!$file_info) return new Output(-1, 'file_not_founded'); + + $source_filename = $output->data->source_filename; + $uploaded_filename = $output->data->uploaded_filename; + + // DB에서 삭제 + $output = $oDB->executeQuery('document.deleteFile', $args); + if(!$output->toBool()) return $output; + + // 삭제 성공하면 파일 삭제 + unlink($uploaded_filename); + + return $output; + }/*}}}*/ + + // public object deleteFiles($module_srl, $document_srl) /*{{{*/ + function deleteFiles($module_srl, $document_srl) { + // DB에서 삭제 + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('document.deleteFiles', $args); + if(!$output->toBool()) return $output; + + // 실제 파일 삭제 + $path[0] = sprintf("./files/attach/images/%s/%s/", $module_srl, $document_srl); + $path[1] = sprintf("./files/attach/binaries/%s/%s/", $module_srl, $document_srl); + + FileHandler::removeDir($path[0]); + FileHandler::removeDir($path[1]); + + return $output; + }/*}}}*/ + + // public object deleteModuleFiles($module_srl) /*{{{*/ + function deleteModuleFiles($module_srl) { + // DB에서 삭제 + $oDB = &DB::getInstance(); + $args->module_srl = $module_srl; + $output = $oDB->executeQuery('document.deleteModuleFiles', $args); + if(!$output->toBool()) return $output; + + // 실제 파일 삭제 + $path[0] = sprintf("./files/attach/images/%s/", $module_srl); + $path[1] = sprintf("./files/attach/binaries/%s/", $module_srl); + FileHandler::removeDir($path[0]); + FileHandler::removeDir($path[1]); + + return $output; + }/*}}}*/ + + // 기타 기능 + // public string transContent($content) {/*{{{*/ + // 내용 관리 + // 내용의 플러그인이나 기타 기능에 대한 code를 실제 code로 변경 + function transContent($content) { + // 멀티미디어 코드의 변환 + $content = preg_replace_callback('!]*)editor_multimedia([^\>]*?)>!is', array('Document','_transMultimedia'), $content); + + //
코드 변환 + $content = str_replace(array("
","
","
"),"
", $content); + + // 코드를 코드로 변환 + $content = preg_replace('!!is','', $content); + + return $content; + }/*}}}*/ + + // public string _transMultimedia($matches)/*{{{*/ + // 로 되어 있는 코드를 변경 + function _transMultimedia($matches) { + preg_match("/style\=(\"|'){0,1}([^\"\']+)(\"|'){0,1}/i",$matches[0], $buff); + $style = str_replace("\"","'",$buff[0]); + preg_match("/alt\=\"{0,1}([^\"]+)\"{0,1}/i",$matches[0], $buff); + $opt = explode('|@|',$buff[1]); + if(count($opt)<1) return $matches[0]; + + for($i=0;$i{$cmd} = $val; + } + + return sprintf("", $obj->type, $obj->src, $style); + }/*}}}*/ + } +?> diff --git a/modules/document/lang/ko.lang.php b/modules/document/lang/ko.lang.php new file mode 100644 index 000000000..601fb4572 --- /dev/null +++ b/modules/document/lang/ko.lang.php @@ -0,0 +1,8 @@ + + * @desc : 문서(document) 모듈의 기본 언어팩 + **/ + $lang->msg_category_not_moved = "이동할 수가 없습니다"; +?> diff --git a/modules/document/module.xml b/modules/document/module.xml new file mode 100644 index 000000000..d8bf37a17 --- /dev/null +++ b/modules/document/module.xml @@ -0,0 +1,11 @@ + + + 문서 + document + + 제로 + zero + 문서 모듈 + document + + diff --git a/modules/document/queries/deleteCategory.xml b/modules/document/queries/deleteCategory.xml new file mode 100644 index 000000000..c1a98762a --- /dev/null +++ b/modules/document/queries/deleteCategory.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/modules/document/queries/deleteDocument.xml b/modules/document/queries/deleteDocument.xml new file mode 100644 index 000000000..36d157a90 --- /dev/null +++ b/modules/document/queries/deleteDocument.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/document/queries/deleteFile.xml b/modules/document/queries/deleteFile.xml new file mode 100644 index 000000000..3584ea182 --- /dev/null +++ b/modules/document/queries/deleteFile.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/document/queries/deleteFiles.xml b/modules/document/queries/deleteFiles.xml new file mode 100644 index 000000000..d4ee8b8df --- /dev/null +++ b/modules/document/queries/deleteFiles.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/document/queries/deleteModuleCategory.xml b/modules/document/queries/deleteModuleCategory.xml new file mode 100644 index 000000000..152826bc4 --- /dev/null +++ b/modules/document/queries/deleteModuleCategory.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/document/queries/deleteModuleDocument.xml b/modules/document/queries/deleteModuleDocument.xml new file mode 100644 index 000000000..0338b85cc --- /dev/null +++ b/modules/document/queries/deleteModuleDocument.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/document/queries/deleteModuleFiles.xml b/modules/document/queries/deleteModuleFiles.xml new file mode 100644 index 000000000..f2f7c2ad7 --- /dev/null +++ b/modules/document/queries/deleteModuleFiles.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/document/queries/getCategory.xml b/modules/document/queries/getCategory.xml new file mode 100644 index 000000000..97ba6536a --- /dev/null +++ b/modules/document/queries/getCategory.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/document/queries/getCategoryDocumentCount.xml b/modules/document/queries/getCategoryDocumentCount.xml new file mode 100644 index 000000000..bf0df824d --- /dev/null +++ b/modules/document/queries/getCategoryDocumentCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/getCategoryList.xml b/modules/document/queries/getCategoryList.xml new file mode 100644 index 000000000..1625c3cfe --- /dev/null +++ b/modules/document/queries/getCategoryList.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/getDocument.xml b/modules/document/queries/getDocument.xml new file mode 100644 index 000000000..eb3b6af8a --- /dev/null +++ b/modules/document/queries/getDocument.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/getDocumentCount.xml b/modules/document/queries/getDocumentCount.xml new file mode 100644 index 000000000..5ea51255e --- /dev/null +++ b/modules/document/queries/getDocumentCount.xml @@ -0,0 +1,19 @@ + + +
+ + + + + + + + + + + + + + + + diff --git a/modules/document/queries/getDocumentList.xml b/modules/document/queries/getDocumentList.xml new file mode 100644 index 000000000..de2f2aa88 --- /dev/null +++ b/modules/document/queries/getDocumentList.xml @@ -0,0 +1,26 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/document/queries/getDocumentPage.xml b/modules/document/queries/getDocumentPage.xml new file mode 100644 index 000000000..35bee06c4 --- /dev/null +++ b/modules/document/queries/getDocumentPage.xml @@ -0,0 +1,12 @@ + + +
+ + + + + + + + + diff --git a/modules/document/queries/getDocuments.xml b/modules/document/queries/getDocuments.xml new file mode 100644 index 000000000..828a6b2db --- /dev/null +++ b/modules/document/queries/getDocuments.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/getFile.xml b/modules/document/queries/getFile.xml new file mode 100644 index 000000000..deb35b994 --- /dev/null +++ b/modules/document/queries/getFile.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/document/queries/getFiles.xml b/modules/document/queries/getFiles.xml new file mode 100644 index 000000000..d4e1510f9 --- /dev/null +++ b/modules/document/queries/getFiles.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/getFilesCount.xml b/modules/document/queries/getFilesCount.xml new file mode 100644 index 000000000..a03e6a3e0 --- /dev/null +++ b/modules/document/queries/getFilesCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/insertCategory.xml b/modules/document/queries/insertCategory.xml new file mode 100644 index 000000000..79bfe78e9 --- /dev/null +++ b/modules/document/queries/insertCategory.xml @@ -0,0 +1,14 @@ + + +
+ + + + + + + + + + + diff --git a/modules/document/queries/insertDocument.xml b/modules/document/queries/insertDocument.xml new file mode 100644 index 000000000..08c0d48eb --- /dev/null +++ b/modules/document/queries/insertDocument.xml @@ -0,0 +1,34 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/document/queries/insertFile.xml b/modules/document/queries/insertFile.xml new file mode 100644 index 000000000..873310014 --- /dev/null +++ b/modules/document/queries/insertFile.xml @@ -0,0 +1,20 @@ + + +
+ + + + + + + + + + + + + + + + + diff --git a/modules/document/queries/updateCategory.xml b/modules/document/queries/updateCategory.xml new file mode 100644 index 000000000..2d1d60687 --- /dev/null +++ b/modules/document/queries/updateCategory.xml @@ -0,0 +1,13 @@ + + +
+ + + + + + + + + + diff --git a/modules/document/queries/updateCategoryCount.xml b/modules/document/queries/updateCategoryCount.xml new file mode 100644 index 000000000..1d4c5fc2f --- /dev/null +++ b/modules/document/queries/updateCategoryCount.xml @@ -0,0 +1,12 @@ + + +
+ + + + + + + + + diff --git a/modules/document/queries/updateCommentCount.xml b/modules/document/queries/updateCommentCount.xml new file mode 100644 index 000000000..8c71dd3c4 --- /dev/null +++ b/modules/document/queries/updateCommentCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/updateDocument.xml b/modules/document/queries/updateDocument.xml new file mode 100644 index 000000000..43d89bc00 --- /dev/null +++ b/modules/document/queries/updateDocument.xml @@ -0,0 +1,31 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/document/queries/updateDocumentCategory.xml b/modules/document/queries/updateDocumentCategory.xml new file mode 100644 index 000000000..67a2976a1 --- /dev/null +++ b/modules/document/queries/updateDocumentCategory.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/updateFileDownloadCount.xml b/modules/document/queries/updateFileDownloadCount.xml new file mode 100644 index 000000000..251291af2 --- /dev/null +++ b/modules/document/queries/updateFileDownloadCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/updateReadedCount.xml b/modules/document/queries/updateReadedCount.xml new file mode 100644 index 000000000..8391d8cd8 --- /dev/null +++ b/modules/document/queries/updateReadedCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/updateTrackbackCount.xml b/modules/document/queries/updateTrackbackCount.xml new file mode 100644 index 000000000..dd8b58c8f --- /dev/null +++ b/modules/document/queries/updateTrackbackCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/queries/updateVotedCount.xml b/modules/document/queries/updateVotedCount.xml new file mode 100644 index 000000000..bd2ddbb04 --- /dev/null +++ b/modules/document/queries/updateVotedCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/document/schemas/category.xml b/modules/document/schemas/category.xml new file mode 100644 index 000000000..a201b6c0b --- /dev/null +++ b/modules/document/schemas/category.xml @@ -0,0 +1,9 @@ +
+ + + + + + + +
diff --git a/modules/document/schemas/documents.xml b/modules/document/schemas/documents.xml new file mode 100644 index 000000000..c5b1c4f27 --- /dev/null +++ b/modules/document/schemas/documents.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/modules/document/schemas/files.xml b/modules/document/schemas/files.xml new file mode 100644 index 000000000..5ee2ee2a8 --- /dev/null +++ b/modules/document/schemas/files.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + +
diff --git a/modules/install/install.module.php b/modules/install/install.module.php new file mode 100644 index 000000000..bebf589e2 --- /dev/null +++ b/modules/install/install.module.php @@ -0,0 +1,264 @@ + + * @desc : 기본 모듈중의 하나인 install module + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class install extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = 'dispIntroduce'; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + Context::loadLang($this->module_path.'lang'); + + // 설치시 필수항목 검사 + $this->checkInstallEnv(); + + if(Context::get('install_enable')) $this->makeDefaultDirectory(); + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + // 설치가 가능하면 기본 디렉토리등을 만듬 + if(!Context::get('install_enable')) { + $this->act = 'dispIntroduce'; + } + + return true; + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + // 설치가 불가능한 환경인데 요청이 오면 에러 표시 + if(!Context::get('install_enable')) return $this->doError('msg_already_installed'); + return true; + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 error, message가 지정되어야 한다 + * + * 변수의 사용은 Context::get('이름')으로 얻어오면 된다 + **/ + function dispIntroduce() {/*{{{*/ + // disp_license.html 파일 출력 + $this->setTemplateFile('disp_license'); + }/*}}}*/ + + function dispDBInfoForm() {/*{{{*/ + // db_type이 지정되지 않았다면 다시 초기화면 출력 + if(!Context::get('db_type')) return $this->dispIntroduce(); + + // disp_db_info_form.html 파일 출력 + $tpl_filename = sprintf('db_form.%s.html', Context::get('db_type')); + $this->setTemplateFile($tpl_filename); + }/*}}}*/ + + function procInstall() {/*{{{*/ + // 설치가 되어 있는지에 대한 체크 + if(Context::isInstalled()) { + return $this->doError('msg_already_installed'); + } + + // DB와 관련된 변수를 받음 + $db_info = Context::gets('db_type','db_hostname','db_userid','db_password','db_database','db_table_prefix'); + + // DB의 타입과 정보를 등록 + Context::setDBInfo($db_info); + + // DB Instance 생성 + $oDB = &DB::getInstance(); + + // DB접속이 가능한지 체크 + if(!$oDB->isConnected()) { + return $this->doError('msg_dbconnect_failed'); + } + + // 모든 모듈의 테이블 생성 + $output = $this->makeTable(); + if(!$output->toBool()) return $output; + + // 관리자 정보 입력 (member 모듈을 찾아서 method 실행) + $oMember = getModule('member'); + + // 그룹을 입력 + $group_args->title = Context::getLang('default_group_1'); + $group_args->is_default = 'Y'; + $oMember->insertGroup($group_args); + + $group_args->title = Context::getLang('default_group_2'); + $group_args->is_default = 'N'; + $oMember->insertGroup($group_args); + + // 금지 아이디 등록 + $oMember->insertDeniedID('www',''); + $oMember->insertDeniedID('root',''); + $oMember->insertDeniedID('admin',''); + $oMember->insertDeniedID('administrator',''); + $oMember->insertDeniedID('ftp',''); + $oMember->insertDeniedID('http',''); + + // 관리자 정보 세팅 + $admin_info = Context::gets('user_id','password','nick_name','user_name', 'email_address'); + + // 관리자 정보 입력 + $oMember->insertAdmin($admin_info); + + // 로그인 처리시킴 + $oMember->doLogin($admin_info->user_id, $admin_info->password); + + // 기본 모듈을 생성 + $oModule = getModule('module_manager'); + $oModule->makeDefaultModule(); + + // config 파일 생성 + if(!$this->makeConfigFile()) return $this->doError('msg_install_failed'); + + // 설치 완료 메세지 출력 + $this->setMessage('msg_install_completed'); + }/*}}}*/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + // public void checkInstallEnv()/*{{{*/ + // 기본적으로 필수적인 체크항목들을 검사하여 Context에 바로 넣어버림.. + function checkInstallEnv() { + // 각 필요한 항목 체크 + $checklist = array(); + + // 1. permission 체크 + if(is_writable('./')||is_writable('./files')) $checklist['permission'] = true; + else $checklist['permission'] = false; + + // 2. xml_parser_create함수 유무 체크 + if(function_exists('xml_parser_create')) $checklist['xml'] = true; + else $checklist['xml'] = false; + + // 3. ini_get(session.auto_start)==1 체크 + if(ini_get(session.auto_start)!=1) $checklist['session'] = true; + else $checklist['session'] = false; + + // 4. iconv 체크 + if(function_exists('iconv')) $checklist['iconv'] = true; + else $checklist['iconv'] = false; + + // 5. gd 체크 (imagecreatefromgif함수) + if(function_exists('imagecreatefromgif')) $checklist['gd'] = true; + else $checklist['gd'] = false; + + // 6. mysql_get_client_info() 체크 + if(mysql_get_client_info() < "4.1.00") $checklist['mysql'] = false; + else $checklist['mysql'] = true; + + if(!$checklist['permission'] || !$checklist['xml'] || !$checklist['session']) $install_enable = false; + else $install_enable = true; + + // 체크 결과를 Context에 저장 + Context::set('install_enable', $install_enable); + Context::set('checklist', $checklist); + }/*}}}*/ + + // public void makeDefaultDirectory()/*{{{*/ + // files 및 하위 디렉토리 생성 + function makeDefaultDirectory() { + $directory_list = array( + './files', + './files/modules', + './files/plugins', + './files/addons', + './files/layouts', + './files/queries', + './files/schemas', + './files/js_filter_compiled', + './files/template_compiled', + './files/config', + './files/attach', + './files/attach/images', + './files/attach/binaries', + ); + + foreach($directory_list as $dir) { + if(is_dir($dir)) continue; + @mkdir($dir, 0707); + @chmod($dir, 0707); + } + }/*}}}*/ + + // public void makeTable()/*{{{*/ + // 모든 모듈의 테이블 생성 schema를 찾아서 생성 + function makeTable() { + // db instance생성 + $oDB = &DB::getInstance(); + + // 각 모듈의 schemas/*.xml 파일을 모두 찾아서 table 생성 + $module_list_1 = FileHandler::readDir('./modules/', NULL, false, true); + $module_list_2 = FileHandler::readDir('./files/modules/', NULL, false, true); + $module_list = array_merge($module_list_1, $module_list_2); + foreach($module_list as $module_path) { + $schema_dir = sprintf('%s/schemas/', $module_path); + $schema_files = FileHandler::readDir($schema_dir, NULL, false, true); + $file_cnt = count($schema_files); + if(!$file_cnt) continue; + + for($i=0;$i<$file_cnt;$i++) { + $file = trim($schema_files[$i]); + if(!$file || substr($file,-4)!='.xml') continue; + $output = $oDB->createTableByXmlFile($file); + if($oDB->isError()) return $oDB->getError(); + } + } + return new Output(); + }/*}}}*/ + + // public boolean makeConfigFile() /*{{{*/ + // config 파일을 생성 + function makeConfigFile() { + $config_file = Context::getConfigFile(); + if(file_exists($config_file)) return; + + $db_info = Context::getDbInfo(); + if(!$db_info) return; + + $buff = ' $val) { + $buff .= sprintf("\$db_info->%s = \"%s\";\n", $key, $val); + } + $buff .= "?>"; + + FileHandler::writeFile($config_file, $buff); + + if(@file_exists($config_file)) return true; + return false; + }/*}}}*/ + } +?> diff --git a/modules/install/lang/ko.lang.php b/modules/install/lang/ko.lang.php new file mode 100644 index 000000000..c2e7c302c --- /dev/null +++ b/modules/install/lang/ko.lang.php @@ -0,0 +1,65 @@ + + * @desc : 한국어 언어팩 (기본적인 내용만 수록) + **/ + + $lang->introduce_title = '제로보드5 설치'; + $lang->introduce = + "제로보드5를 사용해주셔서 감사합니다.\n". + "제로보드5는 GPL라이센스를 따르며 블라블라..\n"; + + $lang->install_condition_title = "설치 조건"; + + $lang->install_checklist_title = array( + 'permission' => '퍼미션', + 'xml' => 'XML 라이브러리', + 'iconv' => 'ICONV 라이브러리', + 'gd' => 'GD 라이브러리', + 'session' => 'Session.auto_start 설정', + 'mysql' => 'MySQL 버전', + ); + + $lang->install_checklist_desc = array( + 'permission' => '[필수] 제로보드의 설치 경로 또는 ./files 디렉토리의 퍼미션이 707이어야 합니다', + 'xml' => '[필수] XML통신을 위하여 XML 라이브러리가 필요합니다', + 'session' => '[필수] 제로보드에서 세션 사용을 위해 php.ini 설정의 session.auto_start=0 이어야 합니다', + 'iconv' => 'UTF-8과 다른 언어셋의 변환을 위한 iconv설치가 필요합니다', + 'gd' => '이미지변환 기능을 사용하기 위해 GD라이브러리가 설치되어 있어야 합니다', + 'mysql' => 'UTF-8 언어셋 사용을 위해 mysql버전이 4.1 이상이어야 합니다', + ); + + $lang->install_checklist_xml = 'XML라이브러리 설치'; + $lang->install_without_xml = 'xml 라이브러리가 설치되어 있지 않습니다'; + $lang->install_checklist_gd = 'GD라이브러리 설치'; + $lang->install_without_gd = '이미지 변환을 위한 gd 라이브러리가 설치되어 있지 않습니다'; + $lang->install_checklist_gd = 'GD라이브러리 설치'; + $lang->install_without_iconv = '문자열을 처리하기 위한 iconv 라이브러리가 설치되어 있지 않습니다'; + $lang->install_mysql_version = 'mysql client version이 4.1 이하라서 문제가 발생할 수 있습니다'; + $lang->install_session_auto_start = 'php설정의 session.auto_start==1 이라 세션 처리에 문제가 발생할 수 있습니다'; + $lang->install_permission_denied = '설치대상 디렉토리의 퍼미션이 707이 아닙니다'; + + $lang->cmd_install_fix_checklist = '필수 조건을 만족시켰습니다.'; + $lang->cmd_install_next = '설치를 진행합니다'; + + $lang->db_title = 'DB정보 입력'; + $lang->db_type = 'DB 종류'; + $lang->db_hostname = 'DB 호스트네임'; + $lang->db_userid = 'DB 아이디'; + $lang->db_password = 'DB 비밀번호'; + $lang->db_database = 'DB 데이터베이스'; + $lang->db_table_prefix = '테이블 머릿말'; + + $lang->admin_title = '관리자정보'; + + $lang->default_group_1 = "준회원"; + $lang->default_group_2 = "정회원"; + + $lang->msg_cannot_proc = '설치 환경이 갖춰지지 않아 요청을 실행할 수가 없습니다'; + $lang->msg_already_installed = '이미 설치가 되어 있습니다'; + $lang->msg_dbconnect_failed = "DB접속 오류가 발생하였습니다.\nDB정보를 다시 확인해주세요"; + $lang->msg_table_is_exists = "이미 DB에 테이블이 생성되어 있습니다.\nconfig파일을 재생성하였습니다"; + $lang->msg_install_completed = "설치가 완료되었습니다.\n감사합니다"; + $lang->msg_install_failed = "설치 파일 생성시에 오류가 발생하였습니다."; +?> diff --git a/modules/install/module.xml b/modules/install/module.xml new file mode 100644 index 000000000..7e85528b8 --- /dev/null +++ b/modules/install/module.xml @@ -0,0 +1,11 @@ + + + 설치관리 + install + + 제로 + zero + 설치 관리 모듈 + install + + diff --git a/modules/install/schemas/sequence.xml b/modules/install/schemas/sequence.xml new file mode 100644 index 000000000..c7cabb213 --- /dev/null +++ b/modules/install/schemas/sequence.xml @@ -0,0 +1,3 @@ + + +
diff --git a/modules/install/skins/default/css/install.css b/modules/install/skins/default/css/install.css new file mode 100644 index 000000000..e69de29bb diff --git a/modules/install/skins/default/db_form.mysql.html b/modules/install/skins/default/db_form.mysql.html new file mode 100644 index 000000000..172911c15 --- /dev/null +++ b/modules/install/skins/default/db_form.mysql.html @@ -0,0 +1,92 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {$lang->db_title} +
{$lang->db_hostname} + +
{$lang->db_userid} + +
{$lang->db_password} + +
{$lang->db_database} + +
{$lang->db_table_prefix} + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {$lang->admin_title} +
{$lang->user_id} + +
{$lang->password1} + +
{$lang->password2} + +
{$lang->user_name} + +
{$lang->nick_name} + +
{$lang->email_address} + +
+ + +
diff --git a/modules/install/skins/default/disp_license.html b/modules/install/skins/default/disp_license.html new file mode 100644 index 000000000..1c8b015e4 --- /dev/null +++ b/modules/install/skins/default/disp_license.html @@ -0,0 +1,48 @@ + + + + + + + + + +
{$lang->introduce_title}
+ {nl2br($lang->introduce)} +
+ + + + + + + + + + + + + + +
{$lang->install_condition_title}
{$lang->install_checklist_title[$key]}{$lang->enable}{$lang->disable}
{$lang->install_checklist_desc[$key]}
+ + +
+ + + + + + + +
{$lang->db_type} + +
+
+ +{$lang->cmd_install_fix_checklist} + diff --git a/modules/install/skins/default/filter/filter.mysql_form.xml b/modules/install/skins/default/filter/filter.mysql_form.xml new file mode 100644 index 000000000..d25c1c0ff --- /dev/null +++ b/modules/install/skins/default/filter/filter.mysql_form.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/install/skins/default/js/install.js b/modules/install/skins/default/js/install.js new file mode 100644 index 000000000..49a692fc5 --- /dev/null +++ b/modules/install/skins/default/js/install.js @@ -0,0 +1,6 @@ +function procInstall(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + alert(message); + location.href = "./"; +} diff --git a/modules/log/log.module.php b/modules/log/log.module.php new file mode 100644 index 000000000..e441cf9c4 --- /dev/null +++ b/modules/log/log.module.php @@ -0,0 +1,60 @@ + + * @desc : 기본 모듈중의 하나인 log module + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class log extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = ''; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 log, log가 지정되어야 한다 + **/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + } +?> diff --git a/modules/log/module.xml b/modules/log/module.xml new file mode 100644 index 000000000..c53da79c9 --- /dev/null +++ b/modules/log/module.xml @@ -0,0 +1,11 @@ + + + 로그 + log + + 제로 + zero + 로그 관리 모듈 + log + + diff --git a/modules/log/schemas/log.xml b/modules/log/schemas/log.xml new file mode 100644 index 000000000..41c7f0345 --- /dev/null +++ b/modules/log/schemas/log.xml @@ -0,0 +1,8 @@ + + + + + + + +
diff --git a/modules/member/admin/delete_form.html b/modules/member/admin/delete_form.html new file mode 100644 index 000000000..3b4b8779f --- /dev/null +++ b/modules/member/admin/delete_form.html @@ -0,0 +1,34 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
{$lang->confirm_delete}
{$lang->user_id}{$member_info->user_id}
{$lang->nick_name}{$member_info->nick_name}
{$lang->email_address}{$member_info->email_address}
+ + +
+ +
+ diff --git a/modules/member/admin/denied_list.html b/modules/member/admin/denied_list.html new file mode 100644 index 000000000..f4cea09ac --- /dev/null +++ b/modules/member/admin/denied_list.html @@ -0,0 +1,67 @@ + + + + + +
+ {number_format($total_count)}, + {$lang->page_count} : {number_format($page)} / {number_format($total_page)} +
+ + +
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + +
{$lang->no}{$lang->user_id}{$lang->regdate}{$lang->description}{$lang->cmd_delete}
{$no}{$val->user_id}{zdate($val->regdate,"Y-m-d")}{$lang->cmd_delete}
+
+ + +
+ [{$lang->first_page}] + + + + {$page_no} + + [{$page_no}] + + + + [{$lang->last_page}] +
+ + +
+ + + + +
+ {$lang->user_id} :
+ {$lang->description} :
+ +
+ +
diff --git a/modules/member/admin/filter/filter.delete.xml b/modules/member/admin/filter/filter.delete.xml new file mode 100644 index 000000000..512dadb63 --- /dev/null +++ b/modules/member/admin/filter/filter.delete.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/modules/member/admin/filter/filter.insert.xml b/modules/member/admin/filter/filter.insert.xml new file mode 100644 index 000000000..afcca3f9a --- /dev/null +++ b/modules/member/admin/filter/filter.insert.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/modules/member/admin/filter/filter.insert_denied_id.xml b/modules/member/admin/filter/filter.insert_denied_id.xml new file mode 100644 index 000000000..113179346 --- /dev/null +++ b/modules/member/admin/filter/filter.insert_denied_id.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/modules/member/admin/filter/filter.insert_group.xml b/modules/member/admin/filter/filter.insert_group.xml new file mode 100644 index 000000000..92c3e41e2 --- /dev/null +++ b/modules/member/admin/filter/filter.insert_group.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/modules/member/admin/filter/filter.update_denied_id.xml b/modules/member/admin/filter/filter.update_denied_id.xml new file mode 100644 index 000000000..c5c17a3b7 --- /dev/null +++ b/modules/member/admin/filter/filter.update_denied_id.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/modules/member/admin/filter/filter.update_group.xml b/modules/member/admin/filter/filter.update_group.xml new file mode 100644 index 000000000..81495886e --- /dev/null +++ b/modules/member/admin/filter/filter.update_group.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/modules/member/admin/group_list.html b/modules/member/admin/group_list.html new file mode 100644 index 000000000..8ff5541c2 --- /dev/null +++ b/modules/member/admin/group_list.html @@ -0,0 +1,64 @@ + + + + + +
+ {$lang->cmd_member_group} +
+ + +
+ + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->group_title}{$lang->regdate}{$lang->description}{$lang->is_default}{$lang->cmd_modify}{$lang->cmd_delete}
{$lang->msg_group_is_null}
{$group_info->title}{zdate($group_info->regdate,"Y-m-d H:i:s")}{nl2br($group_info->description)}{$group_info->is_default}{$lang->cmd_modify} + + {$lang->cmd_delete} + +
+
+ + +
+ + + + + +
+ {$lang->group_title} :
+ {$lang->is_default} :
+ {$lang->description} :
+ +
+ +
diff --git a/modules/member/admin/group_update_form.html b/modules/member/admin/group_update_form.html new file mode 100644 index 000000000..544a7f4f6 --- /dev/null +++ b/modules/member/admin/group_update_form.html @@ -0,0 +1,30 @@ + + + + +
+ {$lang->cmd_member_group} +
+ + + +
+ + + + + + +
+ {$lang->group_title} :
+ + {$lang->is_default} :
+ + {$lang->description} :
+ + +
+ +
+ + diff --git a/modules/member/admin/header.html b/modules/member/admin/header.html new file mode 100644 index 000000000..898b49abe --- /dev/null +++ b/modules/member/admin/header.html @@ -0,0 +1,9 @@ + + +
+ [{$lang->cmd_list}] + style="font-weight:bold">[{$lang->cmd_member_group}] + style="font-weight:bold">[{$lang->cmd_manage_form}] + style="font-weight:bold">[{$lang->cmd_send_mail}] + style="font-weight:bold">[{$lang->cmd_manage_id}] +
diff --git a/modules/member/admin/insert_member.html b/modules/member/admin/insert_member.html new file mode 100644 index 000000000..ea6df7de3 --- /dev/null +++ b/modules/member/admin/insert_member.html @@ -0,0 +1,111 @@ + + + +
+ + {$lang->msg_new_member} + + {$lang->msg_update_member} + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->user_id} + + {$member_info->user_id} + + + +
{$lang->about_user_id}
{$lang->password} + +
{$lang->user_name} + +
{$lang->about_user_name}
{$lang->nick_name} + +
{$lang->about_nick_name}
{$lang->email_address} + +
{$lang->allow_mailing}allow_mailing!='N')-->checked="true"/>
{$lang->about_allow_mailing}
{$lang->denied}denied=='Y')-->checked="true"/>
{$lang->about_denied}
{$lang->is_admin}is_admin=='Y')-->checked="true"/>
{$lang->about_is_admin}
{$lang->description}
{$lang->about_description}
{$lang->group} + + group_list[$key])-->checked="true"/> + + +
{$lang->about_group}
+ + +
+
diff --git a/modules/member/admin/js/admin.js b/modules/member/admin/js/admin.js new file mode 100644 index 000000000..fea743870 --- /dev/null +++ b/modules/member/admin/js/admin.js @@ -0,0 +1,81 @@ +/* 메세지 출력후 현페이지 리로드 */ +function procReload(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + if(message) alert(message); + + location.href = location.href; +} + +/* 사용자 추가 */ +function procInsert(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var sid = ret_obj['sid']; + var member_srl = ret_obj['member_srl']; + var act = ret_obj['act']; + var page = ret_obj['page']; + alert(message); + + url = "./admin.php?sid="+sid+"&member_srl="+member_srl+"&page="+page+"&act="+act; + location.href = url; +} + +/* 사용자 삭제 */ +function procDelete(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var sid = ret_obj['sid']; + var page = ret_obj['page']; + alert(message); + + url = "./admin.php?sid="+sid+"&page="+page; + location.href = url; +} + +/* 그룹 추가 */ +function procInsertGroup(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var sid = ret_obj['sid']; + var act = ret_obj['act']; + var page = ret_obj['page']; + alert(message); + + url = "./admin.php?sid="+sid+"&page="+page+"&act="+act; + location.href = url; +} + +/* 그룹 관련 작업들 */ +function doUpdateGroup(group_srl, mode, message) { + if(typeof(message)!='undefined'&&!confirm(message)) return; + + var fo_obj = xGetElementById('fo_group_info'); + fo_obj.group_srl.value = group_srl; + fo_obj.mode.value = mode; + procFormFilter(fo_obj, update_group, procReload); +} + + +/* 금지아이디 추가 */ +function procInsertDeniedID(ret_obj, response_tags) { + var error = ret_obj['error']; + var message = ret_obj['message']; + var sid = ret_obj['sid']; + var act = ret_obj['act']; + var page = ret_obj['page']; + alert(message); + + url = "./admin.php?sid="+sid+"&page="+page+"&act="+act; + location.href = url; +} + +/* 금지아이디 관련 작업들 */ +function doUpdateDeniedID(user_id, mode, message) { + if(typeof(message)!='undefined'&&!confirm(message)) return; + + var fo_obj = xGetElementById('fo_denied_id_info'); + fo_obj.user_id.value = user_id; + fo_obj.mode.value = mode; + procFormFilter(fo_obj, update_denied_id, procReload); +} diff --git a/modules/member/admin/list.html b/modules/member/admin/list.html new file mode 100644 index 000000000..c78feff66 --- /dev/null +++ b/modules/member/admin/list.html @@ -0,0 +1,58 @@ + + + +
+ {number_format($total_count)}, + {$lang->page_count} : {number_format($page)} / {number_format($total_page)} +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->no}{$lang->user_id}{$lang->user_name}{$lang->nick_name}{$lang->allow_mailing}{$lang->denied}{$lang->regdate}{$lang->last_login}{$lang->cmd_delete}
{$val->member_srl}{$val->user_id}{$val->user_name}{$val->nick_name}{$val->allow_mailing}{$val->denied}{zdate($val->regdate,"Y-m-d")}{zdate($val->last_login,"Y-m-d H:i:s")}{$lang->cmd_delete}
+
+ + + + + +
+ [{$lang->first_page}] + + + + {$page_no} + + [{$page_no}] + + + + [{$lang->last_page}] +
diff --git a/modules/member/admin/member_info.html b/modules/member/admin/member_info.html new file mode 100644 index 000000000..cfce3aceb --- /dev/null +++ b/modules/member/admin/member_info.html @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$lang->user_id}{$member_info->user_id}
{$lang->user_name}{$member_info->user_name}
{$lang->nick_name}{$member_info->nick_name}
{$lang->email_address}{$member_info->email_address}
{$lang->allow_mailing}{$member_info->allow_mailing}
{$lang->denied}{$member_info->denied}
{$lang->is_admin}{$member_info->is_admin}
{$lang->group} + + {$val} + +
{$lang->description}{$member_info->description}
+ +
diff --git a/modules/member/lang/ko.lang.php b/modules/member/lang/ko.lang.php new file mode 100644 index 000000000..d11a19c02 --- /dev/null +++ b/modules/member/lang/ko.lang.php @@ -0,0 +1,45 @@ + + * @desc : 한국어 언어팩 (기본적인 내용만 수록) + **/ + + $lang->cmd_member_group = "그룹 관리"; + $lang->cmd_send_mail = "메일발송"; + $lang->cmd_manage_id = "금지아이디관리"; + $lang->cmd_manage_form = "가입폼관리"; + + $lang->already_logged = "이미 로그인되어 있습니다"; + $lang->denied_user_id = "사용금지된 아이디입니다"; + $lang->null_user_id = "사용자 아이디를 입력해주세요"; + $lang->null_password = "비밀번호를 입력해주세요"; + $lang->invalid_user_id= "존재하지 않는 사용자 아이디입니다"; + $lang->invalid_password = "잘못된 비밀번호입니다"; + + $lang->allow_mailing = "메일링 가입"; + $lang->denied = "사용중지"; + $lang->is_admin = "최고관리 권한"; + $lang->group = "소속 그룹"; + $lang->group_title = "그룹제목"; + $lang->group_srl = "그룹번호"; + + $lang->msg_new_member = "회원 추가"; + $lang->msg_update_member = "회원 정보 수정"; + $lang->msg_group_is_null = "등록된 그룹이 없습니다"; + $lang->msg_not_delete_default = "기본 항목을 삭제할 수 없습니다"; + $lang->msg_not_exists_member = '존재하지 않는 사용자입니다'; + $lang->msg_cannot_delete_admin = '관리자 아이디는 삭제할 수 없습니다. 관리자 해제후 다시 삭제시도해주세요'; + $lang->msg_exists_user_id = '이미 존재하는 아이디입니다. 다른 아이디를 입력해주세요'; + $lang->msg_exists_email_address = '이미 존재하는 메일주소입니다. 다른 메일주소를 입력해주세요'; + $lang->msg_exists_nick_name = '이미 존재하는 닉네임입니다. 다른 닉네임을 입력해주세요'; + + $lang->about_user_id = "사용자 ID는 3~20자 사이의 영문+숫자로 이루어져야 하며 영문으로 시작되어야 합니다"; + $lang->about_user_name = "이름은 2~20자 이내여야 합니다"; + $lang->about_nick_name = "닉네임은 2~20자 이내여야 합니다"; + $lang->about_allow_mailing = "메일링 가입이 체크되지 않으면 단체메일 발송시 메일을 받지 않습니다"; + $lang->about_denied = "체크시 아이디를 사용할 수 없도록 합니다"; + $lang->about_is_admin = "체크시 최고 관리자 권한을 가지게 됩니다"; + $lang->about_description = "회원에 대한 관리자 메모입니다"; + $lang->about_group = "한 아이디는 여러개의 group에 속할 수 있습니다"; +?> diff --git a/modules/member/member.admin.php b/modules/member/member.admin.php new file mode 100644 index 000000000..d9bcd26be --- /dev/null +++ b/modules/member/member.admin.php @@ -0,0 +1,267 @@ + + * @desc : member의 관리자 파일 + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class member_admin extends Module { + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = 'dispContent'; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/system_install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + // 기본 정보를 읽음 + Context::loadLang($this->module_path.'lang'); + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + $oMember = getModule('member'); + + // member_srl이 있으면 미리 체크하여 member_info 세팅 + $member_srl = Context::get('member_srl'); + if($member_srl) { + $member_info = $oMember->getMemberInfoByMemberSrl($member_srl); + if(!$member_info) { + Context::set('member_srl',''); + $this->act = 'dispContent'; + } else Context::set('member_info',$member_info); + } + + // group 목록 가져오기 + $group_list = $oMember->getGroups(); + Context::set('group_list', $group_list); + + return true; + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + return true; + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 error, message가 지정되어야 한다 + **/ + + // 출력 부분 + function dispContent() {/*{{{*/ + + // 등록된 member 모듈을 불러와 세팅 + $oDB = &DB::getInstance(); + $args->sort_index = "member_srl"; + $args->page = Context::get('page'); + $args->list_count = 40; + $args->page_count = 10; + $output = $oDB->executeQuery('member.getMemberList', $args); + + // 템플릿에 쓰기 위해서 context::set + Context::set('total_count', $output->total_count); + Context::set('total_page', $output->total_page); + Context::set('page', $output->page); + Context::set('member_list', $output->data); + Context::set('page_navigation', $output->page_navigation); + + // 템플릿 파일 지정 + $this->setTemplateFile('list'); + }/*}}}*/ + + function dispInfo() {/*{{{*/ + // 템플릿 파일 지정 + $this->setTemplateFile('member_info'); + }/*}}}*/ + + function dispInsert() {/*{{{*/ + // 템플릿 파일 지정 + $this->setTemplateFile('insert_member'); + }/*}}}*/ + + function dispDeleteForm() {/*{{{*/ + if(!Context::get('member_srl')) return $this->dispContent(); + + // 템플릿 파일 지정 + $this->setTemplateFile('delete_form'); + }/*}}}*/ + + function dispGroup() {/*{{{*/ + // 그룹 목록 가져오기 + $oMember = getModule('member'); + $group_list = $oMember->getGroups(); + Context::set('group_list', $group_list); + + // 선택된 gruop_srl이 있으면 selected_group에 담기 + $group_srl = Context::get('group_srl'); + if($group_srl && $group_list[$group_srl]) { + Context::set('selected_group', $group_list[$group_srl]); + $this->setTemplateFile('group_update_form'); + } else { + $this->setTemplateFile('group_list'); + } + + }/*}}}*/ + + function dispDeniedID() {/*{{{*/ + // 사용금지 목록 가져오기 + $oMember = getModule('member'); + $output = $oMember->getDeniedIDList(); + + // 템플릿에 쓰기 위해서 context::set + Context::set('total_count', $output->total_count); + Context::set('total_page', $output->total_page); + Context::set('page', $output->page); + Context::set('member_list', $output->data); + Context::set('page_navigation', $output->page_navigation); + + // 템플릿 파일 지정 + $this->setTemplateFile('denied_list'); + }/*}}}*/ + + // 실행 부분 + function procInsert() {/*{{{*/ + // 일단 입력된 값들을 모두 받아서 db 입력항목과 그외 것으로 분리 + $args = Context::gets('member_srl','user_id','user_name','nick_name','email_address','password','allow_mailing','denied','is_admin','signature','profile_image','image_nick','image_mark','description','group_srl_list'); + + // member_srl이 있으면 원본을 구해온다 + $oMember = getModule('member'); + + // member_srl이 넘어오면 원 모듈이 있는지 확인 + if($args->member_srl) { + $member_info = $oMember->getMemberInfoByMemberSrl($args->member_srl); + // 만약 원래 모듈이 없으면 새로 입력하기 위한 처리 + if($member_info->member_srl != $args->member_srl) unset($args->member_srl); + } + + // member_srl의 값에 따라 insert/update + if(!$args->member_srl) { + $output = $oMember->insertMember($args); + $msg_code = 'success_registed'; + } else { + $output = $oMember->updateMember($args); + $msg_code = 'success_updated'; + } + + if(!$output->toBool()) return $output; + + $this->add('sid','member'); + $this->add('member_srl',$output->get('member_srl')); + $this->add('act','dispInfo'); + $this->add('page',Context::get('page')); + $this->setMessage($msg_code); + }/*}}}*/ + + function procDelete() {/*{{{*/ + // 일단 입력된 값들을 모두 받아서 db 입력항목과 그외 것으로 분리 + $member_srl = Context::get('member_srl'); + + // member_srl이 있으면 원본을 구해온다 + $oMember = getModule('member'); + $output = $oMember->deleteMember($member_srl); + if(!$output->toBool()) return $output; + + $this->add('sid','member'); + $this->add('page',Context::get('page')); + $this->setMessage("success_deleted"); + }/*}}}*/ + + function procInsertGroup() {/*{{{*/ + $args = Context::gets('title','description','is_default'); + $oMember = getModule('member'); + $output = $oMember->insertGroup($args); + if(!$output->toBool()) return $output; + + $this->add('sid','member'); + $this->add('act','dispGroup'); + $this->add('group_srl',''); + $this->add('page',Context::get('page')); + $this->setMessage('success_registed'); + }/*}}}*/ + + function procUpdateGroup() {/*{{{*/ + $group_srl = Context::get('group_srl'); + $mode = Context::get('mode'); + + $oMember = getModule('member'); + + switch($mode) { + case 'delete' : + $output = $oMember->deleteGroup($group_srl); + if(!$output->toBool()) return $output; + $msg_code = 'success_deleted'; + break; + case 'update' : + $args = Context::gets('group_srl','title','description','is_default'); + $output = $oMember->updateGroup($args); + if(!$output->toBool()) return $output; + $msg_code = 'success_updated'; + break; + } + + $this->add('sid','member'); + $this->add('act','dispGroup'); + $this->add('group_srl',''); + $this->add('page',Context::get('page')); + $this->setMessage($msg_code); + }/*}}}*/ + + function procInsertDeniedID() {/*{{{*/ + $user_id = Context::get('user_id'); + $description = Context::get('description'); + $oMember = getModule('member'); + $output = $oMember->insertDeniedID($user_id, $description); + if(!$output->toBool()) return $output; + + $this->add('sid','member'); + $this->add('act','dispDeniedID'); + $this->add('group_srl',''); + $this->add('page',Context::get('page')); + $this->setMessage('success_registed'); + }/*}}}*/ + + function procUpdateDeniedID() {/*{{{*/ + $user_id = Context::get('user_id'); + $mode = Context::get('mode'); + + $oMember = getModule('member'); + + switch($mode) { + case 'delete' : + $output = $oMember->deleteDeniedID($user_id); + if(!$output->toBool()) return $output; + $msg_code = 'success_deleted'; + break; + } + + $this->add('sid','member'); + $this->add('act','dispDeniedID'); + $this->add('page',Context::get('page')); + $this->setMessage($msg_code); + }/*}}}*/ + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + } +?> diff --git a/modules/member/member.module.php b/modules/member/member.module.php new file mode 100644 index 000000000..54761b5d1 --- /dev/null +++ b/modules/member/member.module.php @@ -0,0 +1,477 @@ + + * @desc : 기본 모듈중의 하나인 member module + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class member extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = ''; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/member/"; + **/ + + // 초기화 + function init() {/*{{{*/ + Context::loadLang($this->module_path.'lang'); + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + return true; + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + return true; + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 error, message가 지정되어야 한다 + * + * 변수의 사용은 Context::get('이름')으로 얻어오면 된다 + **/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + + // 로그인/로그아웃 처리 + // public void doLogin($user_id, $password) /*{{{*/ + // user_id, password를 체크하여 로그인 시킴 + function doLogin($user_id, $password) { + // 변수 정리 + $user_id = trim($user_id); + $password = trim($password); + + // 이메일 주소나 비밀번호가 없을때 오류 return + if(!$user_id) return new Output(-1,Context::getLang('null_user_id')); + if(!$password) return new Output(-1,Context::getLang('null_password')); + + $oDB = &DB::getInstance(); + + // user_id 에 따른 정보 가져옴 + $args->user_id = $user_id; + $member_info = $this->getMemberInfo($user_id, false); + + // return 값이 없거나 비밀번호가 틀릴 경우 + if($member_info->user_id != $user_id) return new Output(-1, Context::getLang('invalid_user_id')); + if($member_info->password != md5($password)) return new Output(-1, Context::getLang('invalid_password')); + + // 로그인 처리 + $_SESSION['is_logged'] = true; + $_SESSION['ipaddress'] = $_SERVER['REMOTE_ADDR']; + + unset($member_info->password); + + // 세션에 로그인 사용자 정보 저장 + $_SESSION['member_srl'] = $member_info->member_srl; + $_SESSION['logged_info'] = $member_info; + + // 사용자 정보의 최근 로그인 시간을 기록 + $args->member_srl = $member_info->member_srl; + $oDB->executeQuery('member.updateLastLogin', $args); + + return new Output(); + }/*}}}*/ + + // public void doLogout() /*{{{*/ + // 로그아웃 + function doLogout() { + // 로그인 처리 + $_SESSION['is_logged'] = false; + $_SESSION['ipaddress'] = $_SERVER['REMOTE_ADDR']; + $_SESSION['logged_info'] = NULL; + return new Output(); + }/*}}}*/ + + // member 정보 입출력 관련 + // public void insertAdmin($args)/*{{{*/ + // 관리자를 추가한다 + function insertAdmin($args) { + $args->is_admin = 'Y'; + return $this->insertMember($args); + }/*}}}*/ + + // public void insertMember($args)/*{{{*/ + // member 테이블에 사용자 추가 + function insertMember($args) { + // 필수 변수들의 조절 + if($args->allow_mailing!='Y') $args->allow_mailing = 'N'; + if($args->denied!='Y') $args->denied = 'N'; + if($args->is_admin!='Y') $args->is_admin = 'N'; + list($args->email_id, $args->email_host) = explode('@', $args->email_address); + + // 금지 아이디인지 체크 + if($this->chkDeniedID($args->user_id)) return new Output(-1,'denied_user_id'); + + // 아이디, 닉네임, email address 의 중복 체크 + $member_srl = $this->getMemberSrlByUserID($args->user_id); + if($member_srl) return new Output(-1,'msg_exists_user_id'); + + $member_srl = $this->getMemberSrlByNickName($args->nick_name); + if($member_srl) return new Output(-1,'msg_exists_nick_name'); + + $member_srl = $this->getMemberSrlByEmailAddress($args->email_address); + if($member_srl) return new Output(-1,'msg_exists_email_address'); + + // DB 입력 + $oDB = &DB::getInstance(); + $args->member_srl = $oDB->getNextSequence(); + if($args->password) $args->password = md5($args->password); + else unset($args->password); + $output = $oDB->executeQuery('member.insertMember', $args); + if(!$output->toBool()) return $output; + + // 기본 그룹을 입력 + $default_group = $this->getDefaultGroup(); + + // 기본 그룹에 추가 + $output = $this->addMemberToGroup($args->member_srl,$default_group->group_srl); + if(!$output->toBool()) return $output; + + $output->add('member_srl', $args->member_srl); + return $output; + }/*}}}*/ + + // public void updateMember($args)/*{{{*/ + // member 정보 수정 + function updateMember($args) { + $member_info = $this->getMemberInfoByMemberSrl($args->member_srl); + + // 필수 변수들의 조절 + if($args->allow_mailing!='Y') $args->is_default = 'N'; + if($args->denied!='Y') $args->denied = 'N'; + if($args->is_admin!='Y') $args->use_category = 'N'; + list($args->email_id, $args->email_host) = explode('@', $args->email_address); + + // 아이디, 닉네임, email address 의 중복 체크 + $member_srl = $this->getMemberSrlByUserID($args->user_id); + if($member_srl&&$args->member_srl!=$member_srl) return new Output(-1,'msg_exists_user_id'); + $member_srl = $this->getMemberSrlByNickName($args->nick_name); + if($member_srl&&$args->member_srl!=$member_srl) return new Output(-1,'msg_exists_nick_name'); + $member_srl = $this->getMemberSrlByEmailAddress($args->email_address); + if($member_srl&&$args->member_srl!=$member_srl) return new Output(-1,'msg_exists_email_address'); + + // DB 입력 + $oDB = &DB::getInstance(); + if($args->password) $args->password = md5($args->password); + else $args->password = $member_info->password; + + $output = $oDB->executeQuery('member.updateMember', $args); + if(!$output->toBool()) return $output; + + // 그룹에 추가 + $output = $oDB->executeQuery('member.deleteMemberGroupMember', $args); + if(!$output->toBool()) return $output; + + $group_srl_list = explode(',', $args->group_srl_list); + for($i=0;$iaddMemberToGroup($args->member_srl,$group_srl_list[$i]); + if(!$output->toBool()) return $output; + } + + $output->add('member_srl', $args->member_srl); + return $output; + }/*}}}*/ + + // public void deleteMember($member_srl)/*{{{*/ + // 사용자 삭제 + function deleteMember($member_srl) { + + $oDB = &DB::getInstance(); + + // 해당 사용자의 정보를 가져옴 + $member_info = $this->getMemberInfoByMemberSrl($member_srl); + if(!$member_info) return new Output(-1, 'msg_not_exists_member'); + + // 관리자의 경우 삭제 불가능 + if($member_info->is_admin == 'Y') return new Output(-1, 'msg_cannot_delete_admin'); + + // member_group_member에서 해당 항목들 삭제 + $args->member_srl = $member_srl; + $output = $oDB->executeQuery('member.deleteMemberGroupMember', $args); + if(!$output->toBool()) return $output; + + // member 테이블에서 삭제 + $output = $oDB->executeQuery('member.deleteMember', $args); + return $output; + }/*}}}*/ + + // public boolean isLogged() {/*{{{*/ + // 로그인 되어 있는지에 대한 체크 + function isLogged() { + if($_SESSION['is_logged']&&$_SESSION['ipaddress']==$_SERVER['REMOTE_ADDR']) return true; + + $_SESSION['is_logged'] = false; + $_SESSION['logged_info'] = ''; + return false; + }/*}}}*/ + + // public object getLoggedInfo()/*{{{*/ + // user_id에 해당하는 사용자 정보 return + function getLoggedInfo() { + // 로그인 되어 있고 세션 정보를 요청하면 세션 정보를 return + if($this->isLogged()) return $_SESSION['logged_info']; + }/*}}}*/ + + // public object getMemberInfo($user_id)/*{{{*/ + // user_id에 해당하는 사용자 정보 return + function getMemberInfo($user_id) { + // DB에서 가져오기 + $oDB = &DB::getInstance(); + $args->user_id = $user_id; + $output = $oDB->executeQuery('member.getMemberInfo', $args); + if(!$output) return $output; + + $member_info = $output->data; + $member_info->group_list = $this->getMemberGroups($member_info->member_srl); + + return $member_info; + }/*}}}*/ + + // public object getMemberInfoByMemberSrl($member_srl)/*{{{*/ + // user_id에 해당하는 사용자 정보 return + function getMemberInfoByMemberSrl($member_srl) { + // DB에서 가져오기 + $oDB = &DB::getInstance(); + $args->member_srl = $member_srl; + $output = $oDB->executeQuery('member.getMemberInfoByMemberSrl', $args); + if(!$output) return $output; + + $member_info = $output->data; + $member_info->group_list = $this->getMemberGroups($member_info->member_srl); + + return $member_info; + }/*}}}*/ + + // public int getMemberSrl() /*{{{*/ + // 현재 접속자의 member_srl을 return + function getMemberSrl() { + if(!$this->isLogged()) return; + return $_SESSION['member_srl']; + }/*}}}*/ + + // group 관련 + // public object addMemberToGroup($member_srl, $group_srl) /*{{{*/ + // member_srl에 gruop_srl을 추가 + function addMemberToGroup($member_srl,$group_srl) { + $args->member_srl = $member_srl; + $args->group_srl = $group_srl; + + $oDB = &DB::getInstance(); + + // 추가 + $output = $oDB->executeQuery('member.addMemberToGroup',$args); + if(!$output->toBool()) return $output; + + return $output; + }/*}}}*/ + + // public void changeGroup($source_group_srl, $target_group_srl)/*{{{*/ + // 회원의 그룹값을 변경 + function changeGroup($source_group_srl, $target_group_srl) { + $oDB = &DB::getInstance(); + $args->source_group_srl = $source_group_srl; + $args->target_group_srl = $target_group_srl; + return $oDB->executeQuery('member.changeGroup', $args); + }/*}}}*/ + + // public object getMemberGroups($member_srl) /*{{{*/ + // member_srl이 속한 group 목록을 가져옴 + function getMemberGroups($member_srl) { + $oDB = &DB::getInstance(); + $args->member_srl = $member_srl; + $output = $oDB->executeQuery('member.getMemberGroups', $args); + if(!$output->data) return; + + $group_list = $output->data; + if(!is_array($group_list)) $group_list = array($group_list); + foreach($group_list as $group) { + $result[$group->group_srl] = $group->title; + } + return $result; + }/*}}}*/ + + // public object getDefaultGroup() /*{{{*/ + // 기본 그룹을 가져옴 + function getDefaultGroup() { + $oDB = &DB::getInstance(); + $output = $oDB->executeQuery('member.getDefaultGroup'); + return $output->data; + }/*}}}*/ + + // public object getGroup($group_srl) /*{{{*/ + // group_srl에 해당하는 그룹 정보 가져옴 + function getGroup($group_srl) { + $oDB = &DB::getInstance(); + $args->group_srl = $group_srl; + $output = $oDB->executeQuery('member.getGroup', $args); + return $output->data; + }/*}}}*/ + + // public object getGroups() /*{{{*/ + // 그룹 목록을 가져옴 + function getGroups() { + $oDB = &DB::getInstance(); + $output = $oDB->executeQuery('member.getGroups'); + if(!$output->data) return; + + $group_list = $output->data; + if(!is_array($group_list)) $group_list = array($group_list); + foreach($group_list as $val) { + $result[$val->group_srl] = $val; + } + return $result; + }/*}}}*/ + + // public object insertGroup() /*{{{*/ + // 그룹 등록 + function insertGroup($args) { + $oDB = &DB::getInstance(); + + // is_default값을 체크, Y일 경우 일단 모든 is_default에 대해서 N 처리 + if($args->is_default!='Y') $args->is_default = 'N'; + else $oDB->executeQuery('member.updateGroupDefaultClear'); + + $output = $oDB->executeQuery('member.insertGroup', $args); + return $output; + }/*}}}*/ + + // public object updateGroup() /*{{{*/ + // 그룹 등록 + function updateGroup($args) { + $oDB = &DB::getInstance(); + // is_default값을 체크, Y일 경우 일단 모든 is_default에 대해서 N 처리 + if($args->is_default!='Y') $args->is_default = 'N'; + else { + $oDB->executeQuery('member.updateGroupDefaultClear'); + } + + $output = $oDB->executeQuery('member.updateGroup', $args); + return $output; + }/*}}}*/ + + // public object deleteGroup($group_srl) /*{{{*/ + // 그룹 등록 + function deleteGroup($group_srl) { + // 삭제 대상 그룹을 가져와서 체크 (is_default == 'Y'일 경우 삭제 불가) + $group_info = $this->getGroup($group_srl); + if(!$group_info) return new Output(-1, 'lang->msg_not_founded'); + if($group_info->is_default == 'Y') return new Output(-1, 'msg_not_delete_default'); + + // is_default == 'Y'인 그룹을 가져옴 + $default_group = $this->getDefaultGroup(); + $default_group_srl = $default_group->group_srl; + + // default_group_srl로 변경 + $this->changeGroup($group_srl, $default_group_srl); + + // 그룹 삭제 + $oDB = &DB::getInstance(); + $args->group_srl = $group_srl; + $output = $oDB->executeQuery('member.deleteGroup', $args); + return $output; + }/*}}}*/ + + // 금지 아이디 + // public object getDeniedIDList() /*{{{*/ + // 금지 아이디 목록 가져오기 + function getDeniedIDList() { + $oDB = &DB::getInstance(); + $args->sort_index = "list_order"; + $args->page = Context::get('page'); + $args->list_count = 40; + $args->page_count = 10; + $output = $oDB->executeQuery('member.getDeniedIDList', $args); + return $output; + }/*}}}*/ + + // public object insertDeniedID() /*{{{*/ + // 금지아이디 등록 + function insertDeniedID($user_id, $desription = '') { + $oDB = &DB::getInstance(); + + $args->user_id = $user_id; + $args->description = $description; + $args->list_order = -1*$oDB->getNextSequence(); + + return $oDB->executeQuery('member.insertDeniedID', $args); + }/*}}}*/ + + // public object deleteDeniedID() /*{{{*/ + // 금지아이디 등록 + function deleteDeniedID($user_id) { + $oDB = &DB::getInstance(); + + $args->user_id = $user_id; + return $oDB->executeQuery('member.deleteDeniedID', $args); + }/*}}}*/ + + // public object chkDeniedID($user_id) /*{{{*/ + // 금지아이디 등록 + function chkDeniedID($user_id) { + $oDB = &DB::getInstance(); + + $args->user_id = $user_id; + + $output = $oDB->executeQuery('member.chkDeniedID', $args); + if($output->data->count) return true; + return false; + }/*}}}*/ + + // 기타 + // public boolean getMemberSrlByUserID($user_id) {/*{{{*/ + // userid에 해당하는 member_srl을 구함 + function getMemberSrlByUserID($user_id) { + $oDB = &DB::getInstance(); + $args->user_id = $user_id; + $output = $oDB->executeQuery('member.getMemberSrl', $args); + return $output->data->member_srl; + }/*}}}*/ + + // public boolean getMemberSrlByEmailAddress($email_address) {/*{{{*/ + // userid에 해당하는 member_srl을 구함 + function getMemberSrlByEmailAddress($email_address) { + $oDB = &DB::getInstance(); + $args->email_address = $email_address; + $output = $oDB->executeQuery('member.getMemberSrl', $args); + return $output->data->member_srl; + }/*}}}*/ + + // public boolean getMemberSrlByNickName($nick_name) {/*{{{*/ + // userid에 해당하는 member_srl을 구함 + function getMemberSrlByNickName($nick_name) { + $oDB = &DB::getInstance(); + $args->nick_name = $nick_name; + $output = $oDB->executeQuery('member.getMemberSrl', $args); + return $output->data->member_srl; + }/*}}}*/ + } +?> diff --git a/modules/member/module.xml b/modules/member/module.xml new file mode 100644 index 000000000..97767fae8 --- /dev/null +++ b/modules/member/module.xml @@ -0,0 +1,11 @@ + + + 회원 관리 + member + + 제로 + zero + 회원 관리 모듈 + member + + diff --git a/modules/member/queries/addMemberToGroup.xml b/modules/member/queries/addMemberToGroup.xml new file mode 100644 index 000000000..275893565 --- /dev/null +++ b/modules/member/queries/addMemberToGroup.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/modules/member/queries/changeGroup.xml b/modules/member/queries/changeGroup.xml new file mode 100644 index 000000000..c45084d34 --- /dev/null +++ b/modules/member/queries/changeGroup.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/member/queries/chkDeniedID.xml b/modules/member/queries/chkDeniedID.xml new file mode 100644 index 000000000..5258c11f0 --- /dev/null +++ b/modules/member/queries/chkDeniedID.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/member/queries/deleteDeniedID.xml b/modules/member/queries/deleteDeniedID.xml new file mode 100644 index 000000000..6f9698adb --- /dev/null +++ b/modules/member/queries/deleteDeniedID.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/member/queries/deleteGroup.xml b/modules/member/queries/deleteGroup.xml new file mode 100644 index 000000000..5ae5991a7 --- /dev/null +++ b/modules/member/queries/deleteGroup.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/member/queries/deleteMember.xml b/modules/member/queries/deleteMember.xml new file mode 100644 index 000000000..e8dd2d4a3 --- /dev/null +++ b/modules/member/queries/deleteMember.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/member/queries/deleteMemberGroupMember.xml b/modules/member/queries/deleteMemberGroupMember.xml new file mode 100644 index 000000000..d3415451a --- /dev/null +++ b/modules/member/queries/deleteMemberGroupMember.xml @@ -0,0 +1,9 @@ + + +
+ + + + + + diff --git a/modules/member/queries/getDefaultGroup.xml b/modules/member/queries/getDefaultGroup.xml new file mode 100644 index 000000000..a8db3549b --- /dev/null +++ b/modules/member/queries/getDefaultGroup.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/member/queries/getDeniedIDList.xml b/modules/member/queries/getDeniedIDList.xml new file mode 100644 index 000000000..7ced9bc13 --- /dev/null +++ b/modules/member/queries/getDeniedIDList.xml @@ -0,0 +1,14 @@ + + +
+ + + + + + + + + + + diff --git a/modules/member/queries/getGroup.xml b/modules/member/queries/getGroup.xml new file mode 100644 index 000000000..d782f933f --- /dev/null +++ b/modules/member/queries/getGroup.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/member/queries/getGroups.xml b/modules/member/queries/getGroups.xml new file mode 100644 index 000000000..806806252 --- /dev/null +++ b/modules/member/queries/getGroups.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/member/queries/getMemberGroups.xml b/modules/member/queries/getMemberGroups.xml new file mode 100644 index 000000000..e9336ae6f --- /dev/null +++ b/modules/member/queries/getMemberGroups.xml @@ -0,0 +1,14 @@ + + +
+
+ + + + + + + + + + diff --git a/modules/member/queries/getMemberInfo.xml b/modules/member/queries/getMemberInfo.xml new file mode 100644 index 000000000..36a5e0b97 --- /dev/null +++ b/modules/member/queries/getMemberInfo.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/member/queries/getMemberInfoByMemberSrl.xml b/modules/member/queries/getMemberInfoByMemberSrl.xml new file mode 100644 index 000000000..bc777ece3 --- /dev/null +++ b/modules/member/queries/getMemberInfoByMemberSrl.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/member/queries/getMemberList.xml b/modules/member/queries/getMemberList.xml new file mode 100644 index 000000000..a0d080ab4 --- /dev/null +++ b/modules/member/queries/getMemberList.xml @@ -0,0 +1,14 @@ + + +
+ + + + + + + + + + + diff --git a/modules/member/queries/getMemberSrl.xml b/modules/member/queries/getMemberSrl.xml new file mode 100644 index 000000000..93f413939 --- /dev/null +++ b/modules/member/queries/getMemberSrl.xml @@ -0,0 +1,13 @@ + + +
+ + + + + + + + + + diff --git a/modules/member/queries/insertDeniedID.xml b/modules/member/queries/insertDeniedID.xml new file mode 100644 index 000000000..d428887cf --- /dev/null +++ b/modules/member/queries/insertDeniedID.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/member/queries/insertGroup.xml b/modules/member/queries/insertGroup.xml new file mode 100644 index 000000000..0096f724b --- /dev/null +++ b/modules/member/queries/insertGroup.xml @@ -0,0 +1,12 @@ + + +
+ + + + + + + + + diff --git a/modules/member/queries/insertMember.xml b/modules/member/queries/insertMember.xml new file mode 100644 index 000000000..bacc7366d --- /dev/null +++ b/modules/member/queries/insertMember.xml @@ -0,0 +1,26 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/member/queries/updateGroup.xml b/modules/member/queries/updateGroup.xml new file mode 100644 index 000000000..546ca4edd --- /dev/null +++ b/modules/member/queries/updateGroup.xml @@ -0,0 +1,13 @@ + + +
+ + + + + + + + + + diff --git a/modules/member/queries/updateGroupDefaultClear.xml b/modules/member/queries/updateGroupDefaultClear.xml new file mode 100644 index 000000000..1c4726ab2 --- /dev/null +++ b/modules/member/queries/updateGroupDefaultClear.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/member/queries/updateLastLogin.xml b/modules/member/queries/updateLastLogin.xml new file mode 100644 index 000000000..186e026c8 --- /dev/null +++ b/modules/member/queries/updateLastLogin.xml @@ -0,0 +1,12 @@ + + +
+ + + + + + + + + diff --git a/modules/member/queries/updateMember.xml b/modules/member/queries/updateMember.xml new file mode 100644 index 000000000..1dedebeef --- /dev/null +++ b/modules/member/queries/updateMember.xml @@ -0,0 +1,24 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/modules/member/schemas/member.xml b/modules/member/schemas/member.xml new file mode 100644 index 000000000..169f8e21f --- /dev/null +++ b/modules/member/schemas/member.xml @@ -0,0 +1,23 @@ +
+ + + + + + + + + + + + + + + + + + + + + +
diff --git a/modules/member/schemas/member_denied_user_id.xml b/modules/member/schemas/member_denied_user_id.xml new file mode 100644 index 000000000..8924879e8 --- /dev/null +++ b/modules/member/schemas/member_denied_user_id.xml @@ -0,0 +1,6 @@ + + + + + +
diff --git a/modules/member/schemas/member_group.xml b/modules/member/schemas/member_group.xml new file mode 100644 index 000000000..3abce647f --- /dev/null +++ b/modules/member/schemas/member_group.xml @@ -0,0 +1,7 @@ + + + + + + +
diff --git a/modules/member/schemas/member_group_member.xml b/modules/member/schemas/member_group_member.xml new file mode 100644 index 000000000..69324707a --- /dev/null +++ b/modules/member/schemas/member_group_member.xml @@ -0,0 +1,5 @@ + + + + +
diff --git a/modules/message/message.module.php b/modules/message/message.module.php new file mode 100644 index 000000000..d8029868a --- /dev/null +++ b/modules/message/message.module.php @@ -0,0 +1,66 @@ + + * @desc : 기본 모듈중의 하나인 message module + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class message extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = 'dispSystemMessage'; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + Context::addCssFile($this->template_path.'css/message.css'); + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 message, message가 지정되어야 한다 + **/ + // function void dispSystemMessage()/*{{{*/ + // 메세지 출력 Context의 erro/ message를 출력 + function dispSystemMessage() { + $this->setTemplateFile('system_message'); + }/*}}}*/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + } +?> diff --git a/modules/message/module.xml b/modules/message/module.xml new file mode 100644 index 000000000..27d544ce4 --- /dev/null +++ b/modules/message/module.xml @@ -0,0 +1,11 @@ + + + 메세지 + message + + 제로 + zero + 메세지 관리 모듈 + message + + diff --git a/modules/message/skins/default/css/message.css b/modules/message/skins/default/css/message.css new file mode 100644 index 000000000..e69de29bb diff --git a/modules/message/skins/default/system_message.html b/modules/message/skins/default/system_message.html new file mode 100644 index 000000000..77ad1866e --- /dev/null +++ b/modules/message/skins/default/system_message.html @@ -0,0 +1,11 @@ + + + + + + + + + + +
error{$error}
message{$message}
diff --git a/modules/module_manager/admin/index.html b/modules/module_manager/admin/index.html new file mode 100644 index 000000000..ca3cd2939 --- /dev/null +++ b/modules/module_manager/admin/index.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + +
{$lang->no}{$lang->module_name}{$lang->module_version}{$lang->module_table_count}{$lang->module_installed_path}{$lang->author}
{$no+1}{$module_obj->title}{$module_obj->version}{$module_obj->created_table_count} / {$module_obj->table_count}{$module_obj->path}{$module_obj->author->name}
+ diff --git a/modules/module_manager/lang/ko.lang.php b/modules/module_manager/lang/ko.lang.php new file mode 100644 index 000000000..ef59ce7a3 --- /dev/null +++ b/modules/module_manager/lang/ko.lang.php @@ -0,0 +1,12 @@ + + * @desc : 한국어 언어팩 + **/ + $lang->module_name = "모듈 이름"; + $lang->module_table_count = "테이블수"; + $lang->module_date = "제작일"; + $lang->module_installed_path = "설치경로"; + $lang->module_version = "버전"; +?> diff --git a/modules/module_manager/module.xml b/modules/module_manager/module.xml new file mode 100644 index 000000000..7fee6be0b --- /dev/null +++ b/modules/module_manager/module.xml @@ -0,0 +1,11 @@ + + + 모듈 관리 + module management + + 제로 + zero + 모듈 관리 모듈 + module management + + diff --git a/modules/module_manager/module_manager.admin.php b/modules/module_manager/module_manager.admin.php new file mode 100644 index 000000000..c90a0662c --- /dev/null +++ b/modules/module_manager/module_manager.admin.php @@ -0,0 +1,119 @@ + + * @desc : module_manager의 관리자 파일 + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class module_manager_admin extends Module { + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = 'dispContent'; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/system_install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + + // 기본 정보를 읽음 + Context::loadLang($this->module_path.'lang'); + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + return true; + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + return true; + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 error, message가 지정되어야 한다 + **/ + + // 출력 부분 + function dispContent() {/*{{{*/ + // 등록된 모듈의 목록을 구해옴 + $installed_module_list = $this->getModulesInfo(); + Context::set('installed_module_list', $installed_module_list); + + // 템플릿 파일 지정 + $this->setTemplateFile('index'); + }/*}}}*/ + + // 실행 부분 + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + function getModulesInfo() {/*{{{*/ + // DB 객체 생성 + $oDB = &DB::getInstance(); + + // 다운받은 모듈과 설치된 모듈의 목록을 구함 + $downloaded_list = FileHandler::readDir('./files/modules'); + $installed_list = FileHandler::readDir('./modules'); + + // 찾아진 모듈목록에서 admin은 제외시킴 + $searched_list = array_merge($downloaded_list, $installed_list); + if(!count($searched_list)) return; + + for($i=0;$iisTableExists($table_name)) $created_table_count ++; + } + + // 해당 모듈의 정보를 구함 + $info = module_manager::loadModuleXml($path); + unset($obj); + + $info->module = $module_name; + $info->created_table_count = $created_table_count; + $info->table_count = $table_count; + $info->path = $path; + + $list[] = $info; + } + return $list; + }/*}}}*/ + } + +?> diff --git a/modules/module_manager/module_manager.module.php b/modules/module_manager/module_manager.module.php new file mode 100644 index 000000000..da5ba16a5 --- /dev/null +++ b/modules/module_manager/module_manager.module.php @@ -0,0 +1,455 @@ + + * @desc : 기본 모듈중의 하나 + * Module class에서 상속을 받아서 사용 + * 모듈과 관련된 method들이 존재 + **/ + + class module_manager extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = ''; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/module/"; + **/ + + // 초기화 + function init() {/*{{{*/ + Context::loadLang($this->module_path.'lang'); + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + return true; + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + return true; + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 error, message가 지정되어야 한다 + * + * 변수의 사용은 Context::get('이름')으로 얻어오면 된다 + **/ + + /** + * 여기서부터는 관련 lib... + **/ + // public string getModuleInfoByDocument($document_srl)/*{{{*/ + // $document_srl로 모듈정보를 구함 + function getModuleInfoByDocument($document_srl) { + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('module_manager.getModuleInfoByDocument', $args); + // extra_vars의 정리 + $module_info = module_manager::extractExtraVar($output->data); + return $module_info; + }/*}}}*/ + + // public object getModuleInfo($mid='')/*{{{*/ + // $mid의 정보를 load, mid값이 없다면 기본 mid 정보를 읽음 + function getModuleInfo($mid='') { + // DB에서 가져옴 + $oDB = &DB::getInstance(); + if($mid) { + $args->mid = $mid; + $output = $oDB->executeQuery('module_manager.getMidInfo', $args); + } + if(!$output->data) $output = $oDB->executeQuery('module_manager.getDefaultMidInfo'); + return module_manager::arrangeModuleInfo($output->data); + }/*}}}*/ + + // public object getModuleInfoByModuleSrl($module_srl='')/*{{{*/ + // $modulr_srl로 모듈의 정보를 읽음 + function getModuleInfoByModuleSrl($module_srl='') { + $oDB = &DB::getInstance(); + $args->module_srl = $module_srl; + $output = $oDB->executeQuery('module_manager.getMidInfo', $args); + if(!$output->data) return; + return module_manager::arrangeModuleInfo($output->data); + } + + // public object arrangeModuleInfo($source_module_info) + // grant, extraVar등의 정리 + function arrangeModuleInfo($source_module_info) { + if(!$source_module_info) return; + + // serialize되어 있는 변수들 추출 + $extra_vars = $source_module_info->extra_vars; + $grant = $source_module_info->grant; + //$admin_id = $source_module_info->admin_id; + + unset($source_module_info->extra_vars); + unset($source_module_info->grant); + //unset($source_module_info->admin_id); + + $module_info = clone($source_module_info); + + // extra_vars의 정리 + if($extra_vars) { + $extra_vars = unserialize($extra_vars); + foreach($extra_vars as $key => $val) if(!$module_info->{$key}) $module_info->{$key} = $val; + } + + // 권한의 정리 + if($grant) $module_info->grant = unserialize($grant); + + return $module_info; + }/*}}}*/ + + // public object getModuleObject($module)/*{{{*/ + // module을 찾아서 instance를 생성하여 return + function getModuleObject($module) { + // 요청받은 모듈이 있는지 확인 + $module = strtolower($module); + + // global 변수에 저장한 객체가 있으면 그걸 return + if($GLOBALS['_loaded_module'][$module]) return $GLOBALS['_loaded_module'][$module]; + + $class_path = sprintf('./modules/%s/', $module); + if(!is_dir($class_path)) $class_path = sprintf('./classs/modules/%s/', $module); + if(!is_dir($class_path)) return NULL; + + $class_file = $class_path.$module.'.module.php'; + if(!file_exists($class_file)) return NULL; + + // 새로 객체 생성 + require_once($class_file); + $eval_str = sprintf('$oModule = new %s();', $module); + eval($eval_str); + $oModule->setModulePath($class_path); + $oModule->init(); + + // 언어파일 읽기 + Context::loadLang($class_path.'lang'); + + $GLOBALS['_loaded_module'][$module] = $oModule; + + // 객체 리턴 + return $oModule; + }/*}}}*/ + + // public object getAdminModuleObject($module)/*{{{*/ + // module의 관리자를 찾아서 instance를 생성하여 return + function getAdminModuleObject($module) { + // 요청받은 모듈이 있는지 확인 + $module = strtolower($module); + + // global 변수에 저장한 객체가 있으면 그걸 return + if($GLOBALS['_loaded_admin_module'][$module]) return $GLOBALS['_loaded_admin_module'][$module]; + + $class_path = sprintf('./modules/%s/', $module); + if(!is_dir($class_path)) $class_path = sprintf('./classs/modules/%s/', $module); + if(!is_dir($class_path)) return NULL; + + $class_file = $class_path.$module.'.admin.php'; + if(!file_exists($class_file)) return NULL; + + // 새로 객체 생성 + require_once($class_file); + $eval_str = sprintf('$oModule = new %s_admin();', $module); + eval($eval_str); + $oModule->setModulePath($class_path); + $oModule->init(); + + $template_path = sprintf("%sadmin/", $class_path); + $oModule->setTemplatePath($template_path); + + // 언어파일 읽기 + Context::loadLang($class_path.'lang'); + + // global 변수에 객체 저장 + $GLOBALS['_loaded_admin_module'][$module] = $oModule; + + return $oModule; + }/*}}}*/ + + // public object makeDefaultModule() /*{{{*/ + // 설치시 기본 모듈을 생성 + function makeDefaultModule() { + $oDB = &DB::getInstance(); + + // 설치된 기본 모듈이 있는지 확인 + $output = $oDB->executeQuery('module_manager.getDefaultMidInfo'); + if($output->data) return; + + // 기본 모듈 입력 + $args->mid = 'board'; + $args->browser_title = '테스트 모듈'; + $args->is_default = 'Y'; + $args->module = 'board'; + $args->skin = 'default'; + + $extra_vars->colorset = 'normal'; + $args->extra_vars = serialize($extra_vars); + + return $this->insertModule($args); + }/*}}}*/ + + // public object insertModule($args)/*{{{*/ + // 모듈 입력 + function insertModule($args) { + // 등록하려는 모듈의 path를 구함 + $oModule = getModule($args->module); + + // 선택된 스킨정보에서 colorset을 구함 + $skin_info = $this->loadSkinInfo($oModule->module_path, $args->skin); + $extra_vars->colorset = $skin_info->colorset[0]->name; + + // db에 입력 + $oDB = &DB::getInstance(); + $args->module_srl = $oDB->getNextSequence(); + $args->extra_vars = serialize($extra_vars); + $output = $oDB->executeQuery('module_manager.insertModule', $args); + $output->add('module_srl',$args->module_srl); + return $output; + }/*}}}*/ + + // public object updateModule($args)/*{{{*/ + // 모듈 입력 + function updateModule($args) { + $oDB = &DB::getInstance(); + $output = $oDB->executeQuery('module_manager.updateModule', $args); + $output->add('module_srl',$args->module_srl); + return $output; + }/*}}}*/ + + // public object updateModuleExtraVars($args)/*{{{*/ + // 모듈 입력 + function updateModuleExtraVars($module_srl, $extra_vars) { + $oDB = &DB::getInstance(); + $args->module_srl = $module_srl; + $args->extra_vars = $extra_vars; + $output = $oDB->executeQuery('module_manager.updateModuleExtraVars', $args); + return $output; + }/*}}}*/ + + // public object updateModuleGrant($module_srl, $grant)/*{{{*/ + // 모듈 입력 + function updateModuleGrant($module_srl, $grant) { + $oDB = &DB::getInstance(); + $args->module_srl = $module_srl; + $args->grant = $grant; + $output = $oDB->executeQuery('module_manager.updateModuleGrant', $args); + return $output; + }/*}}}*/ + + // public object deleteModule($module_srl)/*{{{*/ + // 모듈 입력 + function deleteModule($module_srl) { + $oDB = &DB::getInstance(); + $oDocument = getModule('document'); + + // addon 삭제 + // plugin 삭제 + + // document 삭제 + $output = $oDocument->deleteModuleDocument($module_srl); + if(!$output->toBool()) return $output; + + // category 삭제 + $output = $oDocument->deleteModuleCategory($module_srl); + if(!$output->toBool()) return $output; + + // trackbacks 삭제 + $oTrackback = getModule('trackback'); + $output = $oTrackback->deleteModuleTrackbacks($module_srl); + if(!$output->toBool()) return $output; + + // comments 삭제 + $oComment = getModule('comment'); + $output = $oComment->deleteModuleComments($module_srl); + if(!$output->toBool()) return $output; + + // tags 삭제 + $oTag = getModule('tag'); + $output = $oTag->deleteModuleTags($module_srl); + if(!$output->toBool()) return $output; + + // files 삭제 + $output = $oDocument->deleteModuleFiles($module_srl); + if(!$output->toBool()) return $output; + + // module 정보 삭제 + $args->module_srl = $module_srl; + $output = $oDB->executeQuery('module_manager.deleteModule', $args); + + return $output; + }/*}}}*/ + + // public object clearDefaultModule() /*{{{*/ + // 모든 모듈의 is_default='N'로 세팅 + function clearDefaultModule() { + $oDB = &DB::getInstance(); + return $oDB->executeQuery('module_manager.clearDefaultModule'); + }/*}}}*/ + + // public object getAdminModuleList() /*{{{*/ + // 관리자 모듈 목록을 가져옴 + function getAdminModuleList() { + // 다운받은 모듈과 설치된 모듈의 목록을 구함 + $downloaded_list = FileHandler::readDir('./files/modules'); + $installed_list = FileHandler::readDir('./modules'); + + // 찾아진 모듈목록에서 admin은 제외시킴 + $searched_list = array_merge($downloaded_list, $installed_list); + if(!count($searched_list)) return; + + for($i=0;$ititle; + } + if($list) asort($list); + return $list; + }/*}}}*/ + + function loadModuleXml($module_path) {/*{{{*/ + // 현재 선택된 모듈의 스킨의 정보 xml 파일을 읽음 + $xml_file = sprintf("%s/module.xml", $module_path); + if(!file_exists($xml_file)) return; + $oXmlParser = new XmlParser(); + $xml_obj = $oXmlParser->loadXmlFile($xml_file); + + // 스킨 정보를 이용 변수 정리 + if(!$xml_obj) return; + + // 스킨이름 + $info->title = $xml_obj->title->body; + + // 작성자 정보 + $module_info->title = $xml_obj->title->body; + $module_info->version = $xml_obj->attrs->version; + $module_info->author->name = $xml_obj->author->name->body; + $module_info->author->email_address = $xml_obj->author->attrs->email_address; + $module_info->author->homepage = $xml_obj->author->attrs->link; + $module_info->author->date = $xml_obj->author->attrs->date; + $module_info->author->description = $xml_obj->author->description->body; + + // history + if(!is_array($xml_obj->history->author)) $history[] = $xml_obj->history->author; + else $history = $xml_obj->history->author; + foreach($history as $item) { + unset($obj); + $obj->name = $item->name->body; + $obj->email_address = $item->attrs->email_address; + $obj->homepage = $item->attrs->link; + $obj->date = $item->attrs->date; + $obj->description = $item->description->body; + $module_info->history[] = $obj; + } + + return $module_info; + }/*}}}*/ + + function getSkins($module_path) {/*{{{*/ + $skins_path = sprintf("%s/skins/", $module_path); + $list = FileHandler::readDir($skins_path); + return $list; + }/*}}}*/ + + function loadSkinInfo($module_path, $skin) {/*{{{*/ + // 현재 선택된 모듈의 스킨의 정보 xml 파일을 읽음 + $skin_xml_file = sprintf("%sskins/%s/skin.xml", $module_path, $skin); + if(!file_exists($skin_xml_file)) return; + $oXmlParser = new XmlParser(); + $xml_obj = $oXmlParser->loadXmlFile($skin_xml_file); + + // 스킨 정보를 이용 변수 정리 + if(!$xml_obj) return; + + // 스킨이름 + $skin_info->title = $xml_obj->title->body; + + // 작성자 정보 + $skin_info->maker->name = $xml_obj->maker->name->body; + $skin_info->maker->email_address = $xml_obj->maker->attrs->email_address; + $skin_info->maker->homepage = $xml_obj->maker->attrs->link; + $skin_info->maker->date = $xml_obj->maker->attrs->date; + $skin_info->maker->description = $xml_obj->maker->description->body; + + // colorset + if(!is_array($xml_obj->colorset->color)) $colorset[] = $xml_obj->colorset->color; + else $colorset = $xml_obj->colorset->color; + foreach($colorset as $color) { + $name = $color->attrs->name; + $title = $color->title->body; + $screenshot = $color->attrs->src; + if($screenshot && file_exists($screenshot)) $screenshot = sprintf("%sskins/%s/%s",$module_path,$skin,$screenshot); + else $screenshot = ""; + + unset($obj); + $obj->name = $name; + $obj->title = $title; + $obj->screenshot = $screenshot; + $skin_info->colorset[] = $obj; + } + + // 스킨에서 사용되는 변수들 + if(!is_array($xml_obj->extra_vars->var)) $extra_vars[] = $xml_obj->extra_vars->var; + else $extra_vars = $xml_obj->extra_vars->var; + foreach($extra_vars as $var) { + $name = $var->attrs->name; + $type = $var->attrs->type; + $title = $var->title->body; + $description = $var->description->body; + if($var->default) { + unset($default); + if(is_array($var->default)) { + for($i=0;$idefault);$i++) $default[] = $var->default[$i]->body; + } else { + $default = $var->default->body; + } + } + $width = $var->attrs->width; + $height = $var->attrs->height; + + unset($obj); + $obj->title = $title; + $obj->description = $description; + $obj->name = $name; + $obj->type = $type; + $obj->default = $default; + $obj->width = $width; + $obj->height = $height; + + $skin_info->extra_vars[] = $obj; + } + + return $skin_info; + }/*}}}*/ + } +?> diff --git a/modules/module_manager/queries/clearDefaultModule.xml b/modules/module_manager/queries/clearDefaultModule.xml new file mode 100644 index 000000000..8b5716716 --- /dev/null +++ b/modules/module_manager/queries/clearDefaultModule.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/modules/module_manager/queries/deleteModule.xml b/modules/module_manager/queries/deleteModule.xml new file mode 100644 index 000000000..3967fc73d --- /dev/null +++ b/modules/module_manager/queries/deleteModule.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/module_manager/queries/getDefaultMidInfo.xml b/modules/module_manager/queries/getDefaultMidInfo.xml new file mode 100644 index 000000000..cd8391044 --- /dev/null +++ b/modules/module_manager/queries/getDefaultMidInfo.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/module_manager/queries/getMidInfo.xml b/modules/module_manager/queries/getMidInfo.xml new file mode 100644 index 000000000..f50ddb7e7 --- /dev/null +++ b/modules/module_manager/queries/getMidInfo.xml @@ -0,0 +1,12 @@ + + +
+ + + + + + + + + diff --git a/modules/module_manager/queries/getModuleInfoByDocument.xml b/modules/module_manager/queries/getModuleInfoByDocument.xml new file mode 100644 index 000000000..41a934136 --- /dev/null +++ b/modules/module_manager/queries/getModuleInfoByDocument.xml @@ -0,0 +1,24 @@ + + +
+
+ + + + + + + + + + + + + + + + + + + + diff --git a/modules/module_manager/queries/insertModule.xml b/modules/module_manager/queries/insertModule.xml new file mode 100644 index 000000000..70a3cc165 --- /dev/null +++ b/modules/module_manager/queries/insertModule.xml @@ -0,0 +1,22 @@ + + +
+ + + + + + + + + + + + + + + + + + + diff --git a/modules/module_manager/queries/updateModule.xml b/modules/module_manager/queries/updateModule.xml new file mode 100644 index 000000000..736caff11 --- /dev/null +++ b/modules/module_manager/queries/updateModule.xml @@ -0,0 +1,23 @@ + + +
+ + + + + + + + + + + + + + + + + + + + diff --git a/modules/module_manager/queries/updateModuleExtraVars.xml b/modules/module_manager/queries/updateModuleExtraVars.xml new file mode 100644 index 000000000..8b6f15f0f --- /dev/null +++ b/modules/module_manager/queries/updateModuleExtraVars.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/module_manager/queries/updateModuleGrant.xml b/modules/module_manager/queries/updateModuleGrant.xml new file mode 100644 index 000000000..fccdc44e0 --- /dev/null +++ b/modules/module_manager/queries/updateModuleGrant.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/module_manager/schemas/module_addon.xml b/modules/module_manager/schemas/module_addon.xml new file mode 100644 index 000000000..d3ba78007 --- /dev/null +++ b/modules/module_manager/schemas/module_addon.xml @@ -0,0 +1,9 @@ +
+ + + + + + + +
diff --git a/modules/module_manager/schemas/module_plugin.xml b/modules/module_manager/schemas/module_plugin.xml new file mode 100644 index 000000000..67b381f32 --- /dev/null +++ b/modules/module_manager/schemas/module_plugin.xml @@ -0,0 +1,7 @@ + + + + + + +
diff --git a/modules/module_manager/schemas/modules.xml b/modules/module_manager/schemas/modules.xml new file mode 100644 index 000000000..4f633a1d0 --- /dev/null +++ b/modules/module_manager/schemas/modules.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + +
diff --git a/modules/rss/module.xml b/modules/rss/module.xml new file mode 100644 index 000000000..1f24f238e --- /dev/null +++ b/modules/rss/module.xml @@ -0,0 +1,11 @@ + + + RSS + RSS + + 제로 + zero + RSS 관리 모듈 + rss management + + diff --git a/modules/rss/rss.module.php b/modules/rss/rss.module.php new file mode 100644 index 000000000..747c6082c --- /dev/null +++ b/modules/rss/rss.module.php @@ -0,0 +1,111 @@ + + * @desc : 기본 모듈중의 하나인 rss module + * RSS 2.0형식으로 문서 출력 + **/ + + class rss extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = ''; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/system_install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 error, message가 지정되어야 한다 + **/ + + // 출력 부분 + + // 실행 부분 + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + function printRssDocument($info, $content) { /*{{{*/ + header("Content-Type: text/xml; charset=UTF-8"); + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header("Cache-Control: no-store, no-cache, must-revalidate"); + header("Cache-Control: post-check=0, pre-check=0", false); + header("Pragma: no-cache"); + print ''."\n"; + print "\n"; +?> + + <![CDATA[<?=$info->title?>]]> + link?>]]> + description?>]]> + language?> + date?> +regdate,0,4); + $month = substr($item->regdate,4,2); + $day = substr($item->regdate,6,2); + $hour = substr($item->regdate,8,2); + $min = substr($item->regdate,10,2); + $sec = substr($item->regdate,12,2); + $time = mktime($hour,$min,$sec,$month,$day,$year); + + $title = $item->title; + $author = $item->user_name; + $link = sprintf("%s?document_srl=%d", Context::getRequestUri(), $item->document_srl); + $description = $item->content; + $date = gmdate("D, d M Y H:i:s", $time); +?> + + <![CDATA[<?=$title?>]]> + ]]> + ]]> + ]]> + + + + + + diff --git a/modules/tag/module.xml b/modules/tag/module.xml new file mode 100644 index 000000000..d20d63c46 --- /dev/null +++ b/modules/tag/module.xml @@ -0,0 +1,11 @@ + + + 꼬리표 + tag + + 제로 + zero + 꼬리표 관리 모듈 + tag + + diff --git a/modules/tag/queries/deleteModuleTags.xml b/modules/tag/queries/deleteModuleTags.xml new file mode 100644 index 000000000..cf5a19887 --- /dev/null +++ b/modules/tag/queries/deleteModuleTags.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/modules/tag/queries/deleteTag.xml b/modules/tag/queries/deleteTag.xml new file mode 100644 index 000000000..ee9b981dc --- /dev/null +++ b/modules/tag/queries/deleteTag.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/tag/queries/insertTag.xml b/modules/tag/queries/insertTag.xml new file mode 100644 index 000000000..c6155e886 --- /dev/null +++ b/modules/tag/queries/insertTag.xml @@ -0,0 +1,12 @@ + + +
+ + + + + + + + + diff --git a/modules/tag/schemas/tags.xml b/modules/tag/schemas/tags.xml new file mode 100644 index 000000000..1d3613ef6 --- /dev/null +++ b/modules/tag/schemas/tags.xml @@ -0,0 +1,7 @@ +
+ + + + + +
diff --git a/modules/tag/tag.module.php b/modules/tag/tag.module.php new file mode 100644 index 000000000..58e362711 --- /dev/null +++ b/modules/tag/tag.module.php @@ -0,0 +1,110 @@ + + * @desc : 기본 모듈중의 하나인 tag module + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class tag extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = ''; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 tag, tag가 지정되어야 한다 + **/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + + // public string insertTag($module_srl, $document_srl, $tags)/*{{{*/ + // 태그 입력 + function insertTag($module_srl, $document_srl, $tags) { + + // 해당 글의 tags를 모두 삭제 + $this->deleteTag($document_srl); + + if(!$tags) return; + + // tags변수 정리 + $tmp_tag_list = explode(',', $tags); + $tag_count = count($tmp_tag_list); + for($i=0;$i<$tag_count;$i++) { + $tag = trim($tmp_tag_list[$i]); + if(!$tag) continue; + $tag_list[] = $tag; + } + if(!count($tag_list)) return; + + // 다시 태그를 입력 + $oDB = &DB::getInstance(); + + $args->module_srl = $module_srl; + $args->document_srl = $document_srl; + $tag_count = count($tag_list); + for($i=0;$i<$tag_count;$i++) { + $args->tag = $tag_list[$i]; + $oDB->executeQuery('tag.insertTag', $args); + } + + return implode(',',$tag_list); + }/*}}}*/ + + // public boolean deleteTag($document_srl)/*{{{*/ + // 특정 문서의 태그 삭제 + function deleteTag($document_srl) { + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + return $oDB->executeQuery('tag.deleteTag', $args); + }/*}}}*/ + + // public boolean deleteModuleTags($module_sr)/*{{{*/ + // 특정 모듈의 태그 삭제 + function deleteModuleTags($module_srl) { + // 삭제 + $oDB = &DB::getInstance(); + $args->module_srl = $module_srl; + return $oDB->executeQuery('tag.deleteModuleTags', $args); + }/*}}}*/ + } +?> diff --git a/modules/trackback/module.xml b/modules/trackback/module.xml new file mode 100644 index 000000000..53940899d --- /dev/null +++ b/modules/trackback/module.xml @@ -0,0 +1,19 @@ + + + 엮인글 + Trackback + + 제로 + zero + 엮인글 관리 모듈 + module of trackback management + + + + 제로 + zero + 엮인글 관리 모듈 + module of trackback management + + + diff --git a/modules/trackback/queries/deleteModuleTrackbacks.xml b/modules/trackback/queries/deleteModuleTrackbacks.xml new file mode 100644 index 000000000..4ca806765 --- /dev/null +++ b/modules/trackback/queries/deleteModuleTrackbacks.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/modules/trackback/queries/deleteTrackback.xml b/modules/trackback/queries/deleteTrackback.xml new file mode 100644 index 000000000..249ec3056 --- /dev/null +++ b/modules/trackback/queries/deleteTrackback.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/trackback/queries/deleteTrackbacks.xml b/modules/trackback/queries/deleteTrackbacks.xml new file mode 100644 index 000000000..7f254d978 --- /dev/null +++ b/modules/trackback/queries/deleteTrackbacks.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/trackback/queries/getTrackback.xml b/modules/trackback/queries/getTrackback.xml new file mode 100644 index 000000000..d70f3b223 --- /dev/null +++ b/modules/trackback/queries/getTrackback.xml @@ -0,0 +1,8 @@ + + +
+ + + + + diff --git a/modules/trackback/queries/getTrackbackCount.xml b/modules/trackback/queries/getTrackbackCount.xml new file mode 100644 index 000000000..28771c696 --- /dev/null +++ b/modules/trackback/queries/getTrackbackCount.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/trackback/queries/getTrackbackList.xml b/modules/trackback/queries/getTrackbackList.xml new file mode 100644 index 000000000..90ca1705d --- /dev/null +++ b/modules/trackback/queries/getTrackbackList.xml @@ -0,0 +1,14 @@ + + +
+ + + + + + + + + + + diff --git a/modules/trackback/queries/insertTrackback.xml b/modules/trackback/queries/insertTrackback.xml new file mode 100644 index 000000000..ca96d8531 --- /dev/null +++ b/modules/trackback/queries/insertTrackback.xml @@ -0,0 +1,17 @@ + + +
+ + + + + + + + + + + + + + diff --git a/modules/trackback/schemas/trackbacks.xml b/modules/trackback/schemas/trackbacks.xml new file mode 100644 index 000000000..03462beec --- /dev/null +++ b/modules/trackback/schemas/trackbacks.xml @@ -0,0 +1,12 @@ +
+ + + + + + + + + + +
diff --git a/modules/trackback/trackback.module.php b/modules/trackback/trackback.module.php new file mode 100644 index 000000000..1c3959961 --- /dev/null +++ b/modules/trackback/trackback.module.php @@ -0,0 +1,251 @@ + + * @desc : 기본 모듈중의 하나인 trackback module + * Module class에서 상속을 받아서 사용 + * action 의 경우 disp/proc 2가지만 존재하며 이는 action명세서에 + * 미리 기록을 하여야 함 + **/ + + class trackback extends Module { + + /** + * 모듈의 정보 + **/ + var $cur_version = "20070130_0.01"; + + /** + * 기본 action 지정 + * $act값이 없거나 잘못된 값이 들어올 경우 $default_act 값으로 진행 + **/ + var $default_act = ''; + + /** + * 현재 모듈의 초기화를 위한 작업을 지정해 놓은 method + * css/js파일의 load라든지 lang파일 load등을 미리 선언 + * + * Init() => 공통 + * dispInit() => disp시에 + * procInit() => proc시에 + * + * $this->module_path는 현재 이 모듈파일의 위치를 나타낸다 + * (ex: $this->module_path = "./modules/install/"; + **/ + + // 초기화 + function init() {/*{{{*/ + }/*}}}*/ + + // disp 초기화 + function dispInit() {/*{{{*/ + }/*}}}*/ + + // proc 초기화 + function procInit() {/*{{{*/ + }/*}}}*/ + + /** + * 여기서부터는 action의 구현 + * request parameter의 경우 각 method의 첫번째 인자로 넘어온다 + * + * dispXXXX : 출력을 위한 method, output에 tpl file이 지정되어야 한다 + * procXXXX : 처리를 위한 method, output에는 trackback, trackback가 지정되어야 한다 + **/ + + /** + * 여기부터는 이 모듈과 관련된 라이브러리 개념의 method들 + **/ + + // public boolean insertTrackback($obj)/*{{{*/ + // 엮인글 입력 + function insertTrackback($obj) { + // document_srl에 해당하는 글이 있는지 확인 + $document_srl = $obj->document_srl; + if(!$document_srl) $this->dispMessage(-1, 'fail'); + + $oDocument = getModule('document'); + $document = $oDocument->getDocument($document_srl); + + if(!$document_srl) $this->dispMessage(-1,'fail'); + if($document->allow_trackback=='N') $this->dispMessage(-1,'fail'); + + // 엮인글 정리 + $obj = Context::convertEncoding($obj); + if(!$obj->blog_name) $obj->blog_name = $obj->title; + $obj->excerpt = strip_tags($obj->excerpt); + + // 엮인글를 입력 + $oDB = &DB::getInstance(); + $obj->list_order = $obj->trackback_srl = $oDB->getNextSequence(); + $obj->module_srl = $document->module_srl; + $output = $oDB->executeQuery('trackback.insertTrackback', $obj); + + // 입력에 이상이 없으면 해당 글의 엮인글 수를 올림 + if(!$output->toBool()) $this->dispMessage(-1, 'fail'); + + // 해당 글의 전체 엮인글 수를 구해옴 + $trackback_count = $this->getTrackbackCount($document_srl); + + // 해당글의 엮인글 수를 업데이트 + $output = $oDocument->updateTrackbackCount($document_srl, $trackback_count); + + if(!$output->toBool()) $this->dispMessage(-1,'fail'); + else $this->dispMessage(0,'success'); + }/*}}}*/ + + function dispMessage($error, $message) {/*{{{*/ + // 헤더 출력 + header("Content-Type: text/xml; charset=UTF-8"); + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header("Cache-Control: no-store, no-cache, must-revalidate"); + header("Cache-Control: post-check=0, pre-check=0", false); + header("Pragma: no-cache"); + print ''."\n"; + print "\n{$error}{$message}"; + exit(); + }/*}}}*/ + + // public boolean getTrackback($trackback_srl)/*{{{*/ + // 엮인글 삭제 + function getTrackback($trackback_srl) { + $oDB = &DB::getInstance(); + $args->trackback_srl = $trackback_srl; + return $oDB->executeQuery('trackback.getTrackback', $args); + }/*}}}*/ + + // public boolean deleteTrackback($trackback_srl)/*{{{*/ + // 엮인글 삭제 + function deleteTrackback($trackback_srl) { + // 삭제하려는 엮인글이 있는지 확인 + $trackback = $this->getTrackback($trackback_srl); + if($trackback->data->trackback_srl != $trackback_srl) return new Output(-1, 'msg_invalid_request'); + $document_srl = $trackback->data->document_srl; + + // 권한이 있는지 확인 + $oDocument = getModule('document'); + if(!$oDocument->isGranted($document_srl)) return new Output(-1, 'msg_not_permitted'); + + // 삭제 + $oDB = &DB::getInstance(); + $args->trackback_srl = $trackback_srl; + $output = $oDB->executeQuery('trackback.deleteTrackback', $args); + if(!$output->toBool()) return new Output(-1, 'msg_error_occured'); + + // 엮인글 수를 구해서 업데이트 + $trackback_count = $this->getTrackbackCount($document_srl); + + // 해당글의 엮인글 수를 업데이트 + $oDocument = getModule('document'); + $output = $oDocument->updateTrackbackCount($document_srl, $trackback_count); + $output->add('document_srl', $document_srl); + return $output; + }/*}}}*/ + + // public boolean deleteTrackbacks($document_srl)/*{{{*/ + // 엮인글 삭제 + function deleteTrackbacks($document_srl) { + // 삭제 + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('trackback.deleteTrackbacks', $args); + return $output; + }/*}}}*/ + + // public boolean deleteModuleTrackbacks($module_srl)/*{{{*/ + // 엮인글 삭제 + function deleteModuleTrackbacks($module_srl) { + // 삭제 + $oDB = &DB::getInstance(); + $args->module_srl = $module_srl; + $output = $oDB->executeQuery('trackback.deleteModuleTrackbacks', $args); + return $output; + }/*}}}*/ + + // public number getTrackbackCount($module_srl, $search_obj = NULL)/*{{{*/ + // document_srl 에 해당하는 엮인글의 전체 갯수를 가져옴 + function getTrackbackCount($document_srl) { + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $output = $oDB->executeQuery('trackback.getTrackbackCount', $args); + $total_count = $output->data->count; + return (int)$total_count; + }/*}}}*/ + + // public boolean getTrackbackList($document_srl)/*{{{*/ + // module_srl값을 가지는 엮인글의 목록을 가져옴 + function getTrackbackList($document_srl) { + // 엮인글 목록을 가져옴 + $oDB = &DB::getInstance(); + $args->document_srl = $document_srl; + $args->list_order = 'list_order'; + $output = $oDB->executeQuery('trackback.getTrackbackList', $args); + if(!$output->toBool()) return $output; + $trackback_list = $output->data; + if(!is_array($trackback_list)) $trackback_list = array($trackback_list); + return $trackback_list; + }/*}}}*/ + + // public boolean sendTrackback($document)/*{{{*/ + // 엮인글을 발송 + function sendTrackback($document, $trackback_url, $charset) { + // 발송할 정보를 정리 + $http = parse_url($trackback_url); + $obj->blog_name = Context::getBrowserTitle(); + $obj->title = $document->title; + $obj->excerpt = cut_str($document->content, 240); + $obj->url = sprintf("%s?document_srl=%d", Context::getRequestUri(), $document->document_srl); + + if($charset && function_exists('iconv')) { + foreach($obj as $key=>$val) { + $obj->{$key} = iconv('UTF-8',$charset,$val); + } + } + + if($http['query']) $http['query'].="&"; + if(!$http['port']) $http['port'] = 80; + $content = + sprintf( + "title=%s&". + "url=%s&". + "blog_name=%s&". + "excerpt=%s", + urlencode($obj->title), + urlencode($obj->url), + urlencode($obj->blog_name), + urlencode($obj->excerpt) + ); + if($http['query']) $content .= '&'.$http['query']; + + $content_length = strlen($content); + + $header = + sprintf( + "POST %s HTTP/1.1\r\n". + "Host: %s\r\n". + "Content-Type: %s\r\n". + "Content-Length: %s\r\n\r\n". + "%s\r\n", + $http['path'], + $http['host'], + "application/x-www-form-urlencoded", + $content_length, + $content + ); + if(!$http['host']||!$http['port']) return; + + $fp = @fsockopen($http['host'], $http['port'], $errno, $errstr, 5); + if(!$fp) return; + + fputs($fp, $header); + + while(!feof($fp)) { + $line = trim(fgets($fp, 4096)); + if(eregi("^",$line)) break; + } + + fclose($fp); + }/*}}}*/ + } +?> diff --git a/rss.php b/rss.php new file mode 100644 index 000000000..8fd024876 --- /dev/null +++ b/rss.php @@ -0,0 +1,22 @@ + + * @desc : rss를 출력하기 위한 파일. index.php와 거의 동일하나 act를 dispRss 로 고정시키는 것만 다름 + **/ + + // 필요한 설정 파일들을 include + require_once("./config/config.inc.php"); + + // Request Method와 설정값들을 세팅 + $oContext = &Context::getInstance(); + $oContext->init(); + + // act값을 dispRss로 강제 설정 + // 각 모듈마다 dispRss가 필수적으로 있어야 함 + Context::set('act', 'dispRss'); + + // ModuleHandler 호출하여 content 출력 + $oModuleHandler = new ModuleHandler(); + $oModule = $oModuleHandler->proc(); +?> diff --git a/trackback.php b/trackback.php new file mode 100644 index 000000000..e0043a26b --- /dev/null +++ b/trackback.php @@ -0,0 +1,22 @@ + + * @desc : 트랙백을 받기 위한 파일. 파일이름때문에.. index.php와 거의 동일하나 act를 procReceiveTrackback로 고정 + **/ + + // 필요한 설정 파일들을 include + require_once("./config/config.inc.php"); + + // Request Method와 설정값들을 세팅 + $oContext = &Context::getInstance(); + $oContext->init(); + + // act값을 procReceiveTrackback로 강제 설정 + // 각 모듈마다 procReceiveTrackback가 필수적으로 있어야 함 + Context::set('act', 'procReceiveTrackback'); + + // ModuleHandler 호출하여 content 출력 + $oModuleHandler = new ModuleHandler(); + $oModule = $oModuleHandler->proc(); +?>