1.3.0 trunk

git-svn-id: http://xe-core.googlecode.com/svn/trunk@6935 201d5d3c-b55e-5fd7-737f-ddc643e51545
This commit is contained in:
haneul 2009-11-11 11:10:22 +00:00
commit e34d683d7f
153 changed files with 3512 additions and 793 deletions

View file

@ -1,36 +1,67 @@
/**
* @file autolink.js
* @brief javascript code for autolink addon
* @author taggon (gonom9@gmail.com)
*/
(function($){
var protocol_re = '(https?|ftp|news|telnet|irc)://';
var domain_re = '(?:[\\w\\-]+\\.)+(?:[a-z]+)';
var max_255_re = '(?:1[0-9]{2}|2[0-4][0-9]|25[0-5])';
var ip_re = '(?:'+max_255_re+'\\.){3}'+max_255_re;
var port_re = '(?::([0-9]+))?';
var path_re = '((?:/[\\w!"$-/:-@]+)*)';
var hash_re = '(?:#([\\w!-@]+))?';
jQuery(function($) { var url_regex = new RegExp('('+protocol_re+'('+domain_re+'|'+ip_re+')'+port_re+path_re+hash_re+')', 'ig');
var url_regx = /((http|https|ftp|news|telnet|irc):\/\/(([0-9a-z\-._~!$&'\(\)*+,;=:]|(%[0-9a-f]{2}))*\@)?((\[(((([0-9a-f]{1,4}:){6}([0-9a-f]{1,4}:[0-9a-f]{1,4})|(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])){3}[0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])))|(::([0-9a-f]{1,4}:){5}([0-9a-f]{1,4}:[0-9a-f]{1,4})|(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])){3}[0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])))|(([0-9a-f]{1,4})?::([0-9a-f]{1,4}:){4}([0-9a-f]{1,4}:[0-9a-f]{1,4})|(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])){3}[0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])))|((([0-9a-f]{1,4}:)?[0-9a-f]{1,4})?::([0-9a-f]{1,4}:){3}([0-9a-f]{1,4}:[0-9a-f]{1,4})|(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])){3}[0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])))|((([0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::([0-9a-f]{1,4}:){2}([0-9a-f]{1,4}:[0-9a-f]{1,4})|(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])){3}[0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])))|((([0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:([0-9a-f]{1,4}:[0-9a-f]{1,4})|(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])){3}[0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])))|((([0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::([0-9a-f]{1,4}:[0-9a-f]{1,4})|(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])){3}[0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])))|((([0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4})|((([0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::))|(v[0-9a-f]+.[0-9a-z\-._~!$&'\(\)*+,;=:]+))\])|(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])){3}[0-9]|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5]))|(([0-9a-z\-._~!$&'\(\)*+,;=]|(%[0-9a-f]{2}))+))(:[0-9]*)?(\/([0-9a-z\-._~!$&'\(\)*+,;=:@]|(%[0-9a-f]{2}))*)*(\?([0-9a-z\-._~!$&'\(\)*+,;=:@\/\?]|(%[0-9a-f]{2}))*)?(#([0-9a-z\-._~!$&'\(\)*+,;=:@\/\?]|(%[0-9a-f]{2}))*)?)/i;
function replaceHrefLink(obj) { var AutoLink = xe.createPlugin("autolink", {
var obj_list = obj.childNodes; targets : [],
init : function() {
this.targets = [];
},
API_ONREADY : function() {
var thisPlugin = this;
for(var i = 0; i < obj_list.length; ++i) { // extract target text nodes
var obj = obj_list[i]; this.extractTargets($('.xe_content'));
var pObj = obj.parentNode;
if(!pObj) continue;
var pN = pObj.nodeName.toLowerCase(); $(this.targets).each(function(){
if($.inArray(pN, ['a', 'pre', 'xml', 'textarea', 'input', 'select', 'option', 'code', 'script', 'style']) != -1) continue; thisPlugin.cast('AUTOLINK', [this]);
});
},
API_AUTOLINK : function(oSender, params) {
var textNode = params[0];
var content = textNode.nodeValue;
var dummy = $('<span>');
if(obj.nodeType == 3 && obj.length >= 10) { content = content.replace(/</g, '&lt;').replace(/>/g, '&gt;');
var content = obj.nodeValue; content = content.replace(url_regex, '<a href="$1" target="_blank">$1</a>');
if(!/(http|https|ftp|news|telnet|irc):\/\//i.test(content)) continue;
content = content.replace(/</g, '&lt;'); $(textNode).before(dummy);
content = content.replace(/>/g, '&gt;'); $(textNode).replaceWith(content);
content = content.replace(url_regx, '<a href="$1" onclick="window.open(this.href); return false;">$1</a>'); params[0] = dummy.next('a');
dummy.remove();
},
extractTargets : function(obj) {
var thisPlugin = this;
$(obj).replaceWith(content); $(obj)
delete(content); .contents()
.each(function(){
// FIX ME : When this meanless code wasn't executed, url_regex do not run correctly. why?
url_regex.exec('');
} else if(obj.nodeType == 1 && obj.childNodes.length) { if (!$(this).is('a,pre,xml,code,script,style,:input')) {
replaceHrefLink(obj); if (this.nodeType == 3 && url_regex.test(this.nodeValue)) { // text node
} thisPlugin.targets.push(this);
} } else {
}
$('.xe_content').each(function() { thisPlugin.extractTargets(this);
replaceHrefLink(this); }
}); }
}); });
}
});
xe.registerPlugin(new AutoLink());
})(jQuery);

View file

@ -0,0 +1,103 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="ko" xml:lang="ko" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Autolink Addon Unit Test</title>
<link rel="stylesheet" type="text/css" href="../../common/js/unittest/css/JSSpec.css" />
<script type="text/javascript" src="../../common/js/jquery.js"></script>
<script type="text/javascript" src="../../common/js/common.js"></script>
<script type="text/javascript" src="../../common/js/js_app.js"></script>
<script type="text/javascript" src="autolink.js"></script>
<script type="text/javascript" src="../../common/js/unittest/JSSpec/diff_match_patch.js"></script>
<script type="text/javascript" src="../../common/js/unittest/JSSpec/JSSpec.js"></script>
<script type="text/javascript">// <![CDATA[
var testParam = null;
var TestSuite = xe.createPlugin("TestSuite", {
API_BEFORE_AUTOLINK : function(oSender, params) {
return !jQuery(params[0]).parent().is('#test7');
},
API_AFTER_AUTOLINK : function(oSender, params) {
testParam = params[0];
}
});
xe.registerPlugin(new TestSuite);
jQuery(function($){
describe('AutoLink functionality', {
"#test1 - plain text don't have any link text" : function() {
value_of( $('#test1').children().length ).should_be(0);
},
"#test2 - simple link text only" : function() {
value_of( $('#test2 > a').length > 0 ).should_be_true();
value_of( $('#test2 > a').attr('href') ).should_be($('#test2 > a').text());
value_of( $('#test2').children().length ).should_be(1);
},
"#test3 - simple link text and some text" : function() {
value_of( $('#test3 > a').length > 0 ).should_be_true();
value_of( $('#test3 > a').attr('href') ).should_be($('#test3 > a').text());
value_of( $('#test3').contents().length ).should_be(2);
},
"#test4 - complex link text only" : function() {
value_of( $('#test4 > a').length > 0 ).should_be_true();
value_of( $('#test4 > a').attr('href') ).should_be($('#test4 > a').text());
value_of( $('#test4').children().length ).should_be(1);
},
"#test5 - complex link text and some text" : function() {
value_of( $('#test5 > a').length > 0 ).should_be_true();
value_of( $('#test5 > a').attr('href') ).should_be($('#test5 > a').text());
value_of( $('#test5').contents().length ).should_be(3);
},
"#test6 - complex example" : function() {
value_of( $('#test6 a').length ).should_be(4);
value_of( $('#test6 a').eq(0).attr('href') ).should_be($('#test6 a').eq(0).text());
value_of( $('#test6 a').eq(2).parent().is('b') ).should_be_true();
value_of( $('#test6 > textarea > a').length ).should_be(0);
value_of( $('#test6 > div > a').attr("target") ).should_be("_self");
},
"#test9 - don't include parenthesis" : function() {
value_of( $('#test9 a').length ).should_be(1);
value_of( $('#test9 a').attr('href') ).should_be('http://www.naver.com');
}
});
describe('Autolink trigger', {
"#test7 - ignored" : function() {
value_of( $('#test7 > a').length ).should_be(0);
},
"#test8 - parameter on after trigger" : function() {
value_of( $(testParam).is('a') ).should_be_true();
}
});
});
// ]]></script>
</head>
<body>
<div class="xe_content" style="display:none">
<div id="test1">This is autolink test. This text don't have any link text.</div>
<div id="test2">http://mygony.com</div>
<div id="test3">Go to http://mygony.com</div>
<div id="test4">http://www.abc.com/some_program?hello=world&encoded=%ED%C2%C1</div>
<div id="test5">Before text. http://www.abc.com/some_program?hello=world&encoded=%ED%C2%C1 After Text</div>
<div id="test6">
This is text. http://www.abc.com/some_program?hello=world&encoded=%ED%C2%C1 Text Text.
Another URL : http://www.decccccf12312.co.uk/path/to/program?mymy=lovelove. XE!
<b>Bold text and http://mail.abc.com/path/to/one_cgi.cgi?hello=world#hash_text Bold text end</b>
<textarea>this text should be ignored http://mygony.com ignored?</textarea>
<div>
Hello~
<a href="http://mygony.com" target="_self">http://mygony.com</a>
Sayonara~
</div>
</div>
<div id="test7">http://mygony.com</div>
<div id="test8">Go to http://mygony.com</div>
<div id="test9">Naver(http://www.naver.com)</div>
</div>
</body>
</html>

View file

@ -22,16 +22,6 @@
// act가 api가 아니면 그냥 리턴~ // act가 api가 아니면 그냥 리턴~
if($_REQUEST['act']!='api') return; if($_REQUEST['act']!='api') return;
/**
* blogapi의 경우 GET argument와 XML Content가 같이 오기에 XE의 경우 XML Content가 오면 이것만 처리하기에
* GET argument중에 mid값을 강제 설정해야 모듈을 정상적으로 찾는다
**/
if($called_position == 'before_module_init') {
$mid = $_REQUEST['mid'];
Context::set('mid', $mid, true);
$this->mid = $mid;
}
// 관련 func 파일 읽음 // 관련 func 파일 읽음
require_once('./addons/blogapi/blogapi.func.php'); require_once('./addons/blogapi/blogapi.func.php');
@ -88,7 +78,7 @@
switch($method_name) { switch($method_name) {
// 블로그 정보 // 블로그 정보
case 'blogger.getUsersBlogs' : case 'blogger.getUsersBlogs' :
$obj->url = Context::getRequestUri().$this->mid; $obj->url = getFullSiteUrl('');
$obj->blogid = $this->mid; $obj->blogid = $this->mid;
$obj->blogName = $this->module_info->browser_title; $obj->blogName = $this->module_info->browser_title;
$blog_list = array($obj); $blog_list = array($obj);
@ -162,7 +152,6 @@
if(!$document_srl) { if(!$document_srl) {
printContent( getXmlRpcFailure(1, 'no permission') ); printContent( getXmlRpcFailure(1, 'no permission') );
} else { } else {
$oDocumentModel = &getModel('document'); $oDocumentModel = &getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl); $oDocument = $oDocumentModel->getDocument($document_srl);
if(!$oDocument->isExists() || !$oDocument->isGranted()) { if(!$oDocument->isExists() || !$oDocument->isGranted()) {
@ -198,8 +187,8 @@
'</methodResponse>', '</methodResponse>',
$category, $category,
date("Ymd", $oDocument->getRegdateTime()).'T'.date("H:i:s", $oDocument->getRegdateTime()), date("Ymd", $oDocument->getRegdateTime()).'T'.date("H:i:s", $oDocument->getRegdateTime()),
$oDocument->getContent(false), $oDocument->getContent(false, false, true,false),
$oDocument->getPermanentUrl(), getFullUrl('','document_srl', $oDocument->document_srl),
$oDocument->document_srl, $oDocument->document_srl,
$oDocument->getTitleText() $oDocument->getTitleText()
); );
@ -264,7 +253,7 @@
} }
} }
$obj->content = str_replace($uploaded_target_path,sprintf('./files/attach/images/%s/%s%s', $this->module_srl, getNumberingPath($document_srl,3), $filename), $obj->content); $obj->content = str_replace($uploaded_target_path,sprintf('/files/attach/images/%s/%s%s', $this->module_srl, getNumberingPath($document_srl,3), $filename), $obj->content);
$oDocumentController = &getController('document'); $oDocumentController = &getController('document');
$obj->allow_comment = 'Y'; $obj->allow_comment = 'Y';
@ -275,7 +264,7 @@
$content = getXmlRpcFailure(1, $output->getMessage()); $content = getXmlRpcFailure(1, $output->getMessage());
} else { } else {
//$content = getXmlRpcResponse(Context::getRequestUri().$this->mid.'/'.$document_srl); //$content = getXmlRpcResponse(Context::getRequestUri().$this->mid.'/'.$document_srl);
$content = getXmlRpcResponse(''.$document_srl); $content = getXmlRpcResponse($document_srl);
} }
FileHandler::removeDir($tmp_uploaded_path); FileHandler::removeDir($tmp_uploaded_path);
@ -364,7 +353,8 @@
$obj->uploaded_count += $file_count; $obj->uploaded_count += $file_count;
} }
} }
$obj->content = str_replace($uploaded_target_path,sprintf('./files/attach/images/%s/%s%s', $this->module_srl, getNumberingPath($document_srl,3), $filename), $obj->content);
$obj->content = str_replace($uploaded_target_path,sprintf('/files/attach/images/%s/%s%s', $this->module_srl, getNumberingPath($document_srl,3), $filename), $obj->content);
$oDocumentController = &getController('document'); $oDocumentController = &getController('document');
$output = $oDocumentController->updateDocument($oDocument,$obj); $output = $oDocumentController->updateDocument($oDocument,$obj);
@ -372,7 +362,7 @@
if(!$output->toBool()) { if(!$output->toBool()) {
$content = getXmlRpcFailure(1, $output->getMessage()); $content = getXmlRpcFailure(1, $output->getMessage());
} else { } else {
$content = getXmlRpcResponse(Context::getRequestUri().$this->mid.'/'.$document_srl); $content = getXmlRpcResponse(getFullUrl('','document_srl',$document_srl));
FileHandler::removeDir($tmp_uploaded_path); FileHandler::removeDir($tmp_uploaded_path);
} }
@ -389,16 +379,22 @@
$oDocumentModel = &getModel('document'); $oDocumentModel = &getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl); $oDocument = $oDocumentModel->getDocument($document_srl);
// 글 존재
if(!$oDocument->isExists()) {
$content = getXmlRpcFailure(1, 'not exists');
// 글 삭제 권한 체크 // 글 삭제 권한 체크
if(!$oDocument->isGranted()) { } elseif(!$oDocument->isGranted()) {
$content = getXmlRpcFailure(1, 'no permission'); $content = getXmlRpcFailure(1, 'no permission');
break; break;
}
$oDocumentController = &getController('document'); // 삭제
$output = $oDocumentController->deleteDocument($document_srl); } else {
if(!$output->toBool()) $content = getXmlRpcFailure(1, $output->getMessage()); $oDocumentController = &getController('document');
else $content = getXmlRpcResponse(true); $output = $oDocumentController->deleteDocument($document_srl);
if(!$output->toBool()) $content = getXmlRpcFailure(1, $output->getMessage());
else $content = getXmlRpcResponse(true);
}
printContent($content); printContent($content);
break; break;
@ -423,22 +419,16 @@
$posts = array(); $posts = array();
foreach($output->data as $key => $oDocument) { foreach($output->data as $key => $oDocument) {
$post = null; $post = null;
$post->link = $post->permaLink = getUrl('','mid',$this->mid,'document_srl',$oDocument->document_srl); $post->categories = array();
$post->dateCreated = date("Ymd", $oDocument->getRegdateTime()).'T'.date("H:i:s", $oDocument->getRegdateTime());
$post->description = htmlspecialchars($oEditorController->transComponent($oDocument->getContent(false,false,true,false)));
$post->link = $post->permaLink = getFullUrl('','document_srl',$oDocument->document_srl);
$post->postid = $oDocument->document_srl;
$post->title = htmlspecialchars($oDocument->get('title'));
$post->publish = 1;
$post->userid = $oDocument->get('user_id'); $post->userid = $oDocument->get('user_id');
$post->mt_allow_pings = 0; $post->mt_allow_pings = 0;
$post->mt_allow_comments = $oDocument->allowComment()=='Y'?1:0; $post->mt_allow_comments = $oDocument->allowComment()=='Y'?1:0;
$post->description = htmlspecialchars($oEditorController->transComponent($oDocument->get('content')));
$post->postid = $oDocument->document_srl;
$post->title = htmlspecialchars($oDocument->get('title'));
$year = substr($oDocument->get('regdate'),0,4);
$month = substr($oDocument->get('regdate'),4,2);
$day = substr($oDocument->get('regdate'),6,2);
$hour = substr($oDocument->get('regdate'),8,2);
$min = substr($oDocument->get('regdate'),10,2);
$sec = substr($oDocument->get('regdate'),12,2);
$time = mktime($hour,$min,$sec,$month,$day,$year);
$post->dateCreated = gmdate("D, d M Y H:i:s", $time);
$posts[] = $post; $posts[] = $post;
} }
$content = getXmlRpcResponse($posts); $content = getXmlRpcResponse($posts);
@ -456,7 +446,7 @@
<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd" > <rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd" >
<service> <service>
<engineName>XpressEngine</engineName> <engineName>XpressEngine</engineName>
<engineLink>http://www.zeroboard.com/ </engineLink> <engineLink>http://www.xpressengine.com/ </engineLink>
<homePageLink>{$homepagelink}</homePageLink> <homePageLink>{$homepagelink}</homePageLink>
<apis> <apis>
<api name="MetaWeblog" preferred="true" apiLink="{$api_url}" blogID="" /> <api name="MetaWeblog" preferred="true" apiLink="{$api_url}" blogID="" />

View file

@ -29,6 +29,7 @@
// 인코딩 처리 // 인코딩 처리
function _getEncodedVal($val, $is_sub_set = false) { function _getEncodedVal($val, $is_sub_set = false) {
if(is_int($val)) $buff = sprintf("<value><i4>%d</i4></value>", $val); if(is_int($val)) $buff = sprintf("<value><i4>%d</i4></value>", $val);
elseif(is_string($val)&&preg_match('/^([0-9]+)T([0-9\:]+)$/', $val)) $buff = sprintf("<value><dateTime.iso8601>%s</dateTime.iso8601></value>\n", $val);
elseif(is_double($val)) $buff = sprintf("<value><double>%f</double></value>", $val); elseif(is_double($val)) $buff = sprintf("<value><double>%f</double></value>", $val);
elseif(is_bool($val)) $buff = sprintf("<value><boolean>%d</boolean></value>", $val?1:0); elseif(is_bool($val)) $buff = sprintf("<value><boolean>%d</boolean></value>", $val?1:0);
elseif(is_object($val)) { elseif(is_object($val)) {

View file

@ -2,7 +2,7 @@
<addon version="0.2"> <addon version="0.2">
<title xml:lang="ko">Captcha 애드온</title> <title xml:lang="ko">Captcha 애드온</title>
<title xml:lang="en">CAPTCHA addon</title> <title xml:lang="en">CAPTCHA addon</title>
<title xml:lang="vi">Captcha Addon</title> <title xml:lang="vi">Captcha Addon</title>
<title xml:lang="zh-CN">验证码插件</title> <title xml:lang="zh-CN">验证码插件</title>
<title xml:lang="jp">Captchaアドオン</title> <title xml:lang="jp">Captchaアドオン</title>
<title xml:lang="zh-TW">圖形驗證</title> <title xml:lang="zh-TW">圖形驗證</title>
@ -20,7 +20,7 @@
</description> </description>
<description xml:lang="zh-CN"> <description xml:lang="zh-CN">
为了解决互联网垃圾而开发的验证码机制。 为了解决互联网垃圾而开发的验证码机制。
非登录用户发布话题或评论时将会弹出验证图片选择框,选择正确的图片才可以正常发布(适用于版面/issueTracker)。 非登录用户发布话题或评论时将会弹出验证图片选择框,选择正确的图片才可以正常发布(适用于版面/issueTracker)。
</description> </description>
<description xml:lang="jp"> <description xml:lang="jp">
ボット(bot)がプログラムによるスパム行為を防ぐために、掲示板issueTrackerで書き込み・コメントを登録する際、ランダムな文字や数字の列を画面に表示し、表示されたものと一致した情報を入力した時、登録が出来るようにするアドオンです。 ボット(bot)がプログラムによるスパム行為を防ぐために、掲示板issueTrackerで書き込み・コメントを登録する際、ランダムな文字や数字の列を画面に表示し、表示されたものと一致した情報を入力した時、登録が出来るようにするアドオンです。
@ -34,132 +34,132 @@
<author email_address="zero@zeroboard.com" link="http://blog.nzeo.com"> <author email_address="zero@zeroboard.com" link="http://blog.nzeo.com">
<name xml:lang="ko">zero</name> <name xml:lang="ko">zero</name>
<name xml:lang="zh-CN">zero</name> <name xml:lang="zh-CN">zero</name>
<name xml:lang="jp">zero</name> <name xml:lang="jp">zero</name>
<name xml:lang="zh-TW">zero</name> <name xml:lang="zh-TW">zero</name>
<name xml:lang="en">zero</name> <name xml:lang="en">zero</name>
<name xml:lang="vi">zero</name> <name xml:lang="vi">zero</name>
</author> </author>
<extra_vars> <extra_vars>
<var name="target" type="select"> <var name="target" type="select">
<title xml:lang="ko">Captcha 표시 대상</title> <title xml:lang="ko">Captcha 표시 대상</title>
<title xml:lang="zh-CN">应用对象</title>
<title xml:lang="jp">Captchaを表示する対象</title>
<title xml:lang="zh-TW">選擇目標</title>
<title xml:lang="en">Captcha Target</title> <title xml:lang="en">Captcha Target</title>
<title xml:lang="vi">Mục tiêu Captcha hiển thị</title> <title xml:lang="vi">Mục tiêu Captcha hiển thị</title>
<title xml:lang="zh-CN">应用对象</title>
<title xml:lang="jp">Captchaを表示する対象</title>
<title xml:lang="zh-TW">選擇目標</title>
<description xml:lang="ko">글/댓글 등록시 captcha가 동작할 대상을 정할 수 있습니다. 관리자는 무조건 제외됩니다</description> <description xml:lang="ko">글/댓글 등록시 captcha가 동작할 대상을 정할 수 있습니다. 관리자는 무조건 제외됩니다</description>
<description xml:lang="zh-CN">可以指定验证码应用对象(管理员除外)。</description>
<description xml:lang="jp">管理者を除き、書き込み・コメントを入力する際にcaptchaイメージを見せる対象を設定します。</description>
<description xml:lang="zh-TW">除了管理員,在發表主題或評論時,設定圖形驗證應用的對象。</description>
<description xml:lang="en">You may specify targets CAPTCHA work. It's not applied when administrator writes.</description> <description xml:lang="en">You may specify targets CAPTCHA work. It's not applied when administrator writes.</description>
<description xml:lang="vi">Khi gửi bài, bình luận, Capcha sẽ hiển thị để xác nhận hành động của người sử dụng. Chức năng này không hoạt động với người quản lý.</description> <description xml:lang="vi">Khi gửi bài, bình luận, Capcha sẽ hiển thị để xác nhận hành động của người sử dụng. Chức năng này không hoạt động với người quản lý.</description>
<description xml:lang="zh-CN">可以指定验证码应用对象(管理员除外)。</description>
<description xml:lang="jp">管理者を除き、書き込み・コメントを入力する際にcaptchaイメージを見せる対象を設定します。</description>
<description xml:lang="zh-TW">除了管理員,在發表主題或評論時,設定圖形驗證應用的對象。</description>
<options value=""> <options value="">
<title xml:lang="ko">로그인하지 않은 사용자</title> <title xml:lang="ko">로그인하지 않은 사용자</title>
<title xml:lang="zh-CN">非登录用户</title>
<title xml:lang="jp">ログインしてないユーザー</title>
<title xml:lang="zh-TW">非用戶</title>
<title xml:lang="en">Not logged-in users</title> <title xml:lang="en">Not logged-in users</title>
<title xml:lang="vi">Người dùng chưa đăng nhập</title> <title xml:lang="vi">Người dùng chưa đăng nhập</title>
<title xml:lang="zh-CN">非登录用户</title>
<title xml:lang="jp">ログインしてないユーザー</title>
<title xml:lang="zh-TW">非用戶</title>
</options> </options>
<options value="all"> <options value="all">
<title xml:lang="ko">모든 사용자</title> <title xml:lang="ko">모든 사용자</title>
<title xml:lang="zh-CN">所有用户</title>
<title xml:lang="jp">すべてのユーザー</title>
<title xml:lang="zh-TW">所有用戶</title>
<title xml:lang="en">All users</title> <title xml:lang="en">All users</title>
<title xml:lang="vi">Tất cả mọi người</title> <title xml:lang="vi">Tất cả mọi người</title>
<title xml:lang="zh-CN">所有用户</title>
<title xml:lang="jp">すべてのユーザー</title>
<title xml:lang="zh-TW">所有用戶</title>
</options> </options>
</var> </var>
<var name="act_type" type="select"> <var name="act_type" type="select">
<title xml:lang="ko">동작 방식</title> <title xml:lang="ko">동작 방식</title>
<title xml:lang="zh-CN">验证方式</title>
<title xml:lang="jp">動作方式</title>
<title xml:lang="zh-TW">行為模式</title>
<title xml:lang="en">How it works</title> <title xml:lang="en">How it works</title>
<title xml:lang="vi">Sử dụng</title> <title xml:lang="vi">Sử dụng</title>
<title xml:lang="zh-CN">验证方式</title>
<title xml:lang="jp">動作方式</title>
<title xml:lang="zh-TW">行為模式</title>
<description xml:lang="ko">"1번만 동작"을 선택하시면 1번만 동작후 상태를 저장해서 다음부터 물어보지 않고 그렇지 않으면 매번 물어보게 됩니다</description> <description xml:lang="ko">"1번만 동작"을 선택하시면 1번만 동작후 상태를 저장해서 다음부터 물어보지 않고 그렇지 않으면 매번 물어보게 됩니다</description>
<description xml:lang="zh-CN">"一次"就是每个IP只出现一次验证。</description>
<description xml:lang="jp">「1回だけ表示」を選択すると、最初だけ動作した後、その情報を記憶して次回からはCaptchaを見せないようにします。また、もう一つのオプションは毎回Captchaを表示します。</description>
<description xml:lang="zh-TW">選擇"單次",產生第一次動作後,下次不會再顯示;選擇"每次"則會一直顯示。</description>
<description xml:lang="en">If you choose "Once", CAPTCHA works only once for the user by storing status. Otherwise, this addon would show an image every time the user writes.</description> <description xml:lang="en">If you choose "Once", CAPTCHA works only once for the user by storing status. Otherwise, this addon would show an image every time the user writes.</description>
<description xml:lang="vi">Nếu chọn "Chỉ một lần" thì sau lần hiển thị đó Capcha sẽ không hiển thị với người sử dụng đó nữa.</description> <description xml:lang="vi">Nếu chọn "Chỉ một lần" thì sau lần hiển thị đó Capcha sẽ không hiển thị với người sử dụng đó nữa.</description>
<description xml:lang="zh-CN">"一次"就是每个IP只出现一次验证。</description>
<description xml:lang="jp">「1回だけ表示」を選択すると、最初だけ動作した後、その情報を記憶して次回からはCaptchaを見せないようにします。また、もう一つのオプションは毎回Captchaを表示します。</description>
<description xml:lang="zh-TW">選擇"單次",產生第一次動作後,下次不會再顯示;選擇"每次"則會一直顯示。</description>
<options value="onetime"> <options value="onetime">
<title xml:lang="ko">1번만 동작</title> <title xml:lang="ko">1번만 동작</title>
<title xml:lang="zh-CN">一次</title>
<title xml:lang="jp">1回だけ表示</title>
<title xml:lang="zh-TW">單次</title>
<title xml:lang="vi">Chỉ một lần</title> <title xml:lang="vi">Chỉ một lần</title>
<title xml:lang="en">once</title> <title xml:lang="en">once</title>
<title xml:lang="zh-CN">一次</title>
<title xml:lang="jp">1回だけ表示</title>
<title xml:lang="zh-TW">單次</title>
</options> </options>
<options value="everytime"> <options value="everytime">
<title xml:lang="ko">매번 동작</title> <title xml:lang="ko">매번 동작</title>
<title xml:lang="zh-CN">每次</title>
<title xml:lang="jp">毎回表示</title>
<title xml:lang="zh-TW">每次</title>
<title xml:lang="en">every time</title> <title xml:lang="en">every time</title>
<title xml:lang="vi">Luôn sử dụng</title> <title xml:lang="vi">Luôn sử dụng</title>
<title xml:lang="zh-CN">每次</title>
<title xml:lang="jp">毎回表示</title>
<title xml:lang="zh-TW">每次</title>
</options> </options>
</var> </var>
<var name="apply_find_account" type="select"> <var name="apply_find_account" type="select">
<title xml:lang="ko">비밀번호 찾기 적용</title> <title xml:lang="ko">비밀번호 찾기 적용</title>
<title xml:lang="zh-CN">应用到查找密码功能</title>
<title xml:lang="jp">비밀번호 찾기 적용</title>
<title xml:lang="zh-TW">비밀번호 찾기 적용</title>
<title xml:lang="en">applying to an action finding account</title> <title xml:lang="en">applying to an action finding account</title>
<title xml:lang="vi">Khi lấy lại mật khẩu</title> <title xml:lang="vi">Khi lấy lại mật khẩu</title>
<title xml:lang="zh-CN">비밀번호 찾기 적용</title>
<title xml:lang="jp">비밀번호 찾기 적용</title>
<title xml:lang="zh-TW">비밀번호 찾기 적용</title>
<description xml:lang="ko">적용으로 하시면 비밀번호 찾기 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description> <description xml:lang="ko">적용으로 하시면 비밀번호 찾기 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<description xml:lang="zh-CN">启用此项功能可以有效地拦截以查找密码名义发送的垃圾邮件。</description>
<description xml:lang="jp">적용으로 하시면 비밀번호찾기 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<description xml:lang="zh-TW">적용으로 하시면 비밀번호찾기 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<description xml:lang="en">If you set this option as apply, CAPTCHA will work for finding account action, too.</description> <description xml:lang="en">If you set this option as apply, CAPTCHA will work for finding account action, too.</description>
<description xml:lang="vi">Nếu áp dụng, khi thành viên cần lấy lại mật khẩu khi lỡ quên, Capcha sẽ hiện thị để xác nhận việc này.</description> <description xml:lang="vi">Nếu áp dụng, khi thành viên cần lấy lại mật khẩu khi lỡ quên, Capcha sẽ hiện thị để xác nhận việc này.</description>
<description xml:lang="zh-CN">적용으로 하시면 비밀번호 찾기 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<description xml:lang="jp">적용으로 하시면 비밀번호 찾기 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<description xml:lang="zh-TW">적용으로 하시면 비밀번호찾기 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<options value=""> <options value="">
<title xml:lang="ko">적용하지 않음</title> <title xml:lang="ko">적용하지 않음</title>
<title xml:lang="zh-CN">不启用</title>
<title xml:lang="jp">적용하지 않음</title>
<title xml:lang="zh-TW">적용하지 않음</title>
<title xml:lang="en">Not apply</title> <title xml:lang="en">Not apply</title>
<title xml:lang="vi">Không áp dụng</title> <title xml:lang="vi">Không áp dụng</title>
<title xml:lang="zh-CN">적용하지 않음</title>
<title xml:lang="jp">적용하지 않음</title>
<title xml:lang="zh-TW">적용하지 않음</title>
</options> </options>
<options value="apply"> <options value="apply">
<title xml:lang="ko">적용</title> <title xml:lang="ko">적용</title>
<title xml:lang="zh-CN">启用</title>
<title xml:lang="jp">적용</title>
<title xml:lang="zh-TW">적용</title>
<title xml:lang="en">Apply</title> <title xml:lang="en">Apply</title>
<title xml:lang="vi">Áp dụng</title> <title xml:lang="vi">Áp dụng</title>
<title xml:lang="zh-CN">적용</title>
<title xml:lang="jp">적용</title>
<title xml:lang="zh-TW">적용</title>
</options> </options>
</var> </var>
<var name="apply_resend_auth_mail" type="select"> <var name="apply_resend_auth_mail" type="select">
<title xml:lang="ko">인증 메일 재발송 적용</title> <title xml:lang="ko">인증 메일 재발송 적용</title>
<title xml:lang="zh-CN">应用到认证邮件重新发送功能</title>
<title xml:lang="jp">인증 메일 재발송 적용</title>
<title xml:lang="zh-TW">인증 메일 재발송 적용</title>
<title xml:lang="en">apply to an action resending authmail</title> <title xml:lang="en">apply to an action resending authmail</title>
<title xml:lang="vi">Khi lấy lại mã kích hoạt</title> <title xml:lang="vi">Khi lấy lại mã kích hoạt</title>
<title xml:lang="zh-CN">인증 메일 재발송 적용</title>
<title xml:lang="jp">인증 메일 재발송 적용</title>
<title xml:lang="zh-TW">인증 메일 재발송 적용</title>
<description xml:lang="ko">적용으로 하시면 인증 메일 재발송 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description> <description xml:lang="ko">적용으로 하시면 인증 메일 재발송 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<description xml:lang="zh-CN">启用此项功能可以有效地拦截以重新发送认证邮件名义发送的垃圾邮件。</description>
<description xml:lang="jp">적용으로 하시면 인증 메일 재발송 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<description xml:lang="zh-TW">적용으로 하시면 인증 메일 재발송 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<description xml:lang="en">If you set this option as apply, CAPTCHA will work for resending authmail action, too.</description> <description xml:lang="en">If you set this option as apply, CAPTCHA will work for resending authmail action, too.</description>
<description xml:lang="vi">Nếu áp dụng, khi thành viên cần lấy lại mã kích hoạt thành viên, Capcha sẽ hiện thị để xác nhận việc này.</description> <description xml:lang="vi">Nếu áp dụng, khi thành viên cần lấy lại mã kích hoạt thành viên, Capcha sẽ hiện thị để xác nhận việc này.</description>
<description xml:lang="zh-CN">적용으로 하시면 인증 메일 재발송 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<description xml:lang="jp">적용으로 하시면 인증 메일 재발송 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<description xml:lang="zh-TW">적용으로 하시면 인증 메일 재발송 기능에도 적용되어 악의적인 봇(또는 프로그램)에 의한 메일 발송을 막을 수 있습니다.</description>
<options value=""> <options value="">
<title xml:lang="ko">적용하지 않음</title> <title xml:lang="ko">적용하지 않음</title>
<title xml:lang="zh-CN">不启用</title>
<title xml:lang="jp">적용하지 않음</title>
<title xml:lang="zh-TW">적용하지 않음</title>
<title xml:lang="en">Not apply</title> <title xml:lang="en">Not apply</title>
<title xml:lang="vi">Không áp dụng</title> <title xml:lang="vi">Không áp dụng</title>
<title xml:lang="zh-CN">적용하지 않음</title>
<title xml:lang="jp">적용하지 않음</title>
<title xml:lang="zh-TW">적용하지 않음</title>
</options> </options>
<options value="apply"> <options value="apply">
<title xml:lang="ko">적용</title> <title xml:lang="ko">적용</title>
<title xml:lang="zh-CN">启用</title>
<title xml:lang="jp">적용</title>
<title xml:lang="zh-TW">적용</title>
<title xml:lang="en">Apply</title> <title xml:lang="en">Apply</title>
<title xml:lang="vi">Áp dụng</title> <title xml:lang="vi">Áp dụng</title>
<title xml:lang="zh-CN">적용</title>
<title xml:lang="jp">적용</title>
<title xml:lang="zh-TW">적용</title>
</options> </options>
</var> </var>
</extra_vars> </extra_vars>

View file

@ -45,7 +45,7 @@
<history version="0.1.1" date="2009-05-23"> <history version="0.1.1" date="2009-05-23">
<author email_address="misol221@paran.com" link="http://www.imsoo.net"> <author email_address="misol221@paran.com" link="http://www.imsoo.net">
<name xml:lang="ko">misol</name> <name xml:lang="ko">misol</name>
<name xml:lang="jp">misol</name> <name xml:lang="jp">misol</name>
<name xml:lang="zh-CN">misol</name> <name xml:lang="zh-CN">misol</name>
<name xml:lang="en">misol</name> <name xml:lang="en">misol</name>
<name xml:lang="vi">misol</name> <name xml:lang="vi">misol</name>

View file

@ -1,16 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2"> <addon version="0.2">
<title xml:lang="ko">SmartPhone XE 애드온</title> <title xml:lang="ko">SmartPhone XE 애드온</title>
<title xml:lang="en">SmartPhone XE</title> <title xml:lang="en">SmartPhone XE</title>
<title xml:lang="zh-CN">智能手机XE插件</title>
<title xml:lang="vi">SmartPhone XE</title> <title xml:lang="vi">SmartPhone XE</title>
<title xml:lang="zh-TW">SmartPhone XE</title> <title xml:lang="zh-TW">SmartPhone XE</title>
<title xml:lang="jp">SmartPhone XE アドオン</title> <title xml:lang="jp">SmartPhone XE アドオン</title>
<description xml:lang="ko"> <description xml:lang="ko">
IPhone (touch) 등, smartphone 에서 접속시 최적화된 화면을 보여줍니다. IPhone (touch) 등, smartphone 에서 접속시 최적화된 화면을 보여줍니다.
</description> </description>
<description xml:lang="en"> <description xml:lang="en">
This addon displays the best screen for users who use smartphones like IPhone (touch). This addon displays the best screen for users who use smartphones like IPhone (touch).
</description> </description>
<description xml:lang="zh-CN">
用于IPhone(touch)等智能手机访问时的界面优化。
</description>
<description xml:lang="vi"> <description xml:lang="vi">
Addon này sẽ hiển thị Website trên màn hình iPhone một cách tốt nhất khi người dùng sử dụng SmartPhone để truy cập (iPhone cảm ứng) Addon này sẽ hiển thị Website trên màn hình iPhone một cách tốt nhất khi người dùng sử dụng SmartPhone để truy cập (iPhone cảm ứng)
</description> </description>
@ -24,7 +28,8 @@
<date>2009-04-20</date> <date>2009-04-20</date>
<author email_address="haneul0318@gmail.com" link="http://seungyeop.kr"> <author email_address="haneul0318@gmail.com" link="http://seungyeop.kr">
<name xml:lang="ko">haneul</name> <name xml:lang="ko">haneul</name>
<name xml:lang="en">haneul</name> <name xml:lang="en">haneul</name>
<name xml:lang="zh-CN">haneul</name>
<name xml:lang="vi">haneul</name> <name xml:lang="vi">haneul</name>
<name xml:lang="zh-TW">haneul</name> <name xml:lang="zh-TW">haneul</name>
<name xml:lang="jp">haneul</name> <name xml:lang="jp">haneul</name>

View file

@ -163,6 +163,7 @@
$this->addJsFile("./common/js/jquery.js"); $this->addJsFile("./common/js/jquery.js");
$this->addJsFile("./common/js/x.js"); $this->addJsFile("./common/js/x.js");
$this->addJsFile("./common/js/common.js"); $this->addJsFile("./common/js/common.js");
$this->addJsFile("./common/js/js_app.js");
$this->addJsFile("./common/js/xml_handler.js"); $this->addJsFile("./common/js/xml_handler.js");
$this->addJsFile("./common/js/xml_js_filter.js"); $this->addJsFile("./common/js/xml_js_filter.js");
$this->addCSSFile("./common/css/default.css"); $this->addCSSFile("./common/css/default.css");
@ -646,11 +647,10 @@
* @brief GET/POST방식일 경우 처리 * @brief GET/POST방식일 경우 처리
**/ **/
function _setRequestArgument() { function _setRequestArgument() {
if($this->_getRequestMethod() == 'XMLRPC' || $this->_getRequestMethod() == 'JSON') return;
if(!count($_REQUEST)) return; if(!count($_REQUEST)) return;
foreach($_REQUEST as $key => $val) { foreach($_REQUEST as $key => $val) {
if($val === "") continue; if($val === "" || Context::get($key)) continue;
$val = $this->_filterRequestVar($key, $val); $val = $this->_filterRequestVar($key, $val);
if($this->_getRequestMethod()=='GET'&&isset($_GET[$key])) $set_to_vars = true; if($this->_getRequestMethod()=='GET'&&isset($_GET[$key])) $set_to_vars = true;
elseif($this->_getRequestMethod()=='POST'&&isset($_POST[$key])) $set_to_vars = true; elseif($this->_getRequestMethod()=='POST'&&isset($_POST[$key])) $set_to_vars = true;
@ -834,7 +834,7 @@
$val = trim($args_list[$i+1]); $val = trim($args_list[$i+1]);
// 값이 없으면 GET변수에서 해당 키를 제거 // 값이 없으면 GET변수에서 해당 키를 제거
if(!isset($val)) { if(!isset($val) || strlen($val)<1) {
unset($get_vars[$key]); unset($get_vars[$key]);
continue; continue;
} }
@ -847,12 +847,6 @@
if($vid) $get_vars['vid'] = $vid; if($vid) $get_vars['vid'] = $vid;
else unset($get_vars['vid']); else unset($get_vars['vid']);
if(count($get_vars)) {
foreach($get_vars as $key => $val) {
if(!trim($val)) unset($get_vars[$key]);
}
}
// action명이 변경되었던 것에 대해 호환성을 유지하기 위한 강제 값 변경 // action명이 변경되었던 것에 대해 호환성을 유지하기 위한 강제 값 변경
switch($get_vars['act']) { switch($get_vars['act']) {
case 'dispMemberFriend' : $get_vars['act'] = 'dispCommunicationFriend'; break; case 'dispMemberFriend' : $get_vars['act'] = 'dispCommunicationFriend'; break;
@ -936,9 +930,11 @@
if(isset($url[$ssl_mode][$domain_key])) return $url[$ssl_mode][$domain_key]; if(isset($url[$ssl_mode][$domain_key])) return $url[$ssl_mode][$domain_key];
$current_use_ssl = $_SERVER['HTTPS']=='on' ? true : false;
switch($ssl_mode) { switch($ssl_mode) {
case FOLLOW_REQUEST_SSL : case FOLLOW_REQUEST_SSL :
if($_SERVER['HTTPS']=='on') $use_ssl = true; if($current_use_ssl) $use_ssl = true;
else $use_ssl = false; else $use_ssl = false;
break; break;
case ENFORCE_SSL : case ENFORCE_SSL :
@ -957,11 +953,17 @@
} }
$url_info = parse_url('http://'.$target_url); $url_info = parse_url('http://'.$target_url);
if($current_use_ssl != $use_ssl)
{
unset($url_info['port']);
}
if($use_ssl) { if($use_ssl) {
if(Context::get("_https_port") && Context::get("_https_port") != 443) { if(Context::get("_https_port") && Context::get("_https_port") != 443) {
$url_info['port'] = Context::get("_https_port"); $url_info['port'] = Context::get("_https_port");
} }
else elseif($url_info['port']==443)
{ {
unset($url_info['port']); unset($url_info['port']);
} }

View file

@ -226,6 +226,7 @@
* @return object of error * @return object of error
**/ **/
function getError() { function getError() {
$this->errstr = Context::convertEncodingStr($this->errstr);
return new Object($this->errno, $this->errstr); return new Object($this->errno, $this->errstr);
} }
@ -326,7 +327,7 @@
break; break;
} }
if($this->errno != 0 ) $output = new Object($this->errno, $this->errstr); if($this->isError()) $output = $this->getError();
else if(!is_a($output, 'Object') && !is_subclass_of($output, 'Object')) $output = new Object(); else if(!is_a($output, 'Object') && !is_subclass_of($output, 'Object')) $output = new Object();
$output->add('_query', $this->query); $output->add('_query', $this->query);
$output->add('_elapsed_time', sprintf("%0.5f", $this->elapsed_time)); $output->add('_elapsed_time', sprintf("%0.5f", $this->elapsed_time));

View file

@ -87,6 +87,7 @@
} }
$this->is_connected = true; $this->is_connected = true;
$this->password = md5($this->password);
} }
/** /**
@ -618,7 +619,7 @@
$query = sprintf("select %s from %s %s %s", $columns, implode(',',$table_list),implode(' ',$left_join), $condition); $query = sprintf("select %s from %s %s %s", $columns, implode(',',$table_list),implode(' ',$left_join), $condition);
if (count ($output->groups)) { if (count ($output->groups)) {
foreach ($output->groups as &$value) { foreach ($output->groups as $key => $value) {
if (strpos ($value, '.')) { if (strpos ($value, '.')) {
$tmp = explode ('.', $value); $tmp = explode ('.', $value);
$tmp[0] = sprintf ('"%s"', $tmp[0]); $tmp[0] = sprintf ('"%s"', $tmp[0]);
@ -627,6 +628,7 @@
} }
elseif (strpos ($value, '(')) $value = $value; elseif (strpos ($value, '(')) $value = $value;
else $value = sprintf ('"%s"', $value); else $value = sprintf ('"%s"', $value);
$output->groups[$key] = $value;
} }
$query .= sprintf(' group by %s', implode(',',$output->groups)); $query .= sprintf(' group by %s', implode(',',$output->groups));
} }
@ -798,7 +800,7 @@
$query = sprintf("select %s from %s %s %s", $columns, implode(',',$table_list), implode(' ',$left_join), $condition); $query = sprintf("select %s from %s %s %s", $columns, implode(',',$table_list), implode(' ',$left_join), $condition);
if (count ($output->groups)) { if (count ($output->groups)) {
foreach ($output->groups as &$value) { foreach ($output->groups as $key => $value) {
if (strpos ($value, '.')) { if (strpos ($value, '.')) {
$tmp = explode ('.', $value); $tmp = explode ('.', $value);
$tmp[0] = sprintf ('"%s"', $tmp[0]); $tmp[0] = sprintf ('"%s"', $tmp[0]);
@ -807,6 +809,7 @@
} }
elseif (strpos ($value, '(')) $value = $value; elseif (strpos ($value, '(')) $value = $value;
else $value = sprintf ('"%s"', $value); else $value = sprintf ('"%s"', $value);
$output->groups[$key] = $value;
} }
$query .= sprintf(' group by %s', implode(',',$output->groups)); $query .= sprintf(' group by %s', implode(',',$output->groups));
} }

View file

@ -112,6 +112,7 @@
// 접속체크 // 접속체크
$this->is_connected = true; $this->is_connected = true;
$this->password = md5($this->password);
} }
/** /**

View file

@ -83,6 +83,7 @@
// 접속체크 // 접속체크
if($this->conn){ if($this->conn){
$this->is_connected = true; $this->is_connected = true;
$this->password = md5($this->password);
}else{ }else{
$this->is_connected = false; $this->is_connected = false;
} }

View file

@ -97,6 +97,7 @@
// 접속체크 // 접속체크
$this->is_connected = true; $this->is_connected = true;
$this->password = md5($this->password);
// mysql의 경우 utf8임을 지정 // mysql의 경우 utf8임을 지정
$this->_query("set names 'utf8'"); $this->_query("set names 'utf8'");

View file

@ -97,6 +97,7 @@
// 접속체크 // 접속체크
$this->is_connected = true; $this->is_connected = true;
$this->password = md5($this->password);
// mysql의 경우 utf8임을 지정 // mysql의 경우 utf8임을 지정
$this->_query("set names 'utf8'"); $this->_query("set names 'utf8'");

View file

@ -0,0 +1,674 @@
<?php
/**
* @class DBMysqli
* @author sol (ngleader@gmail.com)
* @brief MySQL DBMS를 mysqli_* 이용하기 위한 class
* @version 0.1
*
* mysql handling class
**/
class DBMysqli extends DB {
/**
* @brief Mysql DB에 접속하기 위한 정보
**/
var $hostname = '127.0.0.1'; ///< hostname
var $userid = NULL; ///< user id
var $password = NULL; ///< password
var $database = NULL; ///< database
var $prefix = 'xe'; ///< XE에서 사용할 테이블들의 prefix (한 DB에서 여러개의 XE 설치 가능)
/**
* @brief mysql에서 사용될 column type
*
* column_type은 schema/query xml에서 공통 선언된 type을 이용하기 때문에
* DBMS에 맞게 replace 해주어야 한다
**/
var $column_type = array(
'bignumber' => 'bigint',
'number' => 'bigint',
'varchar' => 'varchar',
'char' => 'char',
'text' => 'text',
'bigtext' => 'longtext',
'date' => 'varchar(14)',
'float' => 'float',
);
/**
* @brief constructor
**/
function DBMysqli() {
$this->_setDBInfo();
$this->_connect();
}
/**
* @brief 설치 가능 여부를 return
**/
function isSupported() {
if(!function_exists('mysqli_connect')) return false;
return true;
}
/**
* @brief DB정보 설정 connect/ close
**/
function _setDBInfo() {
$db_info = Context::getDBInfo();
$this->hostname = $db_info->db_hostname;
$this->port = $db_info->db_port;
$this->userid = $db_info->db_userid;
$this->password = $db_info->db_password;
$this->database = $db_info->db_database;
$this->prefix = $db_info->db_table_prefix;
if(!substr($this->prefix,-1)!='_') $this->prefix .= '_';
}
/**
* @brief DB 접속
**/
function _connect() {
// db 정보가 없으면 무시
if(!$this->hostname || !$this->userid || !$this->password || !$this->database) return;
// 접속시도
if($this->port){
$this->fd = mysqli_connect($this->hostname, $this->userid, $this->password, $this->database, $this->port);
}else{
$this->fd = mysqli_connect($this->hostname, $this->userid, $this->password, $this->database);
}
$error = mysqli_connect_errno();
if($error) {
$this->setError($error);
return;
}
mysqli_set_charset($this->fd,'utf8');
// 접속체크
$this->is_connected = true;
$this->password = md5($this->password);
}
/**
* @brief DB접속 해제
**/
function close() {
if(!$this->isConnected()) return;
mysqli_close($this->fd);
}
/**
* @brief 쿼리에서 입력되는 문자열 변수들의 quotation 조절
**/
function addQuotes($string) {
if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string));
if(!is_numeric($string)) $string = mysqli_escape_string($this->fd,$string);
return $string;
}
/**
* @brief 트랜잭션 시작
**/
function begin() {
}
/**
* @brief 롤백
**/
function rollback() {
}
/**
* @brief 커밋
**/
function commit() {
}
/**
* @brief : 쿼리문의 실행 결과의 fetch 처리
*
* query : query문 실행하고 result return\n
* fetch : reutrn 값이 없으면 NULL\n
* rows이면 array object\n
* row이면 object\n
* return\n
**/
function _query($query) {
if(!$this->isConnected()) return;
// 쿼리 시작을 알림
$this->actStart($query);
// 쿼리 문 실행
$result = mysqli_query($this->fd,$query);
// 오류 체크
$error = mysqli_error($this->fd);
if($error) $this->setError(mysqli_errno($this->fd), $error);
// 쿼리 실행 종료를 알림
$this->actFinish();
// 결과 리턴
return $result;
}
/**
* @brief 결과를 fetch
**/
function _fetch($result) {
if(!$this->isConnected() || $this->isError() || !$result) return;
while($tmp = mysqli_fetch_object($result)) {
$output[] = $tmp;
}
if(count($output)==1) return $output[0];
return $output;
}
/**
* @brief 1 증가되는 sequence값을 return (mysql의 auto_increment는 sequence테이블에서만 사용)
**/
function getNextSequence() {
$query = sprintf("insert into `%ssequence` (seq) values ('0')", $this->prefix);
$this->_query($query);
$sequence = mysqli_insert_id($this->fd);
if($sequence % 10000 == 0) {
$query = sprintf("delete from `%ssequence` where seq < %d", $this->prefix, $sequence);
$this->_query($query);
}
return $sequence;
}
/**
* @brief mysql old password를 가져오는 함수 (mysql에서만 사용)
**/
function isValidOldPassword($password, $saved_password) {
$query = sprintf("select password('%s') as password, old_password('%s') as old_password", $this->addQuotes($password), $this->addQuotes($password));
$result = $this->_query($query);
$tmp = $this->_fetch($result);
if($tmp->password == $saved_password || $tmp->old_password == $saved_password) return true;
return false;
}
/**
* @brief 테이블 기생성 여부 return
**/
function isTableExists($target_name) {
$query = sprintf("show tables like '%s%s'", $this->prefix, $this->addQuotes($target_name));
$result = $this->_query($query);
$tmp = $this->_fetch($result);
if(!$tmp) return false;
return true;
}
/**
* @brief 특정 테이블에 특정 column 추가
**/
function addColumn($table_name, $column_name, $type='number', $size='', $default = '', $notnull=false) {
$type = $this->column_type[$type];
if(strtoupper($type)=='INTEGER') $size = '';
$query = sprintf("alter table %s%s add %s ", $this->prefix, $table_name, $column_name);
if($size) $query .= sprintf(" %s(%s) ", $type, $size);
else $query .= sprintf(" %s ", $type);
if($default) $query .= sprintf(" default '%s' ", $default);
if($notnull) $query .= " not null ";
$this->_query($query);
}
/**
* @brief 특정 테이블에 특정 column 제거
**/
function dropColumn($table_name, $column_name) {
$query = sprintf("alter table %s%s drop %s ", $this->prefix, $table_name, $column_name);
$this->_query($query);
}
/**
* @brief 특정 테이블의 column의 정보를 return
**/
function isColumnExists($table_name, $column_name) {
$query = sprintf("show fields from %s%s", $this->prefix, $table_name);
$result = $this->_query($query);
if($this->isError()) return;
$output = $this->_fetch($result);
if($output) {
$column_name = strtolower($column_name);
foreach($output as $key => $val) {
$name = strtolower($val->Field);
if($column_name == $name) return true;
}
}
return false;
}
/**
* @brief 특정 테이블에 특정 인덱스 추가
* $target_columns = array(col1, col2)
* $is_unique? unique : none
**/
function addIndex($table_name, $index_name, $target_columns, $is_unique = false) {
if(!is_array($target_columns)) $target_columns = array($target_columns);
$query = sprintf("alter table %s%s add %s index %s (%s);", $this->prefix, $table_name, $is_unique?'unique':'', $index_name, implode(',',$target_columns));
$this->_query($query);
}
/**
* @brief 특정 테이블의 특정 인덱스 삭제
**/
function dropIndex($table_name, $index_name, $is_unique = false) {
$query = sprintf("alter table %s%s drop index %s;", $this->prefix, $table_name, $index_name);
$this->_query($query);
}
/**
* @brief 특정 테이블의 index 정보를 return
**/
function isIndexExists($table_name, $index_name) {
//$query = sprintf("show indexes from %s%s where key_name = '%s' ", $this->prefix, $table_name, $index_name);
$query = sprintf("show indexes from %s%s", $this->prefix, $table_name);
$result = $this->_query($query);
if($this->isError()) return;
$output = $this->_fetch($result);
if(!$output) return;
if(!is_array($output)) $output = array($output);
for($i=0;$i<count($output);$i++) {
if($output[$i]->Key_name == $index_name) return true;
}
return false;
}
/**
* @brief xml 받아서 테이블을 생성
**/
function createTableByXml($xml_doc) {
return $this->_createTable($xml_doc);
}
/**
* @brief xml 받아서 테이블을 생성
**/
function createTableByXmlFile($file_name) {
if(!file_exists($file_name)) return;
// xml 파일을 읽음
$buff = FileHandler::readFile($file_name);
return $this->_createTable($buff);
}
/**
* @brief schema xml을 이용하여 create table query생성
*
* type : number, varchar, text, char, date, \n
* opt : notnull, default, size\n
* index : primary key, index, unique\n
**/
function _createTable($xml_doc) {
// xml parsing
$oXml = new XmlParser();
$xml_obj = $oXml->parse($xml_doc);
// 테이블 생성 schema 작성
$table_name = $xml_obj->table->attrs->name;
if($this->isTableExists($table_name)) return;
$table_name = $this->prefix.$table_name;
if(!is_array($xml_obj->table->column)) $columns[] = $xml_obj->table->column;
else $columns = $xml_obj->table->column;
foreach($columns as $column) {
$name = $column->attrs->name;
$type = $column->attrs->type;
$size = $column->attrs->size;
$notnull = $column->attrs->notnull;
$primary_key = $column->attrs->primary_key;
$index = $column->attrs->index;
$unique = $column->attrs->unique;
$default = $column->attrs->default;
$auto_increment = $column->attrs->auto_increment;
$column_schema[] = sprintf('`%s` %s%s %s %s %s',
$name,
$this->column_type[$type],
$size?'('.$size.')':'',
$default?"default '".$default."'":'',
$notnull?'not null':'',
$auto_increment?'auto_increment':''
);
if($primary_key) $primary_list[] = $name;
else if($unique) $unique_list[$unique][] = $name;
else if($index) $index_list[$index][] = $name;
}
if(count($primary_list)) {
$column_schema[] = sprintf("primary key (%s)", '`'.implode($primary_list,'`,`').'`');
}
if(count($unique_list)) {
foreach($unique_list as $key => $val) {
$column_schema[] = sprintf("unique %s (%s)", $key, '`'.implode($val,'`,`').'`');
}
}
if(count($index_list)) {
foreach($index_list as $key => $val) {
$column_schema[] = sprintf("index %s (%s)", $key, '`'.implode($val,'`,`').'`');
}
}
$schema = sprintf('create table `%s` (%s%s) %s;', $this->addQuotes($table_name), "\n", implode($column_schema,",\n"), "ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_general_ci");
$output = $this->_query($schema);
if(!$output) return false;
}
/**
* @brief 조건문 작성하여 return
**/
function getCondition($output) {
if(!$output->conditions) return;
$condition = $this->_getCondition($output->conditions,$output->column_type);
if($condition) $condition = ' where '.$condition;
return $condition;
}
function getLeftCondition($conditions,$column_type){
return $this->_getCondition($conditions,$column_type);
}
function _getCondition($conditions,$column_type) {
$condition = '';
foreach($conditions as $val) {
$sub_condition = '';
foreach($val['condition'] as $v) {
if(!isset($v['value'])) continue;
if($v['value'] === '') continue;
if(!in_array(gettype($v['value']), array('string', 'integer'))) continue;
$name = $v['column'];
$operation = $v['operation'];
$value = $v['value'];
$type = $this->getColumnType($column_type,$name);
$pipe = $v['pipe'];
$value = $this->getConditionValue($name, $value, $operation, $type, $column_type);
if(!$value) $value = $v['value'];
$str = $this->getConditionPart($name, $value, $operation);
if($sub_condition) $sub_condition .= ' '.$pipe.' ';
$sub_condition .= $str;
}
if($sub_condition) {
if($condition && $val['pipe']) $condition .= ' '.$val['pipe'].' ';
$condition .= '('.$sub_condition.')';
}
}
return $condition;
}
/**
* @brief insertAct 처리
**/
function _executeInsertAct($output) {
// 테이블 정리
foreach($output->tables as $key => $val) {
$table_list[] = '`'.$this->prefix.$val.'`';
}
// 컬럼 정리
foreach($output->columns as $key => $val) {
$name = $val['name'];
$value = $val['value'];
$value_list = array();
if($output->column_type[$name]!='number') {
$value = "'".$this->addQuotes($value)."'";
if(!$value) $value = 'null';
} elseif(!$value || is_numeric($value)) $value = (int)$value;
$column_list[] = '`'.$name.'`';
$value_list[] = $value;
}
$query = sprintf("insert into %s (%s) values (%s);", implode(',',$table_list), implode(',',$column_list), implode(',', $value_list));
return $this->_query($query);
}
/**
* @brief updateAct 처리
**/
function _executeUpdateAct($output) {
// 테이블 정리
foreach($output->tables as $key => $val) {
$table_list[] = '`'.$this->prefix.$val.'` as '.$key;
}
// 컬럼 정리
foreach($output->columns as $key => $val) {
if(!isset($val['value'])) continue;
$name = $val['name'];
$value = $val['value'];
if(strpos($name,'.')!==false&&strpos($value,'.')!==false) $column_list[] = $name.' = '.$value;
else {
if($output->column_type[$name]!='number') $value = "'".$this->addQuotes($value)."'";
elseif(!$value || is_numeric($value)) $value = (int)$value;
$column_list[] = sprintf("`%s` = %s", $name, $value);
}
}
// 조건절 정리
$condition = $this->getCondition($output);
$query = sprintf("update %s set %s %s", implode(',',$table_list), implode(',',$column_list), $condition);
return $this->_query($query);
}
/**
* @brief deleteAct 처리
**/
function _executeDeleteAct($output) {
// 테이블 정리
foreach($output->tables as $key => $val) {
$table_list[] = '`'.$this->prefix.$val.'`';
}
// 조건절 정리
$condition = $this->getCondition($output);
$query = sprintf("delete from %s %s", implode(',',$table_list), $condition);
return $this->_query($query);
}
/**
* @brief selectAct 처리
*
* select의 경우 특정 페이지의 목록을 가져오는 것을 편하게 하기 위해\n
* navigation이라는 method를 제공
**/
function _executeSelectAct($output) {
// 테이블 정리
$table_list = array();
foreach($output->tables as $key => $val) {
$table_list[] = '`'.$this->prefix.$val.'` as '.$key;
}
$left_join = array();
// why???
$left_tables= (array)$output->left_tables;
foreach($left_tables as $key => $val) {
$condition = $this->_getCondition($output->left_conditions[$key],$output->column_type);
if($condition){
$left_join[] = $val . ' `'.$this->prefix.$output->_tables[$key].'` as '.$key . ' on (' . $condition . ')';
}
}
$click_count = array();
if(!$output->columns) {
$columns = '*';
} else {
$column_list = array();
foreach($output->columns as $key => $val) {
$name = $val['name'];
$alias = $val['alias'];
if($val['click_count']) $click_count[] = $val['name'];
if(substr($name,-1) == '*') {
$column_list[] = $name;
} elseif(strpos($name,'.')===false && strpos($name,'(')===false) {
if($alias) $column_list[] = sprintf('`%s` as `%s`', $name, $alias);
else $column_list[] = sprintf('`%s`',$name);
} else {
if($alias) $column_list[] = sprintf('%s as `%s`', $name, $alias);
else $column_list[] = sprintf('%s',$name);
}
}
$columns = implode(',',$column_list);
}
$condition = $this->getCondition($output);
if($output->list_count && $output->page) return $this->_getNavigationData($table_list, $columns, $left_join, $condition, $output);
// list_order, update_order 로 정렬시에 인덱스 사용을 위해 condition에 쿼리 추가
if($output->order) {
$conditions = $this->getConditionList($output);
if(!in_array('list_order', $conditions) && !in_array('update_order', $conditions)) {
foreach($output->order as $key => $val) {
$col = $val[0];
if(!in_array($col, array('list_order','update_order'))) continue;
if($condition) $condition .= sprintf(' and %s < 2100000000 ', $col);
else $condition = sprintf(' where %s < 2100000000 ', $col);
}
}
}
$query = sprintf("select %s from %s %s %s", $columns, implode(',',$table_list),implode(' ',$left_join), $condition);
if(count($output->groups)) $query .= sprintf(' group by %s', implode(',',$output->groups));
if($output->order) {
foreach($output->order as $key => $val) {
$index_list[] = sprintf('%s %s', $val[0], $val[1]);
}
if(count($index_list)) $query .= ' order by '.implode(',',$index_list);
}
// list_count를 사용할 경우 적용
if($output->list_count['value']) $query = sprintf('%s limit %d', $query, $output->list_count['value']);
$result = $this->_query($query);
if($this->isError()) return;
if(count($click_count)>0 && count($output->conditions)>0){
$_query = '';
foreach($click_count as $k => $c) $_query .= sprintf(',%s=%s+1 ',$c,$c);
$_query = sprintf('update %s set %s %s',implode(',',$table_list), substr($_query,1), $condition);
$this->_query($_query);
}
$data = $this->_fetch($result);
$buff = new Object();
$buff->data = $data;
return $buff;
}
/**
* @brief query xml에 navigation 정보가 있을 경우 페이징 관련 작업을 처리한다
*
* 그닥 좋지는 않은 구조이지만 편리하다.. -_-;
**/
function _getNavigationData($table_list, $columns, $left_join, $condition, $output) {
require_once(_XE_PATH_.'classes/page/PageHandler.class.php');
// 전체 개수를 구함
$count_condition = count($output->groups) ? sprintf('%s group by %s', $condition, implode(', ', $output->groups)) : $condition;
$total_count = $this->getCountCache($output->tables, $count_condition);
if($total_count === false) {
$count_query = sprintf("select count(*) as count from %s %s %s", implode(', ', $table_list), implode(' ', $left_join), $count_condition);
if (count($output->groups))
$count_query = sprintf('select count(*) as count from (%s) xet', $count_query);
$result = $this->_query($count_query);
$count_output = $this->_fetch($result);
$total_count = (int)$count_output->count;
$this->putCountCache($output->tables, $count_condition, $total_count);
}
$list_count = $output->list_count['value'];
if(!$list_count) $list_count = 20;
$page_count = $output->page_count['value'];
if(!$page_count) $page_count = 10;
$page = $output->page['value'];
if(!$page) $page = 1;
// 전체 페이지를 구함
if($total_count) $total_page = (int)( ($total_count-1) / $list_count) + 1;
else $total_page = 1;
// 페이지 변수를 체크
if($page > $total_page) $page = $total_page;
$start_count = ($page-1)*$list_count;
// list_order, update_order 로 정렬시에 인덱스 사용을 위해 condition에 쿼리 추가
if($output->order) {
$conditions = $this->getConditionList($output);
if(!in_array('list_order', $conditions) && !in_array('update_order', $conditions)) {
foreach($output->order as $key => $val) {
$col = $val[0];
if(!in_array($col, array('list_order','update_order'))) continue;
if($condition) $condition .= sprintf(' and %s < 2100000000 ', $col);
else $condition = sprintf(' where %s < 2100000000 ', $col);
}
}
}
$query = sprintf("select %s from %s %s %s", $columns, implode(',',$table_list), implode(' ',$left_join), $condition);
if(count($output->groups)) $query .= sprintf(' group by %s', implode(',',$output->groups));
if(count($output->order)) {
foreach($output->order as $key => $val) {
$index_list[] = sprintf('%s %s', $val[0], $val[1]);
}
if(count($index_list)) $query .= ' order by '.implode(',',$index_list);
}
$query = sprintf('%s limit %d, %d', $query, $start_count, $list_count);
$result = $this->_query($query);
if($this->isError()) {
$buff = new Object();
$buff->total_count = 0;
$buff->total_page = 0;
$buff->page = 1;
$buff->data = array();
$buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count);
return $buff;
}
$virtual_no = $total_count - ($page-1)*$list_count;
while($tmp = mysqli_fetch_object($result)) {
$data[$virtual_no--] = $tmp;
}
$buff = new Object();
$buff->total_count = $total_count;
$buff->total_page = $total_page;
$buff->page = $page;
$buff->data = $data;
$buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count);
return $buff;
}
}
?>

View file

@ -104,7 +104,7 @@ class DBPostgresql extends DB
// 접속체크 // 접속체크
$this->is_connected = true; $this->is_connected = true;
$this->password = md5($this->password);
// utf8임을 지정 // utf8임을 지정
//$this ->_query('set client_encoding to uhc'); //$this ->_query('set client_encoding to uhc');
} }

View file

@ -76,6 +76,7 @@
// 접속체크 // 접속체크
$this->is_connected = true; $this->is_connected = true;
$this->password = md5($this->password);
} }
/** /**

View file

@ -84,6 +84,7 @@
// 접속체크 // 접속체크
$this->is_connected = true; $this->is_connected = true;
$this->password = md5($this->password);
} }
/** /**

View file

@ -272,7 +272,7 @@
$end = getMicroTime(); $end = getMicroTime();
// Firebug 콘솔 출력 // Firebug 콘솔 출력
if(__DEBUG_OUTPUT__ == 2 && version_compare(PHP_VERSION, '5.2.0', '>=')) { if(__DEBUG_OUTPUT__ == 2 && version_compare(PHP_VERSION, '6.0.0') === -1) {
static $firephp; static $firephp;
if(!isset($firephp)) $firephp = FirePHP::getInstance(true); if(!isset($firephp)) $firephp = FirePHP::getInstance(true);
@ -379,7 +379,7 @@
} }
// HTML 주석으로 출력 // HTML 주석으로 출력
if(__DEBUG_OUTPUT__ == 1 && Context::getResponseMethod() == '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)); $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']) { if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
@ -390,7 +390,7 @@
} }
// 파일에 출력 // 파일에 출력
if(__DEBUG_OUTPUT__ == 0) { if($buff && __DEBUG_OUTPUT__ == 0) {
$debug_file = _XE_PATH_.'files/_debug_message.php'; $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 = sprintf("[%s %s:%d]\n%s\n", date('Y-m-d H:i:s'), $file_name, $line_num, print_r($buff, true));

View file

@ -397,6 +397,40 @@
return true; return true;
} }
/**
* @brief convert size in string into numeric value
* @param[in] $val size in string (ex., 10, 10K, 10M, 10G )
* @return converted size
*/
function returnBytes($val)
{
$val = trim($val);
$last = strtolower(substr($val, -1));
if($last == 'g') $val *= 1024*1024*1024;
else if($last == 'm') $val *= 1024*1024;
else if($last == 'k') $val *= 1024;
return $val;
}
/**
* @brief check available memory to load image file
* @param[in] $imageInfo image info retrieved by getimagesize function
* @return true: it's ok, false: otherwise
*/
function checkMemoryLoadImage(&$imageInfo)
{
if(!function_exists('memory_get_usage')) return true;
$K64 = 65536;
$TWEAKFACTOR = 1.5;
$channels = $imageInfo['channels'];
if(!$channels) $channels = 6; //for png
$memoryNeeded = round( ($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $channels / 8 + $K64 ) * $TWEAKFACTOR );
$availableMemory = FileHandler::returnBytes(ini_get('memory_limit')) - memory_get_usage();
if($availableMemory < $memoryNeeded) return false;
return true;
}
/** /**
* @brief moves an image file (resizing is possible) * @brief moves an image file (resizing is possible)
* @param[in] $source_file path of the source file * @param[in] $source_file path of the source file
@ -416,7 +450,10 @@
if(!$resize_height) $resize_height = $resize_width; if(!$resize_height) $resize_height = $resize_width;
// retrieve source image's information // retrieve source image's information
list($width, $height, $type, $attrs) = @getimagesize($source_file); $imageInfo = getimagesize($source_file);
if(!FileHandler::checkMemoryLoadImage($imageInfo)) return false;
list($width, $height, $type, $attrs) = $imageInfo;
if($width<1 || $height<1) return; if($width<1 || $height<1) return;
switch($type) { switch($type) {
@ -470,20 +507,24 @@
// create temporary image having original type // create temporary image having original type
switch($type) { switch($type) {
case 'gif' : case 'gif' :
if(!function_exists('imagecreatefromgif')) return false;
$source = @imagecreatefromgif($source_file); $source = @imagecreatefromgif($source_file);
break; break;
// jpg // jpg
case 'jpeg' : case 'jpeg' :
case 'jpg' : case 'jpg' :
if(!function_exists('imagecreatefromjpeg')) return false;
$source = @imagecreatefromjpeg($source_file); $source = @imagecreatefromjpeg($source_file);
break; break;
// png // png
case 'png' : case 'png' :
if(!function_exists('imagecreatefrompng')) return false;
$source = @imagecreatefrompng($source_file); $source = @imagecreatefrompng($source_file);
break; break;
// bmp // bmp
case 'wbmp' : case 'wbmp' :
case 'bmp' : case 'bmp' :
if(!function_exists('imagecreatefromwbmp')) return false;
$source = @imagecreatefromwbmp($source_file); $source = @imagecreatefromwbmp($source_file);
break; break;
default : default :
@ -514,17 +555,21 @@
// write into the file // write into the file
switch($target_type) { switch($target_type) {
case 'gif' : case 'gif' :
if(!function_exists('imagegif')) return false;
$output = @imagegif($thumb, $target_file); $output = @imagegif($thumb, $target_file);
break; break;
case 'jpeg' : case 'jpeg' :
case 'jpg' : case 'jpg' :
if(!function_exists('imagejpeg')) return false;
$output = @imagejpeg($thumb, $target_file, 100); $output = @imagejpeg($thumb, $target_file, 100);
break; break;
case 'png' : case 'png' :
if(!function_exists('imagepng')) return false;
$output = @imagepng($thumb, $target_file, 9); $output = @imagepng($thumb, $target_file, 9);
break; break;
case 'wbmp' : case 'wbmp' :
case 'bmp' : case 'bmp' :
if(!function_exists('imagewbmp')) return false;
$output = @imagewbmp($thumb, $target_file, 100); $output = @imagewbmp($thumb, $target_file, 100);
break; break;
} }

View file

@ -2,45 +2,40 @@
/** /**
* @class ModuleHandler * @class ModuleHandler
* @author zero (zero@nzeo.com) * @author zero (zero@nzeo.com)
* @brief 모듈 핸들링을 위한 Handler * @brief Handling modules
* *
* 모듈을 실행시키기 위한 클래스. * @remarks This class is to excute actions of modules.
* constructor에 아무 인자 없이 객체를 생성하면 현재 요청받은 * Constructing an instance without any parameterconstructor, it finds the target module based on Context.
* 상태를 바탕으로 적절한 모듈을 찾게 되고, * If there is no act on the found module, excute an action referencing action_forward.
* 별도의 인자 값을 경우 그에 맞는 모듈을 찾아서 실행한다.
* 만약 찾아진 모듈의 요청된 act 없으면 action_foward를 참조하여 다른 모듈의 act를 실행한다.
**/ **/
class ModuleHandler extends Handler { class ModuleHandler extends Handler {
var $oModule = NULL; ///< 모듈 객체 var $oModule = NULL; ///< Module Instance
var $module = NULL; ///< 모듈 var $module = NULL; ///< Module
var $act = NULL; ///< action var $act = NULL; ///< action
var $mid = NULL; ///< 모듈의 객체명 var $mid = NULL; ///< Module ID
var $document_srl = NULL; ///< 문서 번호 var $document_srl = NULL; ///< Document Number
var $module_srl = NULL; ///< 모듈의 번호 var $module_srl = NULL; ///< Module Number
var $module_info = NULL; ///< 모듈의 정보 var $module_info = NULL; ///< Module Info. Object
var $error = NULL; ///< 진행 도중 에러 발생시 에러 코드를 정의, message 모듈을 호출시 사용 var $error = NULL; ///< an error code.
/** /**
* @brief constructor * @brief constructor
* * @remarks it prepares variables to use in moduleHandler
* ModuleHandler에서 사용할 변수를 미리 세팅
* 인자를 넘겨주지 않으면 페이지 요청받은 Request Arguments를 이용하여
* 변수를 세팅한다.
**/ **/
function ModuleHandler($module = '', $act = '', $mid = '', $document_srl = '', $module_srl = '') { function ModuleHandler($module = '', $act = '', $mid = '', $document_srl = '', $module_srl = '') {
// 설치가 안되어 있다면 install module을 지정 // If XE has not installed yet, set module as install
if(!Context::isInstalled()) { if(!Context::isInstalled()) {
$this->module = 'install'; $this->module = 'install';
$this->act = Context::get('act'); $this->act = Context::get('act');
return; return;
} }
// Request Argument중 모듈을 찾을 수 있는 변수를 구함 // Set variables from request arguments
if(!$module) $this->module = Context::get('module'); if(!$module) $this->module = Context::get('module');
else $this->module = $module; else $this->module = $module;
@ -58,12 +53,12 @@
$this->entry = Context::get('entry'); $this->entry = Context::get('entry');
// 기본 변수들의 검사 (XSS방지를 위한 기초적 검사) // Validate variables to prevent XSS
if($this->module && !preg_match("/^([a-z0-9\_\-]+)$/i",$this->module)) die(Context::getLang("msg_invalid_request")); if($this->module && !preg_match("/^([a-z0-9\_\-]+)$/i",$this->module)) die(Context::getLang("msg_invalid_request"));
if($this->mid && !preg_match("/^([a-z0-9\_\-]+)$/i",$this->mid)) die(Context::getLang("msg_invalid_request")); if($this->mid && !preg_match("/^([a-z0-9\_\-]+)$/i",$this->mid)) die(Context::getLang("msg_invalid_request"));
if($this->act && !preg_match("/^([a-z0-9\_\-]+)$/i",$this->act)) die(Context::getLang("msg_invalid_request")); if($this->act && !preg_match("/^([a-z0-9\_\-]+)$/i",$this->act)) die(Context::getLang("msg_invalid_request"));
// 애드온 실행 (모듈 실행 전) // execute addon (before module initialization)
$called_position = 'before_module_init'; $called_position = 'before_module_init';
$oAddonController = &getController('addon'); $oAddonController = &getController('addon');
$addon_file = $oAddonController->getCacheFilePath(); $addon_file = $oAddonController->getCacheFilePath();
@ -71,10 +66,10 @@
} }
/** /**
* @brief module, mid, document_srl을 이용하여 모듈을 찾고 act를 실행하기 위한 준비를 * @brief Initialization. It finds the target module based on module, mid, document_srl, and prepares to execute an action
* @return true: OK, false: redirected
**/ **/
function init() { function init() {
// ModuleModel 객체 생성
$oModuleModel = &getModel('module'); $oModuleModel = &getModel('module');
$site_module_info = Context::get('site_module_info'); $site_module_info = Context::get('site_module_info');
@ -85,50 +80,50 @@
if($this->document_srl) Context::set('document_srl', $this->document_srl); if($this->document_srl) Context::set('document_srl', $this->document_srl);
} }
// 문서번호(document_srl)가 있을 경우 모듈 정보를 구해옴 // Get module's information based on document_srl, if it's specified
if($this->document_srl && !$this->module) { if($this->document_srl && !$this->module) {
$module_info = $oModuleModel->getModuleInfoByDocumentSrl($this->document_srl); $module_info = $oModuleModel->getModuleInfoByDocumentSrl($this->document_srl);
// 문서가 존재하지 않으면 문서 정보를 제거 // If the document does not exist, remove document_srl
if(!$module_info) { if(!$module_info) {
unset($this->document_srl); unset($this->document_srl);
// 문서가 존재할 경우 모듈 정보를 바탕으로 virtual site 및 mid 비교
} else { } else {
// mid 값이 다르면 문서의 mid로 설정 // If it exists, compare mid based on the module information
// if mids are not matching, set it as the document's mid
if($this->mid != $module_info->mid) { if($this->mid != $module_info->mid) {
$this->mid = $module_info->mid; $this->mid = $module_info->mid;
Context::set('mid', $module_info->mid, true); Context::set('mid', $module_info->mid, true);
} }
} }
// 요청된 모듈과 문서 번호가 다르면 문서 번호에 의한 모듈 정보를 제거 // if requested module is different from one of the document, remove the module information retrieved based on the document number
if($this->module && $module_info->module != $this->module) unset($module_info); if($this->module && $module_info->module != $this->module) unset($module_info);
} }
// 모듈정보를 구하지 못했고 mid 요청이 있으면 mid에 해당하는 모듈 정보를 구함 // If module_info is not set yet, and there exists mid information, get module information based on the mid
if(!$module_info && $this->mid) { if(!$module_info && $this->mid) {
$module_info = $oModuleModel->getModuleInfoByMid($this->mid, $site_module_info->site_srl); $module_info = $oModuleModel->getModuleInfoByMid($this->mid, $site_module_info->site_srl);
//if($this->module && $module_info->module != $this->module) unset($module_info); //if($this->module && $module_info->module != $this->module) unset($module_info);
} }
// module_site_srl과 site_srl 값이 다르면 redirect 시도 // redirect, if module_site_srl and site_srl are different
if(!$this->module && !$module_info && $site_module_info->site_srl == 0 && $site_module_info->module_site_srl > 0) { if(!$this->module && !$module_info && $site_module_info->site_srl == 0 && $site_module_info->module_site_srl > 0) {
$site_info = $oModuleModel->getSiteInfo($site_module_info->module_site_srl); $site_info = $oModuleModel->getSiteInfo($site_module_info->module_site_srl);
header("location:".getNotEncodedSiteUrl($site_info->domain,'mid',$site_module_info->mid)); header("location:".getNotEncodedSiteUrl($site_info->domain,'mid',$site_module_info->mid));
return false; return false;
} }
// 역시 모듈을 못 찾았고 $module이 없다면 기본 모듈을 찾아봄 // If module_info is not set still, and $module does not exist, find the default module
if(!$module_info && !$this->module) $module_info = $site_module_info; if(!$module_info && !$this->module) $module_info = $site_module_info;
if(!$module_info && !$this->module && $site_module_info->module_site_srl) $module_info = $site_module_info; if(!$module_info && !$this->module && $site_module_info->module_site_srl) $module_info = $site_module_info;
// 모듈정보와 사이트 모듈정보가 다르면(다른 사이트이면) 페이지 리다이렉트 // redirect, if site_srl of module_info is different from one of site's module_info
if($module_info && $module_info->site_srl != $site_module_info->site_srl) { if($module_info && $module_info->site_srl != $site_module_info->site_srl) {
// 현재 요청된 모듈이 가상 사이트 모듈일 경우 // If the module is of virtual site
if($module_info->site_srl) { if($module_info->site_srl) {
$site_info = $oModuleModel->getSiteInfo($module_info->site_srl); $site_info = $oModuleModel->getSiteInfo($module_info->site_srl);
$redirect_url = getNotEncodedSiteUrl($site_info->domain, 'mid',Context::get('mid'),'document_srl',Context::get('document_srl'),'module_srl',Context::get('module_srl'),'entry',Context::get('entry')); $redirect_url = getNotEncodedSiteUrl($site_info->domain, 'mid',Context::get('mid'),'document_srl',Context::get('document_srl'),'module_srl',Context::get('module_srl'),'entry',Context::get('entry'));
// 가상 사이트 모듈이 아닌데 가상 사이트에서 호출되었을 경우 // If it's called from a virtual site, though it's not a module of the virtual site
} else { } else {
$db_info = Context::getDBInfo(); $db_info = Context::getDBInfo();
if(!$db_info->default_url) return Context::getLang('msg_default_url_is_not_defined'); if(!$db_info->default_url) return Context::getLang('msg_default_url_is_not_defined');
@ -138,7 +133,7 @@
return false; return false;
} }
// 모듈 정보가 찾아졌을 경우 모듈 정보에서 기본 변수들을 구함, 모듈 정보에서 module 이름을 구해움 // If module info was set, retrieve variables from the module information
if($module_info) { if($module_info) {
$this->module = $module_info->module; $this->module = $module_info->module;
$this->mid = $module_info->mid; $this->mid = $module_info->mid;
@ -148,34 +143,35 @@
Context::addHtmlHeader($part_config->header_script); Context::addHtmlHeader($part_config->header_script);
} }
// 모듈정보에 module과 mid를 강제로 지정 // Set module and mid into module_info
$this->module_info->module = $this->module; $this->module_info->module = $this->module;
$this->module_info->mid = $this->mid; $this->module_info->mid = $this->mid;
// 여기까지도 모듈 정보를 찾지 못했다면 깔끔하게 시스템 오류 표시 // Still no module? it's an error
if(!$this->module) $this->error = 'msg_module_is_not_exists'; if(!$this->module) $this->error = 'msg_module_is_not_exists';
// mid값이 있을 경우 mid값을 세팅 // If mid exists, set mid into context
if($this->mid) Context::set('mid', $this->mid, true); if($this->mid) Context::set('mid', $this->mid, true);
// 실제 동작을 하기 전에 trigger 호출 // Call a trigger after moduleHandler init
$output = ModuleHandler::triggerCall('moduleHandler.init', 'after', $this->module_info); $output = ModuleHandler::triggerCall('moduleHandler.init', 'after', $this->module_info);
if(!$output->toBool()) { if(!$output->toBool()) {
$this->error = $output->getMessage(); $this->error = $output->getMessage();
return false; return false;
} }
// 현재 모듈의 정보를 세팅 // Set current module info into context
Context::set('current_module_info', $this->module_info); Context::set('current_module_info', $this->module_info);
return true; return true;
} }
/** /**
* @brief 모듈과 관련된 정보를 이용하여 객체를 구하고 act 실행까지 진행시킴 * @brief get a module instance and execute an action
* @return executed module instance
**/ **/
function procModule() { function procModule() {
// 에러가 있으면 메세지 객체를 만들어서 return // If error occurred while preparation, return a message instance
if($this->error) { if($this->error) {
$oMessageView = &getView('message'); $oMessageView = &getView('message');
$oMessageView->setError(-1); $oMessageView->setError(-1);
@ -184,99 +180,98 @@
return $oMessageView; return $oMessageView;
} }
// ModuleModel 객체 생성
$oModuleModel = &getModel('module'); $oModuleModel = &getModel('module');
// 해당 모듈의 conf/action.xml 을 분석하여 action 정보를 얻어옴 // Get action information with conf/action.xml
$xml_info = $oModuleModel->getModuleActionXml($this->module); $xml_info = $oModuleModel->getModuleActionXml($this->module);
// 미설치시에는 act값을 강제로 변경 // If not installed yet, modify act
if($this->module=="install") { if($this->module=="install") {
if(!$this->act || !$xml_info->action->{$this->act}) $this->act = $xml_info->default_index_act; if(!$this->act || !$xml_info->action->{$this->act}) $this->act = $xml_info->default_index_act;
} }
// 현재 요청된 act가 있으면 $xml_info에서 type을 찾음, 없다면 기본 action을 이용 // if act exists, find type of the action, if not use default index act
if(!$this->act) $this->act = $xml_info->default_index_act; if(!$this->act) $this->act = $xml_info->default_index_act;
// act값이 지정이 안되어 있으면 오류 표시 // still no act means error
if(!$this->act) { if(!$this->act) {
$this->error = 'msg_module_is_not_exists'; $this->error = 'msg_module_is_not_exists';
return; return;
} }
// type, kind 값 구함 // get type, kind
$type = $xml_info->action->{$this->act}->type; $type = $xml_info->action->{$this->act}->type;
$kind = strpos(strtolower($this->act),'admin')!==false?'admin':''; $kind = strpos(strtolower($this->act),'admin')!==false?'admin':'';
if(!$kind && $this->module == 'admin') $kind = 'admin'; if(!$kind && $this->module == 'admin') $kind = 'admin';
// 모듈 객체 생성 // create a module instance
$oModule = &$this->getModuleInstance($this->module, $type, $kind); $oModule = &$this->getModuleInstance($this->module, $type, $kind);
if(!is_object($oModule)) { if(!is_object($oModule)) {
$this->error = 'msg_module_is_not_exists'; $this->error = 'msg_module_is_not_exists';
return; return;
} }
// 모듈에 act값을 세팅
$oModule->setAct($this->act); $oModule->setAct($this->act);
// 모듈 정보 세팅
$this->module_info->module_type = $type; $this->module_info->module_type = $type;
$oModule->setModuleInfo($this->module_info, $xml_info); $oModule->setModuleInfo($this->module_info, $xml_info);
// 모듈을 수행하고 결과가 false이면 message 모듈 호출 지정 // execute the action, and if failed, set error
if(!$oModule->proc()) $this->error = $oModule->getMessage(); if(!$oModule->proc()) $this->error = $oModule->getMessage();
return $oModule; return $oModule;
} }
/** /**
* @ 실행된 모듈의 컨텐츠를 출력 * @brief display contents from executed module
* @param[in] $oModule module instance
* @return none
**/ **/
function displayContent($oModule = NULL) { function displayContent($oModule = NULL) {
// 설정된 모듈이 정상이지 않을 경우 message 모듈 객체 생성 // If the module is not set or not an object, set error
if(!$oModule || !is_object($oModule)) { if(!$oModule || !is_object($oModule)) {
$this->error = 'msg_module_is_not_exists'; $this->error = 'msg_module_is_not_exists';
} }
// install 모듈이 아닐 때 DB 접속에 문제가 있으면 오류 // If connection to DB has a problem even though it's not install module, set error
if($this->module != 'install' && $GLOBALS['__DB__'][Context::getDBType()]->is_connected == false) { if($this->module != 'install' && $GLOBALS['__DB__'][Context::getDBType()]->is_connected == false) {
$this->error = 'msg_dbconnect_failed'; $this->error = 'msg_dbconnect_failed';
} }
// 모듈 동작을 마친 후 trigger call // Call trigger after moduleHandler proc
$output = ModuleHandler::triggerCall('moduleHandler.proc', 'after', $oModule); $output = ModuleHandler::triggerCall('moduleHandler.proc', 'after', $oModule);
if(!$output->toBool()) $this->error = $output->getMessage(); if(!$output->toBool()) $this->error = $output->getMessage();
// HTML call 이면 message view 객체 이용하도록 // Use message view object, if HTML call
if(!in_array(Context::getRequestMethod(),array('XMLRPC','JSON'))) { if(!in_array(Context::getRequestMethod(),array('XMLRPC','JSON'))) {
// 에러가 발생하였을시 처리 // If error occurred, handle it
if($this->error) { if($this->error) {
// message 모듈 객체를 생성해서 컨텐츠 생성 // display content with message module instance
$oMessageView = &getView('message'); $oMessageView = &getView('message');
$oMessageView->setError(-1); $oMessageView->setError(-1);
$oMessageView->setMessage($this->error); $oMessageView->setMessage($this->error);
$oMessageView->dispMessage(); $oMessageView->dispMessage();
// 정상적으로 호출된 객체가 있을 경우 해당 객체의 template를 변경 // If module was called normally, change the templates of the module into ones of the message view module
if($oModule) { if($oModule) {
$oModule->setTemplatePath($oMessageView->getTemplatePath()); $oModule->setTemplatePath($oMessageView->getTemplatePath());
$oModule->setTemplateFile($oMessageView->getTemplateFile()); $oModule->setTemplateFile($oMessageView->getTemplateFile());
// 그렇지 않으면 message 객체를 호출된 객체로 지정 // Otherwise, set message instance as the target module
} else { } else {
$oModule = $oMessageView; $oModule = $oMessageView;
} }
} }
// 해당 모듈에 layout_srl이 있는지 확인 // Check if layout_srl exists for the module
if($oModule->module_info->layout_srl && !$oModule->getLayoutFile()) { if($oModule->module_info->layout_srl && !$oModule->getLayoutFile()) {
// layout_srl이 있으면 해당 레이아웃 정보를 가져와 layout_path/ layout_file 위치 변경 // If layout_srl exists, get information of the layout, and set the location of layout_path/ layout_file
$oLayoutModel = &getModel('layout'); $oLayoutModel = &getModel('layout');
$layout_info = $oLayoutModel->getLayout($oModule->module_info->layout_srl); $layout_info = $oLayoutModel->getLayout($oModule->module_info->layout_srl);
if($layout_info) { if($layout_info) {
// 레이아웃 정보중 extra_vars의 이름과 값을 $layout_info에 입력 // Input extra_vars into $layout_info
if($layout_info->extra_var_count) { if($layout_info->extra_var_count) {
foreach($layout_info->extra_var as $var_id => $val) { foreach($layout_info->extra_var as $var_id => $val) {
@ -286,7 +281,7 @@
$layout_info->{$var_id} = $val->value; $layout_info->{$var_id} = $val->value;
} }
} }
// 레이아웃 정보중 menu를 Context::set // Set menus into context
if($layout_info->menu_count) { if($layout_info->menu_count) {
foreach($layout_info->menu as $menu_id => $menu) { foreach($layout_info->menu as $menu_id => $menu) {
if(file_exists($menu->php_file)) @include($menu->php_file); if(file_exists($menu->php_file)) @include($menu->php_file);
@ -294,33 +289,40 @@
} }
} }
// 레이아웃 정보를 Context::set // Set layout information into context
Context::set('layout_info', $layout_info); Context::set('layout_info', $layout_info);
$oModule->setLayoutPath($layout_info->path); $oModule->setLayoutPath($layout_info->path);
$oModule->setLayoutFile('layout'); $oModule->setLayoutFile('layout');
// 레이아웃이 수정되었을 경우 수정본을 지정 // If layout was modified, use the modified version
$edited_layout = $oLayoutModel->getUserLayoutHtml($layout_info->layout_srl); $edited_layout = $oLayoutModel->getUserLayoutHtml($layout_info->layout_srl);
if(file_exists($edited_layout)) $oModule->setEditedLayoutFile($edited_layout); if(file_exists($edited_layout)) $oModule->setEditedLayoutFile($edited_layout);
} }
} }
} }
// 컨텐츠 출력 // Display contents
$oDisplayHandler = new DisplayHandler(); $oDisplayHandler = new DisplayHandler();
$oDisplayHandler->printContent($oModule); $oDisplayHandler->printContent($oModule);
} }
/** /**
* @brief module의 위치를 찾아서 return * @brief returns module's path
* @param[in] $module module name
* @return path of the module
**/ **/
function getModulePath($module) { function getModulePath($module) {
return sprintf('./modules/%s/', $module); return sprintf('./modules/%s/', $module);
} }
/** /**
* @brief 모듈 객체를 생성함 * @brief It creates a module instance
* @param[in] $module module name
* @param[in] $type instance type, (e.g., view, controller, model)
* @param[in] $kind admin or svc
* @return module instance (if failed it returns null)
* @remarks if there exists a module instance created before, returns it.
**/ **/
function &getModuleInstance($module, $type = 'view', $kind = '') { function &getModuleInstance($module, $type = 'view', $kind = '') {
$class_path = ModuleHandler::getModulePath($module); $class_path = ModuleHandler::getModulePath($module);
@ -330,21 +332,16 @@
if($kind != 'admin') $kind = 'svc'; if($kind != 'admin') $kind = 'svc';
// global 변수에 미리 생성해 둔 객체가 없으면 새로 생성 // if there is no instance of the module in global variable, create a new one
if(!$GLOBALS['_loaded_module'][$module][$type][$kind]) { if(!$GLOBALS['_loaded_module'][$module][$type][$kind]) {
// Get base class name and load the file contains it
/**
* 모듈의 위치를 파악
**/
// 상위 클래스명 구함
if(!class_exists($module)) { if(!class_exists($module)) {
$high_class_file = sprintf('%s%s%s.class.php', _XE_PATH_,$class_path, $module); $high_class_file = sprintf('%s%s%s.class.php', _XE_PATH_,$class_path, $module);
if(!file_exists($high_class_file)) return NULL; if(!file_exists($high_class_file)) return NULL;
require_once($high_class_file); require_once($high_class_file);
} }
// 객체의 이름을 구함 // Get the object's name
switch($type) { switch($type) {
case 'controller' : case 'controller' :
if($kind == 'admin') { if($kind == 'admin') {
@ -392,43 +389,48 @@
break; break;
} }
// 클래스 파일의 이름을 구함 // Get the name of the class file
if(!file_exists($class_file)) return NULL; if(!file_exists($class_file)) return NULL;
// eval로 객체 생성 // Create an instance with eval function
require_once($class_file); require_once($class_file);
if(!class_exists($instance_name)) return NULL;
$eval_str = sprintf('$oModule = new %s();', $instance_name); $eval_str = sprintf('$oModule = new %s();', $instance_name);
@eval($eval_str); @eval($eval_str);
if(!is_object($oModule)) return NULL; if(!is_object($oModule)) return NULL;
// 해당 위치에 속한 lang 파일을 읽음 // Load language files for the class
Context::loadLang($class_path.'lang'); Context::loadLang($class_path.'lang');
// 생성된 객체에 자신이 호출된 위치를 세팅해줌 // Set variables to the instance
$oModule->setModule($module); $oModule->setModule($module);
$oModule->setModulePath($class_path); $oModule->setModulePath($class_path);
// 요청된 module에 constructor가 있으면 실행 // If the module has a constructor, run it.
if(!isset($GLOBALS['_called_constructor'][$instance_name])) { if(!isset($GLOBALS['_called_constructor'][$instance_name])) {
$GLOBALS['_called_constructor'][$instance_name] = true; $GLOBALS['_called_constructor'][$instance_name] = true;
if(@method_exists($oModule, $instance_name)) $oModule->{$instance_name}(); if(@method_exists($oModule, $instance_name)) $oModule->{$instance_name}();
} }
// GLOBALS 변수에 생성된 객체 저장 // Store the created instance into GLOBALS variable
$GLOBALS['_loaded_module'][$module][$type][$kind] = $oModule; $GLOBALS['_loaded_module'][$module][$type][$kind] = $oModule;
} }
if(__DEBUG__==3) $GLOBALS['__elapsed_class_load__'] += getMicroTime() - $start_time; if(__DEBUG__==3) $GLOBALS['__elapsed_class_load__'] += getMicroTime() - $start_time;
// 객체 리턴 // return the instance
return $GLOBALS['_loaded_module'][$module][$type][$kind]; return $GLOBALS['_loaded_module'][$module][$type][$kind];
} }
/** /**
* @brief trigger_name, called_position을 주고 trigger 호출 * @brief call a trigger
* @param[in] $trigger_name trigger's name to call
* @param[in] $called_position called position
* @param[in] $obj an object as a parameter to trigger
* @return Object
**/ **/
function triggerCall($trigger_name, $called_position, &$obj) { function triggerCall($trigger_name, $called_position, &$obj) {
// 설치가 안되어 있다면 trigger call을 하지 않고 바로 return // skip if not installed
if(!Context::isInstalled()) return new Object(); if(!Context::isInstalled()) return new Object();
$oModuleModel = &getModel('module'); $oModuleModel = &getModel('module');

View file

@ -2,25 +2,29 @@
/** /**
* @class PageHandler * @class PageHandler
* @author zero (zero@nzeo.com) * @author zero (zero@nzeo.com)
* @brief 페이지 네비게이션 담당 * @brief handles page navigation
* @version 0.1 * @version 0.1
* *
* 전체갯수, 전체페이지, 현재페이지, 페이지당 목록의 수를 넘겨주면 \n * @remarks Getting total counts, number of pages, current page number, number of items per page,
* 페이지 네비게이션에 필요한 variables와 method를 구현\n * this class implements methods and contains variables for page navigation
**/ **/
class PageHandler extends Handler { class PageHandler extends Handler {
var $total_count = 0; ///< 전체 item의 갯수 var $total_count = 0; ///< number of total items
var $total_page = 0; ///< 전체 페이지 수 var $total_page = 0; ///< number of total pages
var $cur_page = 0; ///< 현 페이지 var $cur_page = 0; ///< current page number
var $page_count = 10; ///< 한번에 보일 페이지의 수 var $page_count = 10; ///< number of page links displayed at one time
var $first_page = 1; ///< 첫 페이지 var $first_page = 1; ///< first page number
var $last_page = 1; ///< 마지막 페이지 var $last_page = 1; ///< last page number
var $point = 0; ///< getNextPage() 호출시 증가하는 값 var $point = 0; ///< increments per getNextPage()
/** /**
* @brief constructor * @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) { function PageHandler($total_count, $total_page, $cur_page, $page_count = 10) {
$this->total_count = $total_count; $this->total_count = $total_count;
@ -41,7 +45,8 @@
} }
/** /**
* @brief 다음 페이지 요청 * @brief request next page
* @return next page number
**/ **/
function getNextPage() { function getNextPage() {
$page = $this->first_page+$this->point++; $page = $this->first_page+$this->point++;

View file

@ -3,9 +3,9 @@
/* Anchor Button */ /* Anchor Button */
a.button, a.button,
a.button span { position:relative; display:inline-block; text-decoration:none !important; background:url(../tpl/images/buttonWhite.gif) no-repeat; cursor:pointer; white-space:nowrap; vertical-align:middle; *vertical-align:top;} a.button span { position:relative; display:inline-block; text-decoration:none !important; background:url(../tpl/images/buttonWhite.gif) no-repeat; cursor:pointer; white-space:nowrap; vertical-align:middle;}
a.button { padding:0; background-position:left top; overflow:visible;} a.button { padding:0; background-position:left top; overflow:visible;}
a.button span { left:2px; padding:6px 10px 5px 8px; color:#000; font:12px/12px Sans-serif; background-position:right top;} a.button span { left:2px; padding:6px 10px 5px 8px; color:#000; font:12px/12px Sans-serif; background-position:right top; *vertical-align:top;}
/* Large Size */ /* Large Size */
a.button.large { background-position:left -30px; } a.button.large { background-position:left -30px; }
a.button.large span { padding:7px 10px 6px 8px; font:16px/16px Sans-serif; background-position:right -30px;} a.button.large span { padding:7px 10px 6px 8px; font:16px/16px Sans-serif; background-position:right -30px;}
@ -22,11 +22,11 @@ span.button button,
span.button input { position:relative; margin:0; display:inline-block; border:0; font:12px Sans-serif; white-space:nowrap; background:url(../tpl/images/buttonWhite.gif) no-repeat; vertical-align:middle;} span.button input { position:relative; margin:0; display:inline-block; border:0; font:12px Sans-serif; white-space:nowrap; background:url(../tpl/images/buttonWhite.gif) no-repeat; vertical-align:middle;}
span.button { padding:0; background-position:left top;} span.button { padding:0; background-position:left top;}
span.button button, span.button button,
span.button input { height:23px; left:2px; *top:-1px; _top:0; padding:0 10px 0 8px; line-height:24px; background-position:right top; cursor:pointer; *overflow:visible;} span.button input { height:23px; left:2px; *vertical-align:top; padding:0 10px 0 8px; line-height:24px; background-position:right top; cursor:pointer; *overflow:visible;}
/* Large Size */ /* Large Size */
span.button.large { background-position:left -30px;} span.button.large { background-position:left -30px;}
span.button.large button, span.button.large button,
span.button.large input { height:30px; *top:0; _top:-1px; padding:0 10px 0 8px; font:16px/30px Sans-serif; background-position:right -30px;} span.button.large input { height:30px; padding:0 10px 0 8px; font:16px/30px Sans-serif; background-position:right -30px;}
/* xLarge Size */ /* xLarge Size */
span.button.xLarge { background-position:left -65px;} span.button.xLarge { background-position:left -65px;}
span.button.xLarge button, span.button.xLarge button,
@ -34,7 +34,7 @@ span.button.xLarge input { height:35px; padding:0 10px 0 8px; font:20px/36px San
/* Small Size */ /* Small Size */
span.button.small { background-position:left -107px;} span.button.small { background-position:left -107px;}
span.button.small button, span.button.small button,
span.button.small input { height:18px; *top:0; _top:-1px; padding:0 6px 0 4px; font:11px/18px Sans-serif; background-position:right -107px;} span.button.small input { height:18px; padding:0 6px 0 4px; font:11px/18px Sans-serif; background-position:right -107px;}
/* Strong Button */ /* Strong Button */
a.button.strong *, a.button.strong *,

View file

@ -450,8 +450,8 @@ function _displayMultimedia(src, width, height, options) {
}; };
var params = jQuery.extend(defaults, options || {}); var params = jQuery.extend(defaults, options || {});
var autostart = (params.autostart && params.autostart != 'false') ? 'true' : 'false'; var autostart = (params.autostart && params.autostart != 'false') ? 'true' : 'false';
delete(params.autostart); delete(params.autostart);
var clsid = ""; var clsid = "";
var codebase = ""; var codebase = "";
@ -464,8 +464,8 @@ function _displayMultimedia(src, width, height, options) {
} else if(/\.swf/i.test(src)) { } else if(/\.swf/i.test(src)) {
clsid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'; clsid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
if(typeof(enforce_ssl)=='undefined'){ codebase = "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0"; } if(typeof(enforce_ssl)!='undefined' && enforce_ssl){ codebase = "https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0"; }
else { codebase = "https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0"; } else { codebase = "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0"; }
html = '<object classid="'+clsid+'" codebase="'+codebase+'" width="'+width+'" height="'+height+'" flashvars="'+params.flashvars+'">'; html = '<object classid="'+clsid+'" codebase="'+codebase+'" width="'+width+'" height="'+height+'" flashvars="'+params.flashvars+'">';
html += '<param name="movie" value="'+src+'" />'; html += '<param name="movie" value="'+src+'" />';
for(var name in params) { for(var name in params) {
@ -477,6 +477,11 @@ function _displayMultimedia(src, width, height, options) {
+ '<embed src="'+src+'" autostart="'+autostart+'" width="'+width+'" height="'+height+'" flashvars="'+params.flashvars+'" wmode="'+params.wmode+'"></embed>' + '<embed src="'+src+'" autostart="'+autostart+'" width="'+width+'" height="'+height+'" flashvars="'+params.flashvars+'" wmode="'+params.wmode+'"></embed>'
+ '</object>'; + '</object>';
} else { } else {
if (jQuery.browser.mozilla || jQuery.browser.opera) {
// firefox and opera uses 0 or 1 for autostart parameter.
autostart = (params.autostart && params.autostart != 'false') ? '1' : '0';
}
html = '<embed src="'+src+'" autostart="'+autostart+'" width="'+width+'" height="'+height+'"'; html = '<embed src="'+src+'" autostart="'+autostart+'" width="'+width+'" height="'+height+'"';
if(params.wmode == 'transparent') { if(params.wmode == 'transparent') {
html += ' windowlessvideo="1"'; html += ' windowlessvideo="1"';

297
common/js/js_app.js Normal file
View file

@ -0,0 +1,297 @@
/**
* @brief XE Application Framework
* @namespace xe
*/
(function($){
var _xe_base, _app_base, _plugin_base;
var _apps = [];
_xe_base = {
/**
* @brief return the name of Core module
*/
getName : function() {
return 'Core';
},
/**
* @brief Create an application class
*/
createApp : function(sName, oDef) {
var _base = getTypeBase();
$.extend(_base.prototype, _app_base, oDef);
_base.prototype.getName = function() {
return sName;
};
return _base;
},
/**
* @brief Create a plugin class
*/
createPlugin : function(sName, oDef) {
var _base = getTypeBase();
$.extend(_base.prototype, _plugin_base, oDef);
_base.prototype.getName = function() {
return sName;
};
return _base;
},
/**
* @brief Get the array of applications
*/
getApps : function() {
return $.makeArray(_apps);
},
/**
* @brief Get one application
*/
getApp : function(indexOrName) {
if (typeof _apps[indexOrName] != 'undefined') {
return _apps[indexOrName];
} else {
return null;
}
},
/**
* @brief Register an application instance
*/
registerApp : function(oApp) {
var sName = oApp.getName().toLowerCase();
_apps.push(oApp);
if (!$.isArray(_apps[sName])) {
_apps[sName] = [];
}
_apps[sName].push(oApp);
oApp.parent = this;
},
/**
* @brief Unregister an application instance
*/
unregisterApp : function(oApp) {
var sName = oPlugin.getName().toLowerCase();
var nIndex = $.inArray(oApp, _apps);
if (nIndex >= 0) _apps.splice(nIndex, 1);
if ($.isArray(_apps[sName])) {
nIndex = $.inArray(oApp, _apps[sName]);
if (nIndex >= 0) _apps[sName].splice(nIndex, 1);
}
},
/**
* @brief overrides broadcast method
*/
broadcast : function(oSender, msg, params) {
for(var i=0; i < _apps.length; i++) {
_apps[i].cast(oSender, msg, params);
}
// cast to child plugins
this.cast(oSender, msg, params);
}
}
_app_base = {
_plugins : [],
_messages : [],
_fn_level : -1,
/**
* @brief register a plugin instance
*/
registerPlugin : function(oPlugin) {
var sName = oPlugin.getName().toLowerCase();
// check if the plugin is already registered
if ($.inArray(oPlugin, this._plugins) >= 0) return false;
// push the plugin into the _plugins array
this._plugins.push(oPlugin);
if (!$.isArray(this._plugins[sName])) {
this._plugins[sName] = [];
}
this._plugins[sName].push(oPlugin);
// register method pool
var msgs = this._messages;
$.each(oPlugin, function(key, val){
if (!$.isFunction(val)) return true;
if (!/^API_((BEFORE_|AFTER_)?[A-Z0-9_]+)$/.test(key)) return true;
var fn = function(s,p){ return oPlugin[key](s,p) };
fn._fn = val;
if (RegExp.$2) { // is hooker?
if (!$.isArray(msgs[RegExp.$1])) msgs[RegExp.$1] = [];
msgs[RegExp.$1].push(fn);
} else { // register only one main function
msgs[RegExp.$1] = fn;
}
});
// set the application
oPlugin.oApp = this;
// binding
oPlugin.cast = function(msg, params) {
oPlugin._cast(msg, params);
};
oPlugin.broadcast = function(msg, params) {
oPlugin._broadcast(msg, params);
};
return true;
},
/**
* @brief unregister a plugin instance
*/
unregisterPlugin : function(oPlugin) {
var sName = oPlugin.getName().toLowerCase();
// remove from _plugins array
var nIndex = $.inArray(oPlugin, this._plugins);
if (nIndex >= 0) this._plugins.splice(nIndex, 1);
if ($.isArray(this._plugins[sName])) {
nIndex = $.inArray(oPlugin, this._plugins);
if (nIndex >= 0) this._plugins[sName].splice(nIndex, 1);
}
// unregister method pool
var msgs = this._messages;
$.each(oPlugin, function(key, val){
if (!$.isFunction(val)) return true;
if (!/^API_([A-Z0-9_]+)$/.test(key)) return true;
if (typeof msgs[RegExp.$1] == 'undefined') return true;
if ($.isArray(msgs[RegExp.$1])) {
msgs[RegExp.$1] = $.grep(msgs[RegExp.$1], function(fn,i){ return (fn._fn != val); });
if (!msgs[RegExp.$1].length) {
delete msgs[RegExp.$1];
}
} else {
if (msgs[RegExp.$1]._fn == val) {
delete msgs[RegExp.$1];
}
}
});
// unset the application
oPlugin.oApp = null;
},
cast : function(sender, msg, params) {
var i, len;
var aMsg = this._messages;
msg = msg.toUpperCase();
// increase function level
this._fn_level++;
// BEFORE hooker
if (typeof aMsg['BEFORE_'+msg] != 'undefined') {
var bContinue = this.cast(sender, 'BEFORE_'+msg, params);
if (!bContinue) {
this._fn_level--;
return;
}
}
// main api function
var vRet;
if ($.isFunction(aMsg[msg])) {
vRet = aMsg[msg](sender, params);
} else if ($.isArray(aMsg[msg])) {
vRet = [];
for(i=0; i < aMsg[msg].length; i++) {
vRet.push( aMsg[msg][i](sender, params) );
}
}
// AFTER hooker
if (typeof aMsg['AFTER_'+msg] != 'undefined') {
this.cast(sender, 'AFTER_'+msg, params);
}
// decrease function level
this._fn_level--;
if (this._fn_level < 0) { // top level function
return vRet;
} else {
if (typeof vRet == 'undefined') vRet = true;
return $.isArray(vRet)?$.inArray(false, vRet):!!vRet;
}
},
broadcast : function(sender, msg, params) {
if (this.parent && this.parent.broadcast) {
this.parent.broadcast(sender, msg, params);
}
}
};
_plugin_base = {
oApp : null,
_binded_fn : [],
_cast : function(msg, params) {
if (this.oApp && this.oApp.cast) {
this.oApp.cast(this, msg, params || []);
}
},
_broadcast : function(msg, params) {
if (this.oApp && this.oApp.broadcast) {
this.oApp.broadcast(this, mag, params || []);
}
}
/**
* Event handler prototype
*/
};
function getTypeBase() {
var _base = function() {
if ($.isArray(this._plugins)) this._plugins = [];
if ($.isArray(this._messages)) this._messages = [];
if ($.isArray(this._binded_fn)) this._binded_fn = [];
if ($.isFunction(this.init)) {
this.init.apply(this, arguments);
}
};
return _base;
}
window.xe = $.extend(_app_base, _xe_base);
// domready event
$(function(){ xe.broadcast(xe, 'ONREADY'); });
// load event
$(window).load(function(){ xe.broadcast(xe, 'ONLOAD'); });
})(jQuery);

View file

@ -296,6 +296,10 @@
$lang->msg_ftp_chmod_fail = "Chmod failed. Please check the permission and configuration of FTP server."; $lang->msg_ftp_chmod_fail = "Chmod failed. Please check the permission and configuration of FTP server.";
$lang->msg_ftp_connect_success = "Connection and authentication to the FTP server succeeded."; $lang->msg_ftp_connect_success = "Connection and authentication to the FTP server succeeded.";
$lang->ftp_path_title = 'FTP 경로 정보 입력';
$lang->msg_ftp_installed_realpath = '설치된 XE의 절대경로';
$lang->msg_ftp_installed_ftp_realpath = '설치된 XE의 FTP 절대경로 설정';
// Alert messages for Javascript using by XML filter // Alert messages for Javascript using by XML filter
$lang->filter->isnull = 'Please input a value for %s'; $lang->filter->isnull = 'Please input a value for %s';

View file

@ -302,6 +302,11 @@
$lang->msg_ftp_chmod_fail = "Ha fallado el comando de FTP para la modificación de atributos de directorio. Verifique la configuración del servicio FTP en el servidor."; $lang->msg_ftp_chmod_fail = "Ha fallado el comando de FTP para la modificación de atributos de directorio. Verifique la configuración del servicio FTP en el servidor.";
$lang->msg_ftp_connect_success = "conexión con éxito al FTP"; $lang->msg_ftp_connect_success = "conexión con éxito al FTP";
$lang->ftp_path_title = 'FTP 경로 정보 입력';
$lang->msg_ftp_installed_realpath = '설치된 XE의 절대경로';
$lang->msg_ftp_installed_ftp_realpath = '설치된 XE의 FTP 절대경로 설정';
// Mensajes de alerta para Javascript usando el filtro XML // Mensajes de alerta para Javascript usando el filtro XML
$lang->filter->isnull = 'Introduzca valor en el %s'; $lang->filter->isnull = 'Introduzca valor en el %s';

View file

@ -296,6 +296,10 @@
$lang->msg_ftp_chmod_fail = "FTP를 이용한 디렉토리의 속성 변경을 실패하였습니다. FTP 서버의 설정을 확인해주세요"; $lang->msg_ftp_chmod_fail = "FTP를 이용한 디렉토리의 속성 변경을 실패하였습니다. FTP 서버의 설정을 확인해주세요";
$lang->msg_ftp_connect_success = "FTP 접속 및 인증 성공하였습니다"; $lang->msg_ftp_connect_success = "FTP 접속 및 인증 성공하였습니다";
$lang->ftp_path_title = 'FTP 경로 정보 입력';
$lang->msg_ftp_installed_realpath = '설치된 XE의 절대경로';
$lang->msg_ftp_installed_ftp_realpath = '설치된 XE의 FTP 절대경로 설정';
// Messages d\'alerte de le Javascript qui est utilisé dans les filtres en XML // Messages d\'alerte de le Javascript qui est utilisé dans les filtres en XML
$lang->filter->isnull = 'Entrez une valeur pour %s'; $lang->filter->isnull = 'Entrez une valeur pour %s';

View file

@ -296,6 +296,10 @@
$lang->msg_ftp_chmod_fail = "FTP를 이용한 디렉토리의 속성 변경을 실패하였습니다. FTP 서버의 설정을 확인해주세요"; $lang->msg_ftp_chmod_fail = "FTP를 이용한 디렉토리의 속성 변경을 실패하였습니다. FTP 서버의 설정을 확인해주세요";
$lang->msg_ftp_connect_success = "FTP 접속 및 인증 성공하였습니다"; $lang->msg_ftp_connect_success = "FTP 접속 및 인증 성공하였습니다";
$lang->ftp_path_title = 'FTP 경로 정보 입력';
$lang->msg_ftp_installed_realpath = '설치된 XE의 절대경로';
$lang->msg_ftp_installed_ftp_realpath = '설치된 XE의 FTP 절대경로 설정';
// Alert Nachrichten für JavaScript unter Verwendung von XML-Filter // Alert Nachrichten für JavaScript unter Verwendung von XML-Filter
$lang->filter->isnull = 'Bitte geben Sie einen Wert für% s'; $lang->filter->isnull = 'Bitte geben Sie einen Wert für% s';

View file

@ -225,9 +225,9 @@
$lang->msg_invalid_format = '正しくないフォーマットです。'; $lang->msg_invalid_format = '正しくないフォーマットです。';
$lang->msg_not_permitted_act = '現在の操作は実行する権限がありません。'; $lang->msg_not_permitted_act = '現在の操作は実行する権限がありません。';
$lang->msg_module_is_not_exists = "요청하신 모듈을 찾을 수 없습니다.\n사이트 관리자에게 모듈 점검 요청 바랍니다"; $lang->msg_module_is_not_exists = "動作に必要なモジュールが見つかりません。\nサイト管理者へモジュールの点検をお問い合わせ下さい。";
$lang->msg_module_is_not_standalone = 'このモジュールはスタンドアローンでは作動しません。'; $lang->msg_module_is_not_standalone = 'このモジュールはスタンドアローンでは作動しません。';
$lang->msg_default_url_is_not_defined = '기본 URL이 정해지지 않아서 동작을 중지합니다'; $lang->msg_default_url_is_not_defined = 'デフォルトURLが定められてないため、動作を中止します。';
$lang->success_registed = '登録しました。'; $lang->success_registed = '登録しました。';
$lang->success_declared = '通報しました。'; $lang->success_declared = '通報しました。';
@ -298,6 +298,11 @@
$lang->msg_ftp_chmod_fail = 'FTPを用いたディレクトリパーミッション(permission)変更に失敗しました。FTPサーバーの設定を再度ご確認下さい。'; $lang->msg_ftp_chmod_fail = 'FTPを用いたディレクトリパーミッション(permission)変更に失敗しました。FTPサーバーの設定を再度ご確認下さい。';
$lang->msg_ftp_connect_success = 'FTP接続に成功しました。'; $lang->msg_ftp_connect_success = 'FTP接続に成功しました。';
$lang->ftp_path_title = 'FTP 경로 정보 입력';
$lang->msg_ftp_installed_realpath = '설치된 XE의 절대경로';
$lang->msg_ftp_installed_ftp_realpath = '설치된 XE의 FTP 절대경로 설정';
// xml filterで用いられているjavascript用のアラートメッセージ // xml filterで用いられているjavascript用のアラートメッセージ
$lang->filter->isnull = '%sを入力して下さい。'; $lang->filter->isnull = '%sを入力して下さい。';
$lang->filter->outofrange = '%sの文字の長さを合わせて下さい。'; $lang->filter->outofrange = '%sの文字の長さを合わせて下さい。';

View file

@ -279,7 +279,7 @@
$lang->eid = '확장변수 이름'; $lang->eid = '확장변수 이름';
// ftp 관련 // ftp 관련
$lang->ftp_form_title = 'FTP 정보 입력'; $lang->ftp_form_title = 'FTP 계정 정보 입력';
$lang->ftp = 'FTP'; $lang->ftp = 'FTP';
$lang->ftp_port = 'FTP port'; $lang->ftp_port = 'FTP port';
$lang->cmd_check_ftp_connect = 'FTP 접속 확인'; $lang->cmd_check_ftp_connect = 'FTP 접속 확인';
@ -298,6 +298,10 @@
$lang->msg_ftp_chmod_fail = 'FTP를 이용한 디렉토리의 속성 변경에 실패하였습니다. FTP 서버의 설정을 확인해주세요.'; $lang->msg_ftp_chmod_fail = 'FTP를 이용한 디렉토리의 속성 변경에 실패하였습니다. FTP 서버의 설정을 확인해주세요.';
$lang->msg_ftp_connect_success = 'FTP 접속 및 인증에 성공하였습니다.'; $lang->msg_ftp_connect_success = 'FTP 접속 및 인증에 성공하였습니다.';
$lang->ftp_path_title = 'FTP 경로 정보 입력';
$lang->msg_ftp_installed_realpath = '설치된 XE의 절대경로';
$lang->msg_ftp_installed_ftp_realpath = '설치된 XE의 FTP 절대경로 설정';
// xml filter에서 사용되는 javascript용 alert msg // xml filter에서 사용되는 javascript용 alert msg
$lang->filter->isnull = '%s을 입력해주세요.'; $lang->filter->isnull = '%s을 입력해주세요.';
$lang->filter->outofrange = '%s의 글자 수를 맞추어 주세요.'; $lang->filter->outofrange = '%s의 글자 수를 맞추어 주세요.';

View file

@ -291,6 +291,12 @@
$lang->msg_ftp_chmod_fail = "FTP를 이용한 디렉토리의 속성 변경을 실패하였습니다. FTP 서버의 설정을 확인해주세요"; $lang->msg_ftp_chmod_fail = "FTP를 이용한 디렉토리의 속성 변경을 실패하였습니다. FTP 서버의 설정을 확인해주세요";
$lang->msg_ftp_connect_success = "FTP 접속 및 인증 성공하였습니다"; $lang->msg_ftp_connect_success = "FTP 접속 및 인증 성공하였습니다";
$lang->ftp_path_title = 'FTP 경로 정보 입력';
$lang->msg_ftp_installed_realpath = '설치된 XE의 절대경로';
$lang->msg_ftp_installed_ftp_realpath = '설치된 XE의 FTP 절대경로 설정';
$lang->is_active = 'Активно'; $lang->is_active = 'Активно';
$lang->is_required = 'Требуемое поле'; $lang->is_required = 'Требуемое поле';
$lang->eid = '확장변수 이름'; $lang->eid = '확장변수 이름';

View file

@ -286,6 +286,10 @@
$lang->msg_ftp_chmod_fail = "CHMOD không thành công. Xin vui lòng kiểm tra lại."; $lang->msg_ftp_chmod_fail = "CHMOD không thành công. Xin vui lòng kiểm tra lại.";
$lang->msg_ftp_connect_success = "Đã xác nhận và kết nối thành công tới máy chủ bằng FTP."; $lang->msg_ftp_connect_success = "Đã xác nhận và kết nối thành công tới máy chủ bằng FTP.";
$lang->ftp_path_title = 'FTP 경로 정보 입력';
$lang->msg_ftp_installed_realpath = '설치된 XE의 절대경로';
$lang->msg_ftp_installed_ftp_realpath = '설치된 XE의 FTP 절대경로 설정';
// Alert messages for Javascript using by XML filter // Alert messages for Javascript using by XML filter
$lang->filter->isnull = 'Xin vui lòng nhập giá trị cho %s'; $lang->filter->isnull = 'Xin vui lòng nhập giá trị cho %s';

View file

@ -2,7 +2,7 @@
/** /**
* @file common/lang/zh-CN.lang.php * @file common/lang/zh-CN.lang.php
* @author zero (zero@nzeo.com) * @author zero (zero@nzeo.com)
* @brief 简体中文语言包 (只收录基本内容) * @brief 简体中文语言包
**/ **/
// 基本使用的 action 语言 // 基本使用的 action 语言
@ -24,16 +24,16 @@
$lang->cmd_load = '导入'; $lang->cmd_load = '导入';
$lang->cmd_input = '输入'; $lang->cmd_input = '输入';
$lang->cmd_search = '搜索'; $lang->cmd_search = '搜索';
$lang->cmd_find = '찾기'; $lang->cmd_find = '查找';
$lang->cmd_replace = '바꾸기'; $lang->cmd_replace = '替换';
$lang->cmd_confirm = '확인'; $lang->cmd_confirm = '确认';
$lang->cmd_cancel = '取消'; $lang->cmd_cancel = '取消';
$lang->cmd_back = '返回'; $lang->cmd_back = '返回';
$lang->cmd_vote = '推荐'; $lang->cmd_vote = '推荐';
$lang->cmd_vote_down = '反对'; $lang->cmd_vote_down = '反对';
$lang->cmd_declare = '举报'; $lang->cmd_declare = '举报';
$lang->cmd_cancel_declare = '取消举报'; $lang->cmd_cancel_declare = '取消举报';
$lang->cmd_declared_list = '举报目录'; $lang->cmd_declared_list = '举报列表';
$lang->cmd_copy = '复制'; $lang->cmd_copy = '复制';
$lang->cmd_move = '移动'; $lang->cmd_move = '移动';
$lang->cmd_move_up = '向上'; $lang->cmd_move_up = '向上';
@ -124,7 +124,7 @@
$lang->file = '文件'; $lang->file = '文件';
$lang->mid = '模块名称'; $lang->mid = '模块名称';
$lang->sid = 'Site Name'; $lang->sid = '站点名称';
$lang->layout = '布局'; $lang->layout = '布局';
$lang->widget = '控件 '; $lang->widget = '控件 ';
$lang->module = '模块'; $lang->module = '模块';
@ -209,7 +209,7 @@
$lang->about_layout = '布局是布置模块的外观,在上端布局菜里单可以进行管理'; $lang->about_layout = '布局是布置模块的外观,在上端布局菜里单可以进行管理';
// 信息 // 信息
$lang->msg_call_server = '系统正在链接服务器,请稍后。'; $lang->msg_call_server = '系统正在连接服务器,请稍后…';
$lang->msg_db_not_setted = '还没有设定 DB'; $lang->msg_db_not_setted = '还没有设定 DB';
$lang->msg_dbconnect_failed = "连接DB时发生错误。\n请重新确认DB信息。"; $lang->msg_dbconnect_failed = "连接DB时发生错误。\n请重新确认DB信息。";
$lang->msg_invalid_queryid = 'Query ID值指定错误'; $lang->msg_invalid_queryid = 'Query ID值指定错误';
@ -221,18 +221,19 @@
$lang->msg_error_occured = '发生错误'; $lang->msg_error_occured = '发生错误';
$lang->msg_not_founded = '没有找到相关内容'; $lang->msg_not_founded = '没有找到相关内容';
$lang->msg_no_result = '找不到和您查询的相符结果'; $lang->msg_no_result = '找不到和您查询的相符结果';
$lang->msg_fail_to_request_open = 'Fail to open your request'; $lang->msg_fail_to_request_open = '连接失败!';
$lang->msg_invalid_format = 'Invalid Format'; $lang->msg_invalid_format = '错误的格式!';
$lang->msg_not_permitted_act = '没有权限执行 action命令'; $lang->msg_not_permitted_act = '没有权限执行 action命令';
$lang->msg_module_is_not_exists = "요청하신 모듈을 찾을 수 없습니다.\n사이트 관리자에게 모듈 점검 요청 바랍니다"; $lang->msg_module_is_not_exists = "没有找到该模块!\n请联系网站管理员进行模块维护。";
$lang->msg_module_is_not_standalone = '您请求的模块不能单独执行'; $lang->msg_module_is_not_standalone = '您请求的模块不能单独执行';
$lang->msg_default_url_is_not_defined = '기본 URL이 정해지지 않아서 동작을 중지합니다'; $lang->msg_default_url_is_not_defined = '请设置XE通行证';
$lang->success_registed = '提交成功!'; $lang->success_registed = '提交成功!';
$lang->success_declared = '举报成功!'; $lang->success_declared = '举报成功!';
$lang->success_updated = '修改成功!'; $lang->success_updated = '修改成功!';
$lang->success_deleted = '删除成功!'; $lang->success_deleted = '删除成功!';
$lang->success_restore = '复原成功!';
$lang->success_voted = '推荐成功!'; $lang->success_voted = '推荐成功!';
$lang->success_blamed = '反对成功!'; $lang->success_blamed = '反对成功!';
$lang->success_moved = '移动成功!'; $lang->success_moved = '移动成功!';
@ -253,28 +254,29 @@
$lang->confirm_logout = '确定要退出吗?'; $lang->confirm_logout = '确定要退出吗?';
$lang->confirm_vote = '确定要推荐吗?'; $lang->confirm_vote = '确定要推荐吗?';
$lang->confirm_delete = '确定要删除吗?'; $lang->confirm_delete = '确定要删除吗?';
$lang->confirm_restore = '确定要复原吗?';
$lang->confirm_move = '确定要移动吗?'; $lang->confirm_move = '确定要移动吗?';
$lang->confirm_reset = '确定要初始化吗?'; $lang->confirm_reset = '确定要初始化吗?';
$lang->confirm_leave = '确定要注销吗?'; $lang->confirm_leave = '确定要注销吗?';
$lang->column_type = '格式'; $lang->column_type = '格式';
$lang->column_type_list['text'] = '单行文本输入区(text)'; $lang->column_type_list['text'] = '单行文本输入区(text)';
$lang->column_type_list['homepage'] = '网址格式 (url)'; $lang->column_type_list['homepage'] = '网址格式(url)';
$lang->column_type_list['email_address'] = '邮件格式 (email)'; $lang->column_type_list['email_address'] = '邮件格式(email)';
$lang->column_type_list['tel'] = '电话号码格式 (phone)'; $lang->column_type_list['tel'] = '电话号码格式(phone)';
$lang->column_type_list['textarea'] = '多行文本框 (textarea)'; $lang->column_type_list['textarea'] = '多行文本框(textarea)';
$lang->column_type_list['checkbox'] = '复选框 (checkbox)'; $lang->column_type_list['checkbox'] = '复选框(checkbox)';
$lang->column_type_list['select'] = '下拉列表框 (select)'; $lang->column_type_list['select'] = '下拉列表框(select)';
$lang->column_type_list['radio'] = '单选框 (radio)'; $lang->column_type_list['radio'] = '单选框(radio)';
$lang->column_type_list['kr_zip'] = '韩国邮编(zip)'; $lang->column_type_list['kr_zip'] = '韩国邮编(zip)';
$lang->column_type_list['date'] = '日期 (年月日)'; $lang->column_type_list['date'] = '日期(年月日)';
//$lang->column_type_list['jp_zip'] = '日本地址 (zip)'; //$lang->column_type_list['jp_zip'] = '日本地址(zip)';
$lang->column_name = '项目名'; $lang->column_name = '项目名';
$lang->column_title = '项目标题'; $lang->column_title = '项目标题';
$lang->default_value = '缺省值'; $lang->default_value = '缺省值';
$lang->is_active = '激活'; $lang->is_active = '激活';
$lang->is_required = '必填'; $lang->is_required = '必填';
$lang->eid = '확장변수 이름'; $lang->eid = '扩展变量名';
// ftp 相关 // ftp 相关
$lang->ftp_form_title = '设置FTP信息'; $lang->ftp_form_title = '设置FTP信息';
@ -296,6 +298,9 @@
$lang->msg_ftp_chmod_fail = "修改文件夹属性失败。请确认 FTP服务器设置。"; $lang->msg_ftp_chmod_fail = "修改文件夹属性失败。请确认 FTP服务器设置。";
$lang->msg_ftp_connect_success = "FTP连接成功。"; $lang->msg_ftp_connect_success = "FTP连接成功。";
$lang->ftp_path_title = 'FTP 경로 정보 입력';
$lang->msg_ftp_installed_realpath = '설치된 XE의 절대경로';
$lang->msg_ftp_installed_ftp_realpath = '설치된 XE의 FTP 절대경로 설정';
// 在xml filter使用的 javascript用 alert msg // 在xml filter使用的 javascript用 alert msg
$lang->filter->isnull = '请输入%s'; $lang->filter->isnull = '请输入%s';

View file

@ -297,6 +297,11 @@
$lang->msg_ftp_chmod_fail = '修改資料夾權限失敗。請確認FTP主機設置。'; $lang->msg_ftp_chmod_fail = '修改資料夾權限失敗。請確認FTP主機設置。';
$lang->msg_ftp_connect_success = 'FTP連線成功。'; $lang->msg_ftp_connect_success = 'FTP連線成功。';
$lang->ftp_path_title = 'FTP 경로 정보 입력';
$lang->msg_ftp_installed_realpath = '설치된 XE의 절대경로';
$lang->msg_ftp_installed_ftp_realpath = '설치된 XE의 FTP 절대경로 설정';
// 在xml filter中所使用的JavaScript警告訊息 // 在xml filter中所使用的JavaScript警告訊息
$lang->filter->isnull = '請輸入%s'; $lang->filter->isnull = '請輸入%s';
$lang->filter->outofrange = '請確認%s字數'; $lang->filter->outofrange = '請確認%s字數';

View file

@ -13,7 +13,7 @@
* @brief XE의 전체 버전 표기 * @brief XE의 전체 버전 표기
* 파일의 수정이 없더라도 공식 릴리즈시에 수정되어 함께 배포되어야 * 파일의 수정이 없더라도 공식 릴리즈시에 수정되어 함께 배포되어야
**/ **/
define('__ZBXE_VERSION__', '1.2.6'); define('__ZBXE_VERSION__', '1.3.0');
/** /**
* @brief zbXE가 설치된 장소의 base path를 구함 * @brief zbXE가 설치된 장소의 base path를 구함

View file

@ -8,7 +8,7 @@
<title xml:lang="es">Diseño oficial de la página web de XE</title> <title xml:lang="es">Diseño oficial de la página web de XE</title>
<title xml:lang="zh-CN">XE 官方网站布局</title> <title xml:lang="zh-CN">XE 官方网站布局</title>
<title xml:lang="zh-TW">XE 官方網站版面</title> <title xml:lang="zh-TW">XE 官方網站版面</title>
<title xml:lang="vi">Giao diện chính thức của XE</title> <title xml:lang="vi">Giao diện chính thức của XE</title>
<description xml:lang="ko"> <description xml:lang="ko">
XE 공식 사이트 레이아웃입니다. XE 공식 사이트 레이아웃입니다.
디자인 : 이소라 디자인 : 이소라
@ -76,7 +76,7 @@
<name xml:lang="es">zero</name> <name xml:lang="es">zero</name>
<name xml:lang="zh-CN">zero</name> <name xml:lang="zh-CN">zero</name>
<name xml:lang="zh-TW">zero</name> <name xml:lang="zh-TW">zero</name>
<name xml:lang="vi">zero</name> <name xml:lang="vi">zero</name>
</author> </author>
<extra_vars> <extra_vars>
@ -89,7 +89,7 @@
<title xml:lang="ge">Colorset</title> <title xml:lang="ge">Colorset</title>
<title xml:lang="ru">Colorset</title> <title xml:lang="ru">Colorset</title>
<title xml:lang="es">Set de colores</title> <title xml:lang="es">Set de colores</title>
<title xml:lang="vi">Màu sắc</title> <title xml:lang="vi">Màu sắc</title>
<description xml:lang="ko">원하시는 컬러셋을 선택해주세요.</description> <description xml:lang="ko">원하시는 컬러셋을 선택해주세요.</description>
<description xml:lang="jp">希望するカラーセットを選択して下さい。</description> <description xml:lang="jp">希望するカラーセットを選択して下さい。</description>
<description xml:lang="zh-CN">请选择颜色。</description> <description xml:lang="zh-CN">请选择颜色。</description>
@ -98,7 +98,7 @@
<description xml:lang="ge">Bitte wählen Sie ein colorset Sie wollen.</description> <description xml:lang="ge">Bitte wählen Sie ein colorset Sie wollen.</description>
<description xml:lang="ru">Выберите colorset хотите.</description> <description xml:lang="ru">Выберите colorset хотите.</description>
<description xml:lang="es">Seleccione set de colores que desea.</description> <description xml:lang="es">Seleccione set de colores que desea.</description>
<description xml:lang="vi">Hãy chọn màu sắc bạn muốn.</description> <description xml:lang="vi">Hãy chọn màu sắc bạn muốn.</description>
<options value="default"> <options value="default">
<title xml:lang="ko">기본</title> <title xml:lang="ko">기본</title>
<title xml:lang="jp">デフォルト</title> <title xml:lang="jp">デフォルト</title>
@ -108,7 +108,7 @@
<title xml:lang="es">Básico</title> <title xml:lang="es">Básico</title>
<title xml:lang="zh-CN">默认</title> <title xml:lang="zh-CN">默认</title>
<title xml:lang="zh-TW">預設</title> <title xml:lang="zh-TW">預設</title>
<title xml:lang="vi">Cơ bản</title> <title xml:lang="vi">Cơ bản</title>
</options> </options>
<options value="black"> <options value="black">
<title xml:lang="ko">검은색</title> <title xml:lang="ko">검은색</title>
@ -119,7 +119,7 @@
<title xml:lang="es">Negro</title> <title xml:lang="es">Negro</title>
<title xml:lang="zh-CN">黑色</title> <title xml:lang="zh-CN">黑色</title>
<title xml:lang="zh-TW">黑色</title> <title xml:lang="zh-TW">黑色</title>
<title xml:lang="vi">Black</title> <title xml:lang="vi">Black</title>
</options> </options>
<options value="white"> <options value="white">
<title xml:lang="ko">하얀색</title> <title xml:lang="ko">하얀색</title>
@ -130,7 +130,7 @@
<title xml:lang="es">Blanco</title> <title xml:lang="es">Blanco</title>
<title xml:lang="zh-CN">白色</title> <title xml:lang="zh-CN">白色</title>
<title xml:lang="zh-TW">白色</title> <title xml:lang="zh-TW">白色</title>
<title xml:lang="vi">White</title> <title xml:lang="vi">White</title>
</options> </options>
</var> </var>
<var name="logo_image" type="image"> <var name="logo_image" type="image">
@ -142,7 +142,7 @@
<title xml:lang="ge">Logobildes</title> <title xml:lang="ge">Logobildes</title>
<title xml:lang="ru">Изображения логотипа</title> <title xml:lang="ru">Изображения логотипа</title>
<title xml:lang="es">Imagen del logotipo</title> <title xml:lang="es">Imagen del logotipo</title>
<title xml:lang="vi">Hình Logo</title> <title xml:lang="vi">Hình Logo</title>
<description xml:lang="ko">레이아웃의 상단에 표시될 로고이미지를 입력하세요. (세로길이가 23px인 투명이미지가 가장 어울립니다)</description> <description xml:lang="ko">레이아웃의 상단에 표시될 로고이미지를 입력하세요. (세로길이가 23px인 투명이미지가 가장 어울립니다)</description>
<description xml:lang="jp">レイアウトの上段に表示されるロゴイメージを入力して下さい。 (縦幅が23pxである透明イメージをお勧めします。。)</description> <description xml:lang="jp">レイアウトの上段に表示されるロゴイメージを入力して下さい。 (縦幅が23pxである透明イメージをお勧めします。。)</description>
<description xml:lang="zh-CN">请输入显示在布局顶部的LOGO图片(高度为23px的透明图片为适)。</description> <description xml:lang="zh-CN">请输入显示在布局顶部的LOGO图片(高度为23px的透明图片为适)。</description>
@ -151,7 +151,7 @@
<description xml:lang="ge">Bitte geben Sie ein Logo das Bild wird auf dem oberen Layout. (Transparent Bild mit einer Höhe von 23px wird empfohlen).</description> <description xml:lang="ge">Bitte geben Sie ein Logo das Bild wird auf dem oberen Layout. (Transparent Bild mit einer Höhe von 23px wird empfohlen).</description>
<description xml:lang="ru">Введите логотип изображение, которое будет отображаться в верхней части формы. (Прозрачный изображение с высотой 23px рекомендуется.)</description> <description xml:lang="ru">Введите логотип изображение, которое будет отображаться в верхней части формы. (Прозрачный изображение с высотой 23px рекомендуется.)</description>
<description xml:lang="es">Ingresar una imagen para logotipo. ( Se recomienda una imagen de fondo transparente con una altura de 23px.</description> <description xml:lang="es">Ingresar una imagen para logotipo. ( Se recomienda una imagen de fondo transparente con una altura de 23px.</description>
<description xml:lang="vi">Hãy chọn Logo hiển thị phía trên cùng của giao diện. (Đề nghị: Hình ảnh có nền trong suốt và kích thước 23px.)</description> <description xml:lang="vi">Hãy chọn Logo hiển thị phía trên cùng của giao diện. (Đề nghị: Hình ảnh có nền trong suốt và kích thước 23px.)</description>
</var> </var>
<var name="index_url" type="text"> <var name="index_url" type="text">
<title xml:lang="ko">홈 페이지 URL</title> <title xml:lang="ko">홈 페이지 URL</title>
@ -162,7 +162,7 @@
<title xml:lang="ge">Homepage URL</title> <title xml:lang="ge">Homepage URL</title>
<title xml:lang="ru">Домашняя страница URL</title> <title xml:lang="ru">Домашняя страница URL</title>
<title xml:lang="es">URL de la página web</title> <title xml:lang="es">URL de la página web</title>
<title xml:lang="vi">URL Trang chủ</title> <title xml:lang="vi">URL Trang chủ</title>
<description xml:lang="ko">로고를 클릭시에 이동할 홈 페이지 URL을 입력해 주세요.</description> <description xml:lang="ko">로고를 클릭시에 이동할 홈 페이지 URL을 입력해 주세요.</description>
<description xml:lang="jp">ロゴをクリックした時に移動するホームページのURLを入力して下さい。</description> <description xml:lang="jp">ロゴをクリックした時に移動するホームページのURLを入力して下さい。</description>
<description xml:lang="zh-CN">点击网站LOGO时要移动的页面URL。</description> <description xml:lang="zh-CN">点击网站LOGO时要移动的页面URL。</description>
@ -171,7 +171,7 @@
<description xml:lang="ge">Bitte geben Sie die URL umzuleiten, wenn Benutzer klickt das Logo</description> <description xml:lang="ge">Bitte geben Sie die URL umzuleiten, wenn Benutzer klickt das Logo</description>
<description xml:lang="ru">Пожалуйста, введите URL для перенаправления, когда пользователь нажимает логотип</description> <description xml:lang="ru">Пожалуйста, введите URL для перенаправления, когда пользователь нажимает логотип</description>
<description xml:lang="es">Ingresar el URL de la página web para redireccionar al pulsar el logotipo</description> <description xml:lang="es">Ingresar el URL de la página web para redireccionar al pulsar el logotipo</description>
<description xml:lang="vi">Hãy nhập địa chỉ bạn muốn chuyển đến khi bấm vào Logo</description> <description xml:lang="vi">Hãy nhập địa chỉ bạn muốn chuyển đến khi bấm vào Logo</description>
</var> </var>
<var name="background_image" type="image"> <var name="background_image" type="image">
<title xml:lang="ko">배경 이미지</title> <title xml:lang="ko">배경 이미지</title>
@ -182,7 +182,7 @@
<title xml:lang="ge">Hintergrundbild</title> <title xml:lang="ge">Hintergrundbild</title>
<title xml:lang="ru">Фоновое изображение</title> <title xml:lang="ru">Фоновое изображение</title>
<title xml:lang="es">Imagen de fondo</title> <title xml:lang="es">Imagen de fondo</title>
<title xml:lang="vi">Hình nền</title> <title xml:lang="vi">Hình nền</title>
<description xml:lang="ko">배경 이미지를 사용하시려면 등록해주세요.</description> <description xml:lang="ko">배경 이미지를 사용하시려면 등록해주세요.</description>
<description xml:lang="jp">背景イメージを使う場合は、登録して下さい。</description> <description xml:lang="jp">背景イメージを使う場合は、登録して下さい。</description>
<description xml:lang="zh-CN">要想使用背景图片请在这里上传。</description> <description xml:lang="zh-CN">要想使用背景图片请在这里上传。</description>
@ -191,7 +191,7 @@
<description xml:lang="ge">Bitte geben Sie, wenn Sie verwenden wollen Hintergrundbild.</description> <description xml:lang="ge">Bitte geben Sie, wenn Sie verwenden wollen Hintergrundbild.</description>
<description xml:lang="ru">Введите, если вы хотите использовать фоновое изображение.</description> <description xml:lang="ru">Введите, если вы хотите использовать фоновое изображение.</description>
<description xml:lang="es">Ingresar imagen de fondo si desea usar.</description> <description xml:lang="es">Ingresar imagen de fondo si desea usar.</description>
<description xml:lang="vi">Hãy nhập hình nền nếu bạn muốn sử dụng.</description> <description xml:lang="vi">Hãy nhập hình nền nếu bạn muốn sử dụng.</description>
</var> </var>
</extra_vars> </extra_vars>
@ -205,7 +205,7 @@
<title xml:lang="ge">Top Menü</title> <title xml:lang="ge">Top Menü</title>
<title xml:lang="ru">Верхнее меню</title> <title xml:lang="ru">Верхнее меню</title>
<title xml:lang="es">Menú Principal</title> <title xml:lang="es">Menú Principal</title>
<title xml:lang="vi">Menu trên</title> <title xml:lang="vi">Menu trên</title>
</menu> </menu>
<menu name="bottom_menu" maxdepth="1"> <menu name="bottom_menu" maxdepth="1">
<title xml:lang="ko">하단 메뉴 </title> <title xml:lang="ko">하단 메뉴 </title>
@ -216,7 +216,7 @@
<title xml:lang="ge">Bottom-Menü</title> <title xml:lang="ge">Bottom-Menü</title>
<title xml:lang="ru">Внизу меню</title> <title xml:lang="ru">Внизу меню</title>
<title xml:lang="es">Menú Inferior </title> <title xml:lang="es">Menú Inferior </title>
<title xml:lang="vi">Menu dưới</title> <title xml:lang="vi">Menu dưới</title>
</menu> </menu>
</menus> </menus>
</layout> </layout>

View file

@ -48,7 +48,7 @@
/* Constractor */ /* Constractor */
function ftp() function ftp()
{ {
$this->debug = FALSE; $this->debug = false;
$this->umask = 0022; $this->umask = 0022;
$this->timeout = 30; $this->timeout = 30;

View file

@ -13,5 +13,5 @@
$lang->addon_history = '更新纪录 '; $lang->addon_history = '更新纪录 ';
$lang->about_addon_mid = "可以指定使用插件的对象。<br />(全部解除表示可用在所有对象。)"; $lang->about_addon_mid = "可以指定使用插件的对象。<br />(全部解除表示可用在所有对象。)";
$lang->about_addon = '插件是加载扩展功能的动作,而不是输出结果组件。<br />启用/禁用插件,为网站提供强大的功能。'; $lang->about_addon = '插件就是对动作(Action)的有效控制来给核心程序提供扩展功能的一种组件。<br />只需启用/禁用操作,即可为网站提供强大的扩展功能。';
?> ?>

View file

@ -2,35 +2,35 @@
/** /**
* @class adminAdminController * @class adminAdminController
* @author zero (zero@nzeo.com) * @author zero (zero@nzeo.com)
* @brief admin 모듈의 admin controller class * @brief admin controller class of admin module
**/ **/
class adminAdminController extends admin { class adminAdminController extends admin {
/** /**
* @brief 초기화 * @brief initialization
* @return none
**/ **/
function init() { function init() {
// 접속 사용자에 대한 체크 // forbit access if the user is not an administrator
$oMemberModel = &getModel('member'); $oMemberModel = &getModel('member');
$logged_info = $oMemberModel->getLoggedInfo(); $logged_info = $oMemberModel->getLoggedInfo();
// 관리자가 아니면 금지
if($logged_info->is_admin!='Y') return $this->stop("msg_is_not_administrator"); if($logged_info->is_admin!='Y') return $this->stop("msg_is_not_administrator");
} }
/** /**
* @brief 모든 캐시 파일 재생성 * @brief Regenerate all cache files
* @return none
**/ **/
function procAdminRecompileCacheFile() { function procAdminRecompileCacheFile() {
$oModuleModel = &getModel('module'); $oModuleModel = &getModel('module');
$module_list = $oModuleModel->getModuleList(); $module_list = $oModuleModel->getModuleList();
// 개발 디버그 파일들 제거 // remove debug files
FileHandler::removeFile(_XE_PATH_.'files/_debug_message.php'); FileHandler::removeFile(_XE_PATH_.'files/_debug_message.php');
FileHandler::removeFile(_XE_PATH_.'files/_debug_db_query.php'); FileHandler::removeFile(_XE_PATH_.'files/_debug_db_query.php');
FileHandler::removeFile(_XE_PATH_.'files/_db_slow_query.php'); FileHandler::removeFile(_XE_PATH_.'files/_db_slow_query.php');
// 각 모듈마다 돌면서 캐시 파일 제거 // call recompileCache for each module
foreach($module_list as $module) { foreach($module_list as $module) {
$oModule = null; $oModule = null;
$oModule = &getClass($module->module); $oModule = &getClass($module->module);
@ -41,7 +41,8 @@
} }
/** /**
* @brief 관리자 로그아웃 * @brief Logout
* @return none
**/ **/
function procAdminLogout() { function procAdminLogout() {
$oMemberController = &getController('member'); $oMemberController = &getController('member');

View file

@ -2,30 +2,28 @@
/** /**
* @class adminAdminView * @class adminAdminView
* @author zero (zero@nzeo.com) * @author zero (zero@nzeo.com)
* @brief admin 모듈의 admin view class * @brief admin view class of admin module
**/ **/
class adminAdminView extends admin { class adminAdminView extends admin {
/** /**
* @brief 초기화 * @brief Initilization
* @return none
**/ **/
function init() { function init() {
// template path 지정
$this->setTemplatePath($this->module_path.'tpl'); $this->setTemplatePath($this->module_path.'tpl');
// 접속 사용자에 대한 체크 // forbit access if the user is not an administrator
$oMemberModel = &getModel('member'); $oMemberModel = &getModel('member');
$logged_info = $oMemberModel->getLoggedInfo(); $logged_info = $oMemberModel->getLoggedInfo();
// 관리자가 아니면 금지
if($logged_info->is_admin!='Y') return $this->stop("msg_is_not_administrator"); if($logged_info->is_admin!='Y') return $this->stop("msg_is_not_administrator");
// 관리자용 레이아웃으로 변경 // change into administration layout
$this->setLayoutPath($this->getTemplatePath()); $this->setLayoutPath($this->getTemplatePath());
$this->setLayoutFile('layout.html'); $this->setLayoutFile('layout.html');
// 설치된 모듈 목록 가져와서 적절히 분리 // Retrieve the list of installed modules
$oModuleModel = &getModel('module'); $oModuleModel = &getModel('module');
$installed_module_list = $oModuleModel->getModulesXmlInfo(); $installed_module_list = $oModuleModel->getModulesXmlInfo();
@ -33,7 +31,7 @@
$package_idx = 0; $package_idx = 0;
foreach($installed_module_list as $key => $val) { foreach($installed_module_list as $key => $val) {
if($val->module == 'admin' || !$val->admin_index_act) continue; if($val->module == 'admin' || !$val->admin_index_act) continue;
// action 정보 구함 // get action information
$action_spec = $oModuleModel->getModuleActionXml($val->module); $action_spec = $oModuleModel->getModuleActionXml($val->module);
$actions = array(); $actions = array();
if($action_spec->default_index_act) $actions[] = $action_spec->default_index_act; if($action_spec->default_index_act) $actions[] = $action_spec->default_index_act;
@ -47,14 +45,14 @@
$obj->index_act = $val->admin_index_act; $obj->index_act = $val->admin_index_act;
if(in_array(Context::get('act'), $actions)) $obj->selected = true; if(in_array(Context::get('act'), $actions)) $obj->selected = true;
// 패키지 모듈 // Packages
if($val->category == 'package') { if($val->category == 'package') {
if($package_idx == 0) $obj->position = "first"; if($package_idx == 0) $obj->position = "first";
else $obj->position = "mid"; else $obj->position = "mid";
$package_modules[] = $obj; $package_modules[] = $obj;
$package_idx ++; $package_idx ++;
if($obj->selected) Context::set('package_selected',true); if($obj->selected) Context::set('package_selected',true);
// 일반 모듈 // Modules
} else { } else {
$installed_modules[] = $obj; $installed_modules[] = $obj;
} }
@ -83,17 +81,16 @@
} }
/** /**
* @brief 관리자 메인 페이지 출력 * @brief Display main administration page
* @return none
**/ **/
function dispAdminIndex() { function dispAdminIndex() {
/** //Retrieve recent news and set them into context
* 최근 뉴스를 가져와서 세팅
**/
$newest_news_url = sprintf("http://news.xpressengine.com/%s/news.php", Context::getLangType()); $newest_news_url = sprintf("http://news.xpressengine.com/%s/news.php", Context::getLangType());
$cache_file = sprintf("%sfiles/cache/newest_news.%s.cache.php", _XE_PATH_,Context::getLangType()); $cache_file = sprintf("%sfiles/cache/newest_news.%s.cache.php", _XE_PATH_,Context::getLangType());
if(!file_exists($cache_file) || filemtime($cache_file)+ 60*60 < time()) { if(!file_exists($cache_file) || filemtime($cache_file)+ 60*60 < time()) {
// 네트웍 상태로 데이터를 가져오지 못할 상황을 고려해 일단 filemtime을 변경하여 관리자 페이지 refresh시에 다시 읽ㅇ 오지 않도록 함 // Considering if data cannot be retrieved due to network problem, modify filemtime to prevent trying to reload again when refreshing administration page
// 뉴스를 보지는 못하지만 관리자 페이지 접속은 이상없도록 함 // Ensure to access the administration page even though news cannot be displayed
FileHandler::writeFile($cache_file,''); FileHandler::writeFile($cache_file,'');
FileHandler::getRemoteFile($newest_news_url, $cache_file, null, 1, 'GET', 'text/html', array('REQUESTURL'=>getFullUrl(''))); FileHandler::getRemoteFile($newest_news_url, $cache_file, null, 1, 'GET', 'text/html', array('REQUESTURL'=>getFullUrl('')));
} }
@ -120,31 +117,29 @@
Context::set('download_link', $buff->zbxe_news->attrs->download_link); Context::set('download_link', $buff->zbxe_news->attrs->download_link);
} }
// DB 정보를 세팅 // DB Information
$db_info = Context::getDBInfo(); $db_info = Context::getDBInfo();
Context::set('selected_lang', $db_info->lang_type); Context::set('selected_lang', $db_info->lang_type);
// 현재 버젼과 설치 경로 세팅 // Current Version and Installed Path
Context::set('current_version', __ZBXE_VERSION__); Context::set('current_version', __ZBXE_VERSION__);
Context::set('installed_path', realpath('./')); Context::set('installed_path', realpath('./'));
// 모듈 목록을 가져옴 // Get list of modules
$oModuleModel = &getModel('module'); $oModuleModel = &getModel('module');
$module_list = $oModuleModel->getModuleList(); $module_list = $oModuleModel->getModuleList();
Context::set('module_list', $module_list); Context::set('module_list', $module_list);
// 애드온 목록을 가져옴 // Get list of addons
$oAddonModel = &getAdminModel('addon'); $oAddonModel = &getAdminModel('addon');
$addon_list = $oAddonModel->getAddonList(); $addon_list = $oAddonModel->getAddonList();
Context::set('addon_list', $addon_list); Context::set('addon_list', $addon_list);
/** // Get statistics
* 각종 통계를 추출
**/
$args->date = date("Ymd000000", time()-60*60*24); $args->date = date("Ymd000000", time()-60*60*24);
$today = date("Ymd"); $today = date("Ymd");
// 회원현황 // Member Status
$output = executeQueryArray("admin.getMemberStatus", $args); $output = executeQueryArray("admin.getMemberStatus", $args);
if($output->data) { if($output->data) {
foreach($output->data as $var) { foreach($output->data as $var) {
@ -158,7 +153,7 @@
$output = executeQuery("admin.getMemberCount", $args); $output = executeQuery("admin.getMemberCount", $args);
$status->member->total = $output->data->count; $status->member->total = $output->data->count;
// 문서현황 // Document Status
$output = executeQueryArray("admin.getDocumentStatus", $args); $output = executeQueryArray("admin.getDocumentStatus", $args);
if($output->data) { if($output->data) {
foreach($output->data as $var) { foreach($output->data as $var) {
@ -172,7 +167,7 @@
$output = executeQuery("admin.getDocumentCount", $args); $output = executeQuery("admin.getDocumentCount", $args);
$status->document->total = $output->data->count; $status->document->total = $output->data->count;
// 댓글현황 // Comment Status
$output = executeQueryArray("admin.getCommentStatus", $args); $output = executeQueryArray("admin.getCommentStatus", $args);
if($output->data) { if($output->data) {
foreach($output->data as $var) { foreach($output->data as $var) {
@ -186,7 +181,7 @@
$output = executeQuery("admin.getCommentCount", $args); $output = executeQuery("admin.getCommentCount", $args);
$status->comment->total = $output->data->count; $status->comment->total = $output->data->count;
// 엮인글현황 // Trackback Status
$output = executeQueryArray("admin.getTrackbackStatus", $args); $output = executeQueryArray("admin.getTrackbackStatus", $args);
if($output->data) { if($output->data) {
foreach($output->data as $var) { foreach($output->data as $var) {
@ -200,7 +195,7 @@
$output = executeQuery("admin.getTrackbackCount", $args); $output = executeQuery("admin.getTrackbackCount", $args);
$status->trackback->total = $output->data->count; $status->trackback->total = $output->data->count;
// 첨부파일현황 // Attached files Status
$output = executeQueryArray("admin.getFileStatus", $args); $output = executeQueryArray("admin.getFileStatus", $args);
if($output->data) { if($output->data) {
foreach($output->data as $var) { foreach($output->data as $var) {
@ -214,7 +209,7 @@
$output = executeQuery("admin.getFileCount", $args); $output = executeQuery("admin.getFileCount", $args);
$status->file->total = $output->data->count; $status->file->total = $output->data->count;
// 게시물 신고현황 // Reported documents Status
$output = executeQueryArray("admin.getDocumentDeclaredStatus", $args); $output = executeQueryArray("admin.getDocumentDeclaredStatus", $args);
if($output->data) { if($output->data) {
foreach($output->data as $var) { foreach($output->data as $var) {
@ -228,7 +223,7 @@
$output = executeQuery("admin.getDocumentDeclaredCount", $args); $output = executeQuery("admin.getDocumentDeclaredCount", $args);
$status->documentDeclared->total = $output->data->count; $status->documentDeclared->total = $output->data->count;
// 댓글 신고현황 // Reported comments Status
$output = executeQueryArray("admin.getCommentDeclaredStatus", $args); $output = executeQueryArray("admin.getCommentDeclaredStatus", $args);
if($output->data) { if($output->data) {
foreach($output->data as $var) { foreach($output->data as $var) {
@ -253,7 +248,8 @@
} }
/** /**
* @brief 관리자 설정 * @brief Display Configuration(settings) page
* @return none
**/ **/
function dispAdminConfig() { function dispAdminConfig() {
$db_info = Context::getDBInfo(); $db_info = Context::getDBInfo();
@ -272,6 +268,36 @@
$output = executeQuery('module.getSiteInfo', $site_args); $output = executeQuery('module.getSiteInfo', $site_args);
Context::set('start_module', $output->data); Context::set('start_module', $output->data);
$pwd = Context::get('pwd');
if(!$pwd) $pwd = '/';
Context::set('pwd',$pwd);
require_once(_XE_PATH_.'libs/ftp.class.php');
$ftp_info = Context::getFTPInfo();
$oFtp = new ftp();
if($oFtp->ftp_connect('localhost', $ftp_info->ftp_port)){
if($oFtp->ftp_login($ftp_info->ftp_user, $ftp_info->ftp_password)) {
$_list = $oFtp->ftp_rawlist($pwd);
$oFtp->ftp_quit();
}
}
$list = array();
if(count($_list) == 0 || !$_list[0]) {
$oFtp = new ftp();
if($oFtp->ftp_connect($_SERVER['SERVER_NAME'], $ftp_info->ftp_port)){
if($oFtp->ftp_login($ftp_info->ftp_user, $ftp_info->ftp_password)) {
$_list = $oFtp->ftp_rawlist($pwd);
$oFtp->ftp_quit();
}
}
}
if($_list){
foreach($_list as $k => $v){
if(strpos($v,'d') === 0) $list[] = substr(strrchr($v,' '),1) . '/';
}
}
Context::set('list',$list);
Context::set('layout','none'); Context::set('layout','none');
$this->setTemplateFile('config'); $this->setTemplateFile('config');
} }

View file

@ -2,50 +2,53 @@
/** /**
* @class admin * @class admin
* @author zero (zero@nzeo.com) * @author zero (zero@nzeo.com)
* @brief admin 모듈의 high class * @brief base class of admin module
**/ **/
class admin extends ModuleObject { class admin extends ModuleObject {
/** /**
* @brief 설치시 추가 작업이 필요할시 구현 * @brief install admin module
* @return new Object
**/ **/
function moduleInstall() { function moduleInstall() {
return new Object(); return new Object();
} }
/** /**
* @brief 설치가 이상이 없는지 체크하는 method * @brief if update is necessary it returns true
**/ **/
function checkUpdate() { function checkUpdate() {
return false; return false;
} }
/** /**
* @brief 업데이트 실행 * @brief update module
* @return new Object
**/ **/
function moduleUpdate() { function moduleUpdate() {
return new Object(); return new Object();
} }
/** /**
* @brief 캐시 파일 재생성 * @brief regenerate cache file
* @return none
**/ **/
function recompileCache() { function recompileCache() {
// 템플릿 컴파일 파일 삭제 // remove compiled templates
FileHandler::removeFilesInDir("./files/cache/template_compiled"); FileHandler::removeFilesInDir("./files/cache/template_compiled");
// optimized 파일 삭제 // remove optimized files
FileHandler::removeFilesInDir("./files/cache/optimized"); FileHandler::removeFilesInDir("./files/cache/optimized");
// js_filter_compiled 파일 삭제 // remove js_filter_compiled files
FileHandler::removeFilesInDir("./files/cache/js_filter_compiled"); FileHandler::removeFilesInDir("./files/cache/js_filter_compiled");
// queries 파일 삭제 // remove cached queries
FileHandler::removeFilesInDir("./files/cache/queries"); FileHandler::removeFilesInDir("./files/cache/queries");
// ./files/cache/news* 파일 삭제 // remove ./files/cache/news* files
$directory = dir(_XE_PATH_."files/cache/"); $directory = dir(_XE_PATH_."files/cache/");
while($entry = $directory->read()) { while($entry = $directory->read()) {
if(substr($entry,0,11)=='newest_news') FileHandler::removeFile("./files/cache/".$entry); if(substr($entry,0,11)=='newest_news') FileHandler::removeFile("./files/cache/".$entry);

View file

@ -32,10 +32,10 @@
$lang->env_information = '環境情報'; $lang->env_information = '環境情報';
$lang->current_version = 'インストールバージョン'; $lang->current_version = 'インストール済みバージョン';
$lang->current_path = 'インストールパス'; $lang->current_path = 'インストールパス';
$lang->released_version = '最新バージョン'; $lang->released_version = '最新バージョン';
$lang->about_download_link = "インストールされたバージョンより新しいバージョンが配布されています。\n「ダウンロード」リンクをクリックするとダウンロード出来ます。"; $lang->about_download_link = "新しいバージョンが配布されています。\n「ダウンロード」リンクをクリックするとダウンロード出来ます。";
$lang->item_module = 'モジュールリスト'; $lang->item_module = 'モジュールリスト';
$lang->item_addon = 'アドオンリスト'; $lang->item_addon = 'アドオンリスト';
@ -51,12 +51,11 @@
$lang->cmd_shortcut_management = 'メニューの編集'; $lang->cmd_shortcut_management = 'メニューの編集';
$lang->msg_is_not_administrator = '管理者だけアクセス出来ます'; $lang->msg_is_not_administrator = '管理者のみアクセス出来ます';
$lang->msg_manage_module_cannot_delete = 'モジュール、アドオン、ウィジェットのショットカットは削除出来ません。'; $lang->msg_manage_module_cannot_delete = 'モジュール、アドオン、ウィジェットのショットカットは削除出来ません。';
$lang->msg_default_act_is_null = 'デフォルトの管理者のアクションが指定されていないため、ショットカットを登録することが出来ません。'; $lang->msg_default_act_is_null = 'デフォルトの管理者のアクションが指定されていないため、ショットカットを登録することが出来ません。';
$lang->welcome_to_xe = 'XEの管理者ページです。'; $lang->welcome_to_xe = 'XEの管理者ページです。';
$lang->about_admin_page = "管理者ページはまだ未完成です。\nクローズベータバージョンの期間に、多くの方々からご意見をいただきながら、必ず完成したいと思います。";
$lang->about_lang_env = '初めてサイトに訪問したユーザーに対し、上記の選択した言語でサイトを表示させるためには、必ず下記の「保存」ボタンをクリックして適用して下さい。'; $lang->about_lang_env = '初めてサイトに訪問したユーザーに対し、上記の選択した言語でサイトを表示させるためには、必ず下記の「保存」ボタンをクリックして適用して下さい。';
$lang->xe_license = 'XEのライセンスはGPLです。'; $lang->xe_license = 'XEのライセンスはGPLです。';
@ -66,7 +65,7 @@
$lang->today = '今日'; $lang->today = '今日';
$lang->cmd_lang_select = '言語選択'; $lang->cmd_lang_select = '言語選択';
$lang->about_cmd_lang_select = '選択された言語だけでサービスを行います。'; $lang->about_cmd_lang_select = '選択た言語だけでサービスを行います。';
$lang->about_recompile_cache = '要らないかごみのキャッシューファイルを整理します。'; $lang->about_recompile_cache = '要らないかごみのキャッシューファイルを整理します。';
$lang->use_ssl = 'SSL環境設定'; $lang->use_ssl = 'SSL環境設定';
$lang->ssl_options = array( $lang->ssl_options = array(

View file

@ -8,8 +8,8 @@
$lang->admin_info = '管理员信息'; $lang->admin_info = '管理员信息';
$lang->admin_index = '管理首页'; $lang->admin_index = '管理首页';
$lang->control_panel = '控制面板'; $lang->control_panel = '控制面板';
$lang->start_module = '启动模块'; $lang->start_module = '首页模块';
$lang->about_start_module = '您可以指定默认的启动模块。'; $lang->about_start_module = '可指定用户访问网站时的默认首页模块。';
$lang->module_category_title = array( $lang->module_category_title = array(
'service' => '应用管理', 'service' => '应用管理',
@ -30,11 +30,12 @@
$lang->default_url = "XE通行证"; $lang->default_url = "XE通行证";
$lang->about_default_url = "请输入默认站点的XE安装地址(ex: http://域名/xe)。 <br /><strong>说明:</strong>简单的说,就是绑定帐号系统。只需要登录一次,就可以在用站点模块生成的多个子站点中随意漫游。"; $lang->about_default_url = "请输入默认站点的XE安装地址(ex: http://域名/xe)。 <br /><strong>说明:</strong>简单的说,就是绑定帐号系统。只需要登录一次,就可以在用站点模块生成的多个子站点中随意漫游。";
$lang->env_information = "系统信息"; $lang->env_information = "系统信息";
$lang->current_version = "安装版本"; $lang->current_version = "安装版本";
$lang->current_path = "安装路径"; $lang->current_path = "安装路径";
$lang->released_version = "最新版本"; $lang->released_version = "最新版本";
$lang->about_download_link = "官方网站已发布新版本。\n请点击download链接下载最新版本。"; $lang->about_download_link = "官方网站已发布最新版本XE。\n请点击[下载]链接下载最新版本。";
$lang->item_module = "模块目录"; $lang->item_module = "模块目录";
$lang->item_addon = "插件目录"; $lang->item_addon = "插件目录";
@ -55,10 +56,8 @@
$lang->msg_default_act_is_null = '没有指定默认管理员的动作,是不能添加到快捷菜单的。'; $lang->msg_default_act_is_null = '没有指定默认管理员的动作,是不能添加到快捷菜单的。';
$lang->welcome_to_xe = 'XE 管理页面'; $lang->welcome_to_xe = 'XE 管理页面';
$lang->about_admin_page = "后台管理页面未完成";
$lang->about_lang_env = "可以设置显示给首次访问者的同一语言环境。修改语言环境后请点击 [保存] 按钮进行保存。"; $lang->about_lang_env = "可以设置显示给首次访问者的同一语言环境。修改语言环境后请点击 [保存] 按钮进行保存。";
$lang->xe_license = 'XE遵循 GPL协议'; $lang->xe_license = 'XE遵循 GPL协议';
$lang->about_shortcut = '可以删除添加到常用模块中的快捷菜单。'; $lang->about_shortcut = '可以删除添加到常用模块中的快捷菜单。';
@ -77,6 +76,6 @@
$lang->about_use_ssl = "选择性使用选项应用于新用户注册/修改用户信息等已指定的action当中使用选项应用于所有服务。"; $lang->about_use_ssl = "选择性使用选项应用于新用户注册/修改用户信息等已指定的action当中使用选项应用于所有服务。";
$lang->server_ports = "指定服务器端口"; $lang->server_ports = "指定服务器端口";
$lang->about_server_ports = "使用除HTTP80, HTTPS443以外的端口时必须得指定该服务器端口号。"; $lang->about_server_ports = "使用除HTTP80, HTTPS443以外的端口时必须得指定该服务器端口号。";
$lang->use_db_session = '使用DB session认证'; $lang->use_db_session = 'DB储存认证会话';
$lang->about_db_session = '使用DBsession认证时系统会把PHPsession保存到数据库。<br/>不使用这个功能会提高服务器应答速度,但读取不了在线人数。'; $lang->about_db_session = '用DB储存认证时的PHP会话。<br/>服务器使用率较少的网站建议不要勾选此项(可提高网站访问速度)。<br/>只是无法统计在线会员。';
?> ?>

View file

@ -3,6 +3,7 @@
<!--%import("./filter/update_env_config.xml")--> <!--%import("./filter/update_env_config.xml")-->
<!--%import("./filter/update_lang_select.xml")--> <!--%import("./filter/update_lang_select.xml")-->
<!--%import("./filter/install_ftp_info.xml")--> <!--%import("./filter/install_ftp_info.xml")-->
<!--%import("./filter/install_ftp_path.xml")-->
<!--%import("../../install/lang")--> <!--%import("../../install/lang")-->
<!--%import("../../install/tpl/js/install_admin.js",optimized=false)--> <!--%import("../../install/tpl/js/install_admin.js",optimized=false)-->
@ -141,7 +142,46 @@
</tr> </tr>
</table> </table>
</form> </form>
<!--@if($ftp_info && $ftp_info->ftp_password && $ftp_info->ftp_user)-->
<h4 class="xeAdmin" id="ftp_setup">{$lang->ftp_path_title}</h4>
<form action="./" method="get" onsubmit="return procFilter(this, install_ftp_path)">
<input type="hidden" name="ftp_user" value="{$ftp_info->ftp_user}" />
<input type="hidden" name="ftp_password" value="{$ftp_info->ftp_password}" />
<input type="hidden" name="ftp_port" value="{$ftp_info->ftp_port}" />
<table cellspacing="0" class="rowTable">
<tr>
<th scope="col"><div>{$lang->msg_ftp_installed_realpath}</div></th>
<td>{_XE_PATH_}
</td>
</tr>
<tr>
<th scope="col" rowspan="2"><div>{$lang->msg_ftp_installed_ftp_realpath}</div></th>
<td>
<input type="text" name="ftp_root_path" value="<!--@if($pwd && $pwd!='/')-->{$pwd}<!--@else-->{$ftp_info->ftp_root_path}<!--@end-->" class="inputTypeText w400" />
</td>
</tr>
<tr>
<td>
<!--@if($list)-->
<ul>
<!--@foreach($list as $k => $v)-->
<!--@if($v)-->
<li> <a href="{getUrl('pwd',$pwd.$v)}#ftp_setup">{$v}</a></li>
<!--@end-->
<!--@end-->
</ul>
<!--@end-->
</td>
</tr>
<tr class="row2">
<th colspan="2" class="button">
<span class="button black strong"><input type="submit" value="{$lang->cmd_registration}" /></span>
</th>
</tr>
</table>
</form>
<!--@end-->
</div> </div>
<hr /> <hr />

View file

@ -11,10 +11,10 @@
#xeAdmin h1.xeAdmin a{ text-decoration:none !important; font-family:Arial; font-size:16px; color:#fff; margin:0; padding:0;} #xeAdmin h1.xeAdmin a{ text-decoration:none !important; font-family:Arial; font-size:16px; color:#fff; margin:0; padding:0;}
#xeAdmin table th{ color:#666;} #xeAdmin table th{ color:#666;}
#xeAdmin table th a { color:#666;} #xeAdmin table th a { color:#666;}
#xeAdmin table td{ color:#888;} #xeAdmin table td{ color:#767676;}
#xeAdmin table td a { color:#888;} #xeAdmin table td a { color:#767676;}
#xeAdmin caption{ font-size:11px; font-family:Tahoma; color:#888;} #xeAdmin caption{ font-size:11px; font-family:Tahoma; color:#767676;}
#xeAdmin div.summary { font-size:11px; font-family:Tahoma; color:#888;} #xeAdmin div.summary { font-size:11px; font-family:Tahoma; color:#767676;}
#xeAdmin div.summary strong { font-weight:normal; } #xeAdmin div.summary strong { font-weight:normal; }
#xeAdmin button.text{ font-size:12px;} #xeAdmin button.text{ font-size:12px;}
#xeAdmin em, #xeAdmin em,
@ -31,10 +31,10 @@
#xeAdmin .lnb li a{ color:#fff; font-size:14px; font-family:Dotum, Tahoma;} #xeAdmin .lnb li a{ color:#fff; font-size:14px; font-family:Dotum, Tahoma;}
#xeAdmin .path{ color:#ccc; font-size:11px;} #xeAdmin .path{ color:#ccc; font-size:11px;}
#xeAdmin .path a{ color:#888; font-size:11px; font-family:Dotum, Sans-serif;} #xeAdmin .path a{ color:#767676; font-size:11px; font-family:Dotum, Sans-serif;}
.e1 .navigation li a{ color:#000; text-decoration:none;} .e1 .navigation li a{ color:#000; text-decoration:none;}
.e1 .navigation li ul li a{ color:#888;} .e1 .navigation li ul li a{ color:#767676;}
.e1 .navigation li ul li.active a{ font-weight:bold; color:#666;} .e1 .navigation li ul li.active a{ font-weight:bold; color:#666;}
.e2 .section h2.xeAdmin { font-size:12px; margin:0; padding:0;} .e2 .section h2.xeAdmin { font-size:12px; margin:0; padding:0;}
@ -43,15 +43,18 @@
.e2 table tbody th{ font-weight:normal; font-family:Dotum;} .e2 table tbody th{ font-weight:normal; font-family:Dotum;}
.e2 .notice li a{ color:#666; } .e2 .notice li a{ color:#666; }
.e2 .notice li .date{ color:#888; font:10px Tahoma;} .e2 .notice li .date{ color:#767676; font:10px Tahoma;}
.localNavigation li a{ text-decoration:none !important; color:#666;} .localNavigation li a{ text-decoration:none !important; color:#666;}
.localNavigation li.active a{ font-weight:bold; color:#1e6aac;} .localNavigation li.active a{ font-weight:bold; color:#1e6aac;}
#xeAdmin h2.xeAdmin { font-size:12px;} #xeAdmin h2.xeAdmin { font-size:12px;}
#xeAdmin h3.xeAdmin { font-size:12px; color:#666; margin:0; padding:0;} #xeAdmin h3.xeAdmin { font-size:12px; color:#666; margin:0; padding:0;}
#xeAdmin p.summary{ color:#888;} #xeAdmin p.summary{ color:#767676;}
#xeAdmin p.summary a { text-decoration:none; color:#888; } #xeAdmin p.summary a { text-decoration:none; color:#767676; }
#xeAdmin p.summary.red { color:#A54D4D; } #xeAdmin p.summary.red { color:#A54D4D; }
#xeAdmin p.summary.red a { text-decoration:none; color:#A54D4D; } #xeAdmin p.summary.red a { text-decoration:none; color:#A54D4D; }
#xeAdmin div.infoText { color:#888;} #xeAdmin div.infoText { color:#767676;}
#xeAdmin div.infoText p.warning{ margin:0 0 10px 0; padding:0 0 0 25px; background:url(../img/iconWarning.gif) no-repeat left top;}
#xeAdmin div.infoText p.update{ margin:0 0 10px 0; padding:0 0 0 25px; background:url(../img/iconRefresh.gif) no-repeat left top;}
#xeAdmin .buttonAction{}

View file

@ -0,0 +1,9 @@
<filter name="install_ftp_path" module="install" act="procInstallAdminSaveFTPInfo" confirm_msg_code="confirm_submit">
<form>
<node target="ftp_root_path" required="true" />
</form>
<response callback_func="completeFtpPath">
<tag name="error" />
<tag name="message" />
</response>
</filter>

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

View file

@ -33,7 +33,8 @@
</thead> </thead>
<tbody> <tbody>
<!--@foreach($module_list as $key => $val)--> <!--@foreach($module_list as $key => $val)-->
<tr class="bg{$cycle_idx-1}"> <!--@if($val->need_install || $val->need_update)-->
<tr>
<td><a href="{getUrl('','module','admin','act',$val->admin_index_act)}" title="{trim(htmlspecialchars($val->description))}">{$val->title}</a> ({$val->module})</td> <td><a href="{getUrl('','module','admin','act',$val->admin_index_act)}" title="{trim(htmlspecialchars($val->description))}">{$val->title}</a> ({$val->module})</td>
<td>{$val->version}</td> <td>{$val->version}</td>
<td> <td>
@ -44,18 +45,36 @@
<td <!--@if($val->created_table_count != $val->table_count)-->class="alert"<!--@end-->> <td <!--@if($val->created_table_count != $val->table_count)-->class="alert"<!--@end-->>
{$val->created_table_count}/{$val->table_count} {$val->created_table_count}/{$val->table_count}
</td> </td>
<td <!--@if($val->need_install || $val->need_update)-->class="alert"<!--@end-->> <td class="alert">
<!--@if($val->need_install)--> <!--@if($val->need_install)-->
<a href="#" onclick="doInstallModule('{$val->module}');return false;" title="{htmlspecialchars($lang->cmd_install)}">{$lang->cmd_install}</a> <a href="#" onclick="doInstallModule('{$val->module}');return false;" title="{htmlspecialchars($lang->cmd_install)}">{$lang->cmd_install}</a>
<!--@elseif($val->need_update)--> <!--@elseif($val->need_update)-->
<a href="#" onclick="doUpdateModule('{$val->module}'); return false;" title="{htmlspecialchars($lang->cmd_update)}">{$lang->cmd_update}</a> <a href="#" onclick="doUpdateModule('{$val->module}'); return false;" title="{htmlspecialchars($lang->cmd_update)}">{$lang->cmd_update}</a>
<!--@else-->
-
<!--@end--> <!--@end-->
</td> </td>
<td><a href="{getUrl('','module','module','act','dispModuleAdminInfo','selected_module',$val->module)}" onclick="popopen(this.href,'module_info');return false" title="{htmlspecialchars($lang->module_info)}" class="buttonSet buttonInfo"><span>{$lang->module_info}</span></a></td> <td><a href="{getUrl('','module','module','act','dispModuleAdminInfo','selected_module',$val->module)}" onclick="popopen(this.href,'module_info');return false" title="{htmlspecialchars($lang->module_info)}" class="buttonSet buttonInfo"><span>{$lang->module_info}</span></a></td>
</tr> </tr>
<!--@end--> <!--@end-->
<!--@end-->
<!--@foreach($module_list as $key => $val)-->
<!--@if(!$val->need_install && !$val->need_update)-->
<tr>
<td><a href="{getUrl('','module','admin','act',$val->admin_index_act)}" title="{trim(htmlspecialchars($val->description))}">{$val->title}</a> ({$val->module})</td>
<td>{$val->version}</td>
<td>
<!--@foreach($val->author as $author)-->
<!--@if($author->homepage)--><a href="{$author->homepage}" onclick="window.open(this.href);return false;"><!--@end-->{$author->name}<!--@if($author->homepage)--></a><!--@end-->
<!--@endforeach-->
</td>
<td <!--@if($val->created_table_count != $val->table_count)-->class="alert"<!--@end-->>
{$val->created_table_count}/{$val->table_count}
</td>
<td> - </td>
<td><a href="{getUrl('','module','module','act','dispModuleAdminInfo','selected_module',$val->module)}" onclick="popopen(this.href,'module_info');return false" title="{htmlspecialchars($lang->module_info)}" class="buttonSet buttonInfo"><span>{$lang->module_info}</span></a></td>
</tr>
<!--@end-->
<!--@end-->
</tbody> </tbody>
</table> </table>
</div> </div>

View file

@ -0,0 +1,293 @@
<?php
/**
* @class autoinstallAdminController
* @author sol (sol@ngleader.com)
* @brief autoinstall 모듈의 admin controller class
**/
class ModuleInstaller {
var $package = null;
var $base_url = 'http://download.xpressengine.com/';
var $temp_dir = './files/cache/autoinstall/';
var $target_path;
var $download_file;
var $url;
var $download_path;
function ModuleInstaller(&$package)
{
$this->package =& $package;
}
function _download()
{
if($this->package->path == ".")
{
$this->download_file = $this->temp_dir."xe.tar";
$this->target_path = "";
$this->download_path = $this->temp_dir;
}
else
{
$subpath = substr($this->package->path,2);
$this->download_file = $this->temp_dir.$subpath.".tar";
$subpatharr = explode("/", $subpath);
array_pop($subpatharr);
$this->download_path = $this->temp_dir.implode("/", $subpatharr);
$this->target_path = implode("/", $subpatharr);
}
$postdata = array();
$postdata["path"] = $this->package->path;
$postdata["module"] = "resourceapi";
$postdata["act"] = "procResourceapiDownload";
$buff = FileHandler::getRemoteResource($this->base_url, null, 3, "POST", "application/x-www-form-urlencoded; charset=utf-8", array(), array(), $postdata);
FileHandler::writeFile($this->download_file, $buff);
}
function install()
{
$this->_download();
$file_list = $this->_unPack();
$this->_copyDir($file_list);
FileHandler::removeDir($this->temp_dir);
return;
}
function _unPack(){
require_once(_XE_PATH_.'libs/tar.class.php');
$oTar = new tar();
$oTar->openTAR($this->download_file);
$_files = $oTar->files;
$file_list = array();
foreach($_files as $key => $info) {
FileHandler::writeFile($this->download_path."/".$info['name'], $info['file']);
$file_list[] = $info['name'];
}
return $file_list;
}
function _copyDir(&$file_list){
$ftp_info = Context::getFTPInfo();
if(!$ftp_info->ftp_user || !$ftp_info->ftp_password) return new Object(-1,'msg_ftp_invalid_auth_info');
require_once(_XE_PATH_.'libs/ftp.class.php');
$oFtp = new ftp();
if(!$oFtp->ftp_connect('localhost', $ftp_info->ftp_port)) return new Object(-1,'msg_ftp_not_connected');
if(!$oFtp->ftp_login($ftp_info->ftp_user, $ftp_info->ftp_password)) {
$oFtp->ftp_quit();
return new Object(-1,'msg_ftp_invalid_auth_info');
}
$_list = $oFtp->ftp_rawlist($ftp_config->ftp_root_path);
if(count($_list) == 0 || !$_list[0]) {
$oFtp->ftp_quit();
$oFtp = new ftp();
if(!$oFtp->ftp_connect($_SERVER['SERVER_NAME'], $ftp_info->ftp_port)) return new Object(-1,'msg_ftp_not_connected');
if(!$oFtp->ftp_login($ftp_info->ftp_user, $ftp_info->ftp_password)) {
$oFtp->ftp_quit();
return new Object(-1,'msg_ftp_invalid_auth_info');
}
}
$ftp_config = Context::getFTPInfo();
$target_dir = $ftp_config->ftp_root_path.$this->target_path;
foreach($file_list as $k => $file){
$org_file = $file;
if($this->package->path == ".")
{
$file = substr($file,3);
}
$path = FileHandler::getRealPath("./".$this->target_path."/".$file);
$path_list = explode('/', dirname($this->target_path."/".$file));
$real_path = "./";
$ftp_path = $ftp_config->ftp_root_path;
for($i=0;$i<count($path_list);$i++)
{
if($path_list=="") continue;
$real_path .= $path_list[$i]."/";
$ftp_path .= $path_list[$i]."/";
if(!file_exists(FileHandler::getRealPath($real_path)))
{
$oFtp->ftp_mkdir($ftp_path);
$oFtp->ftp_site("CHMOD 755 ".$path);
}
}
$oFtp->ftp_put($target_dir .'/'. $file, FileHandler::getRealPath($this->download_path."/".$org_file));
}
$oFtp->ftp_quit();
return new Object();
}
}
class autoinstallAdminController extends autoinstall {
/**
* @brief 초기화
**/
function init() {
}
function checkFileCheckSum($file, $checksum){
$local_checksum = md5_file(FileHandler::getRealPath($file));
return ($local_checksum === $checksum);
}
function _cleanDownloaded($obj){
FileHandler::removeDir($obj->download_path);
}
function procAutoinstallAdminUpdateinfo()
{
$oModel = &getModel('autoinstall');
$item = $oModel->getLatestPackage();
if($item)
{
$params["updatedate"] = $item->updatedate;
}
$params["act"] = "getResourceapiUpdate";
$body = XmlGenerater::generate($params);
$buff = FileHandler::getRemoteResource($this->uri, $body, 3, "POST", "application/xml");
$xml = new XmlParser();
$xmlDoc = $xml->parse($buff);
$this->updateCategory($xmlDoc);
$this->updatePackages($xmlDoc);
$this->checkInstalled();
$this->setMessage("success_updated");
}
function checkInstalled()
{
executeQuery("autoinstall.deleteInstalledPackage");
$oModel =& getModel('autoinstall');
$packages = $oModel->getPackages();
foreach($packages as $package)
{
$real_path = FileHandler::getRealPath($package->path);
if(!file_exists($real_path)) {
continue;
}
if($package->path == ".")
{
$type = "core";
$version = __ZBXE_VERSION__;
}
else
{
$path_array = explode("/", $package->path);
$target_name = array_pop($path_array);
$type = substr(array_pop($path_array), 0, -1);
switch($type)
{
case "module":
case "addon":
case "layout":
case "widget":
$config_file = "/conf/info.xml";
break;
case "component":
$config_file = "/info.xml";
break;
case "skin":
case "widgetstyle":
$config_file = "/skin.xml";
break;
default:
continue;
}
$xml = new XmlParser();
$xmlDoc = $xml->loadXmlFile($real_path.$config_file);
if(!$xmlDoc) continue;
$version = $xmlDoc->{$type}->version->body;
}
$args = null;
$args->package_srl = $package->package_srl;
$args->version = $package->version;
$args->current_version = $version;
if(version_compare($args->version, $args->current_version, ">"))
{
$args->need_update="Y";
}
else
{
$args->need_update="N";
}
$output = executeQuery("autoinstall.insertInstalledPackage", $args);
}
}
function procAutoinstallAdminPackageinstall()
{
$package_srls = Context::get('package_srl');
$oModel =& getModel('autoinstall');
$packages = explode(',', $package_srls);
foreach($packages as $package_srl)
{
$package = $oModel->getPackage($package_srl);
$oModuleInstaller = new ModuleInstaller($package);
$oModuleInstaller->install();
}
$this->setMessage('success_installed');
}
function updatePackages(&$xmlDoc)
{
$oModel =& getModel('autoinstall');
if(!$xmlDoc->response->packages->item) return;
if(!is_array($xmlDoc->response->packages->item))
{
$xmlDoc->response->packages->item = array($xmlDoc->response->packages->item);
}
$targets = array('package_srl', 'updatedate', 'latest_item_srl', 'path', 'version', 'category_srl');
foreach($xmlDoc->response->packages->item as $item)
{
$args = null;
foreach($targets as $target)
{
$args->{$target} = $item->{$target}->body;
}
if($oModel->getPackage($args->package_srl))
{
executeQuery("autoinstall.updatePackage", $args);
}
else
{
executeQuery("autoinstall.insertPackage", $args);
}
}
}
function updateCategory(&$xmlDoc)
{
executeQuery("autoinstall.deleteCategory", $args);
$oModel =& getModel('autoinstall');
if(!is_array($xmlDoc->response->categorylist->item))
{
$xmlDoc->response->categorylist->item = array($xmlDoc->response->categorylist->item);
}
foreach($xmlDoc->response->categorylist->item as $item)
{
$args = null;
$args->category_srl = $item->category_srl->body;
$args->parent_srl = $item->parent_srl->body;
$args->title = $item->title->body;
executeQuery("autoinstall.insertCategory", $args);
}
}
}
?>

View file

@ -0,0 +1,194 @@
<?php
/**
* @class autoinstallAdminView
* @author sol (sol@ngleader.com)
* @brief autoinstall 모듈의 admin view class
**/
class autoinstallAdminView extends autoinstall {
function init() {
$template_path = sprintf("%stpl/",$this->module_path);
Context::set('original_site', $this->original_site);
Context::set('uri', $this->uri);
$this->setTemplatePath($template_path);
}
function rearrange(&$item, &$targets)
{
$ret = null;
foreach($targets as $target)
{
$ret->{$target} = $item->{$target}->body;
}
return $ret;
}
function rearranges($items)
{
if(!is_array($items)) $items = array($items);
$item_list = array();
$targets = array('category_srl', 'package_srl', 'item_screenshot_url', 'package_voted', 'package_voter', 'package_description', 'package_downloaded', 'item_regdate', 'title', 'item_version', 'package_star');
$targetpackages = array();
foreach($items as $item)
{
$targetpackages[$item->package_srl->body] = 0;
}
$oModel = &getModel('autoinstall');
$packages = $oModel->getInstalledPackages(array_keys($targetpackages));
foreach($items as $item)
{
$v = $this->rearrange($item, $targets);
if($packages[$v->package_srl])
{
$v->current_version = $packages[$v->package_srl]->current_version;
$v->need_update = $packages[$v->package_srl]->need_update;
}
$item_list[$v->package_srl] = $v;
}
return $item_list;
}
function dispAutoinstallAdminInstall() {
$package_srl = Context::get('package_srl');
if(!$package_srl) return $this->dispAutoinstallAdminIndex();
$ftp_info = Context::getFTPInfo();
if(!$ftp_info->ftp_root_path) Context::set('show_ftp_note', true);
$params["act"] = "getResourceapiInstallInfo";
$params["package_srl"] = $package_srl;
$xmlDoc = XmlGenerater::getXmlDoc($params);
$oModel = &getModel('autoinstall');
$targetpackages = array();
if($xmlDoc)
{
$xmlPackage =& $xmlDoc->response->package;
$package->package_srl = $xmlPackage->package_srl->body;
$package->title = $xmlPackage->title->body;
$package->package_description = $xmlPackage->package_description->body;
$package->version = $xmlPackage->version->body;
$package->path = $xmlPackage->path->body;
if($xmlPackage->depends)
{
if(!is_array($xmlPackage->depends->item)) $xmlPackage->depends->item = array($xmlPackage->depends->item);
$package->depends = array();
foreach($xmlPackage->depends->item as $item)
{
$dep_item = null;
$dep_item->package_srl = $item->package_srl->body;
$dep_item->title = $item->title->body;
$dep_item->version = $item->version->body;
$dep_item->path = $item->path->body;
$package->depends[] = $dep_item;
$targetpackages[$dep_item->package_srl] = 1;
}
$packages = $oModel->getInstalledPackages(array_keys($targetpackages));
$package->deplist = "";
foreach($package->depends as $key => $dep)
{
if(!$packages[$dep->package_srl]) {
$package->depends[$key]->installed = false;
$package->package_srl .= ",". $dep->package_srl;
}
else {
$package->depends[$key]->installed = true;
$package->depends[$key]->cur_version = $packages[$dep->package_srl]->version;
if(version_compare($dep->version, $packages[$dep->package_srl]->version, ">"))
{
$package->need_update = true;
$package->package_srl .= ",". $dep->package_srl;
}
else
{
$package->need_update = false;
}
}
}
}
$installedPackage = $oModel->getInstalledPackage($package_srl);
if($installedPackage) {
$package->installed = true;
$package->cur_version = $installedPackage->current_version;
$package->need_update = version_compare($package->version, $installedPackage->current_version, ">");
}
Context::set("package", $package);
}
$this->setTemplateFile('install');
}
function dispAutoinstallAdminIndex() {
$oModuleModel = &getModel('module');
$config = $oModuleModel->getModuleConfig('autoinstall');
$ftp_info = Context::getFTPInfo();
if(!$ftp_info->ftp_root_path) Context::set('show_ftp_note', true);
$this->setTemplateFile('index');
$params = array();
$params["act"] = "getResourceapiLastupdate";
$body = XmlGenerater::generate($params);
$buff = FileHandler::getRemoteResource($this->uri, $body, 3, "POST", "application/xml");
$xml_lUpdate = new XmlParser();
$lUpdateDoc = $xml_lUpdate->parse($buff);
$updateDate = $lUpdateDoc->response->updatedate->body;
$oModel = &getModel('autoinstall');
$item = $oModel->getLatestPackage();
if(!$item || $item->updatedate < $updateDate )
{
Context::set('need_update', true);
return;
}
$page = Context::get('page');
if(!$page) $page = 1;
Context::set('page', $page);
$order_type = Context::get('order_type');
if(!in_array($order_type, array('asc', 'desc'))) $order_type = 'desc';
Context::set('order_type', $order_type);
$order_target = Context::get('order_target');
if(!in_array($order_target, array('newest', 'download', 'popular'))) $order_target = 'newest';
Context::set('order_target', $order_target);
$search_keyword = Context::get('search_keyword');
$childrenList = Context::get('childrenList');
$category_srl = Context::get('category_srl');
if($childrenList) $params["category_srl"] = $childrenList;
else if($category_srl) $params["category_srl"] = $category_srl;
$params["act"] = "getResourceapiPackagelist";
$params["order_target"] = $order_target;
$params["order_type"] = $order_type;
$params["page"] = $page;
if($search_keyword)
{
$params["search_keyword"] = $search_keyword;
}
$xmlDoc = XmlGenerater::getXmlDoc($params);
if($xmlDoc && $xmlDoc->response->packagelist->item)
{
$item_list = $this->rearranges($xmlDoc->response->packagelist->item);
Context::set('item_list', $item_list);
$array = array('total_count', 'total_page', 'cur_page', 'page_count', 'first_page', 'last_page');
$page_nav = $this->rearrange($xmlDoc->response->page_navigation, $array);
$page_navigation = new PageHandler($page_nav->total_count, $page_nav->total_page, $page_nav->cur_page, $page_nav->page_count);
Context::set('page_navigation', $page_navigation);
}
$oModel = &getModel('autoinstall');
$categories = &$oModel->getCategoryList();
Context::set('categories', $categories);
Context::set('tCount', $oModel->getPackageCount(null));
}
}
?>

View file

@ -0,0 +1,64 @@
<?php
/**
* @class autoinstall
* @author sol (sol@ngleader.com)
* @brief autoinstall 모듈의 high class
**/
class XmlGenerater {
function generate(&$params)
{
$xmlDoc = '<?xml version="1.0" encoding="utf-8" ?><methodCall><params>';
if(!is_array($params)) return null;
$params["module"] = "resourceapi";
foreach($params as $key => $val)
{
$xmlDoc .= sprintf("<%s><![CDATA[%s]]></%s>", $key, $val, $key);
}
$xmlDoc .= "</params></methodCall>";
return $xmlDoc;
}
function getXmlDoc(&$params)
{
$body = XmlGenerater::generate($params);
$buff = FileHandler::getRemoteResource($this->uri, $body, 3, "POST", "application/xml");
if(!$buff) return;
$xml = new XmlParser();
$xmlDoc = $xml->parse($buff);
return $xmlDoc;
}
}
class autoinstall extends ModuleObject {
var $uri = "http://download.xpressengine.com/";
var $original_site = "http://www.xpressengine.com/";
var $tmp_dir = './files/cache/autoinstall/';
/**
* @brief 설치시 추가 작업이 필요할시 구현
**/
function moduleInstall() {
}
/**
* @brief 설치가 이상이 없는지 체크하는 method
**/
function checkUpdate() {
return false;
}
/**
* @brief 업데이트 실행
**/
function moduleUpdate() {
return new Object(0, 'success_updated');
}
/**
* @brief 캐시 파일 재생성
**/
function recompileCache() {
}
}
?>

View file

@ -0,0 +1,117 @@
<?php
/**
* @class autoinstallModel
* @author sol (sol@ngleader.com)
* @brief autoinstall 모듈의 Model class
**/
class autoinstallModel extends autoinstall {
function getCategory($category_srl)
{
$args->category_srl = $category_srl;
$output = executeQueryArray("autoinstall.getCategory", $args);
if(!$output->data) return null;
return array_shift($output->data);
}
function getPackages()
{
$output = executeQueryArray("autoinstall.getPackages");
if(!$output->data) return array();
return $output->data;
}
function getInstalledPackage($package_srl)
{
$args->package_srl = $package_srl;
$output = executeQueryArray("autoinstall.getInstalledPackage", $args);
if(!$output->data) return null;
return array_shift($output->data);
}
function getPackage($package_srl)
{
$args->package_srl = $package_srl;
$output = executeQueryArray("autoinstall.getPackage", $args);
if(!$output->data) return null;
return array_shift($output->data);
}
function getCategoryList()
{
$output = executeQueryArray("autoinstall.getCategories");
if(!$output->toBool() || !$output->data) return array();
$categoryList = array();
foreach($output->data as $category)
{
$category->children = array();
$categoryList[$category->category_srl] = $category;
}
$depth0 = array();
foreach($categoryList as $key => $category)
{
if($category->parent_srl)
{
$categoryList[$category->parent_srl]->children[] =& $categoryList[$key];
}
else
{
$depth0[] = $key;
}
}
$resultList = array();
foreach($depth0 as $category_srl)
{
$this->setDepth($categoryList[$category_srl], 0, $categoryList, $resultList);
}
return $resultList;
}
function getPackageCount($category_srl)
{
$args->category_srl = $category_srl;
$output = executeQuery("autoinstall.getPackageCount", $args);
if(!$output->data) return 0;
return $output->data->count;
}
function setDepth(&$item, $depth, &$list, &$resultList)
{
$resultList[$item->category_srl] =& $item;
$item->depth = $depth;
$siblingList = $item->category_srl;
foreach($item->children as $child)
{
$siblingList .= ",".$this->setDepth($list[$child->category_srl], $depth+1, $list, $resultList);
}
if(count($item->children) < 1)
{
$item->nPackages = $this->getPackageCount($item->category_srl);
}
$item->childrenList = $siblingList;
return $siblingList;
}
function getLatestPackage() {
$output = executeQueryArray("autoinstall.getLatestPackage");
if(!$output->data) return null;
return array_shift($output->data);
}
function getInstalledPackages(&$package_list) {
$args->package_list = &$package_list;
$output = executeQueryArray("autoinstall.getInstalledPackages", $args);
$result = array();
if(!$output->data) return $result;
foreach($output->data as $value)
{
$result[$value->package_srl] = $value;
}
return $result;
}
}
?>

View file

@ -0,0 +1,26 @@
<?php
/**
* @class autoinstallView
* @author sol (sol@ngleader.com)
* @brief autoinstall 모듈의 View class
**/
class autoinstallView extends autoinstall {
/**
* @brief 초기화
**/
function init() {
}
function dispAutoinstallTest(){
$file = "modules.test.tar";
$checksum = '549989037bd8401d39b83ca2393d8131';
$file = "modules.test.skins.test.tar";
$oAutoinstallAdminController = &getAdminController('autoinstall');
$output = $oAutoinstallAdminController->install($file, $checksum);
return $output;
}
}
?>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="0.2">
<title xml:lang="ko">쉬운 설치</title>
<title xml:lang="en">Easy-Installation</title>
<title xml:lang="zh-CN">在线安装</title>
<description xml:lang="ko">관리자 모드에서 클릭으로 모듈/스킨/레이아웃/위젯/위젯스타일 등을 설치하는 모듈입니다. </description>
<description xml:lang="en">With this module, you can install and upgrade your programs including modules, skins, layouts, etc., from www.xpressengine.com by one-click. </description>
<description xml:lang="zh-CN">很方便的在管理页面一键安装XE相关模块(模块/皮肤/布局/控件/控件样式等)。</description>
<version>0.1</version>
<date>2009-11-11</date>
<category>system</category>
<author email_address="haneul0318@gmail.com" link="http://www.seungyeop.kr">
<name xml:lang="ko">haneul</name>
<name xml:lang="zh-CN">haneul</name>
<name xml:lang="en">haneul</name>
</author>
<author email_address="sol@ngleader.com" link="http://ngleader.com">
<name xml:lang="ko">sol</name>
<name xml:lang="en">sol</name>
<name xml:lang="zh-CN">sol</name>
</author>
</module>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<module>
<actions>
<action name="dispAutoinstallAdminInstall" type="view" standalone="true" />
<action name="dispAutoinstallAdminIndex" type="view" standalone="true" admin_index="true" />
<action name="procAutoinstallAdminUpdateinfo" type="controller" standalone="true" />
<action name="procAutoinstallAdminPackageinstall" type="controller" standalone="true" />
</actions>
</module>

View file

@ -0,0 +1,30 @@
<?php
/**
* @file ko.lang.php
* @author sol (sol@ngleader.com)
* @brief Autoinstall(autoinstall) 모듈의 기본 언어팩
**/
$lang->autoinstall = 'Easy-install';
$lang->about_autoinstall = 'It helps you install/upgrade progams(skins) of XE.';
$lang->package_update = 'Recent Update';
$lang->package_downloaded_count = 'Download Count';
$lang->need_update = "You need to update package list.";
$lang->order_newest = "Newest";
$lang->order_popular = "Popular";
$lang->order_download = "Download";
$lang->success_installed = "Installations succeeded.";
$lang->view_all_package = "View All";
$lang->description_ftp_note = "If FTP configuration is not set, installation would not work. Please configure FTP information";
$lang->description_update = "If you recently upgrade or install programs without easy installation module, please press update button to keep information of the programs updated.";
$lang->install = "Install";
$lang->update = "Update";
$lang->current_version = "Installed version";
$lang->depending_programs = "This program depends on ";
$lang->require_update = "Update is required.";
$lang->require_installation = "Installation is required.";
$lang->description_install = "Installation process also install/update programs which this program depends on";
$lang->description_download = "When FTP is disabled, you should download it and extract it into target path. (if target path is ./modules/board, extract it at ./modules)";
$lang->path = "Path";
?>

View file

@ -0,0 +1,30 @@
<?php
/**
* @file ko.lang.php
* @author sol (sol@ngleader.com)
* @brief Autoinstall(autoinstall) 모듈의 기본 언어팩
**/
$lang->autoinstall = '쉬운 설치';
$lang->about_autoinstall = 'XpressEngine의 여러 프로그램을 쉽게 설치/업그레이드할 수 있도록 도와주는 모듈입니다.';
$lang->package_update = '최근 업데이트';
$lang->package_downloaded_count = '전체 다운로드';
$lang->need_update = "업데이트가 필요합니다.";
$lang->order_newest = "신규 등록";
$lang->order_popular = "인기";
$lang->order_download = "다운로드";
$lang->success_installed = "설치가 성공하였습니다.";
$lang->view_all_package = "전체 보기";
$lang->description_ftp_note = "FTP 설정이 안되어있으면 설치가 진행되지 않습니다. FTP설정을 해주세요";
$lang->description_update = "새로 설치한 모듈의 버전 정보등은 업데이트를 눌러주시면 반영됩니다.";
$lang->install = "설치";
$lang->update = "업데이트";
$lang->current_version = "현재 설치 버전";
$lang->depending_programs = "의존하고 있는 프로그램";
$lang->require_update = "업데이트가 필요합니다.";
$lang->require_installation = "설치가 필요합니다.";
$lang->description_install = "설치를 진행하면, 이 프로그램이 의존하고 있는 모든 프로그램을 업데이트/설치 합니다.";
$lang->description_download = "FTP를 이용할 수 없는 경우, 직접 다운로드 하여 해당 path에 설치하셔야 합니다. (한칸 상위에서 압축을 푸시면 됩니다. ./modules/board의 경우 ./modules에서 tar를 푸세요)";
$lang->path = "설치경로";
?>

View file

@ -0,0 +1,30 @@
<?php
/**
* @file zh-CN.lang.php
* @author sol (sol@ngleader.com) 翻译guny(space.china@gmail.com)
* @brief 自动安装(autoinstall)模块语言包
**/
$lang->autoinstall = 'Autoinstall';
$lang->about_autoinstall = 'Autoinstall是XpressEngine的自动安装模块。';
$lang->package_update = '最新更新';
$lang->package_downloaded_count = '总下载';
$lang->need_update = "有新的更新。";
$lang->order_newest = "最新发布";
$lang->order_popular = "热门";
$lang->order_download = "下载";
$lang->success_installed = "安装成功!";
$lang->view_all_package = "查看全部";
$lang->description_ftp_note = "请务必完成FTP设置否则将无法在线安装(更新)相关模块。";
$lang->description_update = "新安装(更新)模块的版本信息点击Update按钮后才能正常显示。";
$lang->install = "Install";
$lang->update = "Update";
$lang->depending_programs = "This program depends on ";
$lang->require_update = "Update is required.";
$lang->require_installation = "Installation is required.";
$lang->description_install = "Installation process also install/update programs which this program depends on";
$lang->current_version = "Installed version";
$lang->description_download = "When FTP is disabled, you should download it and extract it into target path. (if target path is ./modules/board, extract it at ./modules)";
$lang->path = "Path";
?>

View file

@ -0,0 +1,7 @@
<query id="deleteCategory" action="delete">
<tables>
<table name="autoinstall_remote_categories" />
</tables>
<conditions>
</conditions>
</query>

View file

@ -0,0 +1,8 @@
<query id="deleteInstalledPackage" action="delete">
<tables>
<table name="autoinstall_installed_packages" />
</tables>
<conditions>
<condition operation="equal" column="package_srl" var="package_srl" filter="number" />
</conditions>
</query>

View file

@ -0,0 +1,8 @@
<query id="getCategories" action="select">
<tables>
<table name="autoinstall_remote_categories" />
</tables>
<columns>
<column name="*" />
</columns>
</query>

View file

@ -0,0 +1,11 @@
<query id="getCategory" action="select">
<tables>
<table name="autoinstall_remote_categories" />
</tables>
<columns>
<column name="*" />
</columns>
<conditions>
<condition operation="equal" column="category_srl" var="category_srl" filter="number" notnull="notnull" />
</conditions>
</query>

View file

@ -0,0 +1,11 @@
<query id="getInstalledPackage" action="select">
<tables>
<table name="autoinstall_installed_packages" />
</tables>
<columns>
<column name="*" />
</columns>
<conditions>
<condition operation="equal" column="package_srl" var="package_srl" filter="number" notnull="notnull" />
</conditions>
</query>

View file

@ -0,0 +1,11 @@
<query id="getInstalledPackages" action="select">
<tables>
<table name="autoinstall_installed_packages" />
</tables>
<columns>
<column name="*" />
</columns>
<conditions>
<condition operation="in" column="package_srl" var="package_list" notnull="notnull" />
</conditions>
</query>

View file

@ -0,0 +1,16 @@
<query id="getLatestPackage" action="select">
<tables>
<table name="autoinstall_packages" alias="packages" />
</tables>
<columns>
<column name="*" />
</columns>
<conditions>
</conditions>
<navigation>
<index var="sort_index" default="updatedate" order="desc" />
<list_count var="list_count" default="1" />
<page_count var="page_count" default="10" />
<page var="page" default="1" />
</navigation>
</query>

View file

@ -0,0 +1,11 @@
<query id="getPackage" action="select">
<tables>
<table name="autoinstall_packages" />
</tables>
<columns>
<column name="*" />
</columns>
<conditions>
<condition operation="equal" column="package_srl" var="package_srl" filter="number" notnull="notnull" />
</conditions>
</query>

View file

@ -0,0 +1,11 @@
<query id="getPackageCount" action="select">
<tables>
<table name="autoinstall_packages" />
</tables>
<columns>
<column name="count(*)" alias="count" />
</columns>
<conditions>
<condition operation="equal" column="category_srl" var="category_srl" filter="number" notnull="notnull" />
</conditions>
</query>

View file

@ -0,0 +1,8 @@
<query id="getPackages" action="select">
<tables>
<table name="autoinstall_packages" />
</tables>
<columns>
<column name="*" />
</columns>
</query>

View file

@ -0,0 +1,10 @@
<query id="insertCategory" action="insert">
<tables>
<table name="autoinstall_remote_categories" />
</tables>
<columns>
<column name="category_srl" var="category_srl" filter="number" notnull="notnull" />
<column name="parent_srl" var="parent_srl" filter="number" notnull="notnull" />
<column name="title" var="title" minlength="1" maxlength="250" />
</columns>
</query>

View file

@ -0,0 +1,11 @@
<query id="insertInstalledPackage" action="insert">
<tables>
<table name="autoinstall_installed_packages" />
</tables>
<columns>
<column name="package_srl" var="package_srl" filter="number" notnull="notnull" />
<column name="version" var="version" notnull="notnull" />
<column name="current_version" var="current_version" notnull="notnull" />
<column name="need_update" var="need_update" />
</columns>
</query>

View file

@ -0,0 +1,13 @@
<query id="insertPackage" action="insert">
<tables>
<table name="autoinstall_packages" />
</tables>
<columns>
<column name="package_srl" var="package_srl" filter="number" notnull="notnull" />
<column name="category_srl" var="category_srl" filter="number" />
<column name="path" var="path" notnull="notnull" />
<column name="updatedate" var="updatedate" notnull="notnull" />
<column name="latest_item_srl" var="latest_item_srl" notnull="notnull" />
<column name="version" var="version" notnull="notnull" />
</columns>
</query>

View file

@ -0,0 +1,12 @@
<query id="updateCategory" action="update">
<tables>
<table name="autoinstall_remote_categories" />
</tables>
<columns>
<column name="parent_srl" var="parent_srl" filter="number" notnull="notnull" />
<column name="title" var="title" minlength="1" maxlength="250" />
</columns>
<conditions>
<condition operation="equal" column="category_srl" var="category_srl" notnull="notnull" />
</conditions>
</query>

View file

@ -0,0 +1,13 @@
<query id="updateInstalledPackage" action="update">
<tables>
<table name="autoinstall_installed_packages" />
</tables>
<columns>
<column name="version" var="version" notnull="notnull" />
<column name="current_version" var="current_version" notnull="notnull" />
<column name="need_update" var="need_update" />
</columns>
<conditions>
<condition operation="equal" column="package_srl" var="package_srl" notnull="notnull" />
</conditions>
</query>

View file

@ -0,0 +1,15 @@
<query id="updatePackage" action="update">
<tables>
<table name="autoinstall_packages" />
</tables>
<columns>
<column name="path" var="path" notnull="notnull" />
<column name="updatedate" var="updatedate" notnull="notnull" />
<column name="category_srl" var="category_srl" filter="number" />
<column name="latest_item_srl" var="latest_item_srl" notnull="notnull" />
<column name="version" var="version" notnull="notnull" />
</columns>
<conditions>
<condition operation="equal" column="package_srl" var="package_srl" notnull="notnull" />
</conditions>
</query>

View file

@ -0,0 +1,6 @@
<table name="autoinstall_installed_packages">
<column name="package_srl" type="number" size="11" notnull="notnull" default="0" index="idx_package_srl" />
<column name="version" type="varchar" size="255" />
<column name="current_version" type="varchar" size="255" />
<column name="need_update" type="char" size="1" default="N" />
</table>

View file

@ -0,0 +1,9 @@
<table name="autoinstall_packages">
<column name="package_srl" type="number" size="11" notnull="notnull" default="0" index="idx_package_srl" />
<column name="category_srl" type="number" size="11" default="0" index="idx_category_srl" />
<column name="path" type="varchar" size="250" notnull="notnull" unique="unique_path" />
<column name="updatedate" type="date" index="idx_regdate " />
<column name="latest_item_srl" type="number" size="11" default="0" notnull="notnull" />
<column name="version" type="varchar" size="255" />
</table>

View file

@ -0,0 +1,5 @@
<table name="autoinstall_remote_categories">
<column name="category_srl" type="number" size="11" default="0" notnull="notnull" primary_key="primary_key" />
<column name="parent_srl" type="number" size="11" default="0" notnull="notnull" index="idx_parent_srl" />
<column name="title" type="varchar" size="250" notnull="notnull" />
</table>

View file

@ -0,0 +1,37 @@
<!--%import("filter/insert_config.xml")-->
<!--#include("header.html")-->
<form action="./" method="get" onsubmit="return procFilter(this, insert_config)">
<table cellspacing="0" class="rowTable">
<tr>
<th scope="col"><div>설치된 XE의 절대경로</div></th>
<td>{_XE_PATH_}
</td>
</tr>
<tr>
<th scope="col" rowspan="2"><div>설치된 XE의 FTP 절대경로 설정</div></th>
<td>
<input type="text" name="ftp_root_path" value="<!--@if($pwd && $pwd!='/')-->{$pwd}<!--@else-->{$config->ftp_root_path}<!--@end-->" class="inputTypeText w400" />
</td>
</tr>
<tr>
<td>
<!--@if($list)-->
<ul>
<!--@foreach($list as $k => $v)-->
<!--@if($v)-->
<li> <a href="{getUrl('pwd',$pwd.$v)}">{$v}</a></li>
<!--@end-->
<!--@end-->
</ul>
<!--@end-->
</td>
</tr>
<tr class="row2">
<th colspan="2" class="button" style="text-align:center">
<span class="button black strong"><input type="submit" value="{$lang->cmd_registration}" accesskey="s" /></span>
</th>
</tr>
</table>
</form>

View file

@ -0,0 +1,55 @@
@charset "utf-8";
/* NHN > UIT Center > Open UI Tech Team > Jeong Chan Myeong(dece24@nhncorp.com) */
.install{ border-top:1px solid #ddd; *zoom:1;}
.install:after{ content:""; display:block; clear:both;}
.aside { width:180px; float:left; margin-right:30px; padding-bottom:30px; }
.aside .categoryBox { background-color:#F8F8F8; padding:10px; width:160px; overflow:hidden; }
.aside .categoryBox h3 { padding:0 0 10px 0; margin:0 0 10px 0; white-space:nowrap; overflow:hidden; color:#48494E; font-size:11px; font-weight:normal; background:transparent url(../img/hrE1.gif) repeat-x scroll left bottom;}
.aside .categoryBox h3 a { color:#48494E; font-size:12px; font-weight:bold; text-decoration:none; }
.aside .categoryBox ul.category { margin:10px 0 0 0; padding:0; list-style:none; }
.aside .categoryBox ul.category li { margin:0 0 10px 10px; }
.aside .categoryBox ul.category li a.selected { font-weight:bold; color:#2893BB; }
.aside .categoryBox ul.category li a { text-decoration:none; color:#7B7575; }
.aside .categoryBox ul.category li span { font-family:verdana; font-size:10px; color:#999; }
.aside .categoryBox ul.resourceManage { margin:0; padding:10px 0 0 0; list-style:none; background:transparent url(../img/hrE1.gif) repeat-x scroll left top; }
.aside .categoryBox ul.resourceManage li { background:url(../img/btnManage.gif) no-repeat 2px 2px; padding-left:14px; white-space:nowrap; overflow:hidden; margin-bottom:10px; }
.aside .categoryBox ul.resourceManage li a { text-decoration:none; color:#747474; }
.aside .categoryBox ul.resourceManage li a.selected { font-weight:bold; }
.aside .searchBox { padding:10px 0; text-align:center; background:transparent url(../img/hrE1.gif) repeat-x scroll left top;}
.aside .searchBox input.input { border:1px solid #ddd; width:120px; height:16px;}
.aside .searchBox input.submit { vertical-align:middle; }
.install .content { position:relative; *zoom:1; overflow:hidden; width:auto; float:none; margin:0;}
.updateList,
.updateList th,
.updateList td{ border:0; vertical-align:top; text-align:left; padding:10px 0;}
.updateList {width:100%; height:100px; table-layout:fixed;}
.updateList th,
.updateList td{ border-bottom:1px dotted #ddd;}
.updateList th img { border:1px solid #ccc; padding:2px; overflow:hidden; *zoom:1; }
.updateList td { padding:10px 0 0 0;}
.updateList td .title{ position:relative;}
.updateList td .title h3 { padding:0; margin:0 0 5px 0; font-size:12px;}
.updateList td .title a {text-decoration:none; color:#333 !important; }
.updateList td .title .button{ position:absolute; top:0; right:0;}
.updateList td .info p{ margin:0 0 5px 0; line-height:1.5;}
.updateList td .info p.desc{ margin:0 100px 10px 0;}
.updateList td .info p.meta{ font-size:11px;}
.updateList td .info p.meta span{ display:inline-block; line-height:1; padding:0 5px 0 9px;}
.updateList td .info p.meta .reputation{ padding:0 5px 0 0;}
.updateList td .info p.meta .reputation img{ float:left; margin:-1px 0 0 0;}
.updateList td .info p.meta .reputation span{ padding:0 0 0 5px;}
.updateList td .info p.meta .lastUpdate{ border-left:1px solid #ddd;}
.updateList td .info p.meta .download{ border-left:1px solid #ddd;}
ul.listOrder { position:relative; overflow:hidden; margin:0; padding:10px 0; text-align:left; background:transparent url(../img/hrE1.gif) repeat-x scroll left bottom;}
ul.listOrder.asc li.arrow { background:url(../img/arrUp.gif) no-repeat right 2px; padding-right:10px; }
ul.listOrder.desc li.arrow { background:url(../img/arrDown.gif) no-repeat right 2px; padding-right:10px; }
ul.listOrder li { position:relative; left:-1px; display:inline; margin:0; padding:0 5px 0 9px; border-left:1px solid #ddd;}
ul.listOrder li.arrow a { text-decoration:none; font-weight:bold; color:#2893BB; }
ul.listOrder li a { text-decoration:none; color:#7B7575; }

View file

@ -0,0 +1,9 @@
<filter name="insert_config" module="autoinstall" act="procAutoinstallAdminInsertConfig" confirm_msg_code="confirm_submit">
<form>
<node target="ftp_root_path" required="true" />
</form>
<response>
<tag name="error" />
<tag name="message" />
</response>
</filter>

View file

@ -0,0 +1 @@
<h3 class="xeAdmin">{$lang->autoinstall} <span class="gray">Beta</span></h3>

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

View file

@ -0,0 +1,21 @@
<!--#include("header.html")-->
<!--%import("css/autoinstall.css")-->
<!--%import("js/autoinstall.js")-->
<div class="infoText">
<!--@if($show_ftp_note)-->
<p class="warning">{$lang->description_ftp_note} <a href="{getUrl('','module','admin','act','dispAdminConfig')}#ftpSetup">FTP Setup</a> </p>
<!--@end-->
<!--@if($need_update)-->
<p class="update">{$lang->need_update}</p>
<!--@else-->
<p class="update">{$lang->description_update}</p>
<!--@end-->
<p><span class="button xLarge strong green"><button type="button" onclick="doUpdate()" title="update">Update</button></span></p>
</div>
<div class="install">
<!--#include("leftBox.html")-->
<!--@if($item_list)-->
<!--#include("list.html")-->
<!--@end-->
</div>

View file

@ -0,0 +1,24 @@
<!--#include("header.html")-->
<!--%import("css/autoinstall.css")-->
<!--%import("js/autoinstall.js")-->
<div class="infoText">
<p><strong>{$package->title}</strong> ver. <strong>{$package->version}</strong> ( <!--@if($package->installed)-->{$lang->current_version}: {$package->cur_version} <!--@if($package->need_update)--> ({$lang->require_update})<!--@end--> <!--@else-->{$lang->require_installation}<!--@end--> )</p>
<!--@foreach($package->depends as $dep)-->
<dl>
<dt><strong>{$lang->depending_programs} :</strong></dt>
<dd> {$dep->title} ver. {$dep->version} -
<!--@if($dep->installed)-->{$lang->current_version}: {$dep->cur_version} <!--@if($dep->need_update)--> ({$lang->require_update})<!--@end--> <!--@else-->{$lang->require_installation}<!--@end-->
<!--@if($dep->need_update || !$dep->installed)--><a href="http://download.xpressengine.com/?module=resourceapi&act=procResourceapiDownload&package_srl={$dep->package_srl}">{$lang->download}</a> ({$lang->path} : {$dep->path})<!--@end-->
</dd>
</dl>
<!--@end-->
<!--@if($show_ftp_note)-->
<p class="warning">{$lang->description_download}. (<a href="{getUrl('','module','admin','act','dispAdminConfig')}#ftpSetup">FTP Setup</a>) </p>
<p>{$lang->path} : {$package->path}</p>
<p><a href="http://download.xpressengine.com/?module=resourceapi&act=procResourceapiDownload&package_srl={$package->package_srl}" class="button large green strong"><span>{$lang->download}</span></a></p>
<!--@else-->
<p>{$lang->description_install}. </p>
<p><!--@if(!$package->installed || $package->need_update)--><a href="#" onclick="doInstallPackage('{$package->package_srl}')" class="button large green strong"><span>{$lang->install}</span></a><!--@end--></p>
<!--@end-->
</div>

View file

@ -0,0 +1,26 @@
function completeUpdate(ret_obj) {
alert(ret_obj['message']);
location.reload();
}
function doUpdate() {
var params = new Array();
exec_xml('autoinstall', 'procAutoinstallAdminUpdateinfo', params, completeUpdate);
}
function doInstallPackage(package_srl) {
var params = new Array();
params['package_srl'] = package_srl;
exec_xml('autoinstall', 'procAutoinstallAdminPackageinstall', params, completeInstall);
}
function completeUpdateNoMsg(ret_obj) {
location.reload();
}
function completeInstall(ret_obj) {
alert(ret_obj['message']);
var params = new Array();
exec_xml('autoinstall', 'procAutoinstallAdminUpdateinfo', params, completeUpdateNoMsg);
}

View file

@ -0,0 +1,47 @@
<div class="aside">
<div class="categoryBox">
<h3><a href="{getUrl('category_srl','')}">{$lang->view_all_package}</a> <span>({$tCount})</span></h3>
{@ $_pDepth = 0;}
<ul class="category">
<!--@foreach($categories as $key => $val)-->
<!--@if($_pDepth > $val->depth)-->
<!--@for($i=$val->depth; $i<$_pDepth; $i++)-->
</ul>
</li>
<!--@end-->
{@ $_pDepth = $val->depth}
<!--@end-->
<li>
<!--@if(count($val->children))-->
<a href="{getUrl('category_srl',$val->category_srl,'childrenList',$val->childrenList)}"<!--@if($val->category_srl == $category_srl)--> class="selected"<!--@end-->>{$val->title}</a>
<!--@else-->
<a href="{getUrl('category_srl',$val->category_srl,'childrenList','')}"<!--@if($val->category_srl == $category_srl)--> class="selected"<!--@end-->>{$val->title}</a>
<!--@end-->
<!--@if($val->nPackages)-->
<span>({$val->nPackages})</span>
<!--@end-->
<!--@if(count($val->children))-->
{@$_pDepth++}
<ul class="category">
<!--@else-->
</li>
<!--@end-->
<!--@end-->
<!--@for($i=0;$i<$_pDepth;$i++)-->
</ul>
<!--@end-->
</li>
</ul>
<div class="searchBox">
<form action="{getUrl()}" method="get">
<input type="hidden" name="category_srl" value="{$category_srl}" />
<input type="hidden" name="module" value="admin" />
<input type="hidden" name="act" value="dispAutoinstallAdminIndex" />
<input type="text" name="search_keyword" value="{htmlspecialchars($search_keyword)}" class="input" />
<input type="image" src="./img/btn_search.gif" class="submit" />
</form>
</div>
</div>
</div>

View file

@ -0,0 +1,79 @@
<div class="content">
<ul class="listOrder {$order_type}">
<!--@if($order_target=='newest')-->
<!--@if($order_type == 'desc')-->{@$_order_type = 'asc'}<!--@else-->{@$_order_type = 'desc'}<!--@end-->
<!--@else-->
{@$_order_type = 'desc'}
<!--@end-->
<li <!--@if($order_target=='newest')-->class="arrow"<!--@end-->><a href="{getUrl('order_target','newest','order_type',$_order_type)}">{$lang->order_newest}</a></li>
<!--@if($order_target=='download')-->
<!--@if($order_type == 'desc')-->{@$_order_type = 'asc'}<!--@else-->{@$_order_type = 'desc'}<!--@end-->
<!--@else-->
{@$_order_type = 'desc'}
<!--@end-->
<li <!--@if($order_target=='download')-->class="arrow"<!--@end-->><a href="{getUrl('order_target','download','order_type',$_order_type)}">{$lang->order_download}</a></li>
<!--@if($order_target=='popular')-->
<!--@if($order_type == 'desc')-->{@$_order_type = 'asc'}<!--@else-->{@$_order_type = 'desc'}<!--@end-->
<!--@else-->
{@$_order_type = 'desc'}
<!--@end-->
<li <!--@if($order_target=='popular')-->class="arrow"<!--@end-->><a href="{getUrl('order_target','popular','order_type',$_order_type)}">{$lang->order_popular}</a></li>
</ul>
<table class="updateList" border="1" cellspacing="0">
<col width="120" /><col />
<!--@foreach($item_list as $key => $val)-->
<tr>
{@ $target_url = $original_site."?mid=download&package_srl=".$val->package_srl; }
<th><a href="{$target_url}"><img src="{str_replace('./', $uri, $val->item_screenshot_url)}" width="100" height="100" alt="" /></a></th>
<td>
<div class="title">
<h3>
<!--@if($val->category_srl)-->
<a href="{getUrl('category_srl',$val->category_srl)}">[{$categories[$val->category_srl]->title}]</a>
<!--@end-->
<a href="{$target_url}">{htmlspecialchars($val->title)} ver. {htmlspecialchars($val->item_version)}</a>
</h3>
<!--@if($val->current_version)-->
{$lang->current_version} : {$val->current_version}
<!--@if($val->need_update == 'Y')-->
<a href="{getUrl('act','dispAutoinstallAdminInstall','package_srl',$val->package_srl)}" class="button"><span>{$lang->update}</span></a>
<!--@end-->
<!--@else-->
<a href="{getUrl('act','dispAutoinstallAdminInstall','package_srl',$val->package_srl)}" class="button"><span>{$lang->install}</span></a>
<!--@end-->
</div>
<div class="info">
<p class="desc">{cut_str(htmlspecialchars($val->package_description),200)}</p>
<p class="meta">
<span class="reputation">
<!--@for($i=0;$i<5;$i++)-->
<!--@if($i<$val->package_star)-->
<img src="./img/starOn.gif" alt="" />
<!--@else-->
<img src="./img/starOff.gif" alt="" />
<!--@end-->
<!--@end-->
<span>{sprintf("%0.1f",$val->package_voted/$val->package_voter*2)}/{number_format($val->package_voter)}</span>
</span>
<span class="lastUpdate">{$lang->package_update} {zdate($val->item_regdate, "Y-m-d H:i")}</span>
<span class="download">{$lang->package_downloaded_count} : {number_format($val->package_downloaded)}</span>
</p>
</div>
</td>
</tr>
<!--@end-->
</table>
<div class="pagination a1">
<a href="{getUrl('page','')}" class="prevEnd">{$lang->first_page}</a>
<!--@while($page_no = $page_navigation->getNextPage())-->
<!--@if($page == $page_no)-->
<strong>{$page_no}</strong>
<!--@else-->
<a href="{getUrl('page',$page_no)}">{$page_no}</a>
<!--@end-->
<!--@end-->
<a href="{getUrl('page',$page_navigation->last_page)}" class="nextEnd">{$lang->last_page}</a>
</div>
</div>

View file

@ -7,7 +7,7 @@
$lang->cmd_comment_do = '将把此评论..'; $lang->cmd_comment_do = '将把此评论..';
$lang->comment_list = '评论目录'; $lang->comment_list = '评论列表';
$lang->cmd_toggle_checked_comment = '反选'; $lang->cmd_toggle_checked_comment = '反选';
$lang->cmd_delete_checked_comment = '删除所选'; $lang->cmd_delete_checked_comment = '删除所选';

View file

@ -33,7 +33,7 @@
$lang->cmd_view_friend = '友達リスト'; $lang->cmd_view_friend = '友達リスト';
$lang->cmd_add_friend = '友達登録'; $lang->cmd_add_friend = '友達登録';
$lang->cmd_view_message_box = 'メッセージ'; $lang->cmd_view_message_box = 'メッセージ';
$lang->cmd_store = "保存"; $lang->cmd_store = '保存';
$lang->cmd_add_friend_group = '友達グループ追加'; $lang->cmd_add_friend_group = '友達グループ追加';
$lang->cmd_rename_friend_group = '友達グループ名変更'; $lang->cmd_rename_friend_group = '友達グループ名変更';

View file

@ -32,7 +32,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<span class="member_{$message->sender_srl}">{$message->nick_name}</span> ({$message->user_id}) <span class="member_{$message->member_srl}">{$message->nick_name}</span> ({$message->user_id})
<span class="regdate">{zdate($message->regdate, "Y.m.d H:i:s")}</span> <span class="regdate">{zdate($message->regdate, "Y.m.d H:i:s")}</span>
</td> </td>
</tr> </tr>

View file

@ -1287,7 +1287,8 @@
'header("Cache-Control: post-check=0, pre-check=0", false); '. 'header("Cache-Control: post-check=0, pre-check=0", false); '.
'header("Pragma: no-cache"); '. 'header("Pragma: no-cache"); '.
'%s'. '%s'.
'%s'. '%s '.
'$oContext->close();'.
'?>'. '?>'.
'<root>%s</root>', '<root>%s</root>',
$header_script, $header_script,

View file

@ -5,12 +5,11 @@
* @brief 文章(document)模块语言包 * @brief 文章(document)模块语言包
**/ **/
$lang->document_list = '主题目录'; $lang->document_list = '主题列表';
$lang->thumbnail_type = '缩略图生成方式'; $lang->thumbnail_type = '缩略图生成方式';
$lang->thumbnail_crop = '裁减'; $lang->thumbnail_crop = '裁减(按指定大小裁剪图片)';
$lang->thumbnail_ratio = '比例'; $lang->thumbnail_ratio = '比例(按原图比例缩略处理)';
$lang->cmd_delete_all_thumbnail = '删除全部缩略图'; $lang->cmd_delete_all_thumbnail = '删除全部缩略图';
$lang->move_target_module = "移动目标模块";
$lang->title_bold = '粗标题'; $lang->title_bold = '粗标题';
$lang->title_color = '标题颜色'; $lang->title_color = '标题颜色';
$lang->new_document_count = '新帖'; $lang->new_document_count = '新帖';
@ -20,8 +19,10 @@
$lang->category_color = '分类颜色'; $lang->category_color = '分类颜色';
$lang->expand = '展开'; $lang->expand = '展开';
$lang->category_group_srls = '用户组'; $lang->category_group_srls = '用户组';
$lang->cmd_make_child = '添加下级分类'; $lang->cmd_make_child = '添加下级分类';
$lang->cmd_enable_move_category = "分类顺序(勾选后用鼠标拖动分类项)"; $lang->cmd_enable_move_category = "分类顺序(勾选后用鼠标拖动分类项)";
$lang->about_category_title = '请输入分类名。'; $lang->about_category_title = '请输入分类名。';
$lang->about_expand = '选择此项将维持展开状态。'; $lang->about_expand = '选择此项将维持展开状态。';
$lang->about_category_group_srls = '所选用户组才可以查看此分类。'; $lang->about_category_group_srls = '所选用户组才可以查看此分类。';
@ -40,6 +41,8 @@
$lang->msg_is_secret = '这是密帖!'; $lang->msg_is_secret = '这是密帖!';
$lang->msg_checked_document_is_deleted = '删除了%d个文章。'; $lang->msg_checked_document_is_deleted = '删除了%d个文章。';
$lang->move_target_module = '目标模块';
// 管理页面查找的对象 // 管理页面查找的对象
$lang->search_target_list = array( $lang->search_target_list = array(
'title' => '标题', 'title' => '标题',
@ -62,8 +65,34 @@
'last_update' => '最近更新日期', 'last_update' => '最近更新日期',
'ipaddress' => 'IP 地址', 'ipaddress' => 'IP 地址',
); );
$lang->alias = "Alias"; $lang->alias = "Alias";
$lang->history = "编辑记录"; $lang->history = "编辑记录";
$lang->about_use_history = "设置启用编辑记录与否。启用将记录修改主题版本,并可以复原。"; $lang->about_use_history = "设置启用编辑记录与否。启用将记录修改主题版本,并可以复原。";
$lang->trace_only = "只留痕迹"; $lang->trace_only = "只留痕迹";
$lang->cmd_trash = "回收箱";
$lang->cmd_restore = "复原";
$lang->cmd_restore_all = "全部复原";
$lang->in_trash = "回收箱";
$lang->trash_nick_name = "操作人昵称";
$lang->trash_date = "删除日期";
$lang->trash_description = "说明";
// 管理页面回收箱搜索对象
$lang->search_target_trash_list = array(
'title' => '标题',
'content' => '内容',
'user_id' => '用户名',
'member_srl' => '会员编号',
'user_name' => '姓名',
'nick_name' => '昵称',
'trash_member_srl' => '操作人会员编号',
'trash_user_name' => '操作人用户名',
'trash_nick_name' => '操作人昵称',
'trash_date' => '删除日期',
'trash_ipaddress' => '操作人IP地址',
);
?> ?>

Some files were not shown because too many files have changed in this diff Show more