merge sandbox to trunk for 1.4.4

git-svn-id: http://xe-core.googlecode.com/svn/trunk@7723 201d5d3c-b55e-5fd7-737f-ddc643e51545
This commit is contained in:
ngleader 2010-09-28 07:24:47 +00:00
parent 200d63636c
commit b8299c8a65
683 changed files with 70982 additions and 69716 deletions

View file

@ -1,72 +1,72 @@
<?php
/**
* @class CacheApc
* @author sol (sol@nhn.com)
* @brief APC Handler
* @version 0.1
*
**/
class CacheApc extends CacheBase {
var $valid_time = 36000;
function getInstance($opt=null){
if(!$GLOBALS['__CacheApc__']) {
$GLOBALS['__CacheApc__'] = new CacheApc();
}
return $GLOBALS['__CacheApc__'];
}
function CacheApc(){
}
function isSupport(){
return function_exists('apc_add');
}
function put($key, $buff, $valid_time = 0){
if($valid_time == 0) $valid_time = $this->valid_time;
return apc_store(md5(_XE_PATH_.$key), array(time(), $buff), $valid_time);
}
function isValid($key, $modified_time = 0) {
$_key = md5(_XE_PATH_.$key);
$obj = apc_fetch($_key, $success);
if(!$success || !is_array($obj)) return false;
unset($obj[1]);
if($modified_time > 0 && $modified_time > $obj[0]) {
$this->_delete($_key);
return false;
}
return true;
}
function get($key, $modified_time = 0) {
$_key = md5(_XE_PATH_.$key);
$obj = apc_fetch($_key, $success);
if(!$success || !is_array($obj)) return false;
if($modified_time > 0 && $modified_time > $obj[0]) {
$this->_delete($_key);
return false;
}
return $obj[1];
}
function _delete($_key) {
$this->put($_key,null,1);
}
function delete($key) {
$this->_delete(md5(_XE_PATH_.$key));
}
function truncate() {
return apc_clear_cache('user');
}
}
?>
<?php
/**
* @class CacheApc
* @author NHN (developer@xpressengine.com)
* @brief APC Handler
* @version 0.1
*
**/
class CacheApc extends CacheBase {
var $valid_time = 36000;
function getInstance($opt=null){
if(!$GLOBALS['__CacheApc__']) {
$GLOBALS['__CacheApc__'] = new CacheApc();
}
return $GLOBALS['__CacheApc__'];
}
function CacheApc(){
}
function isSupport(){
return function_exists('apc_add');
}
function put($key, $buff, $valid_time = 0){
if($valid_time == 0) $valid_time = $this->valid_time;
return apc_store(md5(_XE_PATH_.$key), array(time(), $buff), $valid_time);
}
function isValid($key, $modified_time = 0) {
$_key = md5(_XE_PATH_.$key);
$obj = apc_fetch($_key, $success);
if(!$success || !is_array($obj)) return false;
unset($obj[1]);
if($modified_time > 0 && $modified_time > $obj[0]) {
$this->_delete($_key);
return false;
}
return true;
}
function get($key, $modified_time = 0) {
$_key = md5(_XE_PATH_.$key);
$obj = apc_fetch($_key, $success);
if(!$success || !is_array($obj)) return false;
if($modified_time > 0 && $modified_time > $obj[0]) {
$this->_delete($_key);
return false;
}
return $obj[1];
}
function _delete($_key) {
$this->put($_key,null,1);
}
function delete($key) {
$this->_delete(md5(_XE_PATH_.$key));
}
function truncate() {
return apc_clear_cache('user');
}
}
?>

View file

@ -1,95 +1,95 @@
<?php
/**
* @class CacheHandler
* @author sol (sol@nhn.com)
* @brief Cache Handler
* @version 0.1
*
**/
class CacheHandler extends Handler {
var $handler = null;
function &getInstance($target='object') {
return new CacheHandler($target);
}
function CacheHandler($target, $info=null) {
if(!$info) $info = Context::getDBInfo();
if($info){
if($target == 'object'){
if($info->use_object_cache =='apc') $type = 'apc';
else if(substr($info->use_object_cache,0,8)=='memcache'){
$type = 'memcache';
$url = $info->use_object_cache;
}
}else if($target == 'template'){
if($info->use_template_cache =='apc') $type = 'apc';
else if(substr($info->use_template_cache,0,8)=='memcache'){
$type = 'memcache';
$url = $info->use_template_cache;
}
}
if($type){
$class = 'Cache' . ucfirst($type);
include_once sprintf('%sclasses/cache/%s.class.php', _XE_PATH_, $class);
$this->handler = call_user_func(array($class,'getInstance'), $url);
}
}
}
function isSupport(){
if($this->handler && $this->handler->isSupport()) return true;
return false;
}
function get($key, $modified_time = 0){
if(!$this->handler) return false;
return $this->handler->get($key, $modified_time);
}
function put($key, $obj, $valid_time = 0){
if(!$this->handler) return false;
return $this->handler->put($key, $obj, $valid_time);
}
function delete($key){
if(!$this->handler) return false;
return $this->handler->delete($key);
}
function isValid($key, $modified_time){
if(!$this->handler) return false;
return $this->handler->isValid($key, $modified_time);
}
function truncate(){
if(!$this->handler) return false;
return $this->handler->truncate();
}
}
class CacheBase{
function get($key, $modified_time = 0){
return false;
}
function put($key, $obj, $valid_time = 0){
return false;
}
function isValid($key, $modified_time = 0){
return false;
}
function isSupport(){
return false;
}
function truncate(){
return false;
}
}
?>
<?php
/**
* @class CacheHandler
* @author NHN (developer@xpressengine.com)
* @brief Cache Handler
* @version 0.1
*
**/
class CacheHandler extends Handler {
var $handler = null;
function &getInstance($target='object') {
return new CacheHandler($target);
}
function CacheHandler($target, $info=null) {
if(!$info) $info = Context::getDBInfo();
if($info){
if($target == 'object'){
if($info->use_object_cache =='apc') $type = 'apc';
else if(substr($info->use_object_cache,0,8)=='memcache'){
$type = 'memcache';
$url = $info->use_object_cache;
}
}else if($target == 'template'){
if($info->use_template_cache =='apc') $type = 'apc';
else if(substr($info->use_template_cache,0,8)=='memcache'){
$type = 'memcache';
$url = $info->use_template_cache;
}
}
if($type){
$class = 'Cache' . ucfirst($type);
include_once sprintf('%sclasses/cache/%s.class.php', _XE_PATH_, $class);
$this->handler = call_user_func(array($class,'getInstance'), $url);
}
}
}
function isSupport(){
if($this->handler && $this->handler->isSupport()) return true;
return false;
}
function get($key, $modified_time = 0){
if(!$this->handler) return false;
return $this->handler->get($key, $modified_time);
}
function put($key, $obj, $valid_time = 0){
if(!$this->handler) return false;
return $this->handler->put($key, $obj, $valid_time);
}
function delete($key){
if(!$this->handler) return false;
return $this->handler->delete($key);
}
function isValid($key, $modified_time){
if(!$this->handler) return false;
return $this->handler->isValid($key, $modified_time);
}
function truncate(){
if(!$this->handler) return false;
return $this->handler->truncate();
}
}
class CacheBase{
function get($key, $modified_time = 0){
return false;
}
function put($key, $obj, $valid_time = 0){
return false;
}
function isValid($key, $modified_time = 0){
return false;
}
function isSupport(){
return false;
}
function truncate(){
return false;
}
}
?>

View file

@ -1,91 +1,91 @@
<?php
/**
* @class CacheMemcache
* @author sol (sol@nhn.com)
* @brief Memcache Handler
* @version 0.1
*
**/
class CacheMemcache extends CacheBase {
var $valid_time = 36000;
var $Memcache;
function getInstance($url){
if(!$GLOBALS['__CacheMemcache__']) {
$GLOBALS['__CacheMemcache__'] = new CacheMemcache($url);
}
return $GLOBALS['__CacheMemcache__'];
}
function CacheMemcache($url){
//$config['url'] = array('memcache://localhost:11211');
$config['url'] = is_array($url)?$url:array($url);
$this->Memcache = new Memcache;
foreach($config['url'] as $url) {
$info = parse_url($url);
$this->Memcache->addServer($info['host'], $info['port']);
}
}
function isSupport(){
return $this->Memcache->set('xe', 'xe', MEMCACHE_COMPRESSED, 1);
}
function getKey($key){
return md5(_XE_PATH_.$key);
}
function put($key, $buff, $valid_time = 0){
if($valid_time == 0) $valid_time = $this->valid_time;
return $this->Memcache->set($this->getKey($key), array(time(), $buff), MEMCACHE_COMPRESSED, $valid_time);
}
function isValid($key, $modified_time = 0) {
$_key = $this->getKey($key);
$obj = $this->Memcache->get($_key);
if(!$obj || !is_array($obj)) return false;
unset($obj[1]);
if($modified_time > 0 && $modified_time > $obj[0]) {
$this->_delete($_key);
return false;
}
return true;
}
function get($key, $modified_time = 0) {
$_key = $this->getKey($key);
$obj = $this->Memcache->get($_key);
if(!$obj || !is_array($obj)) return false;
if($modified_time > 0 && $modified_time > $obj[0]) {
$this->_delete($_key);
return false;
}
unset($obj[0]);
return $obj[1];
}
function delete($key) {
$_key = $this->getKey($key);
$this->_delete($_key);
}
function _delete($_key) {
$this->Memcache->delete($_key);
}
function truncate() {
// not support memcached
return false;
}
}
?>
<?php
/**
* @class CacheMemcache
* @author NHN (developer@xpressengine.com)
* @brief Memcache Handler
* @version 0.1
*
**/
class CacheMemcache extends CacheBase {
var $valid_time = 36000;
var $Memcache;
function getInstance($url){
if(!$GLOBALS['__CacheMemcache__']) {
$GLOBALS['__CacheMemcache__'] = new CacheMemcache($url);
}
return $GLOBALS['__CacheMemcache__'];
}
function CacheMemcache($url){
//$config['url'] = array('memcache://localhost:11211');
$config['url'] = is_array($url)?$url:array($url);
$this->Memcache = new Memcache;
foreach($config['url'] as $url) {
$info = parse_url($url);
$this->Memcache->addServer($info['host'], $info['port']);
}
}
function isSupport(){
return $this->Memcache->set('xe', 'xe', MEMCACHE_COMPRESSED, 1);
}
function getKey($key){
return md5(_XE_PATH_.$key);
}
function put($key, $buff, $valid_time = 0){
if($valid_time == 0) $valid_time = $this->valid_time;
return $this->Memcache->set($this->getKey($key), array(time(), $buff), MEMCACHE_COMPRESSED, $valid_time);
}
function isValid($key, $modified_time = 0) {
$_key = $this->getKey($key);
$obj = $this->Memcache->get($_key);
if(!$obj || !is_array($obj)) return false;
unset($obj[1]);
if($modified_time > 0 && $modified_time > $obj[0]) {
$this->_delete($_key);
return false;
}
return true;
}
function get($key, $modified_time = 0) {
$_key = $this->getKey($key);
$obj = $this->Memcache->get($_key);
if(!$obj || !is_array($obj)) return false;
if($modified_time > 0 && $modified_time > $obj[0]) {
$this->_delete($_key);
return false;
}
unset($obj[0]);
return $obj[1];
}
function delete($key) {
$_key = $this->getKey($key);
$this->_delete($_key);
}
function _delete($_key) {
$this->Memcache->delete($_key);
}
function truncate() {
// not support memcached
return false;
}
}
?>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -924,6 +924,7 @@
$count_query = sprintf("select count(*) as \"count\" from %s %s %s", implode(',',$table_list),implode(' ',$left_join), $condition);
$total_count = $this->getCountCache($output->tables, $condition);
if($total_count === false) {
$count_query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id . ' count(*)'):'';
$result = $this->_query($count_query);
$count_output = $this->_fetch($result);
if(!$this->transaction_started) @ibase_commit($this->fd);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -809,6 +809,8 @@ class DBPostgresql extends DB
implode(' ', $left_join), $condition);
$total_count = $this->getCountCache($output->tables, $condition);
if ($total_count === false) {
$count_query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id . ' count(*)'):'';
$result = $this->_query($count_query);
$count_output = $this->_fetch($result);
$total_count = (int)$count_output->count;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,278 +1,278 @@
<?php
/**
* @class DisplayHandler
* @author zero (zero@nzeo.com)
* @brief DisplayHandler is responsible for displaying the execution result. \n
* Depending on the request type, it can display either HTML or XML content.\n
* Xml content is simple xml presentation of variables in oModule while html content
* is the combination of the variables of oModue and template files/.
**/
class DisplayHandler extends Handler {
var $content_size = 0; ///< 출력하는 컨텐츠의 사이즈
var $gz_enabled = false; ///< gzip 압축하여 컨텐츠 호출할 것인지에 대한 flag변수
var $handler = null;
/**
* @brief print either html or xml content given oModule object
* @remark addon execution and the trigger execution are included within this method, which
* might create inflexibility for the fine grained caching
* @param[in] $oModule the module object
**/
function printContent(&$oModule) {
// gzip encoding 지원 여부 체크
if(
(defined('__OB_GZHANDLER_ENABLE__') && __OB_GZHANDLER_ENABLE__ == 1) &&
strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')!==false &&
function_exists('ob_gzhandler') &&
extension_loaded('zlib')
) $this->gz_enabled = true;
// request method에 따른 컨텐츠 결과물 추출
if(Context::get('xeVirtualRequestMethod')=='xml') {
require_once("./classes/display/VirtualXMLDisplayHandler.php");
$handler = new VirtualXMLDisplayHandler();
}
else if(Context::getRequestMethod() == 'XMLRPC') {
require_once("./classes/display/XMLDisplayHandler.php");
$handler = new XMLDisplayHandler();
if(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) $this->gz_enabled = false;
}
else if(Context::getRequestMethod() == 'JSON') {
require_once("./classes/display/JSONDisplayHandler.php");
$handler = new JSONDisplayHandler();
}
else {
require_once("./classes/display/HTMLDisplayHandler.php");
$handler = new HTMLDisplayHandler();
}
$output = $handler->toDoc($oModule);
// 출력하기 전에 trigger 호출 (before)
ModuleHandler::triggerCall('display', 'before', $output);
// 애드온 실행
$called_position = 'before_display_content';
$oAddonController = &getController('addon');
$addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone()?"mobile":"pc");
@include($addon_file);
if(method_exists($handler, "prepareToPrint")) $handler->prepareToPrint($output);
// header 출력
if($this->gz_enabled) header("Content-Encoding: gzip");
if(Context::getResponseMethod() == 'JSON') $this->_printJSONHeader();
else if(Context::getResponseMethod() != 'HTML') $this->_printXMLHeader();
else $this->_printHTMLHeader();
// debugOutput 출력
$this->content_size = strlen($output);
$output .= $this->_debugOutput();
// 결과물 직접 출력
if($this->gz_enabled) print ob_gzhandler($output, 5);
else print $output;
// 출력 후 trigger 호출 (after)
ModuleHandler::triggerCall('display', 'after', $content);
}
/**
* @brief Print debugging message to designated output source depending on the value set to __DEBUG_OUTPUT_. \n
* This method only functions when __DEBUG__ variable is set to 1.
* __DEBUG_OUTPUT__ == 0, messages are written in ./files/_debug_message.php
**/
function _debugOutput() {
if(!__DEBUG__) return;
$end = getMicroTime();
// Firebug 콘솔 출력
if(__DEBUG_OUTPUT__ == 2 && version_compare(PHP_VERSION, '6.0.0') === -1) {
static $firephp;
if(!isset($firephp)) $firephp = FirePHP::getInstance(true);
if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
$firephp->fb('Change the value of __DEBUG_PROTECT_IP__ into your IP address in config/config.user.inc.php or config/config.inc.php', 'The IP address is not allowed.');
return;
}
// 전체 실행 시간 출력, Request/Response info 출력
if(__DEBUG__ & 2) {
$firephp->fb(
array('Request / Response info >>> '.$_SERVER['REQUEST_METHOD'].' / '.Context::getResponseMethod(),
array(
array('Request URI', 'Request method', 'Response method', 'Response contents size'),
array(
sprintf("%s:%s%s%s%s", $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['PHP_SELF'], $_SERVER['QUERY_STRING']?'?':'', $_SERVER['QUERY_STRING']),
$_SERVER['REQUEST_METHOD'],
Context::getResponseMethod(),
$this->content_size.' byte'
)
)
),
'TABLE'
);
$firephp->fb(
array('Elapsed time >>> Total : '.sprintf('%0.5f sec', $end - __StartTime__),
array(array('DB queries', 'class file load', 'Template compile', 'XmlParse compile', 'PHP', 'Widgets', 'Trans Content'),
array(
sprintf('%0.5f sec', $GLOBALS['__db_elapsed_time__']),
sprintf('%0.5f sec', $GLOBALS['__elapsed_class_load__']),
sprintf('%0.5f sec (%d called)', $GLOBALS['__template_elapsed__'], $GLOBALS['__TemplateHandlerCalled__']),
sprintf('%0.5f sec', $GLOBALS['__xmlparse_elapsed__']),
sprintf('%0.5f sec', $end-__StartTime__-$GLOBALS['__template_elapsed__']-$GLOBALS['__xmlparse_elapsed__']-$GLOBALS['__db_elapsed_time__']-$GLOBALS['__elapsed_class_load__']),
sprintf('%0.5f sec', $GLOBALS['__widget_excute_elapsed__']),
sprintf('%0.5f sec', $GLOBALS['__trans_content_elapsed__'])
)
)
),
'TABLE'
);
}
// DB 쿼리 내역 출력
if((__DEBUG__ & 4) && $GLOBALS['__db_queries__']) {
$queries_output = array(array('Query', 'Elapsed time', 'Result'));
foreach($GLOBALS['__db_queries__'] as $query) {
array_push($queries_output, array($query['query'], sprintf('%0.5f', $query['elapsed_time']), $query['result']));
}
$firephp->fb(
array(
'DB Queries >>> '.count($GLOBALS['__db_queries__']).' Queries, '.sprintf('%0.5f sec', $GLOBALS['__db_elapsed_time__']),
$queries_output
),
'TABLE'
);
}
// 파일 및 HTML 주석으로 출력
} else {
// 전체 실행 시간 출력, Request/Response info 출력
if(__DEBUG__ & 2) {
if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
return;
}
// Request/Response 정보 작성
$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 method \t\t: %s\n", Context::getResponseMethod());
$buff .= sprintf("\tResponse contents size\t\t: %d byte\n", $this->content_size);
// 전체 실행 시간
$buff .= sprintf("\n- Total elapsed time : %0.5f sec\n", $end-__StartTime__);
$buff .= sprintf("\tclass file load elapsed time \t: %0.5f sec\n", $GLOBALS['__elapsed_class_load__']);
$buff .= sprintf("\tTemplate compile elapsed time\t: %0.5f sec (%d called)\n", $GLOBALS['__template_elapsed__'], $GLOBALS['__TemplateHandlerCalled__']);
$buff .= sprintf("\tXmlParse compile elapsed time\t: %0.5f sec\n", $GLOBALS['__xmlparse_elapsed__']);
$buff .= sprintf("\tPHP elapsed time \t\t: %0.5f sec\n", $end-__StartTime__-$GLOBALS['__template_elapsed__']-$GLOBALS['__xmlparse_elapsed__']-$GLOBALS['__db_elapsed_time__']-$GLOBALS['__elapsed_class_load__']);
// 위젯 실행 시간 작성
$buff .= sprintf("\n\tWidgets elapsed time \t\t: %0.5f sec", $GLOBALS['__widget_excute_elapsed__']);
// 레이아웃 실행 시간
$buff .= sprintf("\n\tLayout compile elapsed time \t: %0.5f sec", $GLOBALS['__layout_compile_elapsed__']);
// 위젯, 에디터 컴포넌트 치환 시간
$buff .= sprintf("\n\tTrans Content \t\t\t: %0.5f sec\n", $GLOBALS['__trans_content_elapsed__']);
}
// DB 로그 작성
if(__DEBUG__ & 4) {
if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
return;
}
if($GLOBALS['__db_queries__']) {
$buff .= sprintf("\n- DB Queries : %d Queries. %0.5f sec\n", count($GLOBALS['__db_queries__']), $GLOBALS['__db_elapsed_time__']);
$num = 0;
foreach($GLOBALS['__db_queries__'] as $query) {
$buff .= sprintf("\t%02d. %s\n\t\t%0.6f sec. ", ++$num, $query['query'], $query['elapsed_time']);
if($query['result'] == 'Success') {
$buff .= "Query Success\n";
} else {
$buff .= sprintf("Query $s : %d\n\t\t\t %s\n", $query['result'], $query['errno'], $query['errstr']);
}
}
}
}
// HTML 주석으로 출력
if($buff && __DEBUG_OUTPUT__ == 1 && Context::getResponseMethod() == 'HTML') {
$buff = sprintf("[%s %s:%d]\n%s\n", date('Y-m-d H:i:s'), $file_name, $line_num, print_r($buff, true));
if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
$buff = 'The IP address is not allowed. Change the value of __DEBUG_PROTECT_IP__ into your IP address in config/config.user.inc.php or config/config.inc.php';
}
return "<!--\r\n".$buff."\r\n-->";
}
// 파일에 출력
if($buff && __DEBUG_OUTPUT__ == 0) {
$debug_file = _XE_PATH_.'files/_debug_message.php';
$buff = sprintf("[%s %s:%d]\n%s\n", date('Y-m-d H:i:s'), $file_name, $line_num, print_r($buff, true));
$buff = str_repeat('=', 40)."\n".$buff.str_repeat('-', 40);
$buff = "\n<?php\n/*".$buff."*/\n?>\n";
if(@!$fp = fopen($debug_file, 'a')) return;
fwrite($fp, $buff);
fclose($fp);
}
}
}
/**
* @brief print a HTTP HEADER for XML, which is encoded in UTF-8
**/
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");
}
/**
* @brief print a HTTP HEADER for HTML, which is encoded in UTF-8
**/
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");
}
/**
* @brief print a HTTP HEADER for JSON, which is encoded in UTF-8
**/
function _printJSONHeader() {
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");
}
}
?>
<?php
/**
* @class DisplayHandler
* @author NHN (developers@xpressengine.com)
* @brief DisplayHandler is responsible for displaying the execution result. \n
* Depending on the request type, it can display either HTML or XML content.\n
* Xml content is simple xml presentation of variables in oModule while html content
* is the combination of the variables of oModue and template files/.
**/
class DisplayHandler extends Handler {
var $content_size = 0; ///< 출력하는 컨텐츠의 사이즈
var $gz_enabled = false; ///< gzip 압축하여 컨텐츠 호출할 것인지에 대한 flag변수
var $handler = null;
/**
* @brief print either html or xml content given oModule object
* @remark addon execution and the trigger execution are included within this method, which
* might create inflexibility for the fine grained caching
* @param[in] $oModule the module object
**/
function printContent(&$oModule) {
// gzip encoding 지원 여부 체크
if(
(defined('__OB_GZHANDLER_ENABLE__') && __OB_GZHANDLER_ENABLE__ == 1) &&
strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')!==false &&
function_exists('ob_gzhandler') &&
extension_loaded('zlib')
) $this->gz_enabled = true;
// request method에 따른 컨텐츠 결과물 추출
if(Context::get('xeVirtualRequestMethod')=='xml') {
require_once("./classes/display/VirtualXMLDisplayHandler.php");
$handler = new VirtualXMLDisplayHandler();
}
else if(Context::getRequestMethod() == 'XMLRPC') {
require_once("./classes/display/XMLDisplayHandler.php");
$handler = new XMLDisplayHandler();
if(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) $this->gz_enabled = false;
}
else if(Context::getRequestMethod() == 'JSON') {
require_once("./classes/display/JSONDisplayHandler.php");
$handler = new JSONDisplayHandler();
}
else {
require_once("./classes/display/HTMLDisplayHandler.php");
$handler = new HTMLDisplayHandler();
}
$output = $handler->toDoc($oModule);
// 출력하기 전에 trigger 호출 (before)
ModuleHandler::triggerCall('display', 'before', $output);
// 애드온 실행
$called_position = 'before_display_content';
$oAddonController = &getController('addon');
$addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone()?"mobile":"pc");
@include($addon_file);
if(method_exists($handler, "prepareToPrint")) $handler->prepareToPrint($output);
// header 출력
if($this->gz_enabled) header("Content-Encoding: gzip");
if(Context::getResponseMethod() == 'JSON') $this->_printJSONHeader();
else if(Context::getResponseMethod() != 'HTML') $this->_printXMLHeader();
else $this->_printHTMLHeader();
// debugOutput 출력
$this->content_size = strlen($output);
$output .= $this->_debugOutput();
// 결과물 직접 출력
if($this->gz_enabled) print ob_gzhandler($output, 5);
else print $output;
// 출력 후 trigger 호출 (after)
ModuleHandler::triggerCall('display', 'after', $content);
}
/**
* @brief Print debugging message to designated output source depending on the value set to __DEBUG_OUTPUT_. \n
* This method only functions when __DEBUG__ variable is set to 1.
* __DEBUG_OUTPUT__ == 0, messages are written in ./files/_debug_message.php
**/
function _debugOutput() {
if(!__DEBUG__) return;
$end = getMicroTime();
// Firebug 콘솔 출력
if(__DEBUG_OUTPUT__ == 2 && version_compare(PHP_VERSION, '6.0.0') === -1) {
static $firephp;
if(!isset($firephp)) $firephp = FirePHP::getInstance(true);
if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
$firephp->fb('Change the value of __DEBUG_PROTECT_IP__ into your IP address in config/config.user.inc.php or config/config.inc.php', 'The IP address is not allowed.');
return;
}
// 전체 실행 시간 출력, Request/Response info 출력
if(__DEBUG__ & 2) {
$firephp->fb(
array('Request / Response info >>> '.$_SERVER['REQUEST_METHOD'].' / '.Context::getResponseMethod(),
array(
array('Request URI', 'Request method', 'Response method', 'Response contents size'),
array(
sprintf("%s:%s%s%s%s", $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['PHP_SELF'], $_SERVER['QUERY_STRING']?'?':'', $_SERVER['QUERY_STRING']),
$_SERVER['REQUEST_METHOD'],
Context::getResponseMethod(),
$this->content_size.' byte'
)
)
),
'TABLE'
);
$firephp->fb(
array('Elapsed time >>> Total : '.sprintf('%0.5f sec', $end - __StartTime__),
array(array('DB queries', 'class file load', 'Template compile', 'XmlParse compile', 'PHP', 'Widgets', 'Trans Content'),
array(
sprintf('%0.5f sec', $GLOBALS['__db_elapsed_time__']),
sprintf('%0.5f sec', $GLOBALS['__elapsed_class_load__']),
sprintf('%0.5f sec (%d called)', $GLOBALS['__template_elapsed__'], $GLOBALS['__TemplateHandlerCalled__']),
sprintf('%0.5f sec', $GLOBALS['__xmlparse_elapsed__']),
sprintf('%0.5f sec', $end-__StartTime__-$GLOBALS['__template_elapsed__']-$GLOBALS['__xmlparse_elapsed__']-$GLOBALS['__db_elapsed_time__']-$GLOBALS['__elapsed_class_load__']),
sprintf('%0.5f sec', $GLOBALS['__widget_excute_elapsed__']),
sprintf('%0.5f sec', $GLOBALS['__trans_content_elapsed__'])
)
)
),
'TABLE'
);
}
// DB 쿼리 내역 출력
if((__DEBUG__ & 4) && $GLOBALS['__db_queries__']) {
$queries_output = array(array('Query', 'Elapsed time', 'Result'));
foreach($GLOBALS['__db_queries__'] as $query) {
array_push($queries_output, array($query['query'], sprintf('%0.5f', $query['elapsed_time']), $query['result']));
}
$firephp->fb(
array(
'DB Queries >>> '.count($GLOBALS['__db_queries__']).' Queries, '.sprintf('%0.5f sec', $GLOBALS['__db_elapsed_time__']),
$queries_output
),
'TABLE'
);
}
// 파일 및 HTML 주석으로 출력
} else {
// 전체 실행 시간 출력, Request/Response info 출력
if(__DEBUG__ & 2) {
if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
return;
}
// Request/Response 정보 작성
$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 method \t\t: %s\n", Context::getResponseMethod());
$buff .= sprintf("\tResponse contents size\t\t: %d byte\n", $this->content_size);
// 전체 실행 시간
$buff .= sprintf("\n- Total elapsed time : %0.5f sec\n", $end-__StartTime__);
$buff .= sprintf("\tclass file load elapsed time \t: %0.5f sec\n", $GLOBALS['__elapsed_class_load__']);
$buff .= sprintf("\tTemplate compile elapsed time\t: %0.5f sec (%d called)\n", $GLOBALS['__template_elapsed__'], $GLOBALS['__TemplateHandlerCalled__']);
$buff .= sprintf("\tXmlParse compile elapsed time\t: %0.5f sec\n", $GLOBALS['__xmlparse_elapsed__']);
$buff .= sprintf("\tPHP elapsed time \t\t: %0.5f sec\n", $end-__StartTime__-$GLOBALS['__template_elapsed__']-$GLOBALS['__xmlparse_elapsed__']-$GLOBALS['__db_elapsed_time__']-$GLOBALS['__elapsed_class_load__']);
// 위젯 실행 시간 작성
$buff .= sprintf("\n\tWidgets elapsed time \t\t: %0.5f sec", $GLOBALS['__widget_excute_elapsed__']);
// 레이아웃 실행 시간
$buff .= sprintf("\n\tLayout compile elapsed time \t: %0.5f sec", $GLOBALS['__layout_compile_elapsed__']);
// 위젯, 에디터 컴포넌트 치환 시간
$buff .= sprintf("\n\tTrans Content \t\t\t: %0.5f sec\n", $GLOBALS['__trans_content_elapsed__']);
}
// DB 로그 작성
if(__DEBUG__ & 4) {
if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
return;
}
if($GLOBALS['__db_queries__']) {
$buff .= sprintf("\n- DB Queries : %d Queries. %0.5f sec\n", count($GLOBALS['__db_queries__']), $GLOBALS['__db_elapsed_time__']);
$num = 0;
foreach($GLOBALS['__db_queries__'] as $query) {
$buff .= sprintf("\t%02d. %s\n\t\t%0.6f sec. ", ++$num, $query['query'], $query['elapsed_time']);
if($query['result'] == 'Success') {
$buff .= "Query Success\n";
} else {
$buff .= sprintf("Query $s : %d\n\t\t\t %s\n", $query['result'], $query['errno'], $query['errstr']);
}
}
}
}
// HTML 주석으로 출력
if($buff && __DEBUG_OUTPUT__ == 1 && Context::getResponseMethod() == 'HTML') {
$buff = sprintf("[%s %s:%d]\n%s\n", date('Y-m-d H:i:s'), $file_name, $line_num, print_r($buff, true));
if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
$buff = 'The IP address is not allowed. Change the value of __DEBUG_PROTECT_IP__ into your IP address in config/config.user.inc.php or config/config.inc.php';
}
return "<!--\r\n".$buff."\r\n-->";
}
// 파일에 출력
if($buff && __DEBUG_OUTPUT__ == 0) {
$debug_file = _XE_PATH_.'files/_debug_message.php';
$buff = sprintf("[%s %s:%d]\n%s\n", date('Y-m-d H:i:s'), $file_name, $line_num, print_r($buff, true));
$buff = str_repeat('=', 40)."\n".$buff.str_repeat('-', 40);
$buff = "\n<?php\n/*".$buff."*/\n?>\n";
if(@!$fp = fopen($debug_file, 'a')) return;
fwrite($fp, $buff);
fclose($fp);
}
}
}
/**
* @brief print a HTTP HEADER for XML, which is encoded in UTF-8
**/
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");
}
/**
* @brief print a HTTP HEADER for HTML, which is encoded in UTF-8
**/
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");
}
/**
* @brief print a HTTP HEADER for JSON, which is encoded in UTF-8
**/
function _printJSONHeader() {
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");
}
}
?>

View file

@ -1,27 +1,27 @@
<?php
/**
* @class EditorHandler
* @author zero (zero@nzeo.com)
* @brief edit component의 상위 클래스임
*
* 주로 하는 일은 컴포넌트 요청시 컴포넌트에서 필요로 하는 변수를 세팅해준다
**/
class EditorHandler extends Object {
/**
* @brief 컴포넌트의 xml및 관련 정보들을 설정
**/
function setInfo($info) {
Context::set('component_info', $info);
if(!$info->extra_vars) return;
foreach($info->extra_vars as $key => $val) {
$this->{$key} = trim($val->value);
}
}
}
?>
<?php
/**
* @class EditorHandler
* @author NHN (developers@xpressengine.com)
* @brief edit component의 상위 클래스임
*
* 주로 하는 일은 컴포넌트 요청시 컴포넌트에서 필요로 하는 변수를 세팅해준다
**/
class EditorHandler extends Object {
/**
* @brief 컴포넌트의 xml및 관련 정보들을 설정
**/
function setInfo($info) {
Context::set('component_info', $info);
if(!$info->extra_vars) return;
foreach($info->extra_vars as $key => $val) {
$this->{$key} = trim($val->value);
}
}
}
?>

View file

@ -1,300 +1,300 @@
<?php
/**
* @class ExtraVar
* @author zero (zero@nzeo.com)
* @brief 게시글, 회원등에서 사용하는 확장변수를 핸들링하는 클래스
*
**/
class ExtraVar {
var $module_srl = null;
var $keys = null;
/**
* @brief constructor
**/
function &getInstance($module_srl) {
return new ExtraVar($module_srl);
}
/**
* @brief constructor
**/
function ExtraVar($module_srl) {
$this->module_srl = $module_srl;
}
/**
* @brief 확장변수 키를 등록
* @param module_srl, idx, name, type, default, desc, is_required, search, value
**/
function setExtraVarKeys($extra_keys) {
if(!is_array($extra_keys) || !count($extra_keys)) return;
foreach($extra_keys as $key => $val) {
$obj = null;
$obj = new ExtraItem($val->module_srl, $val->idx, $val->name, $val->type, $val->default, $val->desc, $val->is_required, $val->search, $val->value, $val->eid);
$this->keys[$val->idx] = $obj;
}
}
/**
* @brief 확장변수 객체 배열 return
**/
function getExtraVars() {
return $this->keys;
}
}
/**
* @class ExtraItem
* @author zero (zero@nzeo.com)
* @brief 확장변수의 개별
**/
class ExtraItem {
var $module_srl = 0;
var $idx = 0;
var $name = 0;
var $type = 'text';
var $default = null;
var $desc = '';
var $is_required = 'N';
var $search = 'N';
var $value = null;
var $eid = '';
/**
* @brief constructor
**/
function ExtraItem($module_srl, $idx, $name, $type = 'text', $default = null, $desc = '', $is_required = 'N', $search = 'N', $value = null, $eid = '') {
if(!$idx) return;
$this->module_srl = $module_srl;
$this->idx = $idx;
$this->name = $name;
$this->type = $type;
$this->default = $default;
$this->desc = $desc;
$this->is_required = $is_required;
$this->search = $search;
$this->value = $value;
$this->eid = $eid;
}
/**
* @brief 지정
**/
function setValue($value) {
$this->value = $value;
}
/**
* @brief type에 따라서 주어진 값을 변형하여 원형 값을 return
**/
function _getTypeValue($type, $value) {
$value = trim($value);
if(!isset($value)) return;
switch($type) {
case 'homepage' :
if($value && !preg_match('/^([a-z]+):\/\//i',$value)) $value = 'http://'.$value;
return htmlspecialchars($value);
break;
case 'tel' :
if(is_array($value)) $values = $value;
elseif(strpos($value,'|@|')!==false) $values = explode('|@|', $value);
elseif(strpos($value,',')!==false) $values = explode(',', $value);
$values[0] = $values[0];
$values[1] = $values[1];
$values[2] = $values[2];
return $values;
break;
break;
case 'checkbox' :
case 'radio' :
case 'select' :
if(is_array($value)) $values = $value;
elseif(strpos($value,'|@|')!==false) $values = explode('|@|', $value);
elseif(strpos($value,',')!==false) $values = explode(',', $value);
else $values = array($value);
for($i=0;$i<count($values);$i++) $values[$i] = htmlspecialchars($values[$i]);
return $values;
break;
case 'kr_zip' :
if(is_array($value)) $values = $value;
elseif(strpos($value,'|@|')!==false) $values = explode('|@|', $value);
elseif(strpos($value,',')!==false) $values = explode(',', $value);
return $values;
break;
//case 'date' :
//case 'email_address' :
//case 'text' :
//case 'textarea' :
default :
return htmlspecialchars($value);
break;
}
}
/**
* @brief 값을 return
* 원형 값을 HTML 결과물로 return
**/
function getValueHTML() {
$value = $this->_getTypeValue($this->type, $this->value);
switch($this->type) {
case 'homepage' :
return ($value)?sprintf('<a href="%s" onclick="window.open(this.href); return false;">%s</a>', $value, $value):"";
case 'email_address' :
return ($value)?sprintf('<a href="mailto:%s">%s</a>', $value, $value):"";
break;
case 'tel' :
return sprintf('%s - %s - %s', $value[0],$value[1],$value[2]);
break;
case 'textarea' :
return nl2br($value);
break;
case 'checkbox' :
if(is_array($value)) return implode(', ',$value);
else return $value;
break;
case 'date' :
return zdate($value,"Y-m-d");
break;
case 'select' :
case 'radio' :
if(is_array($value)) return implode(', ',$value);
else return $value;
break;
case 'kr_zip' :
if(is_array($value)) return implode(' ',$value);
else return $value;
break;
// case 'text' :
default :
return $value;
}
}
/**
* @brief type에 따른 form을 리턴
**/
function getFormHTML() {
$type = $this->type;
$name = $this->name;
$value = $this->_getTypeValue($this->type, $this->value);
$default = $this->_getTypeValue($this->type, $this->default);
$column_name = 'extra_vars'.$this->idx;
$buff = '';
switch($type) {
// 홈페이지 주소
case 'homepage' :
$buff .= '<input type="text" name="'.$column_name.'" value="'.$value.'" class="homepage" />';
break;
// Email 주소
case 'email_address' :
$buff .= '<input type="text" name="'.$column_name.'" value="'.$value.'" class="email_address" />';
break;
// 전화번호
case 'tel' :
$buff .=
'<input type="text" name="'.$column_name.'" value="'.$value[0].'" size="4" class="tel" />'.
'<input type="text" name="'.$column_name.'" value="'.$value[1].'" size="4" class="tel" />'.
'<input type="text" name="'.$column_name.'" value="'.$value[2].'" size="4" class="tel" />';
break;
// textarea
case 'textarea' :
$buff .= '<textarea name="'.$column_name.'" class="textarea">'.$value.'</textarea>';
break;
// 다중 선택
case 'checkbox' :
$buff .= '<ul>';
foreach($default as $v) {
if($value && in_array($v, $value)) $checked = ' checked="checked"';
else $checked = '';
$buff .='<li><input type="checkbox" name="'.$column_name.'" value="'.htmlspecialchars($v).'" '.$checked.' />'.$v.'</li>';
}
$buff .= '</ul>';
break;
// 단일 선택
case 'select' :
$buff .= '<select name="'.$column_name.'" class="select">';
foreach($default as $v) {
if($value && in_array($v,$value)) $selected = ' selected="selected"';
else $selected = '';
$buff .= '<option value="'.$v.'" '.$selected.'>'.$v.'</option>';
}
$buff .= '</select>';
break;
// radio
case 'radio' :
$buff .= '<ul>';
foreach($default as $v) {
if($value && in_array($v,$value)) $checked = ' checked="checked"';
else $checked = '';
$buff .= '<li><input type="radio" name="'.$column_name.'" '.$checked.' value="'.$v.'" class="radio" />'.$v.'</li>';
}
$buff .= '</ul>';
break;
// 날짜 입력
case 'date' :
// datepicker javascript plugin load
Context::loadJavascriptPlugin('ui.datepicker');
$buff .=
'<input type="hidden" name="'.$column_name.'" value="'.$value.'" />'.
'<input type="text" id="date_'.$column_name.'" value="'.zdate($value,'Y-m-d').'" readonly="readonly" class="date" />'."\n".
'<script type="text/javascript">'."\n".
'(function($){'."\n".
' $(function(){'."\n".
' var option = { changeMonth:true, changeYear:true, gotoCurrent: false,yearRange:\'-100:+10\', onSelect:function(){'."\n".
' $(this).prev(\'input[type="hidden"]\').val(this.value.replace(/-/g,""))}'."\n".
' };'."\n".
' $.extend(option,$.datepicker.regional[\''.Context::getLangType().'\']);'."\n".
' $("#date_'.$column_name.'").datepicker(option);'."\n".
' });'."\n".
'})(jQuery);'."\n".
'</script>';
break;
// 주소 입력
case "kr_zip" :
// krzip address javascript plugin load
Context::loadJavascriptPlugin('ui.krzip');
$buff .=
'<div id="addr_searched_'.$column_name.'" style="display:'.($value[0]?'block':'none').';">'.
'<input type="text" readonly="readonly" name="'.$column_name.'" value="'.$value[0].'" class="address" />'.
'<a href="#" onclick="doShowKrZipSearch(this, \''.$column_name.'\'); return false;" class="button red"><span>'.Context::getLang('cmd_cancel').'</span></a>'.
'</div>'.
'<div id="addr_list_'.$column_name.'" style="display:none;">'.
'<select name="addr_list_'.$column_name.'"></select>'.
'<a href="#" onclick="doSelectKrZip(this, \''.$column_name.'\'); return false;" class="button blue"><span>'.Context::getLang('cmd_select').'</span></a>'.
'<a href="#" onclick="doHideKrZipList(this, \''.$column_name.'\'); return false;" class="button red"><span>'.Context::getLang('cmd_cancel').'</span></a>'.
'</div>'.
'<div id="addr_search_'.$column_name.'" style="display:'.($value[0]?'none':'block').'">'.
'<input type="text" name="addr_search_'.$column_name.'" class="address" value="" />'.
'<a href="#" onclick="doSearchKrZip(this, \''.$column_name.'\'); return false;" class="button green"><span>'.Context::getLang('cmd_search').'</span></a>'.
'</div>'.
'<input type="text" name="'.$column_name.'" value="'.htmlspecialchars($value[1]).'" class="address" />'.
'';
break;
// 일반 text
default :
$buff .=' <input type="text" name="'.$column_name.'" value="'.$value.'" class="text" />';
break;
}
if($this->desc) $buff .= '<p>'.$this->desc.'</p>';
return $buff;
}
}
?>
<?php
/**
* @class ExtraVar
* @author NHN (developers@xpressengine.com)
* @brief 게시글, 회원등에서 사용하는 확장변수를 핸들링하는 클래스
*
**/
class ExtraVar {
var $module_srl = null;
var $keys = null;
/**
* @brief constructor
**/
function &getInstance($module_srl) {
return new ExtraVar($module_srl);
}
/**
* @brief constructor
**/
function ExtraVar($module_srl) {
$this->module_srl = $module_srl;
}
/**
* @brief 확장변수 키를 등록
* @param module_srl, idx, name, type, default, desc, is_required, search, value
**/
function setExtraVarKeys($extra_keys) {
if(!is_array($extra_keys) || !count($extra_keys)) return;
foreach($extra_keys as $key => $val) {
$obj = null;
$obj = new ExtraItem($val->module_srl, $val->idx, $val->name, $val->type, $val->default, $val->desc, $val->is_required, $val->search, $val->value, $val->eid);
$this->keys[$val->idx] = $obj;
}
}
/**
* @brief 확장변수 객체 배열 return
**/
function getExtraVars() {
return $this->keys;
}
}
/**
* @class ExtraItem
* @author NHN (developers@xpressengine.com)
* @brief 확장변수의 개별
**/
class ExtraItem {
var $module_srl = 0;
var $idx = 0;
var $name = 0;
var $type = 'text';
var $default = null;
var $desc = '';
var $is_required = 'N';
var $search = 'N';
var $value = null;
var $eid = '';
/**
* @brief constructor
**/
function ExtraItem($module_srl, $idx, $name, $type = 'text', $default = null, $desc = '', $is_required = 'N', $search = 'N', $value = null, $eid = '') {
if(!$idx) return;
$this->module_srl = $module_srl;
$this->idx = $idx;
$this->name = $name;
$this->type = $type;
$this->default = $default;
$this->desc = $desc;
$this->is_required = $is_required;
$this->search = $search;
$this->value = $value;
$this->eid = $eid;
}
/**
* @brief 지정
**/
function setValue($value) {
$this->value = $value;
}
/**
* @brief type에 따라서 주어진 값을 변형하여 원형 값을 return
**/
function _getTypeValue($type, $value) {
$value = trim($value);
if(!isset($value)) return;
switch($type) {
case 'homepage' :
if($value && !preg_match('/^([a-z]+):\/\//i',$value)) $value = 'http://'.$value;
return htmlspecialchars($value);
break;
case 'tel' :
if(is_array($value)) $values = $value;
elseif(strpos($value,'|@|')!==false) $values = explode('|@|', $value);
elseif(strpos($value,',')!==false) $values = explode(',', $value);
$values[0] = $values[0];
$values[1] = $values[1];
$values[2] = $values[2];
return $values;
break;
break;
case 'checkbox' :
case 'radio' :
case 'select' :
if(is_array($value)) $values = $value;
elseif(strpos($value,'|@|')!==false) $values = explode('|@|', $value);
elseif(strpos($value,',')!==false) $values = explode(',', $value);
else $values = array($value);
for($i=0;$i<count($values);$i++) $values[$i] = htmlspecialchars($values[$i]);
return $values;
break;
case 'kr_zip' :
if(is_array($value)) $values = $value;
elseif(strpos($value,'|@|')!==false) $values = explode('|@|', $value);
elseif(strpos($value,',')!==false) $values = explode(',', $value);
return $values;
break;
//case 'date' :
//case 'email_address' :
//case 'text' :
//case 'textarea' :
default :
return htmlspecialchars($value);
break;
}
}
/**
* @brief 값을 return
* 원형 값을 HTML 결과물로 return
**/
function getValueHTML() {
$value = $this->_getTypeValue($this->type, $this->value);
switch($this->type) {
case 'homepage' :
return ($value)?sprintf('<a href="%s" onclick="window.open(this.href); return false;">%s</a>', $value, $value):"";
case 'email_address' :
return ($value)?sprintf('<a href="mailto:%s">%s</a>', $value, $value):"";
break;
case 'tel' :
return sprintf('%s - %s - %s', $value[0],$value[1],$value[2]);
break;
case 'textarea' :
return nl2br($value);
break;
case 'checkbox' :
if(is_array($value)) return implode(', ',$value);
else return $value;
break;
case 'date' :
return zdate($value,"Y-m-d");
break;
case 'select' :
case 'radio' :
if(is_array($value)) return implode(', ',$value);
else return $value;
break;
case 'kr_zip' :
if(is_array($value)) return implode(' ',$value);
else return $value;
break;
// case 'text' :
default :
return $value;
}
}
/**
* @brief type에 따른 form을 리턴
**/
function getFormHTML() {
$type = $this->type;
$name = $this->name;
$value = $this->_getTypeValue($this->type, $this->value);
$default = $this->_getTypeValue($this->type, $this->default);
$column_name = 'extra_vars'.$this->idx;
$buff = '';
switch($type) {
// 홈페이지 주소
case 'homepage' :
$buff .= '<input type="text" name="'.$column_name.'" value="'.$value.'" class="homepage" />';
break;
// Email 주소
case 'email_address' :
$buff .= '<input type="text" name="'.$column_name.'" value="'.$value.'" class="email_address" />';
break;
// 전화번호
case 'tel' :
$buff .=
'<input type="text" name="'.$column_name.'" value="'.$value[0].'" size="4" class="tel" />'.
'<input type="text" name="'.$column_name.'" value="'.$value[1].'" size="4" class="tel" />'.
'<input type="text" name="'.$column_name.'" value="'.$value[2].'" size="4" class="tel" />';
break;
// textarea
case 'textarea' :
$buff .= '<textarea name="'.$column_name.'" class="textarea">'.$value.'</textarea>';
break;
// 다중 선택
case 'checkbox' :
$buff .= '<ul>';
foreach($default as $v) {
if($value && in_array($v, $value)) $checked = ' checked="checked"';
else $checked = '';
$buff .='<li><input type="checkbox" name="'.$column_name.'" value="'.htmlspecialchars($v).'" '.$checked.' />'.$v.'</li>';
}
$buff .= '</ul>';
break;
// 단일 선택
case 'select' :
$buff .= '<select name="'.$column_name.'" class="select">';
foreach($default as $v) {
if($value && in_array($v,$value)) $selected = ' selected="selected"';
else $selected = '';
$buff .= '<option value="'.$v.'" '.$selected.'>'.$v.'</option>';
}
$buff .= '</select>';
break;
// radio
case 'radio' :
$buff .= '<ul>';
foreach($default as $v) {
if($value && in_array($v,$value)) $checked = ' checked="checked"';
else $checked = '';
$buff .= '<li><input type="radio" name="'.$column_name.'" '.$checked.' value="'.$v.'" class="radio" />'.$v.'</li>';
}
$buff .= '</ul>';
break;
// 날짜 입력
case 'date' :
// datepicker javascript plugin load
Context::loadJavascriptPlugin('ui.datepicker');
$buff .=
'<input type="hidden" name="'.$column_name.'" value="'.$value.'" />'.
'<input type="text" id="date_'.$column_name.'" value="'.zdate($value,'Y-m-d').'" readonly="readonly" class="date" />'."\n".
'<script type="text/javascript">'."\n".
'(function($){'."\n".
' $(function(){'."\n".
' var option = { changeMonth:true, changeYear:true, gotoCurrent: false,yearRange:\'-100:+10\', onSelect:function(){'."\n".
' $(this).prev(\'input[type="hidden"]\').val(this.value.replace(/-/g,""))}'."\n".
' };'."\n".
' $.extend(option,$.datepicker.regional[\''.Context::getLangType().'\']);'."\n".
' $("#date_'.$column_name.'").datepicker(option);'."\n".
' });'."\n".
'})(jQuery);'."\n".
'</script>';
break;
// 주소 입력
case "kr_zip" :
// krzip address javascript plugin load
Context::loadJavascriptPlugin('ui.krzip');
$buff .=
'<div id="addr_searched_'.$column_name.'" style="display:'.($value[0]?'block':'none').';">'.
'<input type="text" readonly="readonly" name="'.$column_name.'" value="'.$value[0].'" class="address" />'.
'<a href="#" onclick="doShowKrZipSearch(this, \''.$column_name.'\'); return false;" class="button red"><span>'.Context::getLang('cmd_cancel').'</span></a>'.
'</div>'.
'<div id="addr_list_'.$column_name.'" style="display:none;">'.
'<select name="addr_list_'.$column_name.'"></select>'.
'<a href="#" onclick="doSelectKrZip(this, \''.$column_name.'\'); return false;" class="button blue"><span>'.Context::getLang('cmd_select').'</span></a>'.
'<a href="#" onclick="doHideKrZipList(this, \''.$column_name.'\'); return false;" class="button red"><span>'.Context::getLang('cmd_cancel').'</span></a>'.
'</div>'.
'<div id="addr_search_'.$column_name.'" style="display:'.($value[0]?'none':'block').'">'.
'<input type="text" name="addr_search_'.$column_name.'" class="address" value="" />'.
'<a href="#" onclick="doSearchKrZip(this, \''.$column_name.'\'); return false;" class="button green"><span>'.Context::getLang('cmd_search').'</span></a>'.
'</div>'.
'<input type="text" name="'.$column_name.'" value="'.htmlspecialchars($value[1]).'" class="address" />'.
'';
break;
// 일반 text
default :
$buff .=' <input type="text" name="'.$column_name.'" value="'.$value.'" class="text" />';
break;
}
if($this->desc) $buff .= '<p>'.$this->desc.'</p>';
return $buff;
}
}
?>

File diff suppressed because it is too large Load diff

View file

@ -1,128 +1,128 @@
<?php
/**
* @class FileObject
* @author haneul (haneul0318@gmail.com)
* @brief file abstraction class
**/
class FileObject extends Object
{
var $fp = null; ///< file descriptor
var $path = null; ///< file path
var $mode = "r"; ///< file open mode
/**
* @brief constructor
* @param[in] $path path of target file
* @param[in] $mode file open mode
* @return file object
**/
function FileObject($path, $mode)
{
if($path != null) $this->Open($path, $mode);
}
/**
* @brief append target file's content to current file
* @param[in] $file_name path of target file
* @return none
**/
function append($file_name)
{
$target = new FileObject($file_name, "r");
while(!$target->feof())
{
$readstr = $target->read();
$this->write($readstr);
}
$target->close();
}
/**
* @brief check current file meets eof
* @return true: if eof. false: otherwise
**/
function feof()
{
return feof($this->fp);
}
/**
* @brief read from current file
* @param[in] $size size to read
* @return read bytes
**/
function read($size = 1024)
{
return fread($this->fp, $size);
}
/**
* @brief write string to current file
* @param[in] $str string to write
* @return written bytes. if failed, it returns false
**/
function write($str)
{
$len = strlen($str);
if(!$str || $len <= 0) return false;
if(!$this->fp) return false;
$written = fwrite($this->fp, $str);
return $written;
}
/**
* @brief open a file
* @param[in] $path path of target file
* @param[in] $mode file open mode
* @remarks if file is opened, close it and open the new path
* @return true if succeed, false otherwise.
*/
function open($path, $mode)
{
if($this->fp != null)
{
$this->close();
}
$this->fp = fopen($path, $mode);
if(! is_resource($this->fp) )
{
$this->fp = null;
return false;
}
$this->path = $path;
return true;
}
/**
* @brief return current file's path
* @return file path
**/
function getPath()
{
if($this->fp != null)
{
return $this->path;
}
else
{
return null;
}
}
/**
* @brief close file
* @return none
**/
function close()
{
if($this->fp != null)
{
fclose($this->fp);
$this->fp = null;
}
}
}
?>
<?php
/**
* @class FileObject
* @author NHN (developers@xpressengine.com)
* @brief file abstraction class
**/
class FileObject extends Object
{
var $fp = null; ///< file descriptor
var $path = null; ///< file path
var $mode = "r"; ///< file open mode
/**
* @brief constructor
* @param[in] $path path of target file
* @param[in] $mode file open mode
* @return file object
**/
function FileObject($path, $mode)
{
if($path != null) $this->Open($path, $mode);
}
/**
* @brief append target file's content to current file
* @param[in] $file_name path of target file
* @return none
**/
function append($file_name)
{
$target = new FileObject($file_name, "r");
while(!$target->feof())
{
$readstr = $target->read();
$this->write($readstr);
}
$target->close();
}
/**
* @brief check current file meets eof
* @return true: if eof. false: otherwise
**/
function feof()
{
return feof($this->fp);
}
/**
* @brief read from current file
* @param[in] $size size to read
* @return read bytes
**/
function read($size = 1024)
{
return fread($this->fp, $size);
}
/**
* @brief write string to current file
* @param[in] $str string to write
* @return written bytes. if failed, it returns false
**/
function write($str)
{
$len = strlen($str);
if(!$str || $len <= 0) return false;
if(!$this->fp) return false;
$written = fwrite($this->fp, $str);
return $written;
}
/**
* @brief open a file
* @param[in] $path path of target file
* @param[in] $mode file open mode
* @remarks if file is opened, close it and open the new path
* @return true if succeed, false otherwise.
*/
function open($path, $mode)
{
if($this->fp != null)
{
$this->close();
}
$this->fp = fopen($path, $mode);
if(! is_resource($this->fp) )
{
$this->fp = null;
return false;
}
$this->path = $path;
return true;
}
/**
* @brief return current file's path
* @return file path
**/
function getPath()
{
if($this->fp != null)
{
return $this->path;
}
else
{
return null;
}
}
/**
* @brief close file
* @return none
**/
function close()
{
if($this->fp != null)
{
fclose($this->fp);
$this->fp = null;
}
}
}
?>

View file

@ -1,11 +1,11 @@
<?php
/**
* @class Handler
* @author zero (zero@nzeo.com)
* @brief an abstract class of (*)Handler
**/
class Handler {
}
?>
<?php
/**
* @class Handler
* @author NHN (developers@xpressengine.com)
* @brief an abstract class of (*)Handler
**/
class Handler {
}
?>

View file

@ -1,85 +1,85 @@
<?php
/**
* @class HttpRequest
* @author haneul (haneul@gmail.com)
* @version 0.1
* @brief a class that is designed to be used for sending out HTTP request to an external server and retrieving response
* @remarks Connection: keep-alive is not supported
*/
class XEHttpRequest {
/// target host
var $m_host;
/// target Port
var $m_port;
/// header array
var $m_headers;
/**
* @brief Constructor
*/
function XEHttpRequest($host, $port)
{
$this->m_host = $host;
$this->m_port = $port;
$this->m_headers = array();
}
/**
* @brief mether to add key/value pair to the HTTP request header
* @param[in] key HTTP header element
* @param[in] value value string for HTTP header element
*/
function AddToHeader($key, $value)
{
$this->m_headers[$key] = $value;
}
/**
* @brief send HTTP message to the host
* @param[in] target ip or url of the external server
* @param[in] method HTTP method such as GET and POST
* @param[in] timeout time out value for HTTP request expiration
* @return Returns an object containing HTTP Response body and HTTP response code
*/
function Send($target, $method="GET", $timeout = 3)
{
$socket = @fsockopen($this->m_host, $this->m_port, $errno, $errstr, $timeout);
if(!$socket)
{
return new Object(-1, "socket_connect_failed");
}
$this->AddToHeader('Host', $this->m_host);
$this->AddToHeader('Connection', "close");
$crlf = "\r\n";
$request = "$method $target HTTP/1.1$crlf";
foreach($this->m_headers as $equiv => $content)
{
$request .= "$equiv: $content$crlf";
}
$request .= $crlf;
fwrite($socket, $request);
list($httpver, $code, $status) = split(' +', rtrim(fgets($socket)));
// read response header
while(strlen(trim($line = fgets($socket))))
{
list($equiv, $content) = split(' *: *', rtrim($line));
}
$body = '';
while(!feof($socket))
{
$body .= fgets($socket, 128);
}
fclose($socket);
$ret->result_code = $code;
$ret->body = $body;
return $ret;
}
}
?>
<?php
/**
* @class HttpRequest
* @author NHN (developers@xpressengine.com)
* @version 0.1
* @brief a class that is designed to be used for sending out HTTP request to an external server and retrieving response
* @remarks Connection: keep-alive is not supported
*/
class XEHttpRequest {
/// target host
var $m_host;
/// target Port
var $m_port;
/// header array
var $m_headers;
/**
* @brief Constructor
*/
function XEHttpRequest($host, $port)
{
$this->m_host = $host;
$this->m_port = $port;
$this->m_headers = array();
}
/**
* @brief mether to add key/value pair to the HTTP request header
* @param[in] key HTTP header element
* @param[in] value value string for HTTP header element
*/
function AddToHeader($key, $value)
{
$this->m_headers[$key] = $value;
}
/**
* @brief send HTTP message to the host
* @param[in] target ip or url of the external server
* @param[in] method HTTP method such as GET and POST
* @param[in] timeout time out value for HTTP request expiration
* @return Returns an object containing HTTP Response body and HTTP response code
*/
function Send($target, $method="GET", $timeout = 3)
{
$socket = @fsockopen($this->m_host, $this->m_port, $errno, $errstr, $timeout);
if(!$socket)
{
return new Object(-1, "socket_connect_failed");
}
$this->AddToHeader('Host', $this->m_host);
$this->AddToHeader('Connection', "close");
$crlf = "\r\n";
$request = "$method $target HTTP/1.1$crlf";
foreach($this->m_headers as $equiv => $content)
{
$request .= "$equiv: $content$crlf";
}
$request .= $crlf;
fwrite($socket, $request);
list($httpver, $code, $status) = split(' +', rtrim(fgets($socket)));
// read response header
while(strlen(trim($line = fgets($socket))))
{
list($equiv, $content) = split(' *: *', rtrim($line));
}
$body = '';
while(!feof($socket))
{
$body .= fgets($socket, 128);
}
fclose($socket);
$ret->result_code = $code;
$ret->body = $body;
return $ret;
}
}
?>

View file

@ -1,353 +1,353 @@
<?php
/**
* @brief 메일 발송
* @author zero (zero@zeroboard.com)
**/
class Mail {
var $sender_name = '';
var $sender_email = '';
var $receiptor_name = '';
var $receiptor_email = '';
var $title = '';
var $content = '';
var $content_type = 'html';
var $messageId = null;
var $replyTo = null;
var $bcc = null;
var $attachments = array();
var $cidAttachments = array();
var $mainMailPart = null;
var $body = '';
var $header = '';
var $eol = '';
var $references = '';
var $additional_params = null;
function Mail() { }
function setAdditionalParams($additional_params)
{
$this->additional_params = $additional_params;
}
function addAttachment($filename, $orgfilename)
{
$this->attachments[$orgfilename] = $filename;
}
function addCidAttachment($filename, $cid)
{
$this->cidAttachments[$cid] = $filename;
}
function setSender($name, $email) {
$this->sender_name = $name;
$this->sender_email = $email;
}
function getSender() {
if(!stristr(PHP_OS, 'win') && $this->sender_name) return sprintf("%s <%s>", '=?utf-8?b?'.base64_encode($this->sender_name).'?=', $this->sender_email);
return $this->sender_email;
}
function setReceiptor($name, $email) {
$this->receiptor_name = $name;
$this->receiptor_email = $email;
}
function getReceiptor() {
if(!stristr(PHP_OS, 'win') && $this->receiptor_name && $this->receiptor_name != $this->receiptor_email) return sprintf("%s <%s>", '=?utf-8?b?'.base64_encode($this->receiptor_name).'?=', $this->receiptor_email);
return $this->receiptor_email;
}
function setTitle($title) {
$this->title = $title;
}
function getTitle() {
return '=?utf-8?b?'.base64_encode($this->title).'?=';
}
function setBCC($bcc)
{
$this->bcc = $bcc;
}
function setMessageID($messageId) {
$this->messageId = $messageId;
}
function setReferences($references) {
$this->references = $references;
}
function setReplyTo($replyTo)
{
$this->replyTo = $replyTo;
}
function setContent($content) {
$content = preg_replace_callback('/<img([^>]+)>/i',array($this,'replaceResourceRealPath'), $content);
$this->content = $content;
}
function replaceResourceRealPath($matches) {
return preg_replace('/src=(["\']?)files/i','src=$1'.Context::getRequestUri().'files', $matches[0]);
}
function getPlainContent() {
return chunk_split(base64_encode(str_replace(array("<",">","&"), array("&lt;","&gt;","&amp;"), $this->content)));
}
function getHTMLContent() {
return chunk_split(base64_encode($this->content_type!='html'?nl2br($this->content):$this->content));
}
function setContentType($mode = 'html') {
$this->content_type = $mode=='html'?'html':'';
}
function procAttachments()
{
if(count($this->attachments) > 0)
{
$this->body = $this->header.$this->body;
$boundary = '----=='.uniqid(rand(),true);
$this->header = "Content-Type: multipart/mixed;".$this->eol."\tboundary=\"".$boundary."\"".$this->eol.$this->eol;
$this->body = "--".$boundary.$this->eol.$this->body.$this->eol.$this->eol;
$res = array();
$res[] = $this->body;
foreach($this->attachments as $filename => $attachment)
{
$type = $this->returnMIMEType($filename);
$file_str = FileHandler::readFile($attachment);
$chunks = chunk_split(base64_encode($file_str));
$tempBody = sprintf(
"--".$boundary.$this->eol.
"Content-Type: %s;".$this->eol.
"\tname=\"%s\"".$this->eol.
"Content-Transfer-Encoding: base64".$this->eol.
"Content-Description: %s".$this->eol.
"Content-Disposition: attachment;".$this->eol.
"\tfilename=\"%s\"".$this->eol.$this->eol.
"%s".$this->eol.$this->eol,
$type,
$filename,
$filename,
$filename,
$chunks);
$res[] = $tempBody;
}
$this->body = implode("", $res);
$this->body .= "--".$boundary."--";
}
}
function procCidAttachments()
{
if(count($this->cidAttachments) > 0)
{
$this->body = $this->header.$this->body;
$boundary = '----=='.uniqid(rand(),true);
$this->header = "Content-Type: multipart/relative;".$this->eol."\ttype=\"multipart/alternative\";".$this->eol."\tboundary=\"".$boundary."\"".$this->eol.$this->eol;
$this->body = "--".$boundary.$this->eol.$this->body.$this->eol.$this->eol;
$res = array();
$res[] = $this->body;
foreach($this->cidAttachments as $cid => $attachment)
{
$filename = basename($attachment);
$type = $this->returnMIMEType(FileHandler::getRealPath($attachment));
$file_str = FileHandler::readFile($attachment);
$chunks = chunk_split(base64_encode($file_str));
$tempBody = sprintf(
"--".$boundary.$this->eol.
"Content-Type: %s;".$this->eol.
"\tname=\"%s\"".$this->eol.
"Content-Transfer-Encoding: base64".$this->eol.
"Content-ID: <%s>".$this->eol.
"Content-Description: %s".$this->eol.
"Content-Location: %s".$this->eol.$this->eol.
"%s".$this->eol.$this->eol,
$type,
$filename,
$cid,
$filename,
$filename,
$chunks);
$res[] = $tempBody;
}
$this->body = implode("", $res);
$this->body .= "--".$boundary."--";
}
}
function send() {
$boundary = '----=='.uniqid(rand(),true);
$this->eol = $GLOBALS['_qmail_compatibility'] == "Y" ? "\n" : "\r\n";
$this->header = "Content-Type: multipart/alternative;".$this->eol."\tboundary=\"".$boundary."\"".$this->eol.$this->eol;
$this->body = sprintf(
"--%s".$this->eol.
"Content-Type: text/plain; charset=utf-8; format=flowed".$this->eol.
"Content-Transfer-Encoding: base64".$this->eol.
"Content-Disposition: inline".$this->eol.$this->eol.
"%s".
"--%s".$this->eol.
"Content-Type: text/html; charset=utf-8".$this->eol.
"Content-Transfer-Encoding: base64".$this->eol.
"Content-Disposition: inline".$this->eol.$this->eol.
"%s".
"--%s--".
"",
$boundary,
$this->getPlainContent(),
$boundary,
$this->getHTMLContent(),
$boundary
);
$this->procCidAttachments();
$this->procAttachments();
$headers = sprintf(
"From: %s".$this->eol.
"%s".
"%s".
"%s".
"%s".
"MIME-Version: 1.0".$this->eol."",
$this->getSender(),
$this->messageId?("Message-ID: <".$this->messageId.">".$this->eol):"",
$this->replyTo?("Reply-To: <".$this->replyTo.">".$this->eol):"",
$this->bcc?("Bcc: ".$this->bcc.$this->eol):"",
$this->references?("References: <".$this->references.">".$this->eol."In-Reply-To: <".$this->references.">".$this->eol):""
);
$headers .= $this->header;
if($this->additional_params) return mail($this->getReceiptor(), $this->getTitle(), $this->body, $headers, $this->additional_params);
return mail($this->getReceiptor(), $this->getTitle(), $this->body, $headers);
}
function checkMailMX($email_address) {
if(!Mail::isVaildMailAddress($email_address)) return false;
list($user, $host) = explode("@", $email_address);
if(function_exists('checkdnsrr')) {
if (checkdnsrr($host, "MX") or checkdnsrr($host, "A")) return true;
else return false;
}
return true;
}
function isVaildMailAddress($email_address) {
if( preg_match("/([a-z0-9\_\-\.]+)@([a-z0-9\_\-\.]+)/i", $email_address) ) return $email_address;
else return '';
}
function returnMIMEType($filename)
{
preg_match("|\.([a-z0-9]{2,4})$|i", $filename, $fileSuffix);
switch(strtolower($fileSuffix[1]))
{
case "js" :
return "application/x-javascript";
case "json" :
return "application/json";
case "jpg" :
case "jpeg" :
case "jpe" :
return "image/jpg";
case "png" :
case "gif" :
case "bmp" :
case "tiff" :
return "image/".strtolower($fileSuffix[1]);
case "css" :
return "text/css";
case "xml" :
return "application/xml";
case "doc" :
case "docx" :
return "application/msword";
case "xls" :
case "xlt" :
case "xlm" :
case "xld" :
case "xla" :
case "xlc" :
case "xlw" :
case "xll" :
return "application/vnd.ms-excel";
case "ppt" :
case "pps" :
return "application/vnd.ms-powerpoint";
case "rtf" :
return "application/rtf";
case "pdf" :
return "application/pdf";
case "html" :
case "htm" :
case "php" :
return "text/html";
case "txt" :
return "text/plain";
case "mpeg" :
case "mpg" :
case "mpe" :
return "video/mpeg";
case "mp3" :
return "audio/mpeg3";
case "wav" :
return "audio/wav";
case "aiff" :
case "aif" :
return "audio/aiff";
case "avi" :
return "video/msvideo";
case "wmv" :
return "video/x-ms-wmv";
case "mov" :
return "video/quicktime";
case "zip" :
return "application/zip";
case "tar" :
return "application/x-tar";
case "swf" :
return "application/x-shockwave-flash";
default :
if(function_exists("mime_content_type"))
{
$fileSuffix = mime_content_type($filename);
}
return "unknown/" . trim($fileSuffix[0], ".");
}
}
}
?>
<?php
/**
* @brief 메일 발송
* @author NHN (developers@xpressengine.com)
**/
class Mail {
var $sender_name = '';
var $sender_email = '';
var $receiptor_name = '';
var $receiptor_email = '';
var $title = '';
var $content = '';
var $content_type = 'html';
var $messageId = null;
var $replyTo = null;
var $bcc = null;
var $attachments = array();
var $cidAttachments = array();
var $mainMailPart = null;
var $body = '';
var $header = '';
var $eol = '';
var $references = '';
var $additional_params = null;
function Mail() { }
function setAdditionalParams($additional_params)
{
$this->additional_params = $additional_params;
}
function addAttachment($filename, $orgfilename)
{
$this->attachments[$orgfilename] = $filename;
}
function addCidAttachment($filename, $cid)
{
$this->cidAttachments[$cid] = $filename;
}
function setSender($name, $email) {
$this->sender_name = $name;
$this->sender_email = $email;
}
function getSender() {
if(!stristr(PHP_OS, 'win') && $this->sender_name) return sprintf("%s <%s>", '=?utf-8?b?'.base64_encode($this->sender_name).'?=', $this->sender_email);
return $this->sender_email;
}
function setReceiptor($name, $email) {
$this->receiptor_name = $name;
$this->receiptor_email = $email;
}
function getReceiptor() {
if(!stristr(PHP_OS, 'win') && $this->receiptor_name && $this->receiptor_name != $this->receiptor_email) return sprintf("%s <%s>", '=?utf-8?b?'.base64_encode($this->receiptor_name).'?=', $this->receiptor_email);
return $this->receiptor_email;
}
function setTitle($title) {
$this->title = $title;
}
function getTitle() {
return '=?utf-8?b?'.base64_encode($this->title).'?=';
}
function setBCC($bcc)
{
$this->bcc = $bcc;
}
function setMessageID($messageId) {
$this->messageId = $messageId;
}
function setReferences($references) {
$this->references = $references;
}
function setReplyTo($replyTo)
{
$this->replyTo = $replyTo;
}
function setContent($content) {
$content = preg_replace_callback('/<img([^>]+)>/i',array($this,'replaceResourceRealPath'), $content);
$this->content = $content;
}
function replaceResourceRealPath($matches) {
return preg_replace('/src=(["\']?)files/i','src=$1'.Context::getRequestUri().'files', $matches[0]);
}
function getPlainContent() {
return chunk_split(base64_encode(str_replace(array("<",">","&"), array("&lt;","&gt;","&amp;"), $this->content)));
}
function getHTMLContent() {
return chunk_split(base64_encode($this->content_type!='html'?nl2br($this->content):$this->content));
}
function setContentType($mode = 'html') {
$this->content_type = $mode=='html'?'html':'';
}
function procAttachments()
{
if(count($this->attachments) > 0)
{
$this->body = $this->header.$this->body;
$boundary = '----=='.uniqid(rand(),true);
$this->header = "Content-Type: multipart/mixed;".$this->eol."\tboundary=\"".$boundary."\"".$this->eol.$this->eol;
$this->body = "--".$boundary.$this->eol.$this->body.$this->eol.$this->eol;
$res = array();
$res[] = $this->body;
foreach($this->attachments as $filename => $attachment)
{
$type = $this->returnMIMEType($filename);
$file_str = FileHandler::readFile($attachment);
$chunks = chunk_split(base64_encode($file_str));
$tempBody = sprintf(
"--".$boundary.$this->eol.
"Content-Type: %s;".$this->eol.
"\tname=\"%s\"".$this->eol.
"Content-Transfer-Encoding: base64".$this->eol.
"Content-Description: %s".$this->eol.
"Content-Disposition: attachment;".$this->eol.
"\tfilename=\"%s\"".$this->eol.$this->eol.
"%s".$this->eol.$this->eol,
$type,
$filename,
$filename,
$filename,
$chunks);
$res[] = $tempBody;
}
$this->body = implode("", $res);
$this->body .= "--".$boundary."--";
}
}
function procCidAttachments()
{
if(count($this->cidAttachments) > 0)
{
$this->body = $this->header.$this->body;
$boundary = '----=='.uniqid(rand(),true);
$this->header = "Content-Type: multipart/relative;".$this->eol."\ttype=\"multipart/alternative\";".$this->eol."\tboundary=\"".$boundary."\"".$this->eol.$this->eol;
$this->body = "--".$boundary.$this->eol.$this->body.$this->eol.$this->eol;
$res = array();
$res[] = $this->body;
foreach($this->cidAttachments as $cid => $attachment)
{
$filename = basename($attachment);
$type = $this->returnMIMEType(FileHandler::getRealPath($attachment));
$file_str = FileHandler::readFile($attachment);
$chunks = chunk_split(base64_encode($file_str));
$tempBody = sprintf(
"--".$boundary.$this->eol.
"Content-Type: %s;".$this->eol.
"\tname=\"%s\"".$this->eol.
"Content-Transfer-Encoding: base64".$this->eol.
"Content-ID: <%s>".$this->eol.
"Content-Description: %s".$this->eol.
"Content-Location: %s".$this->eol.$this->eol.
"%s".$this->eol.$this->eol,
$type,
$filename,
$cid,
$filename,
$filename,
$chunks);
$res[] = $tempBody;
}
$this->body = implode("", $res);
$this->body .= "--".$boundary."--";
}
}
function send() {
$boundary = '----=='.uniqid(rand(),true);
$this->eol = $GLOBALS['_qmail_compatibility'] == "Y" ? "\n" : "\r\n";
$this->header = "Content-Type: multipart/alternative;".$this->eol."\tboundary=\"".$boundary."\"".$this->eol.$this->eol;
$this->body = sprintf(
"--%s".$this->eol.
"Content-Type: text/plain; charset=utf-8; format=flowed".$this->eol.
"Content-Transfer-Encoding: base64".$this->eol.
"Content-Disposition: inline".$this->eol.$this->eol.
"%s".
"--%s".$this->eol.
"Content-Type: text/html; charset=utf-8".$this->eol.
"Content-Transfer-Encoding: base64".$this->eol.
"Content-Disposition: inline".$this->eol.$this->eol.
"%s".
"--%s--".
"",
$boundary,
$this->getPlainContent(),
$boundary,
$this->getHTMLContent(),
$boundary
);
$this->procCidAttachments();
$this->procAttachments();
$headers = sprintf(
"From: %s".$this->eol.
"%s".
"%s".
"%s".
"%s".
"MIME-Version: 1.0".$this->eol."",
$this->getSender(),
$this->messageId?("Message-ID: <".$this->messageId.">".$this->eol):"",
$this->replyTo?("Reply-To: <".$this->replyTo.">".$this->eol):"",
$this->bcc?("Bcc: ".$this->bcc.$this->eol):"",
$this->references?("References: <".$this->references.">".$this->eol."In-Reply-To: <".$this->references.">".$this->eol):""
);
$headers .= $this->header;
if($this->additional_params) return mail($this->getReceiptor(), $this->getTitle(), $this->body, $headers, $this->additional_params);
return mail($this->getReceiptor(), $this->getTitle(), $this->body, $headers);
}
function checkMailMX($email_address) {
if(!Mail::isVaildMailAddress($email_address)) return false;
list($user, $host) = explode("@", $email_address);
if(function_exists('checkdnsrr')) {
if (checkdnsrr($host, "MX") or checkdnsrr($host, "A")) return true;
else return false;
}
return true;
}
function isVaildMailAddress($email_address) {
if( preg_match("/([a-z0-9\_\-\.]+)@([a-z0-9\_\-\.]+)/i", $email_address) ) return $email_address;
else return '';
}
function returnMIMEType($filename)
{
preg_match("|\.([a-z0-9]{2,4})$|i", $filename, $fileSuffix);
switch(strtolower($fileSuffix[1]))
{
case "js" :
return "application/x-javascript";
case "json" :
return "application/json";
case "jpg" :
case "jpeg" :
case "jpe" :
return "image/jpg";
case "png" :
case "gif" :
case "bmp" :
case "tiff" :
return "image/".strtolower($fileSuffix[1]);
case "css" :
return "text/css";
case "xml" :
return "application/xml";
case "doc" :
case "docx" :
return "application/msword";
case "xls" :
case "xlt" :
case "xlm" :
case "xld" :
case "xla" :
case "xlc" :
case "xlw" :
case "xll" :
return "application/vnd.ms-excel";
case "ppt" :
case "pps" :
return "application/vnd.ms-powerpoint";
case "rtf" :
return "application/rtf";
case "pdf" :
return "application/pdf";
case "html" :
case "htm" :
case "php" :
return "text/html";
case "txt" :
return "text/plain";
case "mpeg" :
case "mpg" :
case "mpe" :
return "video/mpeg";
case "mp3" :
return "audio/mpeg3";
case "wav" :
return "audio/wav";
case "aiff" :
case "aif" :
return "audio/aiff";
case "avi" :
return "video/msvideo";
case "wmv" :
return "video/x-ms-wmv";
case "mov" :
return "video/quicktime";
case "zip" :
return "application/zip";
case "tar" :
return "application/x-tar";
case "swf" :
return "application/x-shockwave-flash";
default :
if(function_exists("mime_content_type"))
{
$fileSuffix = mime_content_type($filename);
}
return "unknown/" . trim($fileSuffix[0], ".");
}
}
}
?>

File diff suppressed because it is too large Load diff

View file

@ -1,295 +1,296 @@
<?php
/**
* @class ModuleObject
* @author zero (zero@nzeo.com)
* @brief base class of ModuleHandler
**/
class ModuleObject extends Object {
var $mid = NULL; ///< string to represent run-time instance of Module (XE Module)
var $module = NULL; ///< Class name of Xe Module that is identified by mid
var $module_srl = NULL; ///< integer value to represent a run-time instance of Module (XE Module)
var $module_info = NULL; ///< an object containing the module information
var $xml_info = NULL; ///< an object containing the module description extracted from XML file
var $module_path = NULL; ///< a path to directory where module source code resides
var $act = NULL; ///< a string value to contain the action name
var $template_path = NULL; ///< a path of directory where template files reside
var $template_file = NULL; ///< name of template file
var $layout_path = ''; ///< a path of directory where layout files reside
var $layout_file = ''; ///< name of layout file
var $edited_layout_file = ''; ///< name of temporary layout files that is modified in an admin mode
var $stop_proc = false; ///< a flag to indicating whether to stop the execution of code.
/**
* @brief setter to set the name of module
* @param name of module
**/
function setModule($module) {
$this->module = $module;
}
/**
* @brief setter to set the name of module path
* @param the directory path to a module directory
**/
function setModulePath($path) {
if(substr($path,-1)!='/') $path.='/';
$this->module_path = $path;
}
/**
* @brief setter to set an url for redirection
* @param $url url for redirection
* @remark redirect_url is used only for ajax requests
**/
function setRedirectUrl($url='./') {
$this->add('redirect_url', $url);
}
/**
* @brief sett to set the template path for refresh.html
* @remark refresh.html is executed as a result of method execution
* 공통 tpl중 refresh.html을 실행할 ..
**/
function setRefreshPage() {
$this->setTemplatePath('./common/tpl');
$this->setTemplateFile('refresh');
}
/**
* @brief sett to set the action name
**/
function setAct($act) {
$this->act = $act;
}
/**
* @brief sett to set module information
* @param[in] $module_info object containing module information
* @param[in] $xml_info object containing module description
**/
function setModuleInfo($module_info, $xml_info) {
// 기본 변수 설정
$this->mid = $module_info->mid;
$this->module_srl = $module_info->module_srl;
$this->module_info = $module_info;
$this->xml_info = $xml_info;
$this->skin_vars = $module_info->skin_vars;
// 웹서비스에서 꼭 필요한 인증 정보와 권한 설정 체크
$is_logged = Context::get('is_logged');
$logged_info = Context::get('logged_info');
// module model 객체 생성
$oModuleModel = &getModel('module');
// XE에서 access, manager (== is_admin) 는 고정된 권한명이며 이와 관련된 권한 설정
$module_srl = Context::get('module_srl');
if(!$module_info->mid && preg_match('/^([0-9]+)$/',$module_srl)) {
$request_module = $oModuleModel->getModuleInfoByModuleSrl($module_srl);
if($request_module->module_srl == $module_srl) {
$grant = $oModuleModel->getGrant($request_module, $logged_info);
}
} else {
$grant = $oModuleModel->getGrant($module_info, $logged_info, $xml_info);
}
// 현재 모듈의 access 권한이 없으면 권한 없음 표시
//if(!$grant->access) return $this->stop("msg_not_permitted");
// 관리 권한이 없으면 permision, action 확인
if(!$grant->manager) {
// 현재 요청된 action의 퍼미션 type(guest, member, manager, root)를 구함
$permission_target = $xml_info->permission->{$this->act};
// module.xml에 명시된 퍼미션이 없을때 action명에 Admin이 있으면 manager로 체크
if(!$permission_target && substr_count($this->act, 'Admin')) $permission_target = 'manager';
// 권한 체크
switch($permission_target) {
case 'root' :
$this->stop('msg_not_permitted_act');
break;
case 'manager' :
if(!$grant->manager) $this->stop('msg_not_permitted_act');
break;
case 'member' :
if(!$is_logged) $this->stop('msg_not_permitted_act');
break;
}
}
// 권한변수 설정
$this->grant = $grant;
Context::set('grant', $grant);
if(method_exists($this, 'init')) $this->init();
}
/**
* @brief set the stop_proc and approprate message for msg_code
* @param $msg_code an error code
**/
function stop($msg_code) {
// proc 수행을 중지 시키기 위한 플래그 세팅
$this->stop_proc = true;
// 에러 처리
$this->setError(-1);
$this->setMessage($msg_code);
// message 모듈의 에러 표시
$oMessageView = &getView('message');
$oMessageView->setError(-1);
$oMessageView->setMessage($msg_code);
$oMessageView->dispMessage();
$this->setTemplatePath($oMessageView->getTemplatePath());
$this->setTemplateFile($oMessageView->getTemplateFile());
return $this;
}
/**
* @brief set the file name of the template file
**/
function setTemplateFile($filename) {
if(substr($filename,-5)!='.html') $filename .= '.html';
$this->template_file = $filename;
}
/**
* @brief retrieve the directory path of the template directory
**/
function getTemplateFile() {
return $this->template_file;
}
/**
* @brief set the directory path of the template directory
**/
function setTemplatePath($path) {
if(substr($path,0,1)!='/' && substr($path,0,2)!='./') $path = './'.$path;
if(substr($path,-1)!='/') $path .= '/';
$this->template_path = $path;
}
/**
* @brief retrieve the directory path of the template directory
**/
function getTemplatePath() {
return $this->template_path;
}
/**
* @brief set the file name of the temporarily modified by admin
**/
function setEditedLayoutFile($filename) {
if(substr($filename,-5)!='.html') $filename .= '.html';
$this->edited_layout_file = $filename;
}
/**
* @brief retreived the file name of edited_layout_file
**/
function getEditedLayoutFile() {
return $this->edited_layout_file;
}
/**
* @brief set the file name of the layout file
**/
function setLayoutFile($filename) {
if(substr($filename,-5)!='.html') $filename .= '.html';
$this->layout_file = $filename;
}
/**
* @brief get the file name of the layout file
**/
function getLayoutFile() {
return $this->layout_file;
}
/**
* @brief set the directory path of the layout directory
**/
function setLayoutPath($path) {
if(substr($path,0,1)!='/' && substr($path,0,2)!='./') $path = './'.$path;
if(substr($path,-1)!='/') $path .= '/';
$this->layout_path = $path;
}
/**
* @brief set the directory path of the layout directory
**/
function getLayoutPath() {
return $this->layout_path;
}
/**
* @brief excute the member method specified by $act variable
*
**/
function proc() {
// stop_proc==true이면 그냥 패스
if($this->stop_proc) return false;
// addon 실행(called_position 를 before_module_proc로 하여 호출)
$called_position = 'before_module_proc';
$oAddonController = &getController('addon');
$addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone()?"mobile":"pc");
@include($addon_file);
if(isset($this->xml_info->action->{$this->act}) && method_exists($this, $this->act)) {
// 권한 체크
if(!$this->grant->access) return $this->stop("msg_not_permitted_act");
// 모듈의 스킨 정보를 연동 (스킨 정보의 테이블 분리로 동작대상 모듈에만 스킨 정보를 싱크시키도록 변경)
$oModuleModel = &getModel('module');
$oModuleModel->syncSkinInfoToModuleInfo($this->module_info);
Context::set('module_info', $this->module_info);
// 실행
$output = $this->{$this->act}();
}
else {
return false;
}
// addon 실행(called_position 를 after_module_proc로 하여 호출)
$called_position = 'after_module_proc';
$oAddonController = &getController('addon');
$addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone()?"mobile":"pc");
@include($addon_file);
if(is_a($output, 'Object') || is_subclass_of($output, 'Object')) {
$this->setError($output->getError());
$this->setMessage($output->getMessage());
return false;
}
// view action이고 결과 출력이 XMLRPC 또는 JSON일 경우 해당 모듈의 api method를 실행
if($this->module_info->module_type == 'view'){
if(Context::getResponseMethod() == 'XMLRPC' || Context::getResponseMethod() == 'JSON') {
$oAPI = getAPI($this->module_info->module, 'api');
if(method_exists($oAPI, $this->act)) {
$oAPI->{$this->act}($this);
}
}
}
return true;
}
}
?>
<?php
/**
* @class ModuleObject
* @author NHN (developers@xpressengine.com)
* @brief base class of ModuleHandler
**/
class ModuleObject extends Object {
var $mid = NULL; ///< string to represent run-time instance of Module (XE Module)
var $module = NULL; ///< Class name of Xe Module that is identified by mid
var $module_srl = NULL; ///< integer value to represent a run-time instance of Module (XE Module)
var $module_info = NULL; ///< an object containing the module information
var $xml_info = NULL; ///< an object containing the module description extracted from XML file
var $module_path = NULL; ///< a path to directory where module source code resides
var $act = NULL; ///< a string value to contain the action name
var $template_path = NULL; ///< a path of directory where template files reside
var $template_file = NULL; ///< name of template file
var $layout_path = ''; ///< a path of directory where layout files reside
var $layout_file = ''; ///< name of layout file
var $edited_layout_file = ''; ///< name of temporary layout files that is modified in an admin mode
var $stop_proc = false; ///< a flag to indicating whether to stop the execution of code.
/**
* @brief setter to set the name of module
* @param name of module
**/
function setModule($module) {
$this->module = $module;
}
/**
* @brief setter to set the name of module path
* @param the directory path to a module directory
**/
function setModulePath($path) {
if(substr($path,-1)!='/') $path.='/';
$this->module_path = $path;
}
/**
* @brief setter to set an url for redirection
* @param $url url for redirection
* @remark redirect_url is used only for ajax requests
**/
function setRedirectUrl($url='./') {
$this->add('redirect_url', $url);
}
/**
* @brief sett to set the template path for refresh.html
* @remark refresh.html is executed as a result of method execution
* 공통 tpl중 refresh.html을 실행할 ..
**/
function setRefreshPage() {
$this->setTemplatePath('./common/tpl');
$this->setTemplateFile('refresh');
}
/**
* @brief sett to set the action name
**/
function setAct($act) {
$this->act = $act;
}
/**
* @brief sett to set module information
* @param[in] $module_info object containing module information
* @param[in] $xml_info object containing module description
**/
function setModuleInfo($module_info, $xml_info) {
// 기본 변수 설정
$this->mid = $module_info->mid;
$this->module_srl = $module_info->module_srl;
$this->module_info = $module_info;
$this->xml_info = $xml_info;
$this->skin_vars = $module_info->skin_vars;
// 웹서비스에서 꼭 필요한 인증 정보와 권한 설정 체크
$is_logged = Context::get('is_logged');
$logged_info = Context::get('logged_info');
// module model 객체 생성
$oModuleModel = &getModel('module');
// XE에서 access, manager (== is_admin) 는 고정된 권한명이며 이와 관련된 권한 설정
$module_srl = Context::get('module_srl');
if(!$module_info->mid && preg_match('/^([0-9]+)$/',$module_srl)) {
$request_module = $oModuleModel->getModuleInfoByModuleSrl($module_srl);
if($request_module->module_srl == $module_srl) {
$grant = $oModuleModel->getGrant($request_module, $logged_info);
}
} else {
$grant = $oModuleModel->getGrant($module_info, $logged_info, $xml_info);
}
// 현재 모듈의 access 권한이 없으면 권한 없음 표시
//if(!$grant->access) return $this->stop("msg_not_permitted");
// 관리 권한이 없으면 permision, action 확인
if(!$grant->manager) {
// 현재 요청된 action의 퍼미션 type(guest, member, manager, root)를 구함
$permission_target = $xml_info->permission->{$this->act};
// module.xml에 명시된 퍼미션이 없을때 action명에 Admin이 있으면 manager로 체크
if(!$permission_target && substr_count($this->act, 'Admin')) $permission_target = 'manager';
// 권한 체크
switch($permission_target) {
case 'root' :
$this->stop('msg_not_permitted_act');
break;
case 'manager' :
if(!$grant->manager) $this->stop('msg_not_permitted_act');
break;
case 'member' :
if(!$is_logged) $this->stop('msg_not_permitted_act');
break;
}
}
// 권한변수 설정
$this->grant = $grant;
Context::set('grant', $grant);
if(method_exists($this, 'init')) $this->init();
}
/**
* @brief set the stop_proc and approprate message for msg_code
* @param $msg_code an error code
**/
function stop($msg_code) {
// proc 수행을 중지 시키기 위한 플래그 세팅
$this->stop_proc = true;
// 에러 처리
$this->setError(-1);
$this->setMessage($msg_code);
// message 모듈의 에러 표시
$type = Mobile::isFromMobilePhone() ? 'mobile' : 'view';
$oMessageObject = &ModuleHandler::getModuleInstance('message',$type);
$oMessageObject->setError(-1);
$oMessageObject->setMessage($msg_code);
$oMessageObject->dispMessage();
$this->setTemplatePath($oMessageObject->getTemplatePath());
$this->setTemplateFile($oMessageObject->getTemplateFile());
return $this;
}
/**
* @brief set the file name of the template file
**/
function setTemplateFile($filename) {
if(substr($filename,-5)!='.html') $filename .= '.html';
$this->template_file = $filename;
}
/**
* @brief retrieve the directory path of the template directory
**/
function getTemplateFile() {
return $this->template_file;
}
/**
* @brief set the directory path of the template directory
**/
function setTemplatePath($path) {
if(substr($path,0,1)!='/' && substr($path,0,2)!='./') $path = './'.$path;
if(substr($path,-1)!='/') $path .= '/';
$this->template_path = $path;
}
/**
* @brief retrieve the directory path of the template directory
**/
function getTemplatePath() {
return $this->template_path;
}
/**
* @brief set the file name of the temporarily modified by admin
**/
function setEditedLayoutFile($filename) {
if(substr($filename,-5)!='.html') $filename .= '.html';
$this->edited_layout_file = $filename;
}
/**
* @brief retreived the file name of edited_layout_file
**/
function getEditedLayoutFile() {
return $this->edited_layout_file;
}
/**
* @brief set the file name of the layout file
**/
function setLayoutFile($filename) {
if(substr($filename,-5)!='.html') $filename .= '.html';
$this->layout_file = $filename;
}
/**
* @brief get the file name of the layout file
**/
function getLayoutFile() {
return $this->layout_file;
}
/**
* @brief set the directory path of the layout directory
**/
function setLayoutPath($path) {
if(substr($path,0,1)!='/' && substr($path,0,2)!='./') $path = './'.$path;
if(substr($path,-1)!='/') $path .= '/';
$this->layout_path = $path;
}
/**
* @brief set the directory path of the layout directory
**/
function getLayoutPath() {
return $this->layout_path;
}
/**
* @brief excute the member method specified by $act variable
*
**/
function proc() {
// stop_proc==true이면 그냥 패스
if($this->stop_proc) return false;
// addon 실행(called_position 를 before_module_proc로 하여 호출)
$called_position = 'before_module_proc';
$oAddonController = &getController('addon');
$addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone()?"mobile":"pc");
@include($addon_file);
if(isset($this->xml_info->action->{$this->act}) && method_exists($this, $this->act)) {
// 권한 체크
if(!$this->grant->access) return $this->stop("msg_not_permitted_act");
// 모듈의 스킨 정보를 연동 (스킨 정보의 테이블 분리로 동작대상 모듈에만 스킨 정보를 싱크시키도록 변경)
$oModuleModel = &getModel('module');
$oModuleModel->syncSkinInfoToModuleInfo($this->module_info);
Context::set('module_info', $this->module_info);
// 실행
$output = $this->{$this->act}();
}
else {
return false;
}
// addon 실행(called_position 를 after_module_proc로 하여 호출)
$called_position = 'after_module_proc';
$oAddonController = &getController('addon');
$addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone()?"mobile":"pc");
@include($addon_file);
if(is_a($output, 'Object') || is_subclass_of($output, 'Object')) {
$this->setError($output->getError());
$this->setMessage($output->getMessage());
return false;
}
// view action이고 결과 출력이 XMLRPC 또는 JSON일 경우 해당 모듈의 api method를 실행
if($this->module_info->module_type == 'view'){
if(Context::getResponseMethod() == 'XMLRPC' || Context::getResponseMethod() == 'JSON') {
$oAPI = getAPI($this->module_info->module, 'api');
if(method_exists($oAPI, $this->act)) {
$oAPI->{$this->act}($this);
}
}
}
return true;
}
}
?>

View file

@ -1,137 +1,137 @@
<?php
/**
* @class Object
* @author zero (zero@nzeo.com)
* @brief Base class design to pass the Object instance between XE Modules
*
* @remark Every modules inherits from Object class. It includes error, message, and other variables for communicatin purpose
**/
class Object {
var $error = 0; ///< 에러 코드 (0이면 에러 아님)
var $message = 'success'; ///< 에러 메세지 (success이면 에러 아님)
var $variables = array(); ///< 추가 변수
/**
* @brief constructor
**/
function Object($error = 0, $message = 'success') {
$this->setError($error);
$this->setMessage($message);
}
/**
* @brief Setter to set error code
* @param[in] $error error code
**/
function setError($error = 0) {
$this->error = $error;
}
/**
* @brief Getter to retrieve error code
**/
function getError() {
return $this->error;
}
/**
* @brief Setter to set set the error message
* @param[in] $message a messge string
* @return return True
* @remark this method always returns True. We'd better remove it
**/
function setMessage($message = 'success') {
if(Context::getLang($message)) $message = Context::getLang($message);
$this->message = $message;
return true;
}
/**
* @brief getter to retrieve an error message
**/
function getMessage() {
return $this->message;
}
/**
* @brief setter to set a key/value pair as an additional variable
* @param[in] $key a variable name
* @param[in] $val a value for the variable
**/
function add($key, $val) {
$this->variables[$key] = $val;
}
/**
* @brief method to set multiple key/value pairs as an additional variables
* @param[in] $object either object or array containg key/value pairs to be added
**/
function adds($object) {
if(is_object($object)) {
$vars = get_object_vars($object);
foreach($vars as $key => $val) $this->add($key, $val);
} elseif(is_array($object)) {
foreach($object as $key => $val) $this->add($key, $val);
}
}
/**
* @brief method to retrieve a corresponding value to a given key
**/
function get($key) {
return $this->variables[$key];
}
/**
* @brief method to retrieve an object containing a key/value paris
* @return Returns an object containing key/value pairs
**/
function gets() {
$num_args = func_num_args();
$args_list = func_get_args();
for($i=0;$i<$num_args;$i++) {
$key = $args_list[$i];
$output->{$key} = $this->get($key);
}
return $output;
}
/**
* @brief method to retrieve an array of key/value pairs
* @return Return a list of key/value pairs
**/
function getVariables() {
return $this->variables;
}
/**
* @brief method to retrieve an object of key/value pairs
* @return Return an object of key/value pairs
**/
function getObjectVars() {
foreach($this->variables as $key => $val) $output->{$key} = $val;
return $output;
}
/**
* @brief method to return either true or false depnding on the value in a 'error' variable
* @remark this method is misleading in that it returns true if error is 0, which should be true in
* boolean representation.
**/
function toBool() {
return $this->error==0?true:false;
}
/**
* @brief method to return either true or false depnding on the value in a 'error' variable
**/
function toBoolean() {
return $this->toBool();
}
}
?>
<?php
/**
* @class Object
* @author NHN (developers@xpressengine.com)
* @brief Base class design to pass the Object instance between XE Modules
*
* @remark Every modules inherits from Object class. It includes error, message, and other variables for communicatin purpose
**/
class Object {
var $error = 0; ///< 에러 코드 (0이면 에러 아님)
var $message = 'success'; ///< 에러 메세지 (success이면 에러 아님)
var $variables = array(); ///< 추가 변수
/**
* @brief constructor
**/
function Object($error = 0, $message = 'success') {
$this->setError($error);
$this->setMessage($message);
}
/**
* @brief Setter to set error code
* @param[in] $error error code
**/
function setError($error = 0) {
$this->error = $error;
}
/**
* @brief Getter to retrieve error code
**/
function getError() {
return $this->error;
}
/**
* @brief Setter to set set the error message
* @param[in] $message a messge string
* @return return True
* @remark this method always returns True. We'd better remove it
**/
function setMessage($message = 'success') {
if(Context::getLang($message)) $message = Context::getLang($message);
$this->message = $message;
return true;
}
/**
* @brief getter to retrieve an error message
**/
function getMessage() {
return $this->message;
}
/**
* @brief setter to set a key/value pair as an additional variable
* @param[in] $key a variable name
* @param[in] $val a value for the variable
**/
function add($key, $val) {
$this->variables[$key] = $val;
}
/**
* @brief method to set multiple key/value pairs as an additional variables
* @param[in] $object either object or array containg key/value pairs to be added
**/
function adds($object) {
if(is_object($object)) {
$vars = get_object_vars($object);
foreach($vars as $key => $val) $this->add($key, $val);
} elseif(is_array($object)) {
foreach($object as $key => $val) $this->add($key, $val);
}
}
/**
* @brief method to retrieve a corresponding value to a given key
**/
function get($key) {
return $this->variables[$key];
}
/**
* @brief method to retrieve an object containing a key/value paris
* @return Returns an object containing key/value pairs
**/
function gets() {
$num_args = func_num_args();
$args_list = func_get_args();
for($i=0;$i<$num_args;$i++) {
$key = $args_list[$i];
$output->{$key} = $this->get($key);
}
return $output;
}
/**
* @brief method to retrieve an array of key/value pairs
* @return Return a list of key/value pairs
**/
function getVariables() {
return $this->variables;
}
/**
* @brief method to retrieve an object of key/value pairs
* @return Return an object of key/value pairs
**/
function getObjectVars() {
foreach($this->variables as $key => $val) $output->{$key} = $val;
return $output;
}
/**
* @brief method to return either true or false depnding on the value in a 'error' variable
* @remark this method is misleading in that it returns true if error is 0, which should be true in
* boolean representation.
**/
function toBool() {
return $this->error==0?true:false;
}
/**
* @brief method to return either true or false depnding on the value in a 'error' variable
**/
function toBoolean() {
return $this->toBool();
}
}
?>

View file

@ -1,109 +1,109 @@
<?php
/**
* @class Optimizer
* @author zero (zero@nzeo.com)
* @brief class designed to be used to merge mutiple JS/CSS files into one file to shorten time taken for transmission.
*
**/
class Optimizer {
var $cache_path = "./files/cache/optimized/";
var $script_file = "./common/script.php?l=%s&amp;t=.%s";
/**
* @brief Constructor which check if a directory, 'optimized' exists in designated path. If not create a new one
**/
function Optimizer() {
if(!is_dir($this->cache_path)) {
FileHandler::makeDir($this->cache_path);
}
}
/**
* @brief file that removes 'optimized' in a given array
* @param[in] $files an array to be modified
**/
function _getOptimizedRemoved($files) {
foreach($files as $key => $val) unset($files[$key]['optimized']);
return $files;
}
/**
* @brief method that optimizes a given file and returns a resultant file
* @param[in] source_files an array of source files to be optimized
* @param[in] type a type of source file, either js or css.
* @return Returns a optimized file
**/
function getOptimizedFiles($source_files, $type = "js") {
if(!is_array($source_files) || !count($source_files)) return;
// 관리자 설정시 설정이 되어 있지 않으면 패스
// 캐시 디렉토리가 없으면 실행하지 않음
$db_info = Context::getDBInfo();
if($db_info->use_optimizer == 'N' || !is_dir($this->cache_path)) return $this->_getOptimizedRemoved($source_files);
if(!count($source_files)) return;
$files = array();
$hash = "";
foreach($source_files as $key => $file) {
if($file['file'][0] == '/'){
if(!file_exists($file['file'])){
if(file_exists($_SERVER['DOCUMENT_ROOT'] . $file['file'])){
if($file['optimized']) $source_files[$key]['file'] = $file['file'] = $_SERVER['DOCUMENT_ROOT'].$file['file'];
}else{
continue;
}
}
} else if(!$file || !$file['file'] || !file_exists($file['file'])) continue;
$file['file'] = $source_files[$key]['file'] = str_replace("\\","/",$file['file']);
if(empty($file['optimized']) || preg_match('/^https?:\/\//i', $file['file']) ) $files[] = $file;
else{
$targets[] = $file;
$hash .= $file['file'];
}
}
if(!count($targets)) return $this->_getOptimizedRemoved($files);
$list_file_hash = md5($hash);
$oCacheHandler = &CacheHandler::getInstance('template');
if($oCacheHandler->isSupport()){
if(!$oCacheHandler->isValid($list_file_hash)){
$buff = array();
foreach($targets as $file) $buff[] = $file['file'];
$oCacheHandler->put($list_file_hash, $buff);
}
}else{
$list_file = FileHandler::getRealPath($this->cache_path . $list_file_hash . '.info.php');
if(!file_exists($list_file)){
$str = '<?php $f=array();';
foreach($targets as $file) $str .= '$f[]="'. $file['file'] . '";';
$str .= ' return $f; ?>';
FileHandler::writeFile($list_file, $str);
}
}
array_unshift($files, array('file' => sprintf($this->script_file, $list_file_hash, $type) , 'media' => 'all'));
$files = $this->_getOptimizedRemoved($files);
if(!count($files)) return $files;
$url_info = parse_url(Context::getRequestUri());
$abpath = $url_info['path'];
foreach($files as $key => $val) {
$file = $val['file'];
if($file{0} == '/' || strpos($file,'://')!==false) continue;
if(substr($file,0,2)=='./') $file = substr($file,2);
$file = $abpath.$file;
while(strpos($file,'/../')!==false) {
$file = preg_replace('/\/([^\/]+)\/\.\.\//','/',$file);
}
$files[$key]['file'] = $file;
}
return $files;
}
}
?>
<?php
/**
* @class Optimizer
* @author NHN (developers@xpressengine.com)
* @brief class designed to be used to merge mutiple JS/CSS files into one file to shorten time taken for transmission.
*
**/
class Optimizer {
var $cache_path = "./files/cache/optimized/";
var $script_file = "./common/script.php?l=%s&amp;t=.%s";
/**
* @brief Constructor which check if a directory, 'optimized' exists in designated path. If not create a new one
**/
function Optimizer() {
if(!is_dir($this->cache_path)) {
FileHandler::makeDir($this->cache_path);
}
}
/**
* @brief file that removes 'optimized' in a given array
* @param[in] $files an array to be modified
**/
function _getOptimizedRemoved($files) {
foreach($files as $key => $val) unset($files[$key]['optimized']);
return $files;
}
/**
* @brief method that optimizes a given file and returns a resultant file
* @param[in] source_files an array of source files to be optimized
* @param[in] type a type of source file, either js or css.
* @return Returns a optimized file
**/
function getOptimizedFiles($source_files, $type = "js") {
if(!is_array($source_files) || !count($source_files)) return;
// 관리자 설정시 설정이 되어 있지 않으면 패스
// 캐시 디렉토리가 없으면 실행하지 않음
$db_info = Context::getDBInfo();
if($db_info->use_optimizer == 'N' || !is_dir($this->cache_path)) return $this->_getOptimizedRemoved($source_files);
if(!count($source_files)) return;
$files = array();
$hash = "";
foreach($source_files as $key => $file) {
if($file['file'][0] == '/'){
if(!file_exists($file['file'])){
if(file_exists($_SERVER['DOCUMENT_ROOT'] . $file['file'])){
if($file['optimized']) $source_files[$key]['file'] = $file['file'] = $_SERVER['DOCUMENT_ROOT'].$file['file'];
}else{
continue;
}
}
} else if(!$file || !$file['file'] || !file_exists($file['file'])) continue;
$file['file'] = $source_files[$key]['file'] = str_replace("\\","/",$file['file']);
if(empty($file['optimized']) || preg_match('/^https?:\/\//i', $file['file']) ) $files[] = $file;
else{
$targets[] = $file;
$hash .= $file['file'];
}
}
if(!count($targets)) return $this->_getOptimizedRemoved($files);
$list_file_hash = md5($hash);
$oCacheHandler = &CacheHandler::getInstance('template');
if($oCacheHandler->isSupport()){
if(!$oCacheHandler->isValid($list_file_hash)){
$buff = array();
foreach($targets as $file) $buff[] = $file['file'];
$oCacheHandler->put($list_file_hash, $buff);
}
}else{
$list_file = FileHandler::getRealPath($this->cache_path . $list_file_hash . '.info.php');
if(!file_exists($list_file)){
$str = '<?php $f=array();';
foreach($targets as $file) $str .= '$f[]="'. $file['file'] . '";';
$str .= ' return $f; ?>';
FileHandler::writeFile($list_file, $str);
}
}
array_unshift($files, array('file' => sprintf($this->script_file, $list_file_hash, $type) , 'media' => 'all'));
$files = $this->_getOptimizedRemoved($files);
if(!count($files)) return $files;
$url_info = parse_url(Context::getRequestUri());
$abpath = $url_info['path'];
foreach($files as $key => $val) {
$file = $val['file'];
if($file{0} == '/' || strpos($file,'://')!==false) continue;
if(substr($file,0,2)=='./') $file = substr($file,2);
$file = $abpath.$file;
while(strpos($file,'/../')!==false) {
$file = preg_replace('/\/([^\/]+)\/\.\.\//','/',$file);
}
$files[$key]['file'] = $file;
}
return $files;
}
}
?>

View file

@ -1,57 +1,57 @@
<?php
/**
* @class PageHandler
* @author zero (zero@nzeo.com)
* @brief handles page navigation
* @version 0.1
*
* @remarks Getting total counts, number of pages, current page number, number of items per page,
* this class implements methods and contains variables for page navigation
**/
class PageHandler extends Handler {
var $total_count = 0; ///< number of total items
var $total_page = 0; ///< number of total pages
var $cur_page = 0; ///< current page number
var $page_count = 10; ///< number of page links displayed at one time
var $first_page = 1; ///< first page number
var $last_page = 1; ///< last page number
var $point = 0; ///< increments per getNextPage()
/**
* @brief constructor
* @param[in] $total_count number of total items
* @param[in] $total_page number of total pages
* @param[in] $cur_page current page number
* @param[in] $page_count number of page links displayed at one time
**/
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 = $total_page;
if($last_page>$total_page) $last_page = $total_page;
$this->first_page = $first_page;
$this->last_page = $last_page;
if($total_page < $this->page_count) $this->page_count = $total_page;
}
/**
* @brief request next page
* @return next page number
**/
function getNextPage() {
$page = $this->first_page+$this->point++;
if($this->point > $this->page_count || $page > $this->last_page) $page = 0;
return $page;
}
}
?>
<?php
/**
* @class PageHandler
* @author NHN (developers@xpressengine.com)
* @brief handles page navigation
* @version 0.1
*
* @remarks Getting total counts, number of pages, current page number, number of items per page,
* this class implements methods and contains variables for page navigation
**/
class PageHandler extends Handler {
var $total_count = 0; ///< number of total items
var $total_page = 0; ///< number of total pages
var $cur_page = 0; ///< current page number
var $page_count = 10; ///< number of page links displayed at one time
var $first_page = 1; ///< first page number
var $last_page = 1; ///< last page number
var $point = 0; ///< increments per getNextPage()
/**
* @brief constructor
* @param[in] $total_count number of total items
* @param[in] $total_page number of total pages
* @param[in] $cur_page current page number
* @param[in] $page_count number of page links displayed at one time
**/
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 = $total_page;
if($last_page>$total_page) $last_page = $total_page;
$this->first_page = $first_page;
$this->last_page = $last_page;
if($total_page < $this->page_count) $this->page_count = $total_page;
}
/**
* @brief request next page
* @return next page number
**/
function getNextPage() {
$page = $this->first_page+$this->point++;
if($this->point > $this->page_count || $page > $this->last_page) $page = 0;
return $page;
}
}
?>

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,14 @@
<?php
/**
* @class WidgetHandler
* @author zero (zero@nzeo.com)
* @brief Handler class for widget execution
* @remark it is empty for now, it would be removed in the future
**/
class WidgetHandler {
var $widget_path = '';
}
?>
<?php
/**
* @class WidgetHandler
* @author NHN (developers@xpressengine.com)
* @brief Handler class for widget execution
* @remark it is empty for now, it would be removed in the future
**/
class WidgetHandler {
var $widget_path = '';
}
?>

View file

@ -1,83 +1,83 @@
<?php
/**
* @class GeneralXmlParser
* @author haneul (haneul0318@gmail.com)
* @brief Generic XML parser for XE
* @version 0.1
*/
class GeneralXmlParser {
var $output = array();
/**
* @brief parse a given input to product a object containing parse values.
* @param[in] $input data to be parsed
* @return Returns an object containing parsed values or NULL in case of failure
*/
function parse($input = '') {
$oParser = xml_parser_create('UTF-8');
xml_set_object($oParser, $this);
xml_set_element_handler($oParser, "_tagOpen", "_tagClosed");
xml_set_character_data_handler($oParser, "_tagBody");
xml_parse($oParser, $input);
xml_parser_free($oParser);
if(!count($this->output)) return;
$this->output = array_shift($this->output);
return $this->output;
}
/**
* @brief start element handler
* @param[in] $parse an instance of parser
* @param[in] $node_name a name of node
* @param[in] $attrs attributes to be set
*/
function _tagOpen($parser, $node_name, $attrs) {
$obj->node_name = strtolower($node_name);
$obj->attrs = $attrs;
$obj->childNodes = array();
array_push($this->output, $obj);
}
/**
* @brief character data handler
* variable in the last element of this->output
* @param[in] $parse an instance of parser
* @param[in] $body a data to be added
*/
function _tagBody($parser, $body) {
//if(!trim($body)) return;
$this->output[count($this->output)-1]->body .= $body;
}
/**
* @brief end element handler
* @param[in] $parse an instance of parser
* @param[in] $node_name name of xml node
*/
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($parent_obj->childNodes[$node_name])
{
$tmp_obj = $parent_obj->childNodes[$node_name];
if(is_array($tmp_obj)) {
array_push($parent_obj->childNodes[$node_name], $cur_obj);
} else {
$parent_obj->childNodes[$node_name] = array();
array_push($parent_obj->childNodes[$node_name], $tmp_obj);
array_push($parent_obj->childNodes[$node_name], $cur_obj);
}
} else {
$parent_obj->childNodes[$node_name] = $cur_obj;
}
}
}
?>
<?php
/**
* @class GeneralXmlParser
* @author NHN (developers@xpressengine.com)
* @brief Generic XML parser for XE
* @version 0.1
*/
class GeneralXmlParser {
var $output = array();
/**
* @brief parse a given input to product a object containing parse values.
* @param[in] $input data to be parsed
* @return Returns an object containing parsed values or NULL in case of failure
*/
function parse($input = '') {
$oParser = xml_parser_create('UTF-8');
xml_set_object($oParser, $this);
xml_set_element_handler($oParser, "_tagOpen", "_tagClosed");
xml_set_character_data_handler($oParser, "_tagBody");
xml_parse($oParser, $input);
xml_parser_free($oParser);
if(!count($this->output)) return;
$this->output = array_shift($this->output);
return $this->output;
}
/**
* @brief start element handler
* @param[in] $parse an instance of parser
* @param[in] $node_name a name of node
* @param[in] $attrs attributes to be set
*/
function _tagOpen($parser, $node_name, $attrs) {
$obj->node_name = strtolower($node_name);
$obj->attrs = $attrs;
$obj->childNodes = array();
array_push($this->output, $obj);
}
/**
* @brief character data handler
* variable in the last element of this->output
* @param[in] $parse an instance of parser
* @param[in] $body a data to be added
*/
function _tagBody($parser, $body) {
//if(!trim($body)) return;
$this->output[count($this->output)-1]->body .= $body;
}
/**
* @brief end element handler
* @param[in] $parse an instance of parser
* @param[in] $node_name name of xml node
*/
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($parent_obj->childNodes[$node_name])
{
$tmp_obj = $parent_obj->childNodes[$node_name];
if(is_array($tmp_obj)) {
array_push($parent_obj->childNodes[$node_name], $cur_obj);
} else {
$parent_obj->childNodes[$node_name] = array();
array_push($parent_obj->childNodes[$node_name], $tmp_obj);
array_push($parent_obj->childNodes[$node_name], $cur_obj);
}
} else {
$parent_obj->childNodes[$node_name] = $cur_obj;
}
}
}
?>

View file

@ -1,298 +1,298 @@
<?php
/**
* @class XmlJsFilter
* @author taggon (gonom9@gmail.com)
* @brief filter class traslate xml content into javascript code
* @version 0.2
*
* it convert xml code into js file and save the result as a cache file
* @code
* {
* <filter name="name of javascript funcion" act="action name" confirm_msg_code="message string to be prompted when submitting the form" >
* <form> <-- code to validate data in the form
* <node target="name" required="true" minlength="1" maxlength="5" filter="email,userid,alpha,number" equalto="target" />
* </form>
* <parameter> <-- 항목을 조합하여 key=val js array로 return, act는 필수
* <param name="key" target="target" />
* </parameter>
* <response callback_func="callback 받게 될 js function 이름 지정" > <-- 서버에 ajax로 전송하여 받을 결과값
* <tag name="error" /> <-- error이름의 결과값을 받겠다는
* </response>
* </filter>
* }
*
* @detail {
* - syntax description of <form> node
* target = name of for element
* required = flag indicating whether a field is mandatory or not
* minlength, maxlength = mininum, maxinum length of string allowed for the field
* filter = name of filter to be used for javascript validation. Following is the description of filter available
* 1) email : validate the confirmance of the value against an email format
* 2) userid : validate the confirmance of the value against the format of user id. (combination of number[0-9],alphabet(lower case) and '_', underscore starting with an alphatic character)
* 3) alpha : check if the value is consists of alphabatic characters.
* 4) number : check if the value is consists of numerical digits
* 5) equalto = target : indicate that values in the form should be equal to those in target
*
* - parameter - param
* name = key : indicate that a new array, 'key' will be created and a value will be assigned to it
* target = target_name : target form element의 값을 가져옴
*
* - response
* tag = key : name of variable that will contain the result of the execution
* }
**/
class XmlJsFilter extends XmlParser {
var $version = '0.2.4';
var $compiled_path = './files/cache/js_filter_compiled/'; ///< 컴파일된 캐시 파일이 놓일 위치
var $xml_file = NULL; ///< 대상 xml 파일
var $js_file = NULL; ///< 컴파일된 js 파일
/**
* @brief constructor
**/
function XmlJsFilter($path, $xml_file) {
if(substr($path,-1)!=='/') $path .= '/';
$this->xml_file = sprintf("%s%s",$path, $xml_file);
$this->js_file = $this->_getCompiledFileName($this->xml_file);
}
/**
* @brief compile a xml_file only when a corresponding js file does not exists or is outdated
* @return Returns NULL regardless of the success of failure of the operation
**/
function compile() {
if(!file_exists($this->xml_file)) return;
if(!file_exists($this->js_file)) $this->_compile();
else if(filemtime($this->xml_file)>filemtime($this->js_file)) $this->_compile();
Context::addJsFile($this->js_file);
}
/**
* @brief compile a xml_file into js_file
**/
function _compile() {
global $lang;
// xml 파일을 읽음
$buff = FileHandler::readFile($this->xml_file);
// xml parsing
$xml_obj = parent::parse($buff);
// XmlJsFilter는 filter_name, field, parameter 3개의 데이터를 핸들링
$filter_name = $xml_obj->filter->attrs->name;
$confirm_msg_code = $xml_obj->filter->attrs->confirm_msg_code;
$module = $xml_obj->filter->attrs->module;
$act = $xml_obj->filter->attrs->act;
$extend_filter = $xml_obj->filter->attrs->extend_filter;
$field_node = $xml_obj->filter->form->node;
if($field_node && !is_array($field_node)) $field_node = array($field_node);
$parameter_param = $xml_obj->filter->parameter->param;
if($parameter_param && !is_array($parameter_param)) $parameter_param = array($parameter_param);
$response_tag = $xml_obj->filter->response->tag;
if($response_tag && !is_array($response_tag)) $response_tag = array($response_tag);
// extend_filter가 있을 경우 해당 method를 호출하여 결과를 받음
if($extend_filter) {
// extend_filter가 있을 경우 캐시 사용을 못하도록 js 캐시 파일명을 변경
$this->js_file .= '.nocache.js';
// extend_filter는 module.method 로 지칭되어 이를 분리
list($module_name, $method) = explode('.',$extend_filter);
// 모듈 이름과 method가 있을 경우 진행
if($module_name&&$method) {
// 해당 module의 model 객체를 받음
$oExtendFilter = &getModel($module_name);
// method가 존재하면 실행
if(method_exists($oExtendFilter, $method)) {
// 결과를 받음
$extend_filter_list = $oExtendFilter->{$method}(true);
$extend_filter_count = count($extend_filter_list);
// 결과에서 lang값을 이용 문서 변수에 적용
for($i=0; $i < $extend_filter_count; $i++) {
$name = $extend_filter_list[$i]->name;
$lang_value = $extend_filter_list[$i]->lang;
if($lang_value) $lang->{$name} = $lang_value;
}
}
}
}
$callback_func = $xml_obj->filter->response->attrs->callback_func;
if(!$callback_func) $callback_func = "filterAlertMessage";
// 언어 입력을 위한 사용되는 필드 조사
$target_list = array();
$target_type_list = array();
// js function 을 만들기 시작
$js_doc = array();
$js_doc[] = "function {$filter_name}(fo_obj){";
$js_doc[] = "\tvar validator = xe.getApp('validator')[0];";
$js_doc[] = "\tif(!validator) return false;";
$js_doc[] = "\tif(!fo_obj.elements['_filter']) jQuery(fo_obj).prepend('<input type=\"hidden\" name=\"_filter\" value=\"\" />');";
$js_doc[] = "\tfo_obj.elements['_filter'].value = '{$filter_name}';";
$jsdoc = array();
$jsdoc[] = '(function($){';
$jsdoc[] = "\tvar validator = xe.getApp('Validator')[0];";
$jsdoc[] = "\tif(!validator) return false;";
$jsdoc[] = "\tvalidator.cast('ADD_FILTER', ['{$filter_name}', {";
$fields = array();
// field, 즉 체크항목의 script 생성
$node_count = count($field_node);
if($node_count) {
foreach($field_node as $key =>$node) {
$attrs = $node->attrs;
$target = trim($attrs->target);
if(!$target) continue;
$filter = $attrs->filter;
$attrs->equalto = trim($attrs->equalto);
$field = array();
if($attrs->required == 'true') $field[] = 'required:true';
if($attrs->minlength > 0) $field[] = 'minlength:'.$attrs->minlength;
if($attrs->maxlength > 0) $field[] = 'maxlength:'.$attrs->maxlength;
if($attrs->equalto) $field[] = "equalto:'{$attrs->equalto}'";
if($attrs->filter) $field[] = "rule:'{$attrs->filter}'";
$s_field = implode(',', $field);
$fields[] = "\t\t'{$target}': {{$s_field}}";
if(!in_array($target, $target_list)) $target_list[] = $target;
if(!$target_type_list[$target]) $target_type_list[$target] = $filter;
}
}
// extend_filter_item 체크
for($i=0;$i<$extend_filter_count;$i++) {
$filter_item = $extend_filter_list[$i];
$target = trim($filter_item->name);
if(!$target) continue;
$type = $filter_item->type;
$required = $filter_item->required?'true':'false';
// extend filter item의 type으로 filter를 구함
$types = array('homepage'=>'homepage', 'email_address'=>'email');
$filter = $types[$type]?$types[$type]:'';
$field = array();
if($filter_item->required == 'true') $field[] = 'required:true';
if($filter) $field[] = "rule:'{$filter}'";
$s_field = implode(',', $field);
$fields[] = "\t\t'{$target}' : {{$s_field}}";
if(!in_array($target, $target_list)) $target_list[] = $target;
if(!$target_type_list[$target]) $target_type_list[$target] = $type;
}
$jsdoc[] = implode(",\n", $fields);
$jsdoc[] = "\t}]);";
// javascript callback function
$js_doc[] = "\tvalidator.cast('ADD_CALLBACK', ['{$filter_name}', function(form){";
$js_doc[] = "\t\tvar params={}, responses=[], elms=form.elements, data=jQuery(form).serializeArray();";
$js_doc[] = "\t\tjQuery.each(data, function(i, field){";
$js_doc[] = "\t\t\tvar val = jQuery.trim(field.value);";
$js_doc[] = "\t\t\tif(!val) return true;";
$js_doc[] = "\t\t\tif(/\[\]$/.test(field.name)) field.name = field.name.replace(/\[\]$/, '');";
$js_doc[] = "\t\t\tif(params[field.name]) params[field.name] += '|@|'+val;";
$js_doc[] = "\t\t\telse params[field.name] = field.value;";
$js_doc[] = "\t\t});";
// 데이터를 만들기 위한 parameter script 생성
$parameter_count = count($parameter_param);
if($parameter_count) {
// 기본 필터 내용의 parameter로 구성
foreach($parameter_param as $key =>$param) {
$attrs = $param->attrs;
$name = trim($attrs->name);
$target = trim($attrs->target);
//if($name && $target && ($name != $target)) $js_doc[] = "\t\tparams['{$name}'] = params['{$target}']; delete params['{$target}'];";
if($name && $target && ($name != $target)) $js_doc[] = "\t\tif(params['{$target}']) { params['{$name}'] = params['{$target}']; delete params['{$target}']; }";
if($name && !in_array($name, $target_list)) $target_list[] = $name;
}
// extend_filter_item 체크
for($i=0;$i<$extend_filter_count;$i++) {
$filter_item = $extend_filter_list[$i];
$target = $name = trim($filter_item->name);
if(!$name || !$target) continue;
if(!in_array($name, $target_list)) $target_list[] = $name;
}
}
// response script 생성
$response_count = count($response_tag);
$responses = array();
for($i=0;$i<$response_count;$i++) {
$attrs = $response_tag[$i]->attrs;
$name = $attrs->name;
$responses[] = "'{$name}'";
}
$js_doc[] = "\t\tresponses = [".implode(',', $responses)."];";
if ($confirm_msg_code) $js_doc[] = sprintf("\t\tif(!confirm('%s')) return false;", $lang->{$confirm_msg_code});
$js_doc[] = "\t\texec_xml('{$module}','{$act}', params, {$callback_func}, responses, params, form);";
$js_doc[] = "\t}]);";
// form 필드 lang 값을 기록
$target_count = count($target_list);
for($i=0;$i<$target_count;$i++) {
$target = $target_list[$i];
if(!$lang->{$target}) $lang->{$target} = $target;
$jsdoc[] = sprintf("\tvalidator.cast('ADD_MESSAGE', ['%s', '%s']);", $target, str_replace('\'', '\\\'', $lang->{$target}));
}
// target type을 기록
/*
$target_type_count = count($target_type_list);
if($target_type_count) {
foreach($target_type_list as $target => $type) {
//$js_doc .= sprintf("target_type_list[\"%s\"] = \"%s\";\n", $target, $type);
}
}
*/
// 에러 메세지를 기록
foreach($lang->filter as $key => $val) {
if(!$val) $val = $key;
$jsdoc[] = sprintf("\tvalidator.cast('ADD_MESSAGE', ['%s', '%s']);", $key, $val);
//$jsdoc[] = sprintf("\tvalidator.cast('ADD_MESSAGE', ['%s', '%s']);", $key, str_replace('\'', '\\\'', $val));
}
$jsdoc[] = '})(jQuery);';
$js_doc[] = "\tvalidator.cast('VALIDATE', [fo_obj,'{$filter_name}']);";
$js_doc[] = "\treturn false;";
$js_doc[] = "};\n";
$js_doc = implode("\n", $js_doc);
$jsdoc = implode("\n", $jsdoc);
// js파일 생성
FileHandler::writeFile($this->js_file, $js_doc."\n".$jsdoc);
}
/**
* @brief return a file name of js file corresponding to the xml file
**/
function _getCompiledFileName($xml_file) {
return sprintf('%s%s.%s.compiled.js',$this->compiled_path, md5($this->version.$xml_file),Context::getLangType());
}
}
?>
<?php
/**
* @class XmlJsFilter
* @author NHN (developers@xpressengine.com)
* @brief filter class traslate xml content into javascript code
* @version 0.2
*
* it convert xml code into js file and save the result as a cache file
* @code
* {
* <filter name="name of javascript funcion" act="action name" confirm_msg_code="message string to be prompted when submitting the form" >
* <form> <-- code to validate data in the form
* <node target="name" required="true" minlength="1" maxlength="5" filter="email,userid,alpha,number" equalto="target" />
* </form>
* <parameter> <-- 항목을 조합하여 key=val js array로 return, act는 필수
* <param name="key" target="target" />
* </parameter>
* <response callback_func="callback 받게 될 js function 이름 지정" > <-- 서버에 ajax로 전송하여 받을 결과값
* <tag name="error" /> <-- error이름의 결과값을 받겠다는
* </response>
* </filter>
* }
*
* @detail {
* - syntax description of <form> node
* target = name of for element
* required = flag indicating whether a field is mandatory or not
* minlength, maxlength = mininum, maxinum length of string allowed for the field
* filter = name of filter to be used for javascript validation. Following is the description of filter available
* 1) email : validate the confirmance of the value against an email format
* 2) userid : validate the confirmance of the value against the format of user id. (combination of number[0-9],alphabet(lower case) and '_', underscore starting with an alphatic character)
* 3) alpha : check if the value is consists of alphabatic characters.
* 4) number : check if the value is consists of numerical digits
* 5) equalto = target : indicate that values in the form should be equal to those in target
*
* - parameter - param
* name = key : indicate that a new array, 'key' will be created and a value will be assigned to it
* target = target_name : target form element의 값을 가져옴
*
* - response
* tag = key : name of variable that will contain the result of the execution
* }
**/
class XmlJsFilter extends XmlParser {
var $version = '0.2.4';
var $compiled_path = './files/cache/js_filter_compiled/'; ///< 컴파일된 캐시 파일이 놓일 위치
var $xml_file = NULL; ///< 대상 xml 파일
var $js_file = NULL; ///< 컴파일된 js 파일
/**
* @brief constructor
**/
function XmlJsFilter($path, $xml_file) {
if(substr($path,-1)!=='/') $path .= '/';
$this->xml_file = sprintf("%s%s",$path, $xml_file);
$this->js_file = $this->_getCompiledFileName($this->xml_file);
}
/**
* @brief compile a xml_file only when a corresponding js file does not exists or is outdated
* @return Returns NULL regardless of the success of failure of the operation
**/
function compile() {
if(!file_exists($this->xml_file)) return;
if(!file_exists($this->js_file)) $this->_compile();
else if(filemtime($this->xml_file)>filemtime($this->js_file)) $this->_compile();
Context::addJsFile($this->js_file);
}
/**
* @brief compile a xml_file into js_file
**/
function _compile() {
global $lang;
// xml 파일을 읽음
$buff = FileHandler::readFile($this->xml_file);
// xml parsing
$xml_obj = parent::parse($buff);
// XmlJsFilter는 filter_name, field, parameter 3개의 데이터를 핸들링
$filter_name = $xml_obj->filter->attrs->name;
$confirm_msg_code = $xml_obj->filter->attrs->confirm_msg_code;
$module = $xml_obj->filter->attrs->module;
$act = $xml_obj->filter->attrs->act;
$extend_filter = $xml_obj->filter->attrs->extend_filter;
$field_node = $xml_obj->filter->form->node;
if($field_node && !is_array($field_node)) $field_node = array($field_node);
$parameter_param = $xml_obj->filter->parameter->param;
if($parameter_param && !is_array($parameter_param)) $parameter_param = array($parameter_param);
$response_tag = $xml_obj->filter->response->tag;
if($response_tag && !is_array($response_tag)) $response_tag = array($response_tag);
// extend_filter가 있을 경우 해당 method를 호출하여 결과를 받음
if($extend_filter) {
// extend_filter가 있을 경우 캐시 사용을 못하도록 js 캐시 파일명을 변경
$this->js_file .= '.nocache.js';
// extend_filter는 module.method 로 지칭되어 이를 분리
list($module_name, $method) = explode('.',$extend_filter);
// 모듈 이름과 method가 있을 경우 진행
if($module_name&&$method) {
// 해당 module의 model 객체를 받음
$oExtendFilter = &getModel($module_name);
// method가 존재하면 실행
if(method_exists($oExtendFilter, $method)) {
// 결과를 받음
$extend_filter_list = $oExtendFilter->{$method}(true);
$extend_filter_count = count($extend_filter_list);
// 결과에서 lang값을 이용 문서 변수에 적용
for($i=0; $i < $extend_filter_count; $i++) {
$name = $extend_filter_list[$i]->name;
$lang_value = $extend_filter_list[$i]->lang;
if($lang_value) $lang->{$name} = $lang_value;
}
}
}
}
$callback_func = $xml_obj->filter->response->attrs->callback_func;
if(!$callback_func) $callback_func = "filterAlertMessage";
// 언어 입력을 위한 사용되는 필드 조사
$target_list = array();
$target_type_list = array();
// js function 을 만들기 시작
$js_doc = array();
$js_doc[] = "function {$filter_name}(fo_obj){";
$js_doc[] = "\tvar validator = xe.getApp('validator')[0];";
$js_doc[] = "\tif(!validator) return false;";
$js_doc[] = "\tif(!fo_obj.elements['_filter']) jQuery(fo_obj).prepend('<input type=\"hidden\" name=\"_filter\" value=\"\" />');";
$js_doc[] = "\tfo_obj.elements['_filter'].value = '{$filter_name}';";
$jsdoc = array();
$jsdoc[] = '(function($){';
$jsdoc[] = "\tvar validator = xe.getApp('Validator')[0];";
$jsdoc[] = "\tif(!validator) return false;";
$jsdoc[] = "\tvalidator.cast('ADD_FILTER', ['{$filter_name}', {";
$fields = array();
// field, 즉 체크항목의 script 생성
$node_count = count($field_node);
if($node_count) {
foreach($field_node as $key =>$node) {
$attrs = $node->attrs;
$target = trim($attrs->target);
if(!$target) continue;
$filter = $attrs->filter;
$attrs->equalto = trim($attrs->equalto);
$field = array();
if($attrs->required == 'true') $field[] = 'required:true';
if($attrs->minlength > 0) $field[] = 'minlength:'.$attrs->minlength;
if($attrs->maxlength > 0) $field[] = 'maxlength:'.$attrs->maxlength;
if($attrs->equalto) $field[] = "equalto:'{$attrs->equalto}'";
if($attrs->filter) $field[] = "rule:'{$attrs->filter}'";
$s_field = implode(',', $field);
$fields[] = "\t\t'{$target}': {{$s_field}}";
if(!in_array($target, $target_list)) $target_list[] = $target;
if(!$target_type_list[$target]) $target_type_list[$target] = $filter;
}
}
// extend_filter_item 체크
for($i=0;$i<$extend_filter_count;$i++) {
$filter_item = $extend_filter_list[$i];
$target = trim($filter_item->name);
if(!$target) continue;
$type = $filter_item->type;
$required = $filter_item->required?'true':'false';
// extend filter item의 type으로 filter를 구함
$types = array('homepage'=>'homepage', 'email_address'=>'email');
$filter = $types[$type]?$types[$type]:'';
$field = array();
if($filter_item->required == 'true') $field[] = 'required:true';
if($filter) $field[] = "rule:'{$filter}'";
$s_field = implode(',', $field);
$fields[] = "\t\t'{$target}' : {{$s_field}}";
if(!in_array($target, $target_list)) $target_list[] = $target;
if(!$target_type_list[$target]) $target_type_list[$target] = $type;
}
$jsdoc[] = implode(",\n", $fields);
$jsdoc[] = "\t}]);";
// javascript callback function
$js_doc[] = "\tvalidator.cast('ADD_CALLBACK', ['{$filter_name}', function(form){";
$js_doc[] = "\t\tvar params={}, responses=[], elms=form.elements, data=jQuery(form).serializeArray();";
$js_doc[] = "\t\tjQuery.each(data, function(i, field){";
$js_doc[] = "\t\t\tvar val = jQuery.trim(field.value);";
$js_doc[] = "\t\t\tif(!val) return true;";
$js_doc[] = "\t\t\tif(/\[\]$/.test(field.name)) field.name = field.name.replace(/\[\]$/, '');";
$js_doc[] = "\t\t\tif(params[field.name]) params[field.name] += '|@|'+val;";
$js_doc[] = "\t\t\telse params[field.name] = field.value;";
$js_doc[] = "\t\t});";
// 데이터를 만들기 위한 parameter script 생성
$parameter_count = count($parameter_param);
if($parameter_count) {
// 기본 필터 내용의 parameter로 구성
foreach($parameter_param as $key =>$param) {
$attrs = $param->attrs;
$name = trim($attrs->name);
$target = trim($attrs->target);
//if($name && $target && ($name != $target)) $js_doc[] = "\t\tparams['{$name}'] = params['{$target}']; delete params['{$target}'];";
if($name && $target && ($name != $target)) $js_doc[] = "\t\tif(params['{$target}']) { params['{$name}'] = params['{$target}']; delete params['{$target}']; }";
if($name && !in_array($name, $target_list)) $target_list[] = $name;
}
// extend_filter_item 체크
for($i=0;$i<$extend_filter_count;$i++) {
$filter_item = $extend_filter_list[$i];
$target = $name = trim($filter_item->name);
if(!$name || !$target) continue;
if(!in_array($name, $target_list)) $target_list[] = $name;
}
}
// response script 생성
$response_count = count($response_tag);
$responses = array();
for($i=0;$i<$response_count;$i++) {
$attrs = $response_tag[$i]->attrs;
$name = $attrs->name;
$responses[] = "'{$name}'";
}
$js_doc[] = "\t\tresponses = [".implode(',', $responses)."];";
if ($confirm_msg_code) $js_doc[] = sprintf("\t\tif(!confirm('%s')) return false;", $lang->{$confirm_msg_code});
$js_doc[] = "\t\texec_xml('{$module}','{$act}', params, {$callback_func}, responses, params, form);";
$js_doc[] = "\t}]);";
// form 필드 lang 값을 기록
$target_count = count($target_list);
for($i=0;$i<$target_count;$i++) {
$target = $target_list[$i];
if(!$lang->{$target}) $lang->{$target} = $target;
$jsdoc[] = sprintf("\tvalidator.cast('ADD_MESSAGE', ['%s', '%s']);", $target, str_replace('\'', '\\\'', $lang->{$target}));
}
// target type을 기록
/*
$target_type_count = count($target_type_list);
if($target_type_count) {
foreach($target_type_list as $target => $type) {
//$js_doc .= sprintf("target_type_list[\"%s\"] = \"%s\";\n", $target, $type);
}
}
*/
// 에러 메세지를 기록
foreach($lang->filter as $key => $val) {
if(!$val) $val = $key;
$jsdoc[] = sprintf("\tvalidator.cast('ADD_MESSAGE', ['%s', '%s']);", $key, $val);
//$jsdoc[] = sprintf("\tvalidator.cast('ADD_MESSAGE', ['%s', '%s']);", $key, str_replace('\'', '\\\'', $val));
}
$jsdoc[] = '})(jQuery);';
$js_doc[] = "\tvalidator.cast('VALIDATE', [fo_obj,'{$filter_name}']);";
$js_doc[] = "\treturn false;";
$js_doc[] = "};\n";
$js_doc = implode("\n", $js_doc);
$jsdoc = implode("\n", $jsdoc);
// js파일 생성
FileHandler::writeFile($this->js_file, $js_doc."\n".$jsdoc);
}
/**
* @brief return a file name of js file corresponding to the xml file
**/
function _getCompiledFileName($xml_file) {
return sprintf('%s%s.%s.compiled.js',$this->compiled_path, md5($this->version.$xml_file),Context::getLangType());
}
}
?>

View file

@ -1,154 +1,154 @@
<?php
/**
* @class XmlParser
* @author zero (zero@nzeo.com)
* @brief class parsing a given xmlrpc request and creating a data object
* @version 0.1
*
* @remarks {
* This class may drops unsupported xml lanuage attributes when multiple language attributes are given.
* For example, if 'xml:lang='ko, en, ch, jp..' is given in a xml file, only ko will be left ignoring all other language
* attributes when kor is only supported language. It seems to work fine now but we did not scrutinze any potential side effects,
* }
**/
class XmlParser {
var $oParser = NULL; ///< xml parser
var $input = NULL; ///< input xml
var $output = array(); ///< output object
var $lang = "en"; ///< 기본 언어타입
/**
* @brief load a xml file specified by a filename and parse it to return the resultant data object
* @param[in] $filename a file path of file
* @return Returns a data object containing data extracted from a xml file or NULL if a specified file does not exist
**/
function loadXmlFile($filename) {
if(!file_exists($filename)) return;
$buff = FileHandler::readFile($filename);
$oXmlParser = new XmlParser();
return $oXmlParser->parse($buff);
}
/**
* @brief parse xml data to extract values from it and construct data object
* @param[in] a data buffer containing xml data
* @return Returns a resultant data object or NULL in case of error
**/
function parse($input = '') {
// 디버그를 위한 컴파일 시작 시간 저장
if(__DEBUG__==3) $start = getMicroTime();
$this->lang = Context::getLangType();
$this->input = $input?$input:$GLOBALS['HTTP_RAW_POST_DATA'];
$this->input = str_replace(array('',''),array('',''),$this->input);
// 지원언어 종류를 뽑음
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('UTF-8');
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;
$output = array_shift($this->output);
// 디버그를 위한 컴파일 시작 시간 저장
if(__DEBUG__==3) $GLOBALS['__xmlparse_elapsed__'] += getMicroTime() - $start;
return $output;
}
/**
* @brief start element handler.
* @param[in] $parse an instance of parser
* @param[in] $node_name a name of node
* @param[in] $attrs attributes to be set
*/
function _tagOpen($parser, $node_name, $attrs) {
$obj->node_name = strtolower($node_name);
$obj->attrs = $this->_arrToObj($attrs);
array_push($this->output, $obj);
}
/**
* @brief character data handler
* variable in the last element of this->output
* @param[in] $parse an instance of parser
* @param[in] $body a data to be added
* @remark the first parameter, $parser ought to be remove since it is not used.
*/
function _tagBody($parser, $body) {
//if(!trim($body)) return;
$this->output[count($this->output)-1]->body .= $body;
}
/**
* @brief end element handler
* @param[in] $parse an instance of parser
* @param[in] $node_name name of xml node
*/
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;
}
}
/**
* @brief method to transfer values in an array to a data object
* @param[in] $arr data array
**/
function _arrToObj($arr) {
if(!count($arr)) return;
foreach($arr as $key => $val) {
$key = strtolower($key);
$output->{$key} = $val;
}
return $output;
}
}
?>
<?php
/**
* @class XmlParser
* @author NHN (developers@xpressengine.com)
* @brief class parsing a given xmlrpc request and creating a data object
* @version 0.1
*
* @remarks {
* This class may drops unsupported xml lanuage attributes when multiple language attributes are given.
* For example, if 'xml:lang='ko, en, ch, jp..' is given in a xml file, only ko will be left ignoring all other language
* attributes when kor is only supported language. It seems to work fine now but we did not scrutinze any potential side effects,
* }
**/
class XmlParser {
var $oParser = NULL; ///< xml parser
var $input = NULL; ///< input xml
var $output = array(); ///< output object
var $lang = "en"; ///< 기본 언어타입
/**
* @brief load a xml file specified by a filename and parse it to return the resultant data object
* @param[in] $filename a file path of file
* @return Returns a data object containing data extracted from a xml file or NULL if a specified file does not exist
**/
function loadXmlFile($filename) {
if(!file_exists($filename)) return;
$buff = FileHandler::readFile($filename);
$oXmlParser = new XmlParser();
return $oXmlParser->parse($buff);
}
/**
* @brief parse xml data to extract values from it and construct data object
* @param[in] a data buffer containing xml data
* @return Returns a resultant data object or NULL in case of error
**/
function parse($input = '') {
// 디버그를 위한 컴파일 시작 시간 저장
if(__DEBUG__==3) $start = getMicroTime();
$this->lang = Context::getLangType();
$this->input = $input?$input:$GLOBALS['HTTP_RAW_POST_DATA'];
$this->input = str_replace(array('',''),array('',''),$this->input);
// 지원언어 종류를 뽑음
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('UTF-8');
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;
$output = array_shift($this->output);
// 디버그를 위한 컴파일 시작 시간 저장
if(__DEBUG__==3) $GLOBALS['__xmlparse_elapsed__'] += getMicroTime() - $start;
return $output;
}
/**
* @brief start element handler.
* @param[in] $parse an instance of parser
* @param[in] $node_name a name of node
* @param[in] $attrs attributes to be set
*/
function _tagOpen($parser, $node_name, $attrs) {
$obj->node_name = strtolower($node_name);
$obj->attrs = $this->_arrToObj($attrs);
array_push($this->output, $obj);
}
/**
* @brief character data handler
* variable in the last element of this->output
* @param[in] $parse an instance of parser
* @param[in] $body a data to be added
* @remark the first parameter, $parser ought to be remove since it is not used.
*/
function _tagBody($parser, $body) {
//if(!trim($body)) return;
$this->output[count($this->output)-1]->body .= $body;
}
/**
* @brief end element handler
* @param[in] $parse an instance of parser
* @param[in] $node_name name of xml node
*/
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;
}
}
/**
* @brief method to transfer values in an array to a data object
* @param[in] $arr data array
**/
function _arrToObj($arr) {
if(!count($arr)) return;
foreach($arr as $key => $val) {
$key = strtolower($key);
$output->{$key} = $val;
}
return $output;
}
}
?>

File diff suppressed because it is too large Load diff