merge brache 1.5.0 to trunk (8252-9866)

git-svn-id: http://xe-core.googlecode.com/svn/trunk@9867 201d5d3c-b55e-5fd7-737f-ddc643e51545
This commit is contained in:
flyskyko 2011-11-24 00:02:10 +00:00
commit 2f4b847ae2
2419 changed files with 179593 additions and 181010 deletions

View file

@ -9,7 +9,7 @@ RewriteRule ^(modules|addons|widgets)/(.+)/(conf|queries|schemas)/(.+)\.xml$ ./i
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(.+)/files/(member_extra_info|attach|cache|faceOff)/(.*) ./files/$2/$3 [L]
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(.+)/(files|modules|common|widgets|widgetstyles|layouts|m.layouts|addons)/(.*) ./$2/$3 [L]
RewriteRule ^(.+)/(files|modules|widgets|widgetstyles|layouts|m.layouts|addons)/(.*) ./$2/$3 [L]
# rss , blogAPI
RewriteRule ^(rss|atom)$ ./index.php?module=rss&act=$1 [L]
@ -24,22 +24,22 @@ RewriteRule ^([a-zA-Z0-9_]+)/([0-9]+)/(.+)/trackback$ ./index.php?vid=$1&documen
RewriteRule ^admin/?$ ./index.php?module=admin [L]
# document permanent link
RewriteRule ^([0-9]+)$ ./index.php?document_srl=$1 [L]
RewriteRule ^([0-9]+)$ ./index.php?document_srl=$1 [L,QSA]
# mid link
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_]+)/?$ ./index.php?mid=$1 [L]
RewriteRule ^([a-zA-Z0-9_]+)/?$ ./index.php?mid=$1 [L,QSA]
# mid + document link
RewriteRule ^([a-zA-Z0-9_]+)/([0-9]+)$ ./index.php?mid=$1&document_srl=$2 [L]
RewriteRule ^([a-zA-Z0-9_]+)/([0-9]+)$ ./index.php?mid=$1&document_srl=$2 [L,QSA]
# vid + mid link
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/?$ ./index.php?vid=$1&mid=$2 [L]
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/?$ ./index.php?vid=$1&mid=$2 [L,QSA]
# vid + mid + document link
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([0-9]+)$ ./index.php?vid=$1&mid=$2&document_srl=$3 [L]
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([0-9]+)$ ./index.php?vid=$1&mid=$2&document_srl=$3 [L,QSA]
# mid + entry title
RewriteRule ^([a-zA-Z0-9_]+)/entry/(.+)$ ./index.php?mid=$1&entry=$2 [L]
RewriteRule ^([a-zA-Z0-9_]+)/entry/(.+)$ ./index.php?mid=$1&entry=$2 [L,QSA]
# vid + mid + entry title
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/entry/(.+)$ ./index.php?vid=$1&mid=$2&entry=$3 [L]
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/entry/(.+)$ ./index.php?vid=$1&mid=$2&entry=$3 [L,QSA]

View file

@ -0,0 +1,17 @@
<?php
if(!defined('__XE__')) exit();
/**
* @file adminlogging.addon.php
* @author NHN (developers@xpressengine.com)
* @brief Automatic link add-on
**/
$logged_info = Context::get('logged_info');
$act = Context::get('act');
$kind = strpos(strtolower($act),'admin')!==false?'admin':'';
if($called_position == 'before_module_proc' && $kind == 'admin' && $logged_info->is_admin == 'Y') {
$oAdminloggingController = &getController('adminlogging');
$oAdminloggingController->insertLog($this->module, $this->act);
}
?>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">어드민 메뉴 접근 로깅</title>
<title xml:lang="en">admin menu access logging</title>
<description xml:lang="ko">
admin menu에 접근한 기록을 로깅하는 애드온입니다.
</description>
<version>0.1</version>
<date>2011-09-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>

View file

@ -1,12 +1,12 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file autolink.addon.php
* @author NHN (developers@xpressengine.com)
* @brief 자동 링크 애드온
**/
if($called_position == 'after_module_proc' && Context::getResponseMethod()!="XMLRPC") {
Context::addJsFile('./addons/autolink/autolink.js', false ,'', null, 'body');
}
?>
<?php
if(!defined('__XE__')) exit();
/**
* @file autolink.addon.php
* @author NHN (developers@xpressengine.com)
* @brief Automatic link add-on
**/
if($called_position == 'after_module_proc' && Context::getResponseMethod()!="XMLRPC") {
Context::loadFile(array('./addons/autolink/autolink.js', 'body', '', null), true);
}
?>

View file

@ -1,80 +1,80 @@
/**
* @file autolink.js
* @brief javascript code for autolink addon
* @author NHN (developers@xpressengine.com)
*/
(function($){
var protocol_re = '(https?|ftp|news|telnet|irc|mms)://';
var domain_re = '(?:[\\w\\-]+\\.)+(?:[a-z]+)';
var max_255_re = '(?:1[0-9]{2}|2[0-4][0-9]|25[0-5]|[1-9]?[0-9])';
var ip_re = '(?:'+max_255_re+'\\.){3}'+max_255_re;
var port_re = '(?::([0-9]+))?';
var user_re = '(?:/~[\\w-]+)?';
var path_re = '((?:/[\\w!"$-/:-@]+)*)';
var hash_re = '(?:#([\\w!-@]+))?';
var url_regex = new RegExp('('+protocol_re+'('+domain_re+'|'+ip_re+'|localhost'+')'+port_re+user_re+path_re+hash_re+')', 'ig');
var AutoLink = xe.createPlugin("autolink", {
targets : [],
init : function() {
this.targets = [];
},
API_ONREADY : function() {
var thisPlugin = this;
// extract target text nodes
this.extractTargets($('.xe_content'));
$(this.targets).each(function(){
thisPlugin.cast('AUTOLINK', [this]);
});
},
API_AUTOLINK : function(oSender, params) {
var textNode = params[0];
if(!$(textNode).parent().length || $(textNode).parent().get(0).nodeName.toLowerCase() == 'a') return;
var content = textNode.nodeValue;
var dummy = $('<span>');
content = content.replace(/</g, '&lt;').replace(/>/g, '&gt;');
content = content.replace(url_regex, '<a href="$1" target="_blank">$1</a>');
$(textNode).before(dummy);
$(textNode).replaceWith(content);
params[0] = dummy.next('a');
dummy.remove();
},
extractTargets : function(obj) {
var thisPlugin = this;
var wrap = $('.xe_content', obj);
if(wrap.length) {
this.extractTargets(wrap);
return;
}
$(obj)
.contents()
.each(function(){
var node_name = this.nodeName.toLowerCase();
if($.inArray(node_name, ['a', 'pre', 'xml', 'textarea', 'input', 'select', 'option', 'code', 'script', 'style', 'iframe', 'button', 'img', 'embed', 'object', 'ins']) != -1) return;
// FIX ME : When this meanless code wasn't executed, url_regex do not run correctly. why?
url_regex.exec('');
if(this.nodeType == 3) { // text node
var content = this.nodeValue;
if(content.length < 5) return;
if(!/(http|https|ftp|news|telnet|irc|mms):\/\//i.test(content)) return;
thisPlugin.targets.push(this);
} else {
thisPlugin.extractTargets(this);
}
});
}
});
xe.registerPlugin(new AutoLink());
/**
* @file autolink.js
* @brief javascript code for autolink addon
* @author NHN (developers@xpressengine.com)
*/
(function($){
var protocol_re = '(https?|ftp|news|telnet|irc|mms)://';
var domain_re = '(?:[\\w\\-]+\\.)+(?:[a-z]+)';
var max_255_re = '(?:1[0-9]{2}|2[0-4][0-9]|25[0-5]|[1-9]?[0-9])';
var ip_re = '(?:'+max_255_re+'\\.){3}'+max_255_re;
var port_re = '(?::([0-9]+))?';
var user_re = '(?:/~[\\w-]+)?';
var path_re = '((?:/[\\w!"$-/:-@]+)*)';
var hash_re = '(?:#([\\w!-@]+))?';
var url_regex = new RegExp('('+protocol_re+'('+domain_re+'|'+ip_re+'|localhost'+')'+port_re+user_re+path_re+hash_re+')', 'ig');
var AutoLink = xe.createPlugin("autolink", {
targets : [],
init : function() {
this.targets = [];
},
API_ONREADY : function() {
var thisPlugin = this;
// extract target text nodes
this.extractTargets($('.xe_content'));
$(this.targets).each(function(){
thisPlugin.cast('AUTOLINK', [this]);
});
},
API_AUTOLINK : function(oSender, params) {
var textNode = params[0];
if(!$(textNode).parent().length || $(textNode).parent().get(0).nodeName.toLowerCase() == 'a') return;
var content = textNode.nodeValue;
var dummy = $('<span>');
content = content.replace(/</g, '&lt;').replace(/>/g, '&gt;');
content = content.replace(url_regex, '<a href="$1" target="_blank">$1</a>');
$(textNode).before(dummy);
$(textNode).replaceWith(content);
params[0] = dummy.next('a');
dummy.remove();
},
extractTargets : function(obj) {
var thisPlugin = this;
var wrap = $('.xe_content', obj);
if(wrap.length) {
this.extractTargets(wrap);
return;
}
$(obj)
.contents()
.each(function(){
var node_name = this.nodeName.toLowerCase();
if($.inArray(node_name, ['a', 'pre', 'xml', 'textarea', 'input', 'select', 'option', 'code', 'script', 'style', 'iframe', 'button', 'img', 'embed', 'object', 'ins']) != -1) return;
// FIX ME : When this meanless code wasn't executed, url_regex do not run correctly. why?
url_regex.exec('');
if(this.nodeType == 3) { // text node
var content = this.nodeValue;
if(content.length < 5) return;
if(!/(http|https|ftp|news|telnet|irc|mms):\/\//i.test(content)) return;
thisPlugin.targets.push(this);
} else {
thisPlugin.extractTargets(this);
}
});
}
});
xe.registerPlugin(new AutoLink());
})(jQuery);

View file

@ -1,53 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">자동 링크 애드온</title>
<title xml:lang="jp">自動リンクアドオン</title>
<title xml:lang="en">Auto Link</title>
<title xml:lang="vi">Auto Link</title>
<title xml:lang="zh-CN">自动链接插件</title>
<title xml:lang="es">auto vínculo addon</title>
<title xml:lang="ru">авто ссылка аддон</title>
<title xml:lang="ge">Auto-Link Addon</title>
<title xml:lang="zh-TW">自動連結</title>
<description xml:lang="ko">
글과 댓글의 내용 중 URL 문자열에 링크를 걸어주는 애드온입니다.
</description>
<description xml:lang="jp">
書き込み本文とコメントに登録された内容の中、httpで始まる一般文字列に自動にリンクを貼り付け、そのリンクにマウスオーバすると、別ウィンドウ、または同一ウィンドウに開くメニュが現れるアドオンです。
</description>
<description xml:lang="en">
This addon makes a link to a string that starts with http.
</description>
<description xml:lang="vi">
Addon này sẽ tự động tạo ra một đường Link khi gặp chuỗi kí tự 'http' có trong bài viết.
</description>
<description xml:lang="zh-CN">
主题及评论中以http开始的字符串自动转换为链接。并且鼠标移到链接上方时将出现可选(新窗/本页面)提示框。
</description>
<description xml:lang="es">
Los comentarios que comienzan con http naeyongjung tema común de la cadena para vincular automáticamente a colgar el puntero del ratón sobre cada uno de los vínculos y saechang Ciudad y aparecen en el menú de add-on de decoración.
</description>
<description xml:lang="ru">
Комментарии, которые начинаются с http naeyongjung темой общей строки автоматически ссылку повесить мышь над каждой ссылке и saechang Сити и появляться на меню добавить-на украшения.
</description>
<description xml:lang="ge">
Kommentare beginnen mit http naeyongjung Thema der gemeinsamen String automatisch Link zu hängen Sie mit der Maus über die einzelnen Links und saechang Stadt und auf dem Menü des Add-On Dekoration.
</description>
<description xml:lang="zh-TW">
是種可將主題和評論內容中的URL網址字串自動轉換成連結的附加元件。
</description>
<version>0.1</version>
<date>2008-04-22</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">자동 링크 애드온</title>
<title xml:lang="jp">自動リンクアドオン</title>
<title xml:lang="en">Auto Link Addon</title>
<title xml:lang="vi">Auto Link</title>
<title xml:lang="zh-CN">自动链接插件</title>
<title xml:lang="es">auto vínculo addon</title>
<title xml:lang="ru">Аддон авто-ссылки</title>
<title xml:lang="ge">Auto-Link Addon</title>
<title xml:lang="zh-TW">自動連結</title>
<description xml:lang="ko">
글과 댓글의 내용 중 URL 문자열에 링크를 걸어주는 애드온입니다.
</description>
<description xml:lang="jp">
書き込み本文とコメントに登録された内容の中、httpで始まる一般文字列に自動にリンクを貼り付け、そのリンクにマウスオーバすると、別ウィンドウ、または同一ウィンドウに開くメニュが現れるアドオンです。
</description>
<description xml:lang="en">
This addon automatically transforms text URLs encountered in posts and comments into linkable URLs.
</description>
<description xml:lang="vi">
Addon này sẽ tự động tạo ra một đường Link khi gặp chuỗi kí tự 'http' có trong bài viết.
</description>
<description xml:lang="zh-CN">
主题及评论中以http开始的字符串自动转换为链接。并且鼠标移到链接上方时将出现可选(新窗/本页面)提示框。
</description>
<description xml:lang="es">
Los comentarios que comienzan con http naeyongjung tema común de la cadena para vincular automáticamente a colgar el puntero del ratón sobre cada uno de los vínculos y saechang Ciudad y aparecen en el menú de add-on de decoración.
</description>
<description xml:lang="ru">
Этот аддон-дополнение переводит все неактивные ссылки, которые встречаются в статьях и комментариях, в рабочие ссылки.
</description>
<description xml:lang="ge">
Kommentare beginnen mit http naeyongjung Thema der gemeinsamen String automatisch Link zu hängen Sie mit der Maus über die einzelnen Links und saechang Stadt und auf dem Menü des Add-On Dekoration.
</description>
<description xml:lang="zh-TW">
是種可將主題和評論內容中的URL網址字串自動轉換成連結的附加元件。
</description>
<version>0.1</version>
<date>2008-04-22</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>

View file

@ -1,468 +1,435 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file blogapicounter.addon.php
* @author NHN (developers@xpressengine.com)
* @brief blogAPI 애드온
*
* ms live writer, 파이어폭스의 performancing, zoundry 등의 외부 툴을 이용하여 글을 입력할 있게 합니다.
* 모듈 실행 이전(before_module_proc) 호출이 되어야 하며 정상동작후에는 강제 종료를 한다.
**/
// called_position가 after_module_proc일때 rsd 태그 삽입
if($called_position == 'after_module_proc') {
// 현재 모듈의 rsd주소를 만듬
$site_module_info = Context::get('site_module_info');
$rsd_url = getFullSiteUrl($site_module_info->domain, '', 'mid',$site_module_info->mid, 'act','api');
// 헤더에 rsd태그 삽입
Context::addHtmlHeader(" ".'<link rel="EditURI" type="application/rsd+xml" title="RSD" href="'.$rsd_url.'" />');
}
// act가 api가 아니면 그냥 리턴~
if($_REQUEST['act']!='api') return;
// 관련 func 파일 읽음
require_once('./addons/blogapi/blogapi.func.php');
// xmlprc 파싱
// 요청된 xmlrpc를 파싱
$oXmlParser = new XmlParser();
$xmlDoc = $oXmlParser->parse();
$method_name = $xmlDoc->methodcall->methodname->body;
$params = $xmlDoc->methodcall->params->param;
if($params && !is_array($params)) $params = array($params);
// 일부 methodname에 대한 호환
if(in_array($method_name, array('metaWeblog.deletePost', 'metaWeblog.getUsersBlogs', 'metaWeblog.getUserInfo'))) {
$method_name = str_replace('metaWeblog.', 'blogger.', $method_name);
}
// blogger.deletePost일 경우 첫번째 인자 값 삭제
if($method_name == 'blogger.deletePost') array_shift($params);
// user_id, password를 구해서 로그인 시도
$user_id = trim($params[1]->value->string->body);
$password = trim($params[2]->value->string->body);
// 모듈 실행전이라면 인증을 처리한다.
if($called_position == 'before_module_init') {
// member controller을 이용해서 로그인 시도
if($user_id && $password) {
$oMemberController = &getController('member');
$output = $oMemberController->doLogin($user_id, $password);
// 로그인 실패시 에러 메시지 출력
if(!$output->toBool()) {
$content = getXmlRpcFailure(1, $output->getMessage());
printContent($content);
}
} else {
$content = getXmlRpcFailure(1, 'not logged');
printContent($content);
}
}
// 모듈에서 무언가 작업을 하기 전에 blogapi tool의 요청에 대한 처리를 하고 강제 종료한다.
if($called_position == 'before_module_proc') {
// 글쓰기 권한 체크 (권한명의 경우 약속이 필요할듯..)
if(!$this->grant->write_document) {
printContent( getXmlRpcFailure(1, 'no permission') );
}
// 카테고리의 정보를 구해옴
$oDocumentModel = &getModel('document');
$category_list = $oDocumentModel->getCategoryList($this->module_srl);
// 임시 파일 저장 장소 지정
$tmp_uploaded_path = sprintf('./files/cache/blogapi/%s/%s/', $this->mid, $user_id);
$uploaded_target_path = sprintf('/files/cache/blogapi/%s/%s/', $this->mid, $user_id);
switch($method_name) {
// 블로그 정보
case 'blogger.getUsersBlogs' :
$obj->url = getFullSiteUrl('');
$obj->blogid = $this->mid;
$obj->blogName = $this->module_info->browser_title;
$blog_list = array($obj);
$content = getXmlRpcResponse($blog_list);
printContent($content);
break;
// 카테고리 목록 return
case 'metaWeblog.getCategories' :
$category_obj_list = array();
if($category_list) {
foreach($category_list as $category_srl => $category_info) {
unset($obj);
$obj->description = $category_info->title;
//$obj->htmlUrl = Context::getRequestUri().$this->mid.'/1';
//$obj->rssUrl= Context::getRequestUri().'rss/'.$this->mid.'/1';
$obj->title = $category_info->title;
$obj->categoryid = $category_srl;
$category_obj_list[] = $obj;
}
}
$content = getXmlRpcResponse($category_obj_list);
printContent($content);
break;
// 파일 업로드
case 'metaWeblog.newMediaObject' :
// 파일 업로드 권한 체크
$oFileModel = &getModel('file');
$file_module_config = $oFileModel->getFileModuleConfig($this->module_srl);
if(is_array($file_module_config->download_grant) && count($file_module_config->download_grant)>0) {
$logged_info = Context::get('logged_info');
if($logged_info->is_admin != 'Y') {
$is_permitted = false;
for($i=0;$i<count($file_module_config->download_grant);$i++) {
$group_srl = $file_module_config->download_grant[$i];
if($logged_info->group_list[$group_srl]) {
$is_permitted = true;
break;
}
}
if(!$is_permitted) printContent( getXmlRpcFailure(1, 'no permission') );
}
}
$fileinfo = $params[3]->value->struct->member;
foreach($fileinfo as $key => $val) {
$nodename = $val->name->body;
if($nodename == 'bits') $filedata = base64_decode($val->value->base64->body);
elseif($nodename == 'name') $filename = $val->value->string->body;
}
$tmp_arr = explode('/',$filename);
$filename = array_pop($tmp_arr);
if(!is_dir($tmp_uploaded_path)) FileHandler::makeDir($tmp_uploaded_path);
$target_filename = sprintf('%s%s', $tmp_uploaded_path, $filename);
FileHandler::writeFile($target_filename, $filedata);
$obj->url = Context::getRequestUri().$target_filename;
$content = getXmlRpcResponse($obj);
printContent($content);
break;
// 글 가져오기
case 'metaWeblog.getPost' :
$document_srl = $params[0]->value->string->body;
if(!$document_srl) {
printContent( getXmlRpcFailure(1, 'no permission') );
} else {
$oDocumentModel = &getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl);
if(!$oDocument->isExists() || !$oDocument->isGranted()) {
printContent( getXmlRpcFailure(1, 'no permission') );
} else {
// 카테고리를 사용하는지 확인후 사용시 카테고리 목록을 구해와서 Context에 세팅
$category = "";
if($oDocument->get('category_srl')) {
$oDocumentModel = &getModel('document');
$category_list = $oDocumentModel->getCategoryList($oDocument->get('module_srl'));
if($category_list[$oDocument->get('category_srl')]) {
$category = $category_list[$oDocument->get('category_srl')]->title;
}
}
$content = sprintf(
'<?xml version="1.0" encoding="utf-8"?>'.
'<methodResponse>'.
'<params>'.
'<param>'.
'<value>'.
'<struct>'.
'<member><name>categories</name><value><array><data><value><![CDATA[%s]]></value></data></array></value></member>'.
'<member><name>dateCreated</name><value><dateTime.iso8601>%s</dateTime.iso8601></value></member>'.
'<member><name>description</name><value><![CDATA[%s]]></value></member>'.
'<member><name>link</name><value>%s</value></member>'.
'<member><name>postid</name><value><string>%s</string></value></member>'.
'<member><name>title</name><value><![CDATA[%s]]></value></member>'.
'<member><name>publish</name><value><boolean>1</boolean></value></member>'.
'</struct>'.
'</value>'.
'</param>'.
'</params>'.
'</methodResponse>',
$category,
date("Ymd", $oDocument->getRegdateTime()).'T'.date("H:i:s", $oDocument->getRegdateTime()),
$oDocument->getContent(false, false, true,false),
getFullUrl('','document_srl', $oDocument->document_srl),
$oDocument->document_srl,
$oDocument->getTitleText()
);
printContent($content);
}
}
break;
// 글작성
case 'metaWeblog.newPost' :
unset($obj);
$info = $params[3];
// 글, 제목, 카테고리 정보 구함
for($i=0;$i<count($info->value->struct->member);$i++) {
$val = $info->value->struct->member[$i];
switch($val->name->body) {
case 'title' :
$obj->title = $val->value->string->body;
break;
case 'description' :
$obj->content = $val->value->string->body;
break;
case 'categories' :
$categories = $val->value->array->data->value;
if(!is_array($categories)) $categories = array($categories);
$category = $categories[0]->string->body;
if($category && $category_list) {
foreach($category_list as $category_srl => $category_info) {
if($category_info->title == $category) $obj->category_srl = $category_srl;
}
}
break;
case 'tagwords' :
$tags = $val->value->array->data->value;
if(!is_array($tags)) $tags = array($tags);
for($j=0;$j<count($tags);$j++) {
$tag_list[] = $tags[$j]->string->body;
}
if(count($tag_list)) $obj->tags = implode(',',$tag_list);
break;
}
}
// 문서 번호 설정
$document_srl = getNextSequence();
$obj->document_srl = $document_srl;
$obj->module_srl = $this->module_srl;
// 첨부파일 정리
if(is_dir($tmp_uploaded_path)) {
$file_list = FileHandler::readDir($tmp_uploaded_path);
$file_count = count($file_list);
if($file_count) {
$oFileController = &getController('file');
for($i=0;$i<$file_count;$i++) {
$file_info['tmp_name'] = sprintf('%s%s', $tmp_uploaded_path, $file_list[$i]);
$file_info['name'] = $file_list[$i];
$oFileController->insertFile($file_info, $this->module_srl, $document_srl, 0, true);
}
$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);
$oDocumentController = &getController('document');
$obj->allow_comment = 'Y';
$obj->allow_trackback = 'Y';
$output = $oDocumentController->insertDocument($obj);
if(!$output->toBool()) {
$content = getXmlRpcFailure(1, $output->getMessage());
} else {
$content = getXmlRpcResponse(strval($document_srl));
}
FileHandler::removeDir($tmp_uploaded_path);
printContent($content);
break;
// 글 수정
case 'metaWeblog.editPost' :
$tmp_val = $params[0]->value->string->body;
if(!$tmp_val) $tmp_val = $params[0]->value->i4->body;
if(!$tmp_val) {
$content = getXmlRpcFailure(1, 'no permission');
break;
}
$tmp_arr = explode('/', $tmp_val);
$document_srl = array_pop($tmp_arr);
if(!$document_srl) {
$content = getXmlRpcFailure(1, 'no permission');
break;
}
$oDocumentModel = &getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl);
// 글 수정 권한 체크
if(!$oDocument->isGranted()) {
$content = getXmlRpcFailure(1, 'no permission');
break;
}
$obj = $oDocument->getObjectVars();
$info = $params[3];
// 글, 제목, 카테고리 정보 구함
for($i=0;$i<count($info->value->struct->member);$i++) {
$val = $info->value->struct->member[$i];
switch($val->name->body) {
case 'title' :
$obj->title = $val->value->string->body;
break;
case 'description' :
$obj->content = $val->value->string->body;
break;
case 'categories' :
$categories = $val->value->array->data->value;
if(!is_array($categories)) $categories = array($categories);
$category = $categories[0]->string->body;
if($category && $category_list) {
foreach($category_list as $category_srl => $category_info) {
if($category_info->title == $category) $obj->category_srl = $category_srl;
}
}
break;
case 'tagwords' :
$tags = $val->value->array->data->value;
if(!is_array($tags)) $tags = array($tags);
for($j=0;$j<count($tags);$j++) {
$tag_list[] = $tags[$j]->string->body;
}
if(count($tag_list)) $obj->tags = implode(',',$tag_list);
break;
}
}
// 문서 번호 설정
$obj->document_srl = $document_srl;
$obj->module_srl = $this->module_srl;
// 첨부파일 정리
if(is_dir($tmp_uploaded_path)) {
$file_list = FileHandler::readDir($tmp_uploaded_path);
$file_count = count($file_list);
if($file_count) {
$oFileController = &getController('file');
for($i=0;$i<$file_count;$i++) {
$file_info['tmp_name'] = sprintf('%s%s', $tmp_uploaded_path, $file_list[$i]);
$file_info['name'] = $file_list[$i];
$moved_filename = sprintf('./files/attach/images/%s/%s/%s', $this->module_srl, $document_srl, $file_info['name']);
if(file_exists($moved_filename)) continue;
$oFileController->insertFile($file_info, $this->module_srl, $document_srl, 0, true);
}
$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);
$oDocumentController = &getController('document');
$output = $oDocumentController->updateDocument($oDocument,$obj);
if(!$output->toBool()) {
$content = getXmlRpcFailure(1, $output->getMessage());
} else {
$content = getXmlRpcResponse(true);
FileHandler::removeDir($tmp_uploaded_path);
}
printContent($content);
break;
// 글삭제
case 'blogger.deletePost' :
$tmp_val = $params[0]->value->string->body;
$tmp_arr = explode('/', $tmp_val);
$document_srl = array_pop($tmp_arr);
// 글 받아오기
$oDocumentModel = &getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl);
// 글 존재
if(!$oDocument->isExists()) {
$content = getXmlRpcFailure(1, 'not exists');
// 글 삭제 권한 체크
} elseif(!$oDocument->isGranted()) {
$content = getXmlRpcFailure(1, 'no permission');
break;
// 삭제
} else {
$oDocumentController = &getController('document');
$output = $oDocumentController->deleteDocument($document_srl);
if(!$output->toBool()) $content = getXmlRpcFailure(1, $output->getMessage());
else $content = getXmlRpcResponse(true);
}
printContent($content);
break;
// 최신글 받기
case 'metaWeblog.getRecentPosts' :
// 목록을 구하기 위한 옵션
$args->module_srl = $this->module_srl; ///< 현재 모듈의 module_srl
$args->page = 1;
$args->list_count = 20;
$args->sort_index = 'list_order'; ///< 소팅 값
$logged_info = Context::get('logged_info');
$args->search_target = 'member_srl';
$args->search_keyword = $logged_info->member_srl;
$output = $oDocumentModel->getDocumentList($args);
if(!$output->toBool() || !$output->data) {
$content = getXmlRpcFailure(1, 'post not founded');
printContent($content);
} else {
$oEditorController = &getController('editor');
$posts = array();
foreach($output->data as $key => $oDocument) {
$post = null;
$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->mt_allow_pings = 0;
$post->mt_allow_comments = $oDocument->allowComment()=='Y'?1:0;
$posts[] = $post;
}
$content = getXmlRpcResponse($posts);
printContent($content);
}
break;
// 아무런 요청이 없을 경우 RSD 출력
default :
$homepagelink = getUrl('','mid',$this->mid);
$site_module_info = Context::get('site_module_info');
$api_url = getFullSiteUrl($site_module_info->domain, '', 'mid',$site_module_info->mid, 'act','api');
$content = <<<RSDContent
<?xml version="1.0" ?>
<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd" >
<service>
<engineName>XpressEngine</engineName>
<engineLink>http://www.xpressengine.com/ </engineLink>
<homePageLink>{$homepagelink}</homePageLink>
<apis>
<api name="MetaWeblog" preferred="true" apiLink="{$api_url}" blogID="" />
</apis>
</service>
</rsd>
RSDContent;
printContent($content);
break;
}
}
?>
<?php
if(!defined('__XE__')) exit();
/**
* @file blogapicounter.addon.php
* @author NHN (developers@xpressengine.com)
* @brief Add blogAPI
*
* It enables to write a post by using an external tool such as ms live writer, firefox performancing, zoundry and so on.
* It should be called before executing the module(before_module_proc). If not, it is forced to shut down.
**/
// Insert a rsd tag when called_position is after_module_proc
if($called_position == 'after_module_proc') {
// Create rsd address of the current module
$site_module_info = Context::get('site_module_info');
$rsd_url = getFullSiteUrl($site_module_info->domain, '', 'mid',$site_module_info->mid, 'act','api');
// Insert rsd tag into the header
Context::addHtmlHeader(" ".'<link rel="EditURI" type="application/rsd+xml" title="RSD" href="'.$rsd_url.'" />');
}
// If act isnot api, just return
if($_REQUEST['act']!='api') return;
// Read func file
require_once('./addons/blogapi/blogapi.func.php');
// xmlprc parsing
// Parse the requested xmlrpc
$oXmlParser = new XmlParser();
$xmlDoc = $oXmlParser->parse();
$method_name = $xmlDoc->methodcall->methodname->body;
$params = $xmlDoc->methodcall->params->param;
if($params && !is_array($params)) $params = array($params);
// Compatible with some of methodname
if(in_array($method_name, array('metaWeblog.deletePost', 'metaWeblog.getUsersBlogs', 'metaWeblog.getUserInfo'))) {
$method_name = str_replace('metaWeblog.', 'blogger.', $method_name);
}
// Delete the first argument if it is blogger.deletePost
if($method_name == 'blogger.deletePost') array_shift($params);
// Get user_id, password and attempt log-in
$user_id = trim($params[1]->value->string->body);
$password = trim($params[2]->value->string->body);
// Before executing the module, authentication is processed.
if($called_position == 'before_module_init') {
// Attempt log-in by using member controller
if($user_id && $password) {
$oMemberController = &getController('member');
$output = $oMemberController->doLogin($user_id, $password);
// If login fails, an error message appears
if(!$output->toBool()) {
$content = getXmlRpcFailure(1, $output->getMessage());
printContent($content);
}
} else {
$content = getXmlRpcFailure(1, 'not logged');
printContent($content);
}
}
// Before module processing, handle requests from blogapi tool and then terminate.
if($called_position == 'before_module_proc') {
// Check writing permission
if(!$this->grant->write_document) {
printContent( getXmlRpcFailure(1, 'no permission') );
}
// Get information of the categories
$oDocumentModel = &getModel('document');
$category_list = $oDocumentModel->getCategoryList($this->module_srl);
// Specifies a temporary file storage
$tmp_uploaded_path = sprintf('./files/cache/blogapi/%s/%s/', $this->mid, $user_id);
$uploaded_target_path = sprintf('/files/cache/blogapi/%s/%s/', $this->mid, $user_id);
switch($method_name) {
// Blog information
case 'blogger.getUsersBlogs' :
$obj->url = getFullSiteUrl('');
$obj->blogid = $this->mid;
$obj->blogName = $this->module_info->browser_title;
$blog_list = array($obj);
$content = getXmlRpcResponse($blog_list);
printContent($content);
break;
// Return a list of categories
case 'metaWeblog.getCategories' :
$category_obj_list = array();
if($category_list) {
foreach($category_list as $category_srl => $category_info) {
unset($obj);
$obj->description = $category_info->title;
//$obj->htmlUrl = Context::getRequestUri().$this->mid.'/1';
//$obj->rssUrl= Context::getRequestUri().'rss/'.$this->mid.'/1';
$obj->title = $category_info->title;
$obj->categoryid = $category_srl;
$category_obj_list[] = $obj;
}
}
$content = getXmlRpcResponse($category_obj_list);
printContent($content);
break;
// Upload file
case 'metaWeblog.newMediaObject' :
// Check a file upload permission
$oFileModel = &getModel('file');
$file_module_config = $oFileModel->getFileModuleConfig($this->module_srl);
if(is_array($file_module_config->download_grant) && count($file_module_config->download_grant)>0) {
$logged_info = Context::get('logged_info');
if($logged_info->is_admin != 'Y') {
$is_permitted = false;
for($i=0;$i<count($file_module_config->download_grant);$i++) {
$group_srl = $file_module_config->download_grant[$i];
if($logged_info->group_list[$group_srl]) {
$is_permitted = true;
break;
}
}
if(!$is_permitted) printContent( getXmlRpcFailure(1, 'no permission') );
}
}
$fileinfo = $params[3]->value->struct->member;
foreach($fileinfo as $key => $val) {
$nodename = $val->name->body;
if($nodename == 'bits') $filedata = base64_decode($val->value->base64->body);
elseif($nodename == 'name') $filename = $val->value->string->body;
}
$tmp_arr = explode('/',$filename);
$filename = array_pop($tmp_arr);
if(!is_dir($tmp_uploaded_path)) FileHandler::makeDir($tmp_uploaded_path);
$target_filename = sprintf('%s%s', $tmp_uploaded_path, $filename);
FileHandler::writeFile($target_filename, $filedata);
$obj->url = Context::getRequestUri().$target_filename;
$content = getXmlRpcResponse($obj);
printContent($content);
break;
// Get posts
case 'metaWeblog.getPost' :
$document_srl = $params[0]->value->string->body;
if(!$document_srl) {
printContent( getXmlRpcFailure(1, 'no permission') );
} else {
$oDocumentModel = &getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl);
if(!$oDocument->isExists() || !$oDocument->isGranted()) {
printContent( getXmlRpcFailure(1, 'no permission') );
} else {
// Get a list of categories and set Context
$category = "";
if($oDocument->get('category_srl')) {
$oDocumentModel = &getModel('document');
$category_list = $oDocumentModel->getCategoryList($oDocument->get('module_srl'));
if($category_list[$oDocument->get('category_srl')]) {
$category = $category_list[$oDocument->get('category_srl')]->title;
}
}
$content = sprintf(
'<?xml version="1.0" encoding="utf-8"?>'.
'<methodResponse>'.
'<params>'.
'<param>'.
'<value>'.
'<struct>'.
'<member><name>categories</name><value><array><data><value><![CDATA[%s]]></value></data></array></value></member>'.
'<member><name>dateCreated</name><value><dateTime.iso8601>%s</dateTime.iso8601></value></member>'.
'<member><name>description</name><value><![CDATA[%s]]></value></member>'.
'<member><name>link</name><value>%s</value></member>'.
'<member><name>postid</name><value><string>%s</string></value></member>'.
'<member><name>title</name><value><![CDATA[%s]]></value></member>'.
'<member><name>publish</name><value><boolean>1</boolean></value></member>'.
'</struct>'.
'</value>'.
'</param>'.
'</params>'.
'</methodResponse>',
$category,
date("Ymd", $oDocument->getRegdateTime()).'T'.date("H:i:s", $oDocument->getRegdateTime()),
$oDocument->getContent(false, false, true,false),
getFullUrl('','document_srl', $oDocument->document_srl),
$oDocument->document_srl,
$oDocument->getTitleText()
);
printContent($content);
}
}
break;
// Write a new post
case 'metaWeblog.newPost' :
unset($obj);
$info = $params[3];
// Get information of post, title, and category
for($i=0;$i<count($info->value->struct->member);$i++) {
$val = $info->value->struct->member[$i];
switch($val->name->body) {
case 'title' :
$obj->title = $val->value->string->body;
break;
case 'description' :
$obj->content = $val->value->string->body;
break;
case 'categories' :
$categories = $val->value->array->data->value;
if(!is_array($categories)) $categories = array($categories);
$category = $categories[0]->string->body;
if($category && $category_list) {
foreach($category_list as $category_srl => $category_info) {
if($category_info->title == $category) $obj->category_srl = $category_srl;
}
}
break;
case 'tagwords' :
$tags = $val->value->array->data->value;
if(!is_array($tags)) $tags = array($tags);
for($j=0;$j<count($tags);$j++) {
$tag_list[] = $tags[$j]->string->body;
}
if(count($tag_list)) $obj->tags = implode(',',$tag_list);
break;
}
}
// Set document srl
$document_srl = getNextSequence();
$obj->document_srl = $document_srl;
$obj->module_srl = $this->module_srl;
// Attachment
if(is_dir($tmp_uploaded_path)) {
$file_list = FileHandler::readDir($tmp_uploaded_path);
$file_count = count($file_list);
if($file_count) {
$oFileController = &getController('file');
for($i=0;$i<$file_count;$i++) {
$file_info['tmp_name'] = sprintf('%s%s', $tmp_uploaded_path, $file_list[$i]);
$file_info['name'] = $file_list[$i];
$oFileController->insertFile($file_info, $this->module_srl, $document_srl, 0, true);
}
$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);
$oDocumentController = &getController('document');
$obj->commentStatus = 'ALLOW';
$obj->allow_trackback = 'Y';
$output = $oDocumentController->insertDocument($obj);
if(!$output->toBool()) {
$content = getXmlRpcFailure(1, $output->getMessage());
} else {
$content = getXmlRpcResponse(strval($document_srl));
}
FileHandler::removeDir($tmp_uploaded_path);
printContent($content);
break;
// Edit post
case 'metaWeblog.editPost' :
$tmp_val = $params[0]->value->string->body;
if(!$tmp_val) $tmp_val = $params[0]->value->i4->body;
if(!$tmp_val) {
$content = getXmlRpcFailure(1, 'no permission');
break;
}
$tmp_arr = explode('/', $tmp_val);
$document_srl = array_pop($tmp_arr);
if(!$document_srl) {
$content = getXmlRpcFailure(1, 'no permission');
break;
}
$oDocumentModel = &getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl);
// Check if a permission to modify a document is granted
if(!$oDocument->isGranted()) {
$content = getXmlRpcFailure(1, 'no permission');
break;
}
$obj = $oDocument->getObjectVars();
$info = $params[3];
// Get information of post, title, and category
for($i=0;$i<count($info->value->struct->member);$i++) {
$val = $info->value->struct->member[$i];
switch($val->name->body) {
case 'title' :
$obj->title = $val->value->string->body;
break;
case 'description' :
$obj->content = $val->value->string->body;
break;
case 'categories' :
$categories = $val->value->array->data->value;
if(!is_array($categories)) $categories = array($categories);
$category = $categories[0]->string->body;
if($category && $category_list) {
foreach($category_list as $category_srl => $category_info) {
if($category_info->title == $category) $obj->category_srl = $category_srl;
}
}
break;
case 'tagwords' :
$tags = $val->value->array->data->value;
if(!is_array($tags)) $tags = array($tags);
for($j=0;$j<count($tags);$j++) {
$tag_list[] = $tags[$j]->string->body;
}
if(count($tag_list)) $obj->tags = implode(',',$tag_list);
break;
}
}
// Document srl
$obj->document_srl = $document_srl;
$obj->module_srl = $this->module_srl;
// Attachment
if(is_dir($tmp_uploaded_path)) {
$file_list = FileHandler::readDir($tmp_uploaded_path);
$file_count = count($file_list);
if($file_count) {
$oFileController = &getController('file');
for($i=0;$i<$file_count;$i++) {
$file_info['tmp_name'] = sprintf('%s%s', $tmp_uploaded_path, $file_list[$i]);
$file_info['name'] = $file_list[$i];
$moved_filename = sprintf('./files/attach/images/%s/%s/%s', $this->module_srl, $document_srl, $file_info['name']);
if(file_exists($moved_filename)) continue;
$oFileController->insertFile($file_info, $this->module_srl, $document_srl, 0, true);
}
$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);
$oDocumentController = &getController('document');
$output = $oDocumentController->updateDocument($oDocument,$obj);
if(!$output->toBool()) {
$content = getXmlRpcFailure(1, $output->getMessage());
} else {
$content = getXmlRpcResponse(true);
FileHandler::removeDir($tmp_uploaded_path);
}
printContent($content);
break;
// Delete the post
case 'blogger.deletePost' :
$tmp_val = $params[0]->value->string->body;
$tmp_arr = explode('/', $tmp_val);
$document_srl = array_pop($tmp_arr);
// Get a document
$oDocumentModel = &getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl);
// If the document exists
if(!$oDocument->isExists()) {
$content = getXmlRpcFailure(1, 'not exists');
// Check if a permission to delete a document is granted
} elseif(!$oDocument->isGranted()) {
$content = getXmlRpcFailure(1, 'no permission');
break;
// Delete
} else {
$oDocumentController = &getController('document');
$output = $oDocumentController->deleteDocument($document_srl);
if(!$output->toBool()) $content = getXmlRpcFailure(1, $output->getMessage());
else $content = getXmlRpcResponse(true);
}
printContent($content);
break;
// Get recent posts
case 'metaWeblog.getRecentPosts' :
// Options to get a list
$args->module_srl = $this->module_srl; // /< module_srl of the current module
$args->page = 1;
$args->list_count = 20;
$args->sort_index = 'list_order'; // /< Sorting values
$logged_info = Context::get('logged_info');
$args->search_target = 'member_srl';
$args->search_keyword = $logged_info->member_srl;
$output = $oDocumentModel->getDocumentList($args);
if(!$output->toBool() || !$output->data) {
$content = getXmlRpcFailure(1, 'post not founded');
printContent($content);
} else {
$oEditorController = &getController('editor');
$posts = array();
foreach($output->data as $key => $oDocument) {
$post = null;
$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->mt_allow_pings = 0;
$post->mt_allow_comments = $oDocument->allowComment()?1:0;
$posts[] = $post;
}
$content = getXmlRpcResponse($posts);
printContent($content);
}
break;
// Display RSD if there is no request
default :
$homepagelink = getUrl('','mid',$this->mid);
$site_module_info = Context::get('site_module_info');
$api_url = getFullSiteUrl($site_module_info->domain, '', 'mid',$site_module_info->mid, 'act','api');
$content = <<<RSDContent
<?xml version="1.0" ?>
<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd" >
<service>
<engineName>XpressEngine</engineName>
<engineLink>http://www.xpressengine.com/ </engineLink>
<homePageLink>{$homepagelink}</homePageLink>
<apis>
<api name="MetaWeblog" preferred="true" apiLink="{$api_url}" blogID="" />
</apis>
</service>
</rsd>
RSDContent;
printContent($content);
break;
}
}
?>

View file

@ -1,69 +1,66 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file ./addons/blogapi/blogapi.func.php
* @author NHN (developers@xpressengine.com)
* @brief blogapi구현을 위한 함수 모음집
**/
// 오류 표시
function getXmlRpcFailure($error, $message) {
return
sprintf(
"<methodResponse>\n<fault><value><struct>\n<member>\n<name>faultCode</name>\n<value><int>%d</int></value>\n</member>\n<member>\n<name>faultString</name>\n<value><string>%s</string></value>\n</member>\n</struct></value></fault>\n</methodResponse>\n",
$error,
htmlspecialchars($message)
);
}
// 결과 표시
function getXmlRpcResponse($params) {
$buff = '<?xml version="1.0" encoding="utf-8"?>'."\n<methodResponse><params>";
$buff .= _getEncodedVal($params);
$buff .= "</params>\n</methodResponse>\n";
return $buff;
}
// 인코딩 처리
function _getEncodedVal($val, $is_sub_set = false) {
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_bool($val)) $buff = sprintf("<value><boolean>%d</boolean></value>", $val?1:0);
elseif(is_object($val)) {
$values = get_object_vars($val);
$val_count = count($values);
$buff = "<value><struct>";
foreach($values as $k => $v) {
$buff .= sprintf("<member>\n<name>%s</name>\n%s</member>\n", htmlspecialchars($k), _getEncodedVal($v, true));
}
$buff .= "</struct></value>\n";
} elseif(is_array($val)) {
$val_count = count($val);
$buff = "<value><array>\n<data>";
for($i=0;$i<$val_count;$i++) {
$buff .= _getEncodedVal($val[$i], true);
}
$buff .= "</data>\n</array></value>";
} else {
$buff = sprintf("<value><string>%s</string></value>\n", $val);
}
if(!$is_sub_set) return sprintf("<param>\n%s</param>", $buff);
return $buff;
}
// 결과 출력
function printContent($content) {
header("Content-Type: text/xml; charset=UTF-8");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
print $content;
Context::close();
exit();
}
?>
<?php
if(!defined('__XE__')) exit();
/**
* @file ./addons/blogapi/blogapi.func.php
* @author NHN (developers@xpressengine.com)
* @brief Function collections for the implementation of blogapi
**/
// Error messages
function getXmlRpcFailure($error, $message) {
return
sprintf(
"<methodResponse>\n<fault><value><struct>\n<member>\n<name>faultCode</name>\n<value><int>%d</int></value>\n</member>\n<member>\n<name>faultString</name>\n<value><string>%s</string></value>\n</member>\n</struct></value></fault>\n</methodResponse>\n",
$error,
htmlspecialchars($message)
);
}
// Display results
function getXmlRpcResponse($params) {
$buff = '<?xml version="1.0" encoding="utf-8"?>'."\n<methodResponse><params>";
$buff .= _getEncodedVal($params);
$buff .= "</params>\n</methodResponse>\n";
return $buff;
}
// Encoding
function _getEncodedVal($val, $is_sub_set = false) {
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_bool($val)) $buff = sprintf("<value><boolean>%d</boolean></value>", $val?1:0);
elseif(is_object($val)) {
$values = get_object_vars($val);
$val_count = count($values);
$buff = "<value><struct>";
foreach($values as $k => $v) {
$buff .= sprintf("<member>\n<name>%s</name>\n%s</member>\n", htmlspecialchars($k), _getEncodedVal($v, true));
}
$buff .= "</struct></value>\n";
} elseif(is_array($val)) {
$val_count = count($val);
$buff = "<value><array>\n<data>";
for($i=0;$i<$val_count;$i++) {
$buff .= _getEncodedVal($val[$i], true);
}
$buff .= "</data>\n</array></value>";
} else {
$buff = sprintf("<value><string>%s</string></value>\n", $val);
}
if(!$is_sub_set) return sprintf("<param>\n%s</param>", $buff);
return $buff;
}
// Display the result
function printContent($content) {
header("Content-Type: text/xml; charset=UTF-8");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
print $content;
Context::close();
exit();
}
?>

View file

@ -1,80 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">BlogAPI 애드온</title>
<title xml:lang="jp">BlogAPIアドオン</title>
<title xml:lang="zh-CN">BlogAPI</title>
<title xml:lang="en">Addon for BlogAPI</title>
<title xml:lang="vi">BlogAPI Addon</title>
<title xml:lang="ge">Addon für BlogAPI</title>
<title xml:lang="es">Addon para BlogAPI</title>
<title xml:lang="ru">Аддон для BlogAPI</title>
<title xml:lang="zh-TW">部落格 API</title>
<description xml:lang="ko">
metaWeblog를 지원하는 blogApi애드온입니다.
사용으로 설정하시면 각 모듈마다 RSD 태그를 노출합니다.
api의 주소는 http://설치주소/모듈명/api 입니다.
사용으로 하셔야 RSD태그 및 api가 동작을 합니다.
</description>
<description xml:lang="jp">
MetaWeblogをサポートするBlog APIアドオンです。
「使用する」にチェックすると各モジュールごとにRSDのアドレスを表示します。
APIのアドレスは「http://インストールURL/モジュール名/api」です。
「使用する」に設定してから、RSDタグ、およびAPIが作動します。
</description>
<description xml:lang="zh-CN">
支持metaWeblog的 blogApi插件。
设置为"启用"时,会使每个模块都会显示RSD标签。
api地址为http://安装地址/模块名/api。
把状态设置为"使用"时才会激活RSD标签及api。
</description>
<description xml:lang="en">
This blogApi addon supports metaWeblog.
By using this option, it lets the RSD tag to be exposed to each module.
URL to the api is http://setup_path/module_name/api.
RSD tag and the api will work only if u use this addon.
</description>
<description xml:lang="vi">
Addon BlogAPI này hỗ trợ metaWeblog..
Bằng việc sử dụng tùy chọn này, Tag RSD sẽ được hiển thị đến mỗi Module.
URL cho API có dạng http://setup_path/module_name/api.
RSD Tag và API chỉ làm việc khi Addon này được kích hoạt.
</description>
<description xml:lang="ge">
Diese blogApi addon metaWeblog unterstützt.
Durch die Verwendung dieser Option, die es ermöglicht RSD Tag ausgesetzt werden jedes Modul.
URL der api ist http://setup_path/module_name/api.
RSD-Tag und dem API arbeiten und nur dann, wenn Sie über dieses Addon.
</description>
<description xml:lang="es">
Este blogApi addon soporta el metaWeblog.
Si seleccionas la optión usar, cada módulo entregará la etiqueta RSD.
La dirección de api es http://dirección de la instalación/nombre de módulo/api.
Sólo si seleccionas la opción usar, funcionará la etiqueta RSD y api.
</description>
<description xml:lang="ru">
Этот blogApi аддон поддерживает metaWeblog.
Используя этот аддон, RSD тег становится доступным для каждого модуля.
URL для api - http://setup_path/module_name/api.
тег RSD и api работают только при включенном аддоне.
</description>
<description xml:lang="zh-TW">
支援 MetaWeblog 的部落格 API 附加元件。
設置成"啟用"時,會使每個模組都顯示 RSD 圖示。
API網址是 http://安裝位置/模組名稱/api。
將狀態設置成"啟用"時,才可使用 RSD 和 API
</description>
<version>0.1</version>
<date>2007-02-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">BlogAPI 애드온</title>
<title xml:lang="jp">BlogAPIアドオン</title>
<title xml:lang="zh-CN">BlogAPI</title>
<title xml:lang="en">Addon for BlogAPI</title>
<title xml:lang="vi">BlogAPI Addon</title>
<title xml:lang="ge">Addon für BlogAPI</title>
<title xml:lang="es">Addon para BlogAPI</title>
<title xml:lang="ru">Аддон для BlogAPI</title>
<title xml:lang="zh-TW">部落格 API</title>
<description xml:lang="ko">
metaWeblog를 지원하는 blogApi애드온입니다.
사용으로 설정하시면 각 모듈마다 RSD 태그를 노출합니다.
api의 주소는 http://설치주소/모듈명/api 입니다.
사용으로 하셔야 RSD태그 및 api가 동작을 합니다.
</description>
<description xml:lang="jp">
MetaWeblogをサポートするBlog APIアドオンです。
「使用する」にチェックすると各モジュールごとにRSDのアドレスを表示します。
APIのアドレスは「http://インストールURL/モジュール名/api」です。
「使用する」に設定してから、RSDタグ、およびAPIが作動します。
</description>
<description xml:lang="zh-CN">
支持metaWeblog的 blogApi插件。
设置为"启用"时,会使每个模块都会显示RSD标签。
api地址为http://安装地址/模块名/api。
把状态设置为"使用"时才会激活RSD标签及api。
</description>
<description xml:lang="en">
This blogAPI addon supports metaWeblog.
By using this option, it lets the RSD tag to be exposed to each module.
URL to the API is http://setup_path/module_name/api.
RSD tag and the api will work only if you use this addon.
</description>
<description xml:lang="vi">
Addon BlogAPI này hỗ trợ metaWeblog..
Bằng việc sử dụng tùy chọn này, Tag RSD sẽ được hiển thị đến mỗi Module.
URL cho API có dạng http://setup_path/module_name/api.
RSD Tag và API chỉ làm việc khi Addon này được kích hoạt.
</description>
<description xml:lang="ge">
Diese blogApi addon metaWeblog unterstützt.
Durch die Verwendung dieser Option, die es ermöglicht RSD Tag ausgesetzt werden jedes Modul.
URL der api ist http://setup_path/module_name/api.
RSD-Tag und dem API arbeiten und nur dann, wenn Sie über dieses Addon.
</description>
<description xml:lang="es">
Este blogApi addon soporta el metaWeblog.
Si seleccionas la optión usar, cada módulo entregará la etiqueta RSD.
La dirección de api es http://dirección de la instalación/nombre de módulo/api.
Sólo si seleccionas la opción usar, funcionará la etiqueta RSD y api.
</description>
<description xml:lang="ru">
Этот blogApi аддон поддерживает metaWeblog.
Используя этот аддон, RSD тег становится доступным для каждого модуля.
URL для api - http://setup_path/module_name/api.
тег RSD и api работают только при включенном аддоне.
</description>
<description xml:lang="zh-TW">
支援 MetaWeblog 的部落格 API 附加元件。
設置成"啟用"時,會使每個模組都顯示 RSD 圖示。
API網址是 http://安裝位置/模組名稱/api。
將狀態設置成"啟用"時,才可使用 RSD 和 API
</description>
<version>0.1</version>
<date>2007-02-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>

View file

@ -1,263 +1,326 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file captcha.addon.php
* @author NHN (developers@xpressengine.com)
* @brief 특정 action을 실행할때 captcha를 띄우도록
* 영어 알파벳을 입력, 음성기능 추가
**/
if(!class_exists('AddonCaptcha'))
{
class AddonCaptcha
{
var $addon_info;
function setInfo(&$addon_info)
{
$this->addon_info = $addon_info;
}
function before_module_proc()
{
if($this->addon_info->act_type == 'everytime' && $_SESSION['captcha_authed']) {
unset($_SESSION['captcha_authed']);
}
}
function before_module_init(&$ModuleHandler)
{
$logged_info = Context::get('logged_info');
if($logged_info->is_admin == 'Y' || $logged_info->is_site_admin) return false;
if($this->addon_info->target != 'all' && Context::get('is_logged')) return false;
if($_SESSION['captcha_authed']) return false;
$target_acts = array('procBoardInsertDocument','procBoardInsertComment','procIssuetrackerInsertIssue','procIssuetrackerInsertHistory','procTextyleInsertComment');
if($this->addon_info->apply_find_account=='apply') $target_acts[] = 'procMemberFindAccount';
if($this->addon_info->apply_resend_auth_mail=='apply') $target_acts[] = 'procMemberResendAuthMail';
if($this->addon_info->apply_signup=='apply') $target_acts[] = 'procMemberInsert';
if(Context::getRequestMethod()!='XMLRPC' && Context::getRequestMethod()!=='JSON')
{
Context::addHtmlHeader('<script type="text/javascript"> var captchaTargetAct = new Array("'.implode('","',$target_acts).'"); </script>');
Context::addJsFile('./addons/captcha/captcha.js',false, '', null, 'body');
}
// 게시판/ 이슈트래커의 글쓰기/댓글쓰기 액션 호출시 세션 비교
if(!$_SESSION['captcha_authed'] && in_array(Context::get('act'), $target_acts)) {
Context::loadLang('./addons/captcha/lang');
$ModuleHandler->error = "captcha_denied";
}
return true;
}
function before_module_init_setCaptchaSession()
{
if($_SESSION['captcha_authed']) return false;
// 언어파일 로드
Context::loadLang(_XE_PATH_.'addons/captcha/lang');
// 키워드 생성
$arr = range('A','Y');
shuffle($arr);
$arr = array_slice($arr,0,6);
$_SESSION['captcha_keyword'] = join('', $arr);
$target = Context::getLang('target_captcha');
header("Content-Type: text/xml; charset=UTF-8");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
printf("<response>\r\n <error>0</error>\r\n <message>success</message>\r\n <about_captcha><![CDATA[%s]]></about_captcha>\r\n <captcha_reload><![CDATA[%s]]></captcha_reload>\r\n <captcha_play><![CDATA[%s]]></captcha_play>\r\n <cmd_input><![CDATA[%s]]></cmd_input>\r\n <cmd_cancel><![CDATA[%s]]></cmd_cancel>\r\n </response>"
,Context::getLang('about_captcha')
,Context::getLang('captcha_reload')
,Context::getLang('captcha_play')
,Context::getLang('cmd_input')
,Context::getLang('cmd_cancel')
);
Context::close();
exit();
}
function before_module_init_captchaImage()
{
if($_SESSION['captcha_authed']) return false;
$keyword = $_SESSION['captcha_keyword'];
$im = $this->createCaptchaImage($keyword);
header("Cache-Control: ");
header("Pragma: ");
header("Content-Type: image/png");
imagepng($im);
imagedestroy($im);
Context::close();
exit();
}
function createCaptchaImage($string)
{
$arr = array();
for($i=0,$c=strlen($string);$i<$c;$i++) $arr[] = $string{$i};
// 글자 하나 사이즈
$w = 18;
$h = 25;
// 글자 수
$c = count($arr);
// 글자 이미지
$im = array();
// 총사이즈로 바탕 이미지 생성
$im[] = imagecreate(($w+2)*count($arr), $h);
$deg = range(-30,30);
shuffle($deg);
// 글자별 이미지 생성
foreach($arr as $i => $str)
{
$im[$i+1] = @imagecreate($w, $h);
$background_color = imagecolorallocate($im[$i+1], 255, 255, 255);
$text_color = imagecolorallocate($im[$i+1], 0, 0, 0);
// 글자폰트(사이즈) 조절
$ran = range(1,20);
shuffle($ran);
if(function_exists('imagerotate'))
{
imagestring($im[$i+1], (array_pop($ran)%3)+3, 2, (array_pop($ran)%8), $str, $text_color);
$im[$i+1] = imagerotate($im[$i+1], array_pop($deg), 0);
$background_color = imagecolorallocate($im[$i+1], 255, 255, 255);
imagecolortransparent($im[$i+1], $background_color);
}
else
{
imagestring($im[$i+1], (array_pop($ran)%3)+3, 2, (array_pop($ran)%4), $str, $text_color);
}
}
// 각글자 이미지를 합침
for($i=1;$i<count($im);$i++)
{
imagecopy($im[0],$im[$i],(($w+2)*($i-1)),0,0,0,$w,$h);
imagedestroy($im[$i]);
}
// 이미지 확대
$big_count = 2;
$big = imagecreatetruecolor(($w+2)*$big_count*$c, $h*$big_count);
imagecopyresized($big, $im[0], 0, 0, 0, 0, ($w+2)*$big_count*$c, $h*$big_count, ($w+2)*$c, $h);
imagedestroy($im[0]);
if(function_exists('imageantialias')) imageantialias($big,true);
// 배경 라인 및 점찍기
$line_color = imagecolorallocate($big, 0, 0, 0);
$w = ($w+2)*$big_count*$c;
$h = $h*$big_count;
$d = array_pop($deg);
for($i=-abs($d);$i<$h+abs($d);$i=$i+7) imageline($big,0,$i+$d,$w,$i,$line_color);
$x = range(0,($w-10));
shuffle($x);
for($i=0;$i<200;$i++) imagesetpixel($big,$x[$i]%$w,$x[$i+1]%$h,$line_color);
return $big;
}
function before_module_init_captchaAudio()
{
if($_SESSION['captcha_authed']) return false;
$keyword = strtoupper($_SESSION['captcha_keyword']);
$data = $this->createCaptchaAudio($keyword);
header('Content-type: audio/mpeg');
header("Content-Disposition: attachment; filename=\"captcha_audio.mp3\"");
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Expires: Sun, 1 Jan 2000 12:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT');
header('Content-Length: ' . strlen($data));
echo $data;
Context::close();
exit();
}
function createCaptchaAudio($string)
{
$data = '';
$_audio = './addons/captcha/audio/F_%s.mp3';
for($i=0,$c=strlen($string);$i<$c;$i++)
{
$_data = FileHandler::readFile(sprintf($_audio, $string{$i}));
$start = rand(5, 68); // 해더 4바이트, 데이터 영역 64바이트 정도 랜덤하게 시작
$datalen = strlen($_data) - $start - 256; // 마지막 unchanged 256 바이트
for($j=$start;$j<$datalen;$j+=64)
{
$ch = ord($_data{$j});
if($ch<9 || $ch>119) continue;
$_data{$j} = chr($ch+rand(-8,8));
}
$data .= $_data;
}
return $data;
}
function before_module_init_captchaCompare()
{
if($_SESSION['captcha_authed']) return false;
if(strtoupper($_SESSION['captcha_keyword']) == strtoupper(Context::get('secret_text'))) $_SESSION['captcha_authed'] = true;
else unset($_SESSION['captcha_authed']);
header("Content-Type: text/xml; charset=UTF-8");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
print("<response>\r\n<error>0</error>\r\n<message>success</message>\r\n</response>");
Context::close();
exit();
}
}
$GLOBALS['__AddonCaptcha__'] = new AddonCaptcha;
$GLOBALS['__AddonCaptcha__']->setInfo($addon_info);
}
$oAddonCaptcha = &$GLOBALS['__AddonCaptcha__'];
if(method_exists(&$oAddonCaptcha, $called_position))
{
if(!call_user_func(array(&$oAddonCaptcha, $called_position), &$this)) return false;
}
$addon_act = Context::get('captcha_action');
if($addon_act && method_exists(&$oAddonCaptcha, $called_position.'_'.$addon_act))
{
if(!call_user_func(array(&$oAddonCaptcha, $called_position.'_'.$addon_act), &$this)) return false;
}
?>
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file captcha.addon.php
* @author NHN (developers@xpressengine.com)
* @brief Captcha for a particular action
* English alphabets and voice verification added
**/
if(!class_exists('AddonCaptcha'))
{
class AddonCaptcha
{
var $addon_info;
function setInfo(&$addon_info)
{
$this->addon_info = $addon_info;
}
function before_module_proc()
{
if($this->addon_info->act_type == 'everytime' && $_SESSION['captcha_authed']) {
unset($_SESSION['captcha_authed']);
}
}
function before_module_init(&$ModuleHandler)
{
$logged_info = Context::get('logged_info');
if($logged_info->is_admin == 'Y' || $logged_info->is_site_admin) return false;
if($this->addon_info->target != 'all' && Context::get('is_logged')) return false;
if($_SESSION['captcha_authed']) return false;
$type = Context::get('captchaType');
$target_acts = array('procBoardInsertDocument','procBoardInsertComment','procIssuetrackerInsertIssue','procIssuetrackerInsertHistory','procTextyleInsertComment');
if($this->addon_info->apply_find_account=='apply') $target_acts[] = 'procMemberFindAccount';
if($this->addon_info->apply_resend_auth_mail=='apply') $target_acts[] = 'procMemberResendAuthMail';
if($this->addon_info->apply_signup=='apply') $target_acts[] = 'procMemberInsert';
if(Context::getRequestMethod()!='XMLRPC' && Context::getRequestMethod()!=='JSON')
{
if($type == 'inline') {
$this->compareCaptcha();
} else {
Context::addHtmlHeader('<script type="text/javascript"> var captchaTargetAct = new Array("'.implode('","',$target_acts).'"); </script>');
Context::loadFile(array('./addons/captcha/captcha.js', 'body', '', null), true);
}
}
// compare session when calling actions such as writing a post or a comment on the board/issue tracker module
if(!$_SESSION['captcha_authed'] && in_array(Context::get('act'), $target_acts)) {
Context::loadLang('./addons/captcha/lang');
$ModuleHandler->error = "captcha_denied";
}
return true;
}
function createKeyword()
{
$type = Context::get('captchaType');
if ($type == 'inline' && $_SESSION['captcha_keyword']) return;
$arr = range('A','Y');
shuffle($arr);
$arr = array_slice($arr,0,6);
$_SESSION['captcha_keyword'] = join('', $arr);
}
function before_module_init_setCaptchaSession()
{
if($_SESSION['captcha_authed']) return false;
// Load language files
Context::loadLang(_XE_PATH_.'addons/captcha/lang');
// Generate keywords
$this->createKeyword();
$target = Context::getLang('target_captcha');
header("Content-Type: text/xml; charset=UTF-8");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
printf("<response>\r\n <error>0</error>\r\n <message>success</message>\r\n <about_captcha><![CDATA[%s]]></about_captcha>\r\n <captcha_reload><![CDATA[%s]]></captcha_reload>\r\n <captcha_play><![CDATA[%s]]></captcha_play>\r\n <cmd_input><![CDATA[%s]]></cmd_input>\r\n <cmd_cancel><![CDATA[%s]]></cmd_cancel>\r\n </response>"
,Context::getLang('about_captcha')
,Context::getLang('captcha_reload')
,Context::getLang('captcha_play')
,Context::getLang('cmd_input')
,Context::getLang('cmd_cancel')
);
Context::close();
exit();
}
function before_module_init_captchaImage()
{
if($_SESSION['captcha_authed']) return false;
if(Context::get('renew')) $this->createKeyword();
$keyword = $_SESSION['captcha_keyword'];
$im = $this->createCaptchaImage($keyword);
header("Cache-Control: ");
header("Pragma: ");
header("Content-Type: image/png");
imagepng($im);
imagedestroy($im);
Context::close();
exit();
}
function createCaptchaImage($string)
{
$arr = array();
for($i=0,$c=strlen($string);$i<$c;$i++) $arr[] = $string{$i};
// Font site
$w = 18;
$h = 25;
// Character length
$c = count($arr);
// Character image
$im = array();
// Create an image by total size
$im[] = imagecreate(($w+2)*count($arr), $h);
$deg = range(-30,30);
shuffle($deg);
// Create an image for each letter
foreach($arr as $i => $str)
{
$im[$i+1] = @imagecreate($w, $h);
$background_color = imagecolorallocate($im[$i+1], 255, 255, 255);
$text_color = imagecolorallocate($im[$i+1], 0, 0, 0);
// Control font size
$ran = range(1,20);
shuffle($ran);
if(function_exists('imagerotate'))
{
imagestring($im[$i+1], (array_pop($ran)%3)+3, 2, (array_pop($ran)%8), $str, $text_color);
$im[$i+1] = imagerotate($im[$i+1], array_pop($deg), 0);
$background_color = imagecolorallocate($im[$i+1], 255, 255, 255);
imagecolortransparent($im[$i+1], $background_color);
}
else
{
imagestring($im[$i+1], (array_pop($ran)%3)+3, 2, (array_pop($ran)%4), $str, $text_color);
}
}
// Combine images of each character
for($i=1;$i<count($im);$i++)
{
imagecopy($im[0],$im[$i],(($w+2)*($i-1)),0,0,0,$w,$h);
imagedestroy($im[$i]);
}
// Larger image
$big_count = 2;
$big = imagecreatetruecolor(($w+2)*$big_count*$c, $h*$big_count);
imagecopyresized($big, $im[0], 0, 0, 0, 0, ($w+2)*$big_count*$c, $h*$big_count, ($w+2)*$c, $h);
imagedestroy($im[0]);
if(function_exists('imageantialias')) imageantialias($big,true);
// Background line
$line_color = imagecolorallocate($big, 0, 0, 0);
$w = ($w+2)*$big_count*$c;
$h = $h*$big_count;
$d = array_pop($deg);
for($i=-abs($d);$i<$h+abs($d);$i=$i+7) imageline($big,0,$i+$d,$w,$i,$line_color);
$x = range(0,($w-10));
shuffle($x);
for($i=0;$i<200;$i++) imagesetpixel($big,$x[$i]%$w,$x[$i+1]%$h,$line_color);
return $big;
}
function before_module_init_captchaAudio()
{
if($_SESSION['captcha_authed']) return false;
$keyword = strtoupper($_SESSION['captcha_keyword']);
$data = $this->createCaptchaAudio($keyword);
header('Content-type: audio/mpeg');
header("Content-Disposition: attachment; filename=\"captcha_audio.mp3\"");
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Expires: Sun, 1 Jan 2000 12:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT');
header('Content-Length: ' . strlen($data));
echo $data;
Context::close();
exit();
}
function createCaptchaAudio($string)
{
$data = '';
$_audio = './addons/captcha/audio/F_%s.mp3';
for($i=0,$c=strlen($string);$i<$c;$i++)
{
$_data = FileHandler::readFile(sprintf($_audio, $string{$i}));
$start = rand(5, 68); // Random start in 4-byte header and 64 byte data
$datalen = strlen($_data) - $start - 256; // Last unchanged 256 bytes
for($j=$start;$j<$datalen;$j+=64)
{
$ch = ord($_data{$j});
if($ch<9 || $ch>119) continue;
$_data{$j} = chr($ch+rand(-8,8));
}
$data .= $_data;
}
return $data;
}
function compareCaptcha()
{
if($_SESSION['captcha_authed']) return true;
if(strtoupper($_SESSION['captcha_keyword']) == strtoupper(Context::get('secret_text'))) {
$_SESSION['captcha_authed'] = true;
return true;
}
unset($_SESSION['captcha_authed']);
return false;
}
function before_module_init_captchaCompare()
{
if(!$this->compareCaptcha()) return false;
header("Content-Type: text/xml; charset=UTF-8");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
print("<response>\r\n<error>0</error>\r\n<message>success</message>\r\n</response>");
Context::close();
exit();
}
function inlineDisplay()
{
unset($_SESSION['captcha_authed']);
$this->createKeyword();
$swfURL = getUrl().'addons/captcha/swf/play.swf';
Context::unloadFile('./addons/captcha/captcha.js');
Context::loadFile(array('./addons/captcha/inline_captcha.js','body'));
global $lang;
$tags=<<<EOD
<img src="%s" id="captcha_image" alt="CAPTCHA" width="240" height="50" style="width:240px; height:50px; border:1px solid #b0b0b0" />
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="0" height="0" id="captcha_audio" align="middle">
<param name="allowScriptAccess" value="always" />
<param name="quality" value="high" />
<param name="movie" value="%s" />
<param name="wmode" value="window" />
<param name="allowFullScreen" value="false">
<param name="bgcolor" value="#fffff" />
<embed src="%s" quality="high" wmode="window" allowFullScreen="false" bgcolor="#ffffff" width="0" height="0" name="captcha_audio" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>
<button type="button" class="captchaReload text">%s</button>
<button type="button" class="captchaPlay text">%s</button><br />
<input type="hidden" name="captchaType" value="inline" />
<input name="secret_text" type="text" id="secret_text" />
EOD;
$tags = sprintf($tags, getUrl('captcha_action','captchaImage', 'rand', mt_rand(10000, 99999))
, $swfURL
, $swfURL
, $lang->reload
, $lang->play);
return $tags;
}
}
$GLOBALS['__AddonCaptcha__'] = new AddonCaptcha;
$GLOBALS['__AddonCaptcha__']->setInfo($addon_info);
Context::set('oCaptcha', &$GLOBALS['__AddonCaptcha__']);
}
$oAddonCaptcha = &$GLOBALS['__AddonCaptcha__'];
if(method_exists($oAddonCaptcha, $called_position))
{
if(!call_user_func_array(array(&$oAddonCaptcha, $called_position), array(&$this))) return false;
}
$addon_act = Context::get('captcha_action');
if($addon_act && method_exists($oAddonCaptcha, $called_position.'_'.$addon_act))
{
if(!call_user_func_array(array(&$oAddonCaptcha, $called_position.'_'.$addon_act), array(&$this))) return false;
}
?>

View file

@ -1,222 +1,221 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">Captcha 애드온</title>
<title xml:lang="en">CAPTCHA</title>
<title xml:lang="vi">Captcha Addon</title>
<title xml:lang="zh-CN">验证码插件</title>
<title xml:lang="jp">Captchaアドオン</title>
<title xml:lang="ru">Аддон Captcha</title>
<title xml:lang="zh-TW">圖形驗證</title>
<description xml:lang="ko">
프로그램 글 등록기를 막기 위해 게시판/ issueTracker에서 글/ 댓글을 입력하려 할 때 알파벳을 입력해야 글/댓글이 입력되는 애드온 입니다.
로그인하지 않은 경우에만 해당됩니다.
</description>
<description xml:lang="en">
To block spam written by programs, let users to choose a suitable image to text when writing a posting or comment.
This addon applies only to not-logged-in users.
</description>
<description xml:lang="vi">
Addon này tạo ra một hình ảnh xác nhận khi đăng kí, gửi bài, hay viết bình luận nếu thành viên không đăng nhập.
Addon này chỉ hoạt động khi được kích hoạt.
</description>
<description xml:lang="zh-CN">
为了解决互联网垃圾而开发的验证码机制。
非登录用户发布话题或评论时将会弹出验证图片选择框,选择正确的图片才可以正常发布(适用于版面/issueTracker)。
</description>
<description xml:lang="jp">
ボット(bot)がプログラムによるスパム行為を防ぐために、掲示板issueTrackerで書き込み・コメントを登録する際、ランダムな文字や数字の列を画面に表示し、表示されたものと一致した情報を入力した時、登録が出来るようにするアドオンです。
ログインしてない時だけ、動作します。
</description>
<description xml:lang="ru">
To block spam written by programs, let users to choose a suitable image to text when writing a posting or comment.
This addon applies only to not-logged-in users.
</description>
<description xml:lang="zh-TW">
可防止機器人程式的垃圾留言,非用戶要發表主題或回覆時,必須要輸入正確圖片中所顯示的文字才能發表。
</description>
<version>1.0</version>
<date>2010-08-19</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-TW">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="vi">NHN</name>
</author>
<extra_vars>
<var name="target" type="select">
<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="ru">Captcha Target</title>
<title xml:lang="vi">Mục tiêu Captcha hiển thị</title>
<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="ru">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>
<options value="">
<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="ru">Not logged-in users</title>
<title xml:lang="vi">Người dùng chưa đăng nhập</title>
</options>
<options value="all">
<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="ru">All users</title>
<title xml:lang="vi">Tất cả mọi người</title>
</options>
</var>
<var name="act_type" type="select">
<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="ru">How it works</title>
<title xml:lang="vi">Sử dụng</title>
<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="ru">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>
<options value="onetime">
<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="en">once</title>
<title xml:lang="ru">1 раз</title>
</options>
<options value="everytime">
<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="ru">каждый раз</title>
<title xml:lang="vi">Luôn sử dụng</title>
</options>
</var>
<var name="apply_find_account" type="select">
<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="ru">applying to an action finding account</title>
<title xml:lang="vi">Khi lấy lại mật khẩu</title>
<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="ru">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>
<options value="">
<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="ru">Not apply</title>
<title xml:lang="vi">Không áp dụng</title>
</options>
<options value="apply">
<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="ru">Apply</title>
<title xml:lang="vi">Áp dụng</title>
</options>
</var>
<var name="apply_resend_auth_mail" type="select">
<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="ru">apply to an action resending authmail</title>
<title xml:lang="vi">Khi lấy lại mã kích hoạt</title>
<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="ru">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>
<options value="">
<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="ru">Not apply</title>
<title xml:lang="vi">Không áp dụng</title>
</options>
<options value="apply">
<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="ru">Apply</title>
<title xml:lang="vi">Áp dụng</title>
</options>
</var>
<var name="apply_signup" type="select">
<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 member signup</title>
<title xml:lang="ru">Apply to member signup</title>
<title xml:lang="vi">Apply to member signup</title>
<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 signup action, too.</description>
<description xml:lang="ru">If you set this option as apply, CAPTCHA will work for signup action, too.</description>
<description xml:lang="vi">If you set this option as apply, CAPTCHA will work for signup action, too.</description>
<options value="">
<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="ru">Not apply</title>
<title xml:lang="vi">Không áp dụng</title>
</options>
<options value="apply">
<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="ru">Apply</title>
<title xml:lang="vi">Áp dụng</title>
</options>
</var>
</extra_vars>
</addon>
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">Captcha 애드온</title>
<title xml:lang="en">CAPTCHA</title>
<title xml:lang="vi">Captcha Addon</title>
<title xml:lang="zh-CN">验证码插件</title>
<title xml:lang="jp">Captchaアドオン</title>
<title xml:lang="ru">Аддон Captcha</title>
<title xml:lang="zh-TW">圖形驗證</title>
<description xml:lang="ko">
프로그램 글 등록기를 막기 위해 게시판/ issueTracker에서 글/ 댓글을 입력하려 할 때 알파벳을 입력해야 글/댓글이 입력되는 애드온 입니다.
로그인하지 않은 경우에만 해당됩니다.
</description>
<description xml:lang="en">
This addon helps to prevent spam messages to be posted by requesting non-logged-in users to type characters displayed in the image before submitting comments or posts.
</description>
<description xml:lang="vi">
Addon này tạo ra một hình ảnh xác nhận khi đăng kí, gửi bài, hay viết bình luận nếu thành viên không đăng nhập.
Addon này chỉ hoạt động khi được kích hoạt.
</description>
<description xml:lang="zh-CN">
为了解决互联网垃圾而开发的验证码机制。
非登录用户发布话题或评论时将会弹出验证图片选择框,选择正确的图片才可以正常发布(适用于版面/issueTracker)。
</description>
<description xml:lang="jp">
ボット(bot)がプログラムによるスパム行為を防ぐために、掲示板issueTrackerで書き込み・コメントを登録する際、ランダムな文字や数字の列を画面に表示し、表示されたものと一致した情報を入力した時、登録が出来るようにするアドオンです。
ログインしてない時だけ、動作します。
</description>
<description xml:lang="ru">
To block spam written by programs, let users to choose a suitable image to text when writing a posting or comment.
This addon applies only to not-logged-in users.
</description>
<description xml:lang="zh-TW">
可防止機器人程式的垃圾留言,非用戶要發表主題或回覆時,必須要輸入正確圖片中所顯示的文字才能發表。
</description>
<version>1.0</version>
<date>2010-08-19</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-TW">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="vi">NHN</name>
</author>
<extra_vars>
<var name="target" type="select">
<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="ru">Captcha Target</title>
<title xml:lang="vi">Mục tiêu Captcha hiển thị</title>
<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 can specify if CAPTCHA should be displayed when posting an article or comment. It will not apply to administrators.</description>
<description xml:lang="ru">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>
<options value="">
<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="ru">Not logged-in users</title>
<title xml:lang="vi">Người dùng chưa đăng nhập</title>
</options>
<options value="all">
<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="ru">All users</title>
<title xml:lang="vi">Tất cả mọi người</title>
</options>
</var>
<var name="act_type" type="select">
<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="ru">How it works</title>
<title xml:lang="vi">Sử dụng</title>
<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="ru">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>
<options value="onetime">
<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="en">once</title>
<title xml:lang="ru">1 раз</title>
</options>
<options value="everytime">
<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="ru">каждый раз</title>
<title xml:lang="vi">Luôn sử dụng</title>
</options>
</var>
<var name="apply_find_account" type="select">
<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="ru">applying to an action finding account</title>
<title xml:lang="vi">Khi lấy lại mật khẩu</title>
<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="ru">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>
<options value="">
<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="ru">Not apply</title>
<title xml:lang="vi">Không áp dụng</title>
</options>
<options value="apply">
<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="ru">Apply</title>
<title xml:lang="vi">Áp dụng</title>
</options>
</var>
<var name="apply_resend_auth_mail" type="select">
<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="ru">apply to an action resending authmail</title>
<title xml:lang="vi">Khi lấy lại mã kích hoạt</title>
<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="ru">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>
<options value="">
<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="ru">Not apply</title>
<title xml:lang="vi">Không áp dụng</title>
</options>
<options value="apply">
<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="ru">Apply</title>
<title xml:lang="vi">Áp dụng</title>
</options>
</var>
<var name="apply_signup" type="select">
<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 member signup</title>
<title xml:lang="ru">Apply to member signup</title>
<title xml:lang="vi">Apply to member signup</title>
<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 signup action, too.</description>
<description xml:lang="ru">If you set this option as apply, CAPTCHA will work for signup action, too.</description>
<description xml:lang="vi">If you set this option as apply, CAPTCHA will work for signup action, too.</description>
<options value="">
<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="ru">Not apply</title>
<title xml:lang="vi">Không áp dụng</title>
</options>
<options value="apply">
<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="ru">Apply</title>
<title xml:lang="vi">Áp dụng</title>
</options>
</var>
</extra_vars>
</addon>

View file

@ -0,0 +1,17 @@
jQuery(function($){
$('button.captchaPlay')
.click(function(){
var swf = document['captcha_audio'] || window['captcha_audio'];
var audio = current_url.setQuery('captcha_action','captchaAudio').setQuery('rand', (new Date).getTime());
if(swf.length > 1) swf = swf[0];
$('input[type=text]#secret_text').focus();
swf.setSoundTarget(audio,'1');
});
$('button.captchaReload')
.click(function(){
$("#captcha_image").attr("src", current_url.setQuery('captcha_action','captchaImage').setQuery('rand', (new Date).getTime()).setQuery('renew',1));
});
});

View file

@ -1,6 +0,0 @@
<?php
$lang->about_captcha = "Please type alphabets above in order. They are not case-sensitive.";
$lang->captcha_reload = 'Refresh Image';
$lang->captcha_play = 'Play sound of words';
$lang->captcha_denied = 'You have typed wrong alphabets.';
?>

View file

@ -1,6 +0,0 @@
<?php
$lang->about_captcha = "위 영어 알파벳을 순서대로 입력해 주세요. 대소문자는 구분하지 않습니다.";
$lang->captcha_reload = '이미지 새로고침';
$lang->captcha_play = '음성으로 듣기';
$lang->captcha_denied = '잘못 입력하셨습니다';
?>

View file

@ -1,6 +0,0 @@
<?php
$lang->about_captcha = "위 영어 알파벳을 순서대로 입력해 주세요. 대소문자는 구분하지 않습니다.";
$lang->captcha_reload = '이미지 새로고침';
$lang->captcha_play = '음성으로 듣기';
$lang->captcha_denied = '잘못 입력하셨습니다';
?>

View file

@ -0,0 +1,27 @@
<?xml version='1.0' encoding='UTF-8'?>
<lang>
<item name="about_captcha">
<value xml:lang="ko"><![CDATA[위 영어 알파벳을 순서대로 입력해 주세요. 대소문자는 구분하지 않습니다.]]></value>
<value xml:lang="en"><![CDATA[Please type the characters you see in the picture above. They are not case-sensitive.]]></value>
<value xml:lang="jp"><![CDATA[アルファベット順に入力してください。大文字、小文字は区別しません。]]></value>
<value xml:lang="zh-TW"><![CDATA[請依序輸入圖片中的文字,不分大小寫。]]></value>
</item>
<item name="captcha_reload">
<value xml:lang="ko"><![CDATA[이미지 새로고침]]></value>
<value xml:lang="en"><![CDATA[Refresh the image]]></value>
<value xml:lang="jp"><![CDATA[リフレッシュ]]></value>
<value xml:lang="zh-TW"><![CDATA[更換]]></value>
</item>
<item name="captcha_play">
<value xml:lang="ko"><![CDATA[음성으로 듣기]]></value>
<value xml:lang="en"><![CDATA[Listen and type the letters you hear.]]></value>
<value xml:lang="en"><![CDATA[音声]]></value>
<value xml:lang="zh-TW"><![CDATA[播放]]></value>
</item>
<item name="captcha_denied">
<value xml:lang="ko"><![CDATA[잘못 입력하셨습니다]]></value>
<value xml:lang="en"><![CDATA[The characters you entered didn't match the word verification.]]></value>
<value xml:lang="jp"><![CDATA[正しく入力してください。]]></value>
<value xml:lang="zh-TW"><![CDATA[輸入錯誤]]></value>
</item>
</lang>

View file

@ -1,6 +0,0 @@
<?php
$lang->about_captcha = "위 영어 알파벳을 순서대로 입력해 주세요. 대소문자는 구분하지 않습니다.";
$lang->captcha_reload = '이미지 새로고침';
$lang->captcha_play = '음성으로 듣기';
$lang->captcha_denied = '잘못 입력하셨습니다';
?>

View file

@ -1,6 +0,0 @@
<?php
$lang->about_captcha = "위 영어 알파벳을 순서대로 입력해 주세요. 대소문자는 구분하지 않습니다.";
$lang->captcha_reload = '이미지 새로고침';
$lang->captcha_play = '음성으로 듣기';
$lang->captcha_denied = '잘못 입력하셨습니다';
?>

View file

@ -1,6 +0,0 @@
<?php
$lang->about_captcha = "위 영어 알파벳을 순서대로 입력해 주세요. 대소문자는 구분하지 않습니다.";
$lang->captcha_reload = '이미지 새로고침';
$lang->captcha_play = '음성으로 듣기';
$lang->captcha_denied = '잘못 입력하셨습니다';
?>

View file

@ -1,6 +0,0 @@
<?php
$lang->about_captcha = "請依序輸入圖片中的文字,不分大小寫。";
$lang->captcha_reload = '更換';
$lang->captcha_play = '播放';
$lang->captcha_denied = '輸入錯誤';
?>

View file

@ -1,62 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">기본 카운터 애드온</title>
<title xml:lang="jp">アクセスカウンターアドオン</title>
<title xml:lang="zh-CN">网站访问统计</title>
<title xml:lang="en">Counter Addon</title>
<title xml:lang="vi">Counter Addon</title>
<title xml:lang="ge">Counter Addon</title>
<title xml:lang="es">Addon contador básico</title>
<title xml:lang="ru">Аддон счетчика</title>
<title xml:lang="zh-TW">網站訪問統計</title>
<description xml:lang="ko">
XE의 기본 카운터 모듈을 이용하여 접속 정보를 기록합니다.
이 애드온을 켜셔야 접속 정보 수집이 됩니다.
</description>
<description xml:lang="jp">
XEのアクセスカウンターモジュールで接続アクセス情報を記録します。
このアドオンを「使用」に設定してから、接続(アクセス)情報が記録されます。
</description>
<description xml:lang="zh-CN">
利用XE的网站访问统计模块记录网站访问信息。
把状态设置为"使用"时,才会记录网站访问信息.
</description>
<description xml:lang="en">
This addon logs access information based on the basic counter module within XE.
The access information will be collected only if you turn on this addon.
</description>
<description xml:lang="vi">
Addon này sẽ tổng hợp tất cả những lượt truy cập vào Website qua Module Counter có sẵn bên trong XE.
Thông tin truy nhập chỉ được tập hợp khi bạn bật Addon này..
</description>
<description xml:lang="ge">
Dieses Addon-Logs Zugriff auf Informationen basiert auf den grundlegenden Zähler-Modul innerhalb XE.
Der Zugang zu Informationen wird nur erhoben, wenn Sie über dieses Addon.
</description>
<description xml:lang="es">
Este addon contador básico de XE permite llevar la información de acceso a la página web de los visitantes.
Es necesario activar este addon para agregar la información de acceso.
</description>
<description xml:lang="ru">
Этот аддон пишет в лог информацию о доступе к сайту, основанную на базовом модуле счетчика в XE.
Для сбора информации необходимо включить этот аддон.
</description>
<description xml:lang="zh-TW">
使用XE的網站訪問統計模組記錄網站訪問資料。
將狀態設置成"使用"時,才會紀錄網站訪問資料。
</description>
<version>0.1</version>
<date>2007-02-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">기본 카운터 애드온</title>
<title xml:lang="jp">アクセスカウンターアドオン</title>
<title xml:lang="zh-CN">网站访问统计</title>
<title xml:lang="en">Counter Addon</title>
<title xml:lang="vi">Counter Addon</title>
<title xml:lang="ge">Counter Addon</title>
<title xml:lang="es">Addon contador básico</title>
<title xml:lang="ru">Аддон счетчика</title>
<title xml:lang="zh-TW">網站訪問統計</title>
<description xml:lang="ko">
XE의 기본 카운터 모듈을 이용하여 접속 정보를 기록합니다.
이 애드온을 켜셔야 접속 정보 수집이 됩니다.
</description>
<description xml:lang="jp">
XEのアクセスカウンターモジュールで接続アクセス情報を記録します。
このアドオンを「使用」に設定してから、接続(アクセス)情報が記録されます。
</description>
<description xml:lang="zh-CN">
利用XE的网站访问统计模块记录网站访问信息。
把状态设置为"使用"时,才会记录网站访问信息.
</description>
<description xml:lang="en">
This addon logs access information based on the basic counter module within XE.
The access information will be collected only if you enable this addon.
</description>
<description xml:lang="vi">
Addon này sẽ tổng hợp tất cả những lượt truy cập vào Website qua Module Counter có sẵn bên trong XE.
Thông tin truy nhập chỉ được tập hợp khi bạn bật Addon này..
</description>
<description xml:lang="ge">
Dieses Addon-Logs Zugriff auf Informationen basiert auf den grundlegenden Zähler-Modul innerhalb XE.
Der Zugang zu Informationen wird nur erhoben, wenn Sie über dieses Addon.
</description>
<description xml:lang="es">
Este addon contador básico de XE permite llevar la información de acceso a la página web de los visitantes.
Es necesario activar este addon para agregar la información de acceso.
</description>
<description xml:lang="ru">
Этот аддон пишет в лог информацию о доступе к сайту, основанную на базовом модуле счетчика в XE.
Для сбора информации необходимо включить этот аддон.
</description>
<description xml:lang="zh-TW">
使用XE的網站訪問統計模組記錄網站訪問資料。
將狀態設置成"使用"時,才會紀錄網站訪問資料。
</description>
<version>0.1</version>
<date>2007-02-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>

View file

@ -1,14 +1,14 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file counter.addon.php
* @author NHN (developers@xpressengine.com)
* @brief 카운터 애드온
**/
// called_position가 before_display_content 일 경우 실행
if(Context::isInstalled() && $called_position == 'before_module_init' && Context::get('module')!='admin' && Context::getResponseMethod() == 'HTML') {
$oCounterController = &getController('counter');
$oCounterController->procCounterExecute();
}
?>
<?php
if(!defined('__XE__')) exit();
/**
* @file counter.addon.php
* @author NHN (developers@xpressengine.com)
* @brief Counter add-on
**/
// Execute if called_position is before_display_content
if(Context::isInstalled() && $called_position == 'before_module_init' && Context::get('module')!='admin' && Context::getResponseMethod() == 'HTML') {
$oCounterController = &getController('counter');
$oCounterController->counterExecute();
}
?>

View file

@ -1,58 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">커뮤니케이션</title>
<title xml:lang="jp">コミュニケーション</title>
<title xml:lang="zh-CN">会员交流</title>
<title xml:lang="en">Communication</title>
<title xml:lang="vi">Truyền thông</title>
<title xml:lang="ge">커뮤니케이션</title>
<title xml:lang="es">커뮤니케이션</title>
<title xml:lang="ru">Общение</title>
<title xml:lang="zh-TW">交流</title>
<description xml:lang="ko">
커뮤니케이션 모듈의 기능을 활성화 시켜 쪽지나 친구기능을 사용할 수 있도록 해줍니다.
쪽지, 친구기능등을 사용하기 위해서는 이 애드온을 사용으로 해주시면 됩니다.
</description>
<description xml:lang="jp">
メッセージ・友達機能を使うにはこのアドオンを「使用」にして下さい。
</description>
<description xml:lang="zh-CN">
此插件可激活短信箱及添加好友功能。
</description>
<description xml:lang="en">
This addon enables communication module in order to use message or friend function.
Please enable this addon in case you want to use those functions.
</description>
<description xml:lang="vi">
Addon này cho phép sử dụng Module truyền thông để sử dụng tin nhắn hay chức năng bạn bè.
Hãy kích hoạt nếu bạn muốn sử dụng chức năng này.
</description>
<description xml:lang="ge">
커뮤니케이션 모듈의 기능을 활성화 시켜 쪽지나 친구기능을 사용할 수 있도록 해줍니다.
쪽지, 친구기능등을 사용하기 위해서는 이 애드온을 사용으로 해주시면 됩니다.
</description>
<description xml:lang="es">
커뮤니케이션 모듈의 기능을 활성화 시켜 쪽지나 친구기능을 사용할 수 있도록 해줍니다.
쪽지, 친구기능등을 사용하기 위해서는 이 애드온을 사용으로 해주시면 됩니다.
</description>
<description xml:lang="ru">
Активизирует модуль Общение, позволяет использование сообщений между друзьями.
</description>
<description xml:lang="zh-TW">
讓會員擁有短訊和新增好友功能。
</description>
<version>0.1</version>
<date>2008-05-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">커뮤니케이션</title>
<title xml:lang="jp">コミュニケーション</title>
<title xml:lang="zh-CN">会员交流</title>
<title xml:lang="en">Communication</title>
<title xml:lang="vi">Truyền thông</title>
<title xml:lang="ge">커뮤니케이션</title>
<title xml:lang="es">커뮤니케이션</title>
<title xml:lang="ru">Общение</title>
<title xml:lang="zh-TW">交流</title>
<description xml:lang="ko">
커뮤니케이션 모듈의 기능을 활성화 시켜 쪽지나 친구기능을 사용할 수 있도록 해줍니다.
쪽지, 친구기능등을 사용하기 위해서는 이 애드온을 사용으로 해주시면 됩니다.
</description>
<description xml:lang="jp">
メッセージ・友達機能を使うにはこのアドオンを「使用」にして下さい。
</description>
<description xml:lang="zh-CN">
此插件可激活短信箱及添加好友功能。
</description>
<description xml:lang="en">
This addon enables the communication module in order to use messaging or friend functions.
Please enable this addon in case you want to use those functions.
</description>
<description xml:lang="vi">
Addon này cho phép sử dụng Module truyền thông để sử dụng tin nhắn hay chức năng bạn bè.
Hãy kích hoạt nếu bạn muốn sử dụng chức năng này.
</description>
<description xml:lang="ge">
커뮤니케이션 모듈의 기능을 활성화 시켜 쪽지나 친구기능을 사용할 수 있도록 해줍니다.
쪽지, 친구기능등을 사용하기 위해서는 이 애드온을 사용으로 해주시면 됩니다.
</description>
<description xml:lang="es">
커뮤니케이션 모듈의 기능을 활성화 시켜 쪽지나 친구기능을 사용할 수 있도록 해줍니다.
쪽지, 친구기능등을 사용하기 위해서는 이 애드온을 사용으로 해주시면 됩니다.
</description>
<description xml:lang="ru">
Активизирует модуль Общение, позволяет использование сообщений между друзьями.
</description>
<description xml:lang="zh-TW">
讓會員擁有短訊和新增好友功能。
</description>
<version>0.1</version>
<date>2008-05-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>

View file

@ -1,3 +0,0 @@
<?php
$lang->alert_new_message_arrived = 'You have a new message. Do you want to check now?';
?>

View file

@ -1,3 +0,0 @@
<?php
$lang->alert_new_message_arrived = 'Usted tiene un nuevo mensaje. Quiere comprobar ahora?';
?>

View file

@ -1,3 +0,0 @@
<?php
$lang->alert_new_message_arrived = 'Sie haben eine neue Nachricht. Wollen Sie jetzt prüfen, ob?';
?>

View file

@ -1,3 +0,0 @@
<?php
$lang->alert_new_message_arrived = '%d個の新しいメッセージが届いています。 確認しますか?';
?>

View file

@ -1,3 +0,0 @@
<?php
$lang->alert_new_message_arrived = '%d개의 새로운 메시지가 도착하였습니다. 확인하시겠습니까?';
?>

View file

@ -0,0 +1,13 @@
<?xml version='1.0' encoding='UTF-8'?>
<lang>
<item name="alert_new_message_arrived">
<value xml:lang="ko"><![CDATA[%d개의 새로운 메시지가 도착하였습니다. 확인하시겠습니까?]]></value>
<value xml:lang="en"><![CDATA[You have %d new message(s). Do you want to check it now?]]></value>
<value xml:lang="jp"><![CDATA[%d件の新しいメッセージがあります。確認しますか]]></value>
<value xml:lang="zh-CN"><![CDATA[您有新消息。要确认吗?]]></value>
<value xml:lang="zh-TW"><![CDATA[您收到%d個新訊息。您想要檢視嗎?]]></value>
<value xml:lang="ru"><![CDATA[У Вас новые сообщения. Проверите сейчас?]]></value>
<value xml:lang="es"><![CDATA[Usted tiene un nuevo mensaje. Quiere comprobar ahora?]]></value>
<value xml:lang="vi"><![CDATA[Bạn có một tin nhắn mới. bạn có muốn kiểm tra ngay bây giờ không?]]></value>
</item>
</lang>

View file

@ -1,9 +0,0 @@
<?php
/**
* @file ru.lang.php
* @author NHN (developers@xpressengine.com) | translation by Maslennikov Evgeny aka X-[Vr]bL1s5 | e-mail: x-bliss[a]tut.by; ICQ: 225035467;
* @brief Russian basic language pack
**/
$lang->alert_new_message_arrived = 'У Вас новые сообщения. Проверите сейчас?';
?>

View file

@ -1,11 +0,0 @@
<?php
/* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░ * @File : common/lang/vi.lang.php ░░
░░ * @Author : NHN (developers@xpressengine.com) ░░
░░ * @Trans : Đào Đức Duy (ducduy.dao.vn@vietxe.net) ░░
░░ * @Website: http://vietxe.net ░░
░░ * @Brief : Vietnamese Language Pack (Only basic words are included here) ░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ */
$lang->alert_new_message_arrived = 'Bạn có một tin nhắn mới. bạn có muốn kiểm tra ngay bây giờ không?';
?>

View file

@ -1,3 +0,0 @@
<?php
$lang->alert_new_message_arrived = '您有新消息。要确认吗?';
?>

View file

@ -1,3 +0,0 @@
<?php
$lang->alert_new_message_arrived = '您收到%d個新訊息。您想要檢視嗎?';
?>

View file

@ -1,85 +1,71 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file member_communication.addon.php
* @author NHN (developers@xpressengine.com)
* @brief 사용자의 커뮤니케이션 기능을 활성화
*
* - 새로운 쪽지가 왔을 경우 팝업으로 띄움
* - MemberModel::getMemberMenu 호출시 대상이 회원일 경우 쪽지 보내기 기능 추가합니다.
* - MemberModel::getMemberMenu 호출시 친구 등록 메뉴를 추가합니다.
**/
// 비로그인 사용자면 중지
$logged_info = Context::get('logged_info');
if(!$logged_info) return;
/**
* 기능 수행 : 팝업 회원정보 보기에서 쪽지/친구 메뉴 추가. 시작할때 새쪽지가 왔는지 검사
**/
if($called_position == 'before_module_init' && $this->module != 'member') {
// 커뮤니케이션 모듈의 언어파일을 읽음
Context::loadLang('./modules/communication/lang');
// 회원 로그인 정보중에서 쪽지등의 메뉴를 추가
$oMemberController = &getController('member');
$oMemberController->addMemberMenu('dispCommunicationFriend', 'cmd_view_friend');
$oMemberController->addMemberMenu('dispCommunicationMessages', 'cmd_view_message_box');
// 새로운 쪽지에 대한 플래그가 있으면 쪽지 보기 팝업 띄움
$flag_path = './files/member_extra_info/new_message_flags/'.getNumberingPath($logged_info->member_srl);
$flag_file = sprintf('%s%s', $flag_path, $logged_info->member_srl);
if(file_exists($flag_file)) {
$new_message_count = FileHandler::readFile($flag_file);
FileHandler::removeFile($flag_file);
Context::loadLang('./addons/member_communication/lang');
$script = sprintf('<script type="text/javascript"> jQuery(function() { if(confirm("%s")) { popopen("%s"); } }); </script>', sprintf(Context::getLang('alert_new_message_arrived'), $new_message_count), Context::getRequestUri().'?module=communication&act=dispCommunicationNewMessage');
Context::addHtmlHeader( $script );
}
/**
* 기능 수행 : 사용자 이름을 클릭시 요청되는 팝업메뉴의 메뉴에 쪽지 발송, 친구추가등의 링크 추가
**/
} elseif($called_position == 'before_module_proc' && $this->act == 'getMemberMenu') {
$oMemberController = &getController('member');
$member_srl = Context::get('target_srl');
$mid = Context::get('cur_mid');
// communication 모델 객체 생성
$oCommunicationModel = &getModel('communication');
// 자신이라면 쪽지함 보기 기능 추가
if($logged_info->member_srl == $member_srl) {
// 자신의 쪽지함 보기 기능 추가
$oMemberController->addMemberPopupMenu(getUrl('','mid',$mid,'act','dispCommunicationMessages'), 'cmd_view_message_box', './modules/communication/tpl/images/icon_message_box.gif', 'self');
// 친구 목록 보기
$oMemberController->addMemberPopupMenu(getUrl('','mid',$mid,'act','dispCommunicationFriend'), 'cmd_view_friend', './modules/communication/tpl/images/icon_friend_box.gif', 'self');
// 아니라면 쪽지 발송, 친구 등록 추가
} else {
// 대상 회원의 정보를 가져옴
$oMemberModel = &getModel('member');
$target_member_info = $oMemberModel->getMemberInfoByMemberSrl($member_srl);
if(!$target_member_info->member_srl) return;
// 로그인된 사용자 정보를 구함
$logged_info = Context::get('logged_info');
// 쪽지 발송 메뉴를 만듬
if( $logged_info->is_admin == 'Y' || $target_member_info->allow_message =='Y' || ($target_member_info->allow_message == 'F' && $oCommunicationModel->isFriend($member_srl)))
$oMemberController->addMemberPopupMenu(getUrl('','module','communication','act','dispCommunicationSendMessage','receiver_srl',$member_srl), 'cmd_send_message', './modules/communication/tpl/images/icon_write_message.gif', 'popup');
// 친구 등록 메뉴를 만듬 (이미 등록된 친구가 아닐 경우)
if(!$oCommunicationModel->isAddedFriend($member_srl))
$oMemberController->addMemberPopupMenu(getUrl('','module','communication','act','dispCommunicationAddFriend','target_srl',$member_srl), 'cmd_add_friend', './modules/communication/tpl/images/icon_add_friend.gif', 'popup');
}
}
?>
<?php
if(!defined('__XE__')) exit();
/**
* @file member_communication.addon.php
* @author NHN (developers@xpressengine.com)
* @brief Promote user communication
*
* - Pop-up the message if new message comes in
* - When calling MemberModel::getMemberMenu, feature to send a message is added
* - When caliing MemberModel::getMemberMenu, feature to add a friend is added
**/
// Stop if non-logged-in user is
$logged_info = Context::get('logged_info');
if(!$logged_info) return;
/**
* Message/Friend munus are added on the pop-up window and member profile. Check if a new message is received
**/
if($called_position == 'before_module_init' && $this->module != 'member') {
// Load a language file from the communication module
Context::loadLang('./modules/communication/lang');
// Add menus on the member login information
$oMemberController = &getController('member');
$oMemberController->addMemberMenu('dispCommunicationFriend', 'cmd_view_friend');
$oMemberController->addMemberMenu('dispCommunicationMessages', 'cmd_view_message_box');
// Pop-up to display messages if a flag on new message is set
$flag_path = './files/member_extra_info/new_message_flags/'.getNumberingPath($logged_info->member_srl);
$flag_file = $flag_path.$logged_info->member_srl;
if(file_exists($flag_file)) {
$new_message_count = trim(FileHandler::readFile($flag_file));
FileHandler::removeFile($flag_file);
Context::loadLang('./addons/member_communication/lang');
Context::loadFile(array('./addons/member_communication/tpl/member_communication.js'), true);
$text = preg_replace('@\r?\n@', '\\n', addslashes(Context::getLang('alert_new_message_arrived')));
$link = Context::getRequestUri().'?module=communication&act=dispCommunicationNewMessage';
$script = "<script type=\"text/javascript\">jQuery(function(){ xeNotifyMessage('{$text}','{$new_message_count}'); });</script>";
Context::addHtmlFooter($script);
}
} elseif($called_position == 'before_module_proc' && $this->act == 'getMemberMenu') {
$oMemberController = &getController('member');
$member_srl = Context::get('target_srl');
$mid = Context::get('cur_mid');
// Creates communication model object
$oCommunicationModel = &getModel('communication');
// Add a feature to display own message box.
if($logged_info->member_srl == $member_srl) {
// Add your own viewing Note Template
$oMemberController->addMemberPopupMenu(getUrl('','mid',$mid,'act','dispCommunicationMessages'), 'cmd_view_message_box', '', 'self');
// Display a list of friends
$oMemberController->addMemberPopupMenu(getUrl('','mid',$mid,'act','dispCommunicationFriend'), 'cmd_view_friend', '', 'self');
// If not, Add menus to send message and to add friends
} else {
// Get member information
$oMemberModel = &getModel('member');
$target_member_info = $oMemberModel->getMemberInfoByMemberSrl($member_srl);
if(!$target_member_info->member_srl) return;
// Get logged-in user information
$logged_info = Context::get('logged_info');
// Add a menu for sending message
if( $logged_info->is_admin == 'Y' || $target_member_info->allow_message =='Y' || ($target_member_info->allow_message == 'F' && $oCommunicationModel->isFriend($member_srl)))
$oMemberController->addMemberPopupMenu(getUrl('','module','communication','act','dispCommunicationSendMessage','receiver_srl',$member_srl), 'cmd_send_message', '', 'popup');
// Add a menu for listing friends (if a friend is new)
if(!$oCommunicationModel->isAddedFriend($member_srl))
$oMemberController->addMemberPopupMenu(getUrl('','module','communication','act','dispCommunicationAddFriend','target_srl',$member_srl), 'cmd_add_friend', '', 'popup');
}
}
?>

View file

@ -0,0 +1,29 @@
(function($){
window.xeNotifyMessage = function(text, count){
var $bar;
$bar = $('div.notifyMessage');
if(!$bar.length) {
$bar = $('<div class="notifyMessage" />')
.hide()
.css({
position : 'absolute',
background : '#ff0',
border : '1px solid #990',
textAlign : 'center'
})
.appendTo(document.body);
}
text = text.replace('%d', count);
h = $bar.html('<a href="'+current_url.setQuery('act','dispCommunicationMessages')+'">'+text+'</a>').height();
$bar.css('top', -h-4).show().animate({top:0});
// hide after 10 seconds
setTimeout(function(){
$bar.animate({top:-h-4}, function(){ $bar.hide() });
}, 10000);
};
})(jQuery);

View file

@ -1,53 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">회원 확장 정보 출력</title>
<title xml:lang="jp">会員情報拡張表示</title>
<title xml:lang="zh-CN">用户扩展信息</title>
<title xml:lang="en">Extra Member Info</title>
<title xml:lang="vi">Bổ xung thông tin thành viên</title>
<title xml:lang="ge">회원 확장 정보 출력</title>
<title xml:lang="es">회원 확장 정보 출력</title>
<title xml:lang="ru">Экстраинформация о пользователях</title>
<title xml:lang="zh-TW">用戶延伸資料</title>
<description xml:lang="ko">
회원이 등록한 이미지이름, 이미지마크를 사용하기 위해서는 이 애드온을 활성화 시키세요.
</description>
<description xml:lang="jp">
会員が登録したイメージニックネーム、イメージマークを使うためにはこのアドオンをオンにして下さい。
</description>
<description xml:lang="zh-CN">
此插件将把用户信息中的昵称图片,用户图标,签名等信息显示到页面当中。
</description>
<description xml:lang="en">
This addon displays a member's image name, image mark.
</description>
<description xml:lang="vi">
Addon này sẽ hiển thị hình ảnh thay thế tên và hình đánh dấu của thành viên.
</description>
<description xml:lang="ge">
This addon displays a member's image name, image mark.
</description>
<description xml:lang="es">
This addon displays a member's image name, image mark.
</description>
<description xml:lang="ru">
Аддон изображает имя, марку картинки пользователя.
</description>
<description xml:lang="zh-TW">
可將用戶資料中的暱稱圖片、用戶圖示、簽名檔等資料顯示到頁面當中。
</description>
<version>0.2</version>
<date>2007-02-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">회원 확장 정보 출력</title>
<title xml:lang="jp">会員情報拡張表示</title>
<title xml:lang="zh-CN">用户扩展信息</title>
<title xml:lang="en">Extra Member Info</title>
<title xml:lang="vi">Bổ xung thông tin thành viên</title>
<title xml:lang="ge">회원 확장 정보 출력</title>
<title xml:lang="es">회원 확장 정보 출력</title>
<title xml:lang="ru">Экстраинформация о пользователях</title>
<title xml:lang="zh-TW">用戶延伸資料</title>
<description xml:lang="ko">
회원이 등록한 이미지이름, 이미지마크를 사용하기 위해서는 이 애드온을 활성화 시키세요.
</description>
<description xml:lang="jp">
会員が登録したイメージニックネーム、イメージマークを使うためにはこのアドオンをオンにして下さい。
</description>
<description xml:lang="zh-CN">
此插件将把用户信息中的昵称图片,用户图标,签名等信息显示到页面当中。
</description>
<description xml:lang="en">
This addon displays a member's image name, image mark.
</description>
<description xml:lang="vi">
Addon này sẽ hiển thị hình ảnh thay thế tên và hình đánh dấu của thành viên.
</description>
<description xml:lang="ge">
This addon displays a member's image name, image mark.
</description>
<description xml:lang="es">
This addon displays a member's image name, image mark.
</description>
<description xml:lang="ru">
Аддон изображает имя, марку картинки пользователя.
</description>
<description xml:lang="zh-TW">
可將用戶資料中的暱稱圖片、用戶圖示、簽名檔等資料顯示到頁面當中。
</description>
<version>0.2</version>
<date>2007-02-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>

View file

@ -1,23 +1,21 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file image_name.addon.php
* @author NHN (developers@xpressengine.com)
* @brief 사용자의 이미지이름/ 이미지마크등을 출력
*
* <div class="member_회원번호">....</div> 정의가 부분을 찾아 회원번호를 구해서
* 이미지이름, 이미지마크가 있는지를 확인하여 있으면 내용을 변경해버립니다.
**/
/**
* 출력되기 바로 직전일 경우에 이미지이름/이미지마크등을 변경
**/
if($called_position != "before_display_content" || Context::get('act')=='dispPageAdminContentModify') return;
// 회원 이미지이름/ 마크/ 찾아서 대체할 함수를 담고 있는 파일을 include
require_once('./addons/member_extra_info/member_extra_info.lib.php');
// 1. 출력문서중에서 <div class="member_번호">content</div>를 찾아 MemberController::transImageName() 를 이용하여 이미지이름/마크로 변경
$output = preg_replace_callback('!<(div|span|a)([^\>]*)member_([0-9]+)([^\>]*)>(.*?)\<\/(div|span|a)\>!is', 'memberTransImageName', $output);
?>
<?php
if(!defined('__XE__')) exit();
/**
* @file image_name.addon.php
* @author NHN (developers@xpressengine.com)
* @brief Display user image name/image mark
*
* Find member_srl in the part with <div class="member_MemberSerialNumber"> .... </div>
* Check if ther is image name and image mark. Then change it.
**/
/**
* Just before displaying, change image name/ image mark
**/
if($called_position != "before_display_content" || Context::get('act')=='dispPageAdminContentModify') return;
// Include a file having functions to replace member image name/mark
require_once('./addons/member_extra_info/member_extra_info.lib.php');
// 1. Find a part <div class="member_MemberSerialNumber"> content </div> in the output document, change it to image name/mark by using MemberController::transImageName()
$output = preg_replace_callback('!<(div|span|a)([^\>]*)member_([0-9]+)([^\>]*)>(.*?)\<\/(div|span|a)\>!is', 'memberTransImageName', $output);
?>

View file

@ -1,22 +1,19 @@
<?php
/**
* @brief div 또는 span에 member_번호 있을때 해당 회원 번호에 맞는 이미지이름이나 닉이미지를 대체
* @brief If member_srl exists in the div or span, replace to image name or nick image for each member_srl
**/
function memberTransImageName($matches) {
// 회원번호를 추출하여 0보다 찾으면 본문중 text만 return
// If member_srl < 0, then return text only in the body
$member_srl = $matches[3];
if($member_srl<0) return $matches[5];
$site_module_info = Context::get('site_module_info');
$oMemberModel = &getModel('member');
$group_image = $oMemberModel->getGroupImageMark($member_srl,$site_module_info->site_srl);
// 회원이 아닐경우(member_srl = 0) 본문 전체를 return
// If member_srl=o(not a member), return the entire body
$nick_name = $matches[5];
if(!$member_srl) return $matches[0];
// 전역변수에 미리 설정한 데이터가 있다면 그걸 return
// If pre-defined data in the global variablesm return it
if(!$GLOBALS['_transImageNameList'][$member_srl]->cached) {
$GLOBALS['_transImageNameList'][$member_srl]->cached = true;
$image_name_file = sprintf('files/member_extra_info/image_name/%s%d.gif', getNumberingPath($member_srl), $member_srl);
@ -29,14 +26,17 @@
$image_name_file = $GLOBALS['_transImageNameList'][$member_srl]->image_name_file;
$image_mark_file = $GLOBALS['_transImageNameList'][$member_srl]->image_mark_file;
}
// 이미지이름이나 마크가 없으면 원본 정보를 세팅
// If image name and mark doesn't exist, set the original information
if(!$image_name_file && !$image_mark_file && !$group_image) return $matches[0];
if($image_name_file) $nick_name = sprintf('<img src="%s%s" border="0" alt="id: %s" title="id: %s" style="vertical-align:middle;margin-right:3px" />', Context::getRequestUri(),$image_name_file, strip_tags($nick_name), strip_tags($nick_name));
if($image_mark_file) $nick_name = sprintf('<img src="%s%s" border="0" alt="id: %s" title="id : %s" style="vertical-align:middle;margin-right:3px"/>%s', Context::getRequestUri(),$image_mark_file, strip_tags($nick_name), strip_tags($nick_name), $nick_name);
// check member_config
$config = $oMemberModel->getMemberConfig();
if($group_image) $nick_name = sprintf('<img src="%s" border="0" style="vertical-align:middle;margin-right:3px" alt="%s" title="%s" />%s', $group_image->src, $group_image->title, $group_image->description, $nick_name);
if($config->image_name == 'Y' && $image_name_file) $nick_name = sprintf('<img src="%s%s" border="0" alt="id: %s" title="id: %s" style="vertical-align:middle;margin-right:3px" />', Context::getRequestUri(),$image_name_file, strip_tags($nick_name), strip_tags($nick_name));
if($config->image_mark == 'Y' && $image_mark_file) $nick_name = sprintf('<img src="%s%s" border="0" alt="id: %s" title="id : %s" style="vertical-align:middle;margin-right:3px"/>%s', Context::getRequestUri(),$image_mark_file, strip_tags($nick_name), strip_tags($nick_name), $nick_name);
if($group_image) $nick_name = sprintf('<img src="%s" border="0" style="max-height:16px;vertical-align:middle;margin-right:3px" alt="%s" title="%s" />%s', $group_image->src, $group_image->title, $group_image->description, $nick_name);
$orig_text = preg_replace('/'.preg_quote($matches[5],'/').'<\/'.$matches[6].'>$/', '', $matches[0]);

View file

@ -1,103 +1,103 @@
<?php
/**
* HDML Library ver 0.1
* @author NHN (developers@xpressengine.com)
**/
class wap extends mobileXE {
/**
* @brief constructor
**/
function wap() {
parent::mobileXE();
}
/**
* @brief hdml 헤더 출력
**/
function printHeader() {
header("Content-Type:text/x-hdml; charset=".$this->charset);
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
print '<hdml version=3.0 ttl=0 markable=true>';
print "\n";
print $this->hasChilds()?'<choice name=main>':'<display>';
print "\n";
if($this->upperUrl) {
$url = $this->upperUrl;
printf('<action type=soft1 task=go dest="%s" label="%s">%s', $url->url, $url->text, "\n");
}
}
/**
* @brief 제목을 출력
**/
function printTitle() {
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
printf('<b>&lt;%s%s&gt;%s', $this->title,$titlePageStr,"\n");
}
/**
* @brief 내용을 출력
* hasChilds() 있으면 목록형을 그렇지 않으면 컨텐츠를 출력
**/
function printContent() {
if($this->hasChilds()) {
foreach($this->getChilds() as $key => $val) {
if(!$val['link']) continue;
printf('<ce task=go label="%s" dest="%s">%s%s',Context::getLang('cmd_select'), $val['href'], $val['text'], "\n");
}
} else {
printf('<wrap>%s<br>%s', $this->getContent(),"\n");
}
}
/**
* @brief 버튼을 출력함
**/
function printBtn() {
// 메뉴 형식
if($this->hasChilds()) {
if($this->nextUrl) {
$url = $this->nextUrl;
printf('<ce task=go label="%s" dest="%s">%s%s', $url->text, $url->url, $url->text, "\n");
}
if($this->prevUrl) {
$url = $this->prevUrl;
printf('<ce task=go label="%s" dest="%s">%s%s', $url->text, $url->url, $url->text, "\n");
}
if($this->homeUrl) {
$url = $this->homeUrl;
printf('<ce task=go label="%s" dest="%s">%s%s', $url->text, $url->url, $url->text, "\n");
}
// 컨텐츠 형식
} else {
if($this->nextUrl) {
$url = $this->nextUrl;
printf('<a task=gosub label="%s" dest="%s">%s</a>', $url->text, $url->url, $url->text);
}
if($this->prevUrl) {
$url = $this->prevUrl;
printf('<a task=gosub label="%s" dest="%s">%s</a>', $url->text, $url->url, $url->text);
}
if($this->homeUrl) {
$url = $this->homeUrl;
printf('<a task=gosub label="%s" dest="%s">%s</a>', $url->text, $url->url, $url->text);
}
}
}
/**
* @brief 푸터 정보를 출력
**/
function printFooter() {
print $this->hasChilds()?'</choice>':'</display>';
print "\n";
print("</hdml>");
}
}
?>
<?php
/**
* HDML Library ver 0.1
* @author NHN (developers@xpressengine.com)
**/
class wap extends mobileXE {
/**
* @brief constructor
**/
function wap() {
parent::mobileXE();
}
/**
* @brief hdml header output
**/
function printHeader() {
header("Content-Type:text/x-hdml; charset=".$this->charset);
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
print '<hdml version=3.0 ttl=0 markable=true>';
print "\n";
print $this->hasChilds()?'<choice name=main>':'<display>';
print "\n";
if($this->upperUrl) {
$url = $this->upperUrl;
printf('<action type=soft1 task=go dest="%s" label="%s">%s', $url->url, $url->text, "\n");
}
}
/**
* @brief Output title
**/
function printTitle() {
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
printf('<b>&lt;%s%s&gt;%s', $this->title,$titlePageStr,"\n");
}
/**
* @brief Output information
* hasChilds() if there is a list of content types, otherwise output
**/
function printContent() {
if($this->hasChilds()) {
foreach($this->getChilds() as $key => $val) {
if(!$val['link']) continue;
printf('<ce task=go label="%s" dest="%s">%s%s',Context::getLang('cmd_select'), $val['href'], $val['text'], "\n");
}
} else {
printf('<wrap>%s<br>%s', $this->getContent(),"\n");
}
}
/**
* @brief Button to output
**/
function printBtn() {
// Menu Types
if($this->hasChilds()) {
if($this->nextUrl) {
$url = $this->nextUrl;
printf('<ce task=go label="%s" dest="%s">%s%s', $url->text, $url->url, $url->text, "\n");
}
if($this->prevUrl) {
$url = $this->prevUrl;
printf('<ce task=go label="%s" dest="%s">%s%s', $url->text, $url->url, $url->text, "\n");
}
if($this->homeUrl) {
$url = $this->homeUrl;
printf('<ce task=go label="%s" dest="%s">%s%s', $url->text, $url->url, $url->text, "\n");
}
// Content Types
} else {
if($this->nextUrl) {
$url = $this->nextUrl;
printf('<a task=gosub label="%s" dest="%s">%s</a>', $url->text, $url->url, $url->text);
}
if($this->prevUrl) {
$url = $this->prevUrl;
printf('<a task=gosub label="%s" dest="%s">%s</a>', $url->text, $url->url, $url->text);
}
if($this->homeUrl) {
$url = $this->homeUrl;
printf('<a task=gosub label="%s" dest="%s">%s</a>', $url->text, $url->url, $url->text);
}
}
}
/**
* @brief Footer information output
**/
function printFooter() {
print $this->hasChilds()?'</choice>':'</display>';
print "\n";
print("</hdml>");
}
}
?>

View file

@ -1,82 +1,80 @@
<?php
/**
* mhtml Library ver 0.1
* @author NHN (developers@xpressengine.com) / lang_select : misol
**/
class wap extends mobileXE {
/**
* @brief constructor
**/
function wap() {
parent::mobileXE();
}
/**
* @brief hdml 헤더 출력
**/
function printHeader() {
print("<html><head>\n");
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
printf("<title>%s%s</title></head><body>\n", htmlspecialchars($this->title),htmlspecialchars($titlePageStr));
}
// 제목을 출력
function printTitle() {
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
printf('&lt;%s%s&gt;<br>%s', htmlspecialchars($this->title),htmlspecialchars($titlePageStr),"\n");
}
/**
* @brief 내용을 출력
* hasChilds() 있으면 목록형을 그렇지 않으면 컨텐츠를 출력
**/
function printContent() {
if($this->hasChilds()) {
foreach($this->getChilds() as $key => $val) {
if(!$val['link']) continue;
printf('<a href="%s" accesskey="%s">%s</a><br>%s', $val['href'], $this->getNo(), $val['text'], "\n");
if($val['extra']) printf("<br>%s\n",str_replace('<br/>','<br>',$val['extra']));
}
} else {
print(str_replace('<br/>','<br>',$this->getContent())."\n");
}
print "<hr><br>";
}
/**
* @brief 버튼을 출력함
**/
function printBtn() {
if($this->nextUrl) {
$url = $this->nextUrl;
printf('<a href="%s">%s</a><br>%s', $url->url, $url->text, "\n");
}
if($this->prevUrl) {
$url = $this->prevUrl;
printf('<a href="%s">%s</a><br>%s', $url->url, $url->text, "\n");
}
// 언어선택
if(!parent::isLangChange()){
$url = getUrl('','lcm','1','sel_lang',Context::getLangType(),'return_uri',Context::get('current_url'));
printf('<a href="%s">%s</a><br>%s', $url, 'Language : '.Context::getLang('select_lang'), "\n");
}
else {
printf('<a href="%s">%s</a><br>%s', Context::get('return_uri'), Context::getLang('lang_return'), "\n");
}
if($this->upperUrl) {
$url = $this->upperUrl;
printf('<btn href="%s" name="%s">%s', $url->url, $url->text, "\n");
}
if($this->homeUrl) {
$url = $this->homeUrl;
printf('<a btn="%s" href="%s">%s</a><br>%s', $url->text, $url->url, $url->text, "\n");
}
}
// 푸터 정보를 출력
function printFooter() {
print("</body></html>\n");
}
}
?>
<?php
/**
* mhtml Library ver 0.1
* @author NHN (developers@xpressengine.com) / lang_select : misol
**/
class wap extends mobileXE {
/**
* @brief constructor
**/
function wap() {
parent::mobileXE();
}
/**
* @brief hdml header output
**/
function printHeader() {
print("<html><head>\n");
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
printf("<title>%s%s</title></head><body>\n", htmlspecialchars($this->title),htmlspecialchars($titlePageStr));
}
// Output title
function printTitle() {
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
printf('&lt;%s%s&gt;<br>%s', htmlspecialchars($this->title),htmlspecialchars($titlePageStr),"\n");
}
/**
* @brief Output information
* hasChilds() if there is a list of content types, otherwise output
**/
function printContent() {
if($this->hasChilds()) {
foreach($this->getChilds() as $key => $val) {
if(!$val['link']) continue;
printf('<a href="%s" accesskey="%s">%s</a><br>%s', $val['href'], $this->getNo(), $val['text'], "\n");
if($val['extra']) printf("<br>%s\n",str_replace('<br/>','<br>',$val['extra']));
}
} else {
print(str_replace('<br/>','<br>',$this->getContent())."\n");
}
print "<hr><br>";
}
/**
* @brief Button to output
**/
function printBtn() {
if($this->nextUrl) {
$url = $this->nextUrl;
printf('<a href="%s">%s</a><br>%s', $url->url, $url->text, "\n");
}
if($this->prevUrl) {
$url = $this->prevUrl;
printf('<a href="%s">%s</a><br>%s', $url->url, $url->text, "\n");
}
// Select Language
if(!parent::isLangChange()){
$url = getUrl('','lcm','1','sel_lang',Context::getLangType(),'return_uri',Context::get('current_url'));
printf('<a href="%s">%s</a><br>%s', $url, 'Language : '.Context::getLang('select_lang'), "\n");
}
else {
printf('<a href="%s">%s</a><br>%s', Context::get('return_uri'), Context::getLang('lang_return'), "\n");
}
if($this->upperUrl) {
$url = $this->upperUrl;
printf('<btn href="%s" name="%s">%s', $url->url, $url->text, "\n");
}
if($this->homeUrl) {
$url = $this->homeUrl;
printf('<a btn="%s" href="%s">%s</a><br>%s', $url->text, $url->url, $url->text, "\n");
}
}
// Footer information output
function printFooter() {
print("</body></html>\n");
}
}
?>

File diff suppressed because it is too large Load diff

View file

@ -1,106 +1,104 @@
<?php
/**
* WML Library ver 0.1
* @author NHN (developers@xpressengine.com) / lang_select : misol
**/
class wap extends mobileXE {
/**
* @brief constructor
**/
function wap() {
parent::mobileXE();
}
/**
* @brief wml 헤더 출력
**/
function printHeader() {
header("Content-Type: text/vnd.wap.wml");
header("charset: ".$this->charset);
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
print("<?xml version=\"1.0\" encoding=\"".$this->charset."\"?><!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">\n");
// 카드제목
printf("<wml>\n<card title=\"%s%s\">\n<p>\n",htmlspecialchars($this->title),htmlspecialchars($titlePageStr));
}
/**
* @brief 제목을 출력
**/
function printTitle() {
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
printf('&lt;%s%s&gt;<br/>%s', htmlspecialchars($this->title),htmlspecialchars($titlePageStr),"\n");
}
/**
* @brief 내용을 출력
* hasChilds() 있으면 목록형을 그렇지 않으면 컨텐츠를 출력
**/
function printContent() {
if($this->hasChilds()) {
foreach($this->getChilds() as $key => $val) {
if(!$val['link']) continue;
printf('<do type="%s" label="%s"><go href="%s" /></do>%s', $this->getNo(), htmlspecialchars($val['text']), $val['href'], "\n");
if($val['extra']) printf("%s\n",$val['extra']);
}
} else {
printf('%s<br/>%s', str_replace("<br>","<br/>",$this->getContent()),"\n");
}
print('<br/>');
}
/**
* @brief 버튼을 출력함
**/
function printBtn() {
if($this->nextUrl) {
$url = $this->nextUrl;
printf('<do type="vnd.next" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n");
}
if($this->prevUrl) {
$url = $this->prevUrl;
printf('<do type="vnd.prev" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n");
}
// 기타 해당사항 없는 버튼 출력 담당 (array로 전달) type??
if($this->etcBtn) {
if(is_array($this->etcBtn)) {
foreach($this->etcBtn as $key=>$val) {
printf('<do type="vnd.btn%s" label="%s"><go href="%s"/></do>%s', $key, $val['text'], $val['url'], "\n");
}
}
}
// 언어선택
if(!parent::isLangChange()){
$url = getUrl('','lcm','1','sel_lang',Context::getLangType(),'return_uri',Context::get('current_url'));
printf('<do type="vnd.lang" label="%s"><go href="%s"/></do>%s', 'Language : '.Context::getLang('select_lang'), $url, "\n");
}
else {
printf('<do type="vnd.lang" label="%s"><go href="%s"/></do>%s', Context::getLang('lang_return'), Context::get('return_uri'), "\n");
}
if($this->homeUrl) {
$url = $this->homeUrl;
printf('<do type="access" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n");
}
if($this->upperUrl) {
$url = $this->upperUrl;
printf('<do type="vnd.up" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n");
}
}
// 푸터 정보를 출력
function printFooter() {
print("</p>\n</card>\n</wml>");
}
// 목록등에서 일련 번호를 리턴한다
function getNo() {
if(Context::get('mobile_skt')==1) {
return "vnd.skmn".parent::getNo();
}
else {
return parent::getNo();
}
return $str;
}
}
?>
<?php
/**
* WML Library ver 0.1
* @author NHN (developers@xpressengine.com) / lang_select : misol
**/
class wap extends mobileXE {
/**
* @brief constructor
**/
function wap() {
parent::mobileXE();
}
/**
* @brief wml header output
**/
function printHeader() {
header("Content-Type: text/vnd.wap.wml");
header("charset: ".$this->charset);
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
print("<?xml version=\"1.0\" encoding=\"".$this->charset."\"?><!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">\n");
// Card Title
printf("<wml>\n<card title=\"%s%s\">\n<p>\n",htmlspecialchars($this->title),htmlspecialchars($titlePageStr));
}
/**
* @brief Output title
**/
function printTitle() {
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
printf('&lt;%s%s&gt;<br/>%s', htmlspecialchars($this->title),htmlspecialchars($titlePageStr),"\n");
}
/**
* @brief Output information
* hasChilds() if there is a list of content types, otherwise output
**/
function printContent() {
if($this->hasChilds()) {
foreach($this->getChilds() as $key => $val) {
if(!$val['link']) continue;
printf('<do type="%s" label="%s"><go href="%s" /></do>%s', $this->getNo(), htmlspecialchars($val['text']), $val['href'], "\n");
if($val['extra']) printf("%s\n",$val['extra']);
}
} else {
printf('%s<br/>%s', str_replace("<br>","<br/>",$this->getContent()),"\n");
}
print('<br/>');
}
/**
* @brief Button to output
**/
function printBtn() {
if($this->nextUrl) {
$url = $this->nextUrl;
printf('<do type="vnd.next" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n");
}
if($this->prevUrl) {
$url = $this->prevUrl;
printf('<do type="vnd.prev" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n");
}
// Others are not applicable in charge of the button output (array passed) type??
if($this->etcBtn) {
if(is_array($this->etcBtn)) {
foreach($this->etcBtn as $key=>$val) {
printf('<do type="vnd.btn%s" label="%s"><go href="%s"/></do>%s', $key, $val['text'], $val['url'], "\n");
}
}
}
// Select Language
if(!parent::isLangChange()){
$url = getUrl('','lcm','1','sel_lang',Context::getLangType(),'return_uri',Context::get('current_url'));
printf('<do type="vnd.lang" label="%s"><go href="%s"/></do>%s', 'Language : '.Context::getLang('select_lang'), $url, "\n");
}
else {
printf('<do type="vnd.lang" label="%s"><go href="%s"/></do>%s', Context::getLang('lang_return'), Context::get('return_uri'), "\n");
}
if($this->homeUrl) {
$url = $this->homeUrl;
printf('<do type="access" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n");
}
if($this->upperUrl) {
$url = $this->upperUrl;
printf('<do type="vnd.up" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n");
}
}
// Footer information output
function printFooter() {
print("</p>\n</card>\n</wml>");
}
// And returns a list of serial numbers in
function getNo() {
if(Context::get('mobile_skt')==1) {
return "vnd.skmn".parent::getNo();
}
else {
return parent::getNo();
}
return $str;
}
}
?>

View file

@ -1,112 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">모바일XE 애드온</title>
<title xml:lang="jp">モバイルXEアドオン</title>
<title xml:lang="zh-CN">手机XE插件</title>
<title xml:lang="en">Mobile XE</title>
<title xml:lang="vi">Mobile XE</title>
<title xml:lang="ru">Mobile XE</title>
<title xml:lang="zh-TW">XE行動上網</title>
<description xml:lang="ko">
모바일에서 접속시 헤더 정보를 분석하여 메뉴 - 모듈의 관계를 이용하여 WAP 태그로 출력하는 애드온입니다.
wml, hdml, mhtml를 지원하고 그 이외의 경우에는 동작하지 않습니다.
</description>
<description xml:lang="jp">
モバイル端末機からアクセス時、ヘッダーheader情報を分析して「メニュー」と「モジュール」の関係を利用してWAPタグに変換表示するアドオンです。
wml, hdml, mhtmlをサポートし、その以外は対応していません。
</description>
<description xml:lang="zh-CN">
通过手机访问网站时将网页输出为WAP标签的插件。
支持语言wml, hdml, mhtml
</description>
<description xml:lang="en">
This addon displays WAP tag by analyzing header information on mobile connection.
Only wml, hdml, mhtml formats are provided.
</description>
<description xml:lang="vi">
Addon này hiển thị WAP Tag bởi việc phân tích thông tin khi kết nối bằng di động.
Chỉ hỗ trợ cho các định dạng wml, hdml, mhtml.
</description>
<description xml:lang="ru">
Данный аддон показывает WAP теги, анализирую информацию мобильного соединения.
Поддерживаются только wml, hdml, mhtml форматы.
</description>
<description xml:lang="zh-TW">
透過行動工具上網時會將網頁轉換為WAP標籤顯示。
只限於 wml, hdml, mhtml格式。
</description>
<version>0.1.1</version>
<date>2009-05-23</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
<history version="0.1.1" date="2009-05-23">
<author email_address="misol221@paran.com" link="http://www.imsoo.net">
<name xml:lang="ko">misol</name>
<name xml:lang="jp">misol</name>
<name xml:lang="zh-CN">misol</name>
<name xml:lang="en">misol</name>
<name xml:lang="vi">misol</name>
<name xml:lang="ru">misol</name>
<name xml:lang="zh-TW">misol</name>
</author>
<log>언어선택 추가(WML, mHTML)</log>
<log>인코딩 설정 개선</log>
<log>그 외 소소한 개선들</log>
</history>
<extra_vars>
<var name="charset">
<title xml:lang="ko">문자셋</title>
<title xml:lang="jp">文字コード</title>
<title xml:lang="zh-CN">编码</title>
<title xml:lang="en">Charset</title>
<title xml:lang="vi">Charset</title>
<title xml:lang="ru">Charset</title>
<title xml:lang="zh-TW">編碼</title>
<description xml:lang="ko">
모바일 기기의 경우 UTF-8 문자셋을 인식하지 못할 수 있습니다.
문자셋에 원하시는 문자셋을 입력하면 자동으로 변환하여 출력하여 모바일에서 이상없이 출력하도록 합니다.
기본값은 UTF-8입니다.
(*SK Telecom 휴대전화의 경우 euc-kr인코딩만 지원하므로, 강제로 euc-kr인코딩만 지원합니다.)
</description>
<description xml:lang="jp">
ある特定のモバイル機器ではutf-8文字コードの認識が出来ない場合があります。
文字コードを設定すると、(日本語だけの場合)該当文字コードに自動変換して正常に表示出来るようになります。
本アドオンのデフォルト値はUTF-8で、日本の携帯はshift-jisが一般的です。
</description>
<description xml:lang="zh-CN">
手机有时无法识别utf-8编码这时输入相应的编码值即可自动转换。
默认编码为UTF-8。
</description>
<description xml:lang="en">
utf-8 may be read with mobile tools.
Mobile tools will display correct charset when you input charset you want.
Default charset is UTF-8.
</description>
<description xml:lang="vi">
UTF-8 không thể đọc được cho các công cụ di động.
Những công cụ di động sẽ trình bày Charset đúng khi bạn nhập vào Charset bạn muốn.
Charset mặc định là UTF-8.
</description>
<description xml:lang="ru">
utf-8 may be read with mobile tools.
Mobile tools will display correct charset when you input charset you want.
Default charset is UTF-8.
</description>
<description xml:lang="zh-TW">
行動工具無法讀取utf-8編碼。
當您輸入所想要的編碼時,行動工具將會正確的顯示。
預設編碼是UTF-8.
</description>
</var>
</extra_vars>
</addon>
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">모바일XE 애드온</title>
<title xml:lang="jp">モバイルXEアドオン</title>
<title xml:lang="zh-CN">手机XE插件</title>
<title xml:lang="en">Mobile XE</title>
<title xml:lang="vi">Mobile XE</title>
<title xml:lang="ru">Mobile XE</title>
<title xml:lang="zh-TW">XE行動上網</title>
<description xml:lang="ko">
모바일에서 접속시 헤더 정보를 분석하여 메뉴 - 모듈의 관계를 이용하여 WAP 태그로 출력하는 애드온입니다.
wml, hdml, mhtml를 지원하고 그 이외의 경우에는 동작하지 않습니다.
</description>
<description xml:lang="jp">
モバイル端末機からアクセス時、ヘッダーheader情報を分析して「メニュー」と「モジュール」の関係を利用してWAPタグに変換表示するアドオンです。
wml, hdml, mhtmlをサポートし、その以外は対応していません。
</description>
<description xml:lang="zh-CN">
通过手机访问网站时将网页输出为WAP标签的插件。
支持语言wml, hdml, mhtml
</description>
<description xml:lang="en">
This addon displays WAP tag by analyzing header information on mobile connection.
Only wml, hdml, mhtml formats are provided.
</description>
<description xml:lang="vi">
Addon này hiển thị WAP Tag bởi việc phân tích thông tin khi kết nối bằng di động.
Chỉ hỗ trợ cho các định dạng wml, hdml, mhtml.
</description>
<description xml:lang="ru">
Данный аддон показывает WAP теги, анализирую информацию мобильного соединения.
Поддерживаются только wml, hdml, mhtml форматы.
</description>
<description xml:lang="zh-TW">
透過行動工具上網時會將網頁轉換為WAP標籤顯示。
只限於 wml, hdml, mhtml格式。
</description>
<version>0.1.1</version>
<date>2009-05-23</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
<history version="0.1.1" date="2009-05-23">
<author email_address="misol221@paran.com" link="http://www.imsoo.net">
<name xml:lang="ko">misol</name>
<name xml:lang="jp">misol</name>
<name xml:lang="zh-CN">misol</name>
<name xml:lang="en">misol</name>
<name xml:lang="vi">misol</name>
<name xml:lang="ru">misol</name>
<name xml:lang="zh-TW">misol</name>
</author>
<log>언어선택 추가(WML, mHTML)</log>
<log>인코딩 설정 개선</log>
<log>그 외 소소한 개선들</log>
</history>
<extra_vars>
<var name="charset">
<title xml:lang="ko">문자셋</title>
<title xml:lang="jp">文字コード</title>
<title xml:lang="zh-CN">编码</title>
<title xml:lang="en">Charset</title>
<title xml:lang="vi">Charset</title>
<title xml:lang="ru">Charset</title>
<title xml:lang="zh-TW">編碼</title>
<description xml:lang="ko">
모바일 기기의 경우 UTF-8 문자셋을 인식하지 못할 수 있습니다.
문자셋에 원하시는 문자셋을 입력하면 자동으로 변환하여 출력하여 모바일에서 이상없이 출력하도록 합니다.
기본값은 UTF-8입니다.
(*SK Telecom 휴대전화의 경우 euc-kr인코딩만 지원하므로, 강제로 euc-kr인코딩만 지원합니다.)
</description>
<description xml:lang="jp">
ある特定のモバイル機器ではutf-8文字コードの認識が出来ない場合があります。
文字コードを設定すると、(日本語だけの場合)該当文字コードに自動変換して正常に表示出来るようになります。
本アドオンのデフォルト値はUTF-8で、日本の携帯はshift-jisが一般的です。
</description>
<description xml:lang="zh-CN">
手机有时无法识别utf-8编码这时输入相应的编码值即可自动转换。
默认编码为UTF-8。
</description>
<description xml:lang="en">
utf-8 may be read with mobile tools.
Mobile tools will display correct charset when you input charset you want.
Default charset is UTF-8.
</description>
<description xml:lang="vi">
UTF-8 không thể đọc được cho các công cụ di động.
Những công cụ di động sẽ trình bày Charset đúng khi bạn nhập vào Charset bạn muốn.
Charset mặc định là UTF-8.
</description>
<description xml:lang="ru">
utf-8 may be read with mobile tools.
Mobile tools will display correct charset when you input charset you want.
Default charset is UTF-8.
</description>
<description xml:lang="zh-TW">
行動工具無法讀取utf-8編碼。
當您輸入所想要的編碼時,行動工具將會正確的顯示。
預設編碼是UTF-8.
</description>
</var>
</extra_vars>
</addon>

View file

@ -1,15 +0,0 @@
<?php
/**
* @file addons/mobile/lang/ko.lang.php
* @author NHN (developers@xpressengine.com)
* @brief English Language Pack (Basic Contents only)
**/
// lang select by misol
$lang->president_lang = 'selected Language';
$lang->select_lang = 'select Language';
$lang->lang_return = 'Go Back';
$lang->cmd_go_upper = 'Upper';
$lang->cmd_go_home = 'Go Home';
$lang->cmd_view_sitemap = 'View site map';
?>

View file

@ -1,17 +0,0 @@
<?php
/**
* @file addons/mobile/lang/jp.lang.php
* @author NHN (developers@xpressengine.com) 翻訳:ミニミ
* @brief 日本語言語パッケージ
**/
// 言語選択部分 by misol
$lang->president_lang = '現在言語';
$lang->select_lang = '言語選択';
$lang->lang_return = '戻る';
$lang->cmd_go_upper = '上位メニュー';
$lang->cmd_go_home = 'トップへ';
$lang->cmd_view_sitemap = 'サイトマップ';
?>

View file

@ -1,17 +0,0 @@
<?php
/**
* @file addons/mobile/lang/ko.lang.php
* @author NHN (developers@xpressengine.com)
* @brief 한국어 언어팩 (기본적인 내용만 수록)
**/
// 언어 선택부분 by misol
$lang->president_lang = '현재 언어';
$lang->select_lang = '언어 선택';
$lang->lang_return = '돌아가기';
$lang->cmd_go_upper = '상위';
$lang->cmd_go_home = '홈으로';
$lang->cmd_view_sitemap = '사이트맵 보기';
?>

View file

@ -0,0 +1,54 @@
<?xml version='1.0' encoding='UTF-8'?>
<lang>
<item name="president_lang">
<value xml:lang="ko"><![CDATA[현재 언어]]></value>
<value xml:lang="en"><![CDATA[Selected Language]]></value>
<value xml:lang="jp"><![CDATA[現在言語]]></value>
<value xml:lang="zh-TW"><![CDATA[已選擇語言]]></value>
<value xml:lang="ru"><![CDATA[Дейсвующй язык]]></value>
<value xml:lang="vi"><![CDATA[Chọn ngôn ngữ]]></value>
</item>
<item name="select_lang">
<value xml:lang="ko"><![CDATA[언어 선택]]></value>
<value xml:lang="en"><![CDATA[Select Language]]></value>
<value xml:lang="jp"><![CDATA[言語選択]]></value>
<value xml:lang="zh-TW"><![CDATA[選擇語言]]></value>
<value xml:lang="ru"><![CDATA[Выбор языка]]></value>
<value xml:lang="vi"><![CDATA[Chọn ngôn ngữ]]></value>
</item>
<item name="lang_return">
<value xml:lang="ko"><![CDATA[돌아가기]]></value>
<value xml:lang="en"><![CDATA[Go Back]]></value>
<value xml:lang="jp"><![CDATA[戻る]]></value>
<value xml:lang="zh-TW"><![CDATA[返回]]></value>
<value xml:lang="ru"><![CDATA[Вернуться]]></value>
<value xml:lang="vi"><![CDATA[Trở lại]]></value>
</item>
<item name="cmd_go_upper">
<value xml:lang="ko"><![CDATA[상위]]></value>
<value xml:lang="en"><![CDATA[Upper]]></value>
<value xml:lang="jp"><![CDATA[上位メニュー]]></value>
<value xml:lang="zh-CN"><![CDATA[上一级]]></value>
<value xml:lang="zh-TW"><![CDATA[回上頁]]></value>
<value xml:lang="ru"><![CDATA[Вверх]]></value>
<value xml:lang="vi"><![CDATA[Lên trên]]></value>
</item>
<item name="cmd_go_home">
<value xml:lang="ko"><![CDATA[홈으로]]></value>
<value xml:lang="en"><![CDATA[Go Home]]></value>
<value xml:lang="jp"><![CDATA[トップへ]]></value>
<value xml:lang="zh-CN"><![CDATA[首页]]></value>
<value xml:lang="zh-TW"><![CDATA[回首頁]]></value>
<value xml:lang="ru"><![CDATA[На главную страницу]]></value>
<value xml:lang="vi"><![CDATA[Về trang chủ]]></value>
</item>
<item name="cmd_view_sitemap">
<value xml:lang="ko"><![CDATA[사이트맵 보기]]></value>
<value xml:lang="en"><![CDATA[View site map]]></value>
<value xml:lang="jp"><![CDATA[サイトマップ]]></value>
<value xml:lang="zh-CN"><![CDATA[网站地图]]></value>
<value xml:lang="zh-TW"><![CDATA[網站地圖]]></value>
<value xml:lang="ru"><![CDATA[Посмотреть карту сайта]]></value>
<value xml:lang="vi"><![CDATA[Xem sơ đồ Web]]></value>
</item>
</lang>

View file

@ -1,17 +0,0 @@
<?php
/**
* @file addons/mobile/lang/ko.lang.php
* @author NHN (developers@xpressengine.com)
* @brief 한국어 언어팩 (기본적인 내용만 수록)
**/
// 언어 선택부분 by misol
$lang->president_lang = 'Дейсвующй язык';
$lang->select_lang = 'Выбор языка';
$lang->lang_return = 'Вернуться';
$lang->cmd_go_upper = 'Вверх';
$lang->cmd_go_home = 'На главную страницу';
$lang->cmd_view_sitemap = 'Посмотреть карту сайта';
?>

View file

@ -1,18 +0,0 @@
<?php
/* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░ * @File : common/lang/vi.lang.php ░░
░░ * @Author : NHN (developers@xpressengine.com) ░░
░░ * @Trans : Đào Đức Duy (ducduy.dao.vn@vietxe.net) ░░
░░ * @Website: http://vietxe.net ░░
░░ * @Brief : Vietnamese Language Pack (Only basic words are included here) ░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ */
// lang select by misol
$lang->president_lang = 'Chọn ngôn ngữ';
$lang->select_lang = 'Chọn ngôn ngữ';
$lang->lang_return = 'Trở lại';
$lang->cmd_go_upper = 'Lên trên';
$lang->cmd_go_home = 'Về trang chủ';
$lang->cmd_view_sitemap = 'Xem sơ đồ Web';
?>

View file

@ -1,11 +0,0 @@
<?php
/**
* @file addons/mobile/lang/zh-CN.lang.php
* @author NHN (developers@xpressengine.com) 翻译guny
* @brief 手机XE插件简体中文语言包
**/
$lang->cmd_go_upper = '上一级';
$lang->cmd_go_home = '首页';
$lang->cmd_view_sitemap = '网站地图';
?>

View file

@ -1,15 +0,0 @@
<?php
/**
* @file addons/mobile/lang/zh-TW.lang.php
* @author NHN (developers@xpressengine.com) 翻譯royallin
* @brief XE行動上網正體中文語言
**/
// lang select by misol
$lang->president_lang = '已選擇語言';
$lang->select_lang = '選擇語言';
$lang->lang_return = '返回';
$lang->cmd_go_upper = '回上頁';
$lang->cmd_go_home = '回首頁';
$lang->cmd_view_sitemap = '網站地圖';
?>

View file

@ -1,61 +1,50 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file mobile.addon.php
* @author NHN (developers@xpressengine.com)
* @brief 모바일XE 애드온
*
* 헤더정보를 가로채서 모바일에서의 접속일 경우 WAP 태그로 컨텐츠를 출력함
*
* 동작 시점
*
* before_module_proc > 모바일 처리를 위해 모듈의 일반 설정을 변경해야 경우 호출
*
* after_module_proc > 모바일 컨텐츠 출력
* 동작 조건
**/
// 관리자 페이지는 무시
if(Context::get('module')=='admin') return;
// 동작 시점 관리
if($called_position != 'before_module_proc' && $called_position != 'after_module_proc' ) return;
// 모바일 브라우저가 아니라면 무시
require_once(_XE_PATH_.'addons/mobile/classes/mobile.class.php');
if(!mobileXE::getBrowserType()) return;
// mobile instance 생성
$oMobile = &mobileXE::getInstance();
if(!$oMobile) return;
// 애드온 설정에서 지정된 charset으로 지정
$oMobile->setCharSet($addon_info->charset);
// 모듈의 정보를 세팅
$oMobile->setModuleInfo($this->module_info);
// 현재 모듈 객체 등록
$oMobile->setModuleInstance($this);
// 네비게이트 모드이거나 WAP class가 있을 경우 미리 컨텐츠를 추출하여 출력/ 종료
if($called_position == 'before_module_proc') {
if($oMobile->isLangChange()) {
$oMobile->setLangType();
$oMobile->displayLangSelect();
}
// 네비게이트 모드이면 네비게이션 컨텐츠 출력
if($oMobile->isNavigationMode()) $oMobile->displayNavigationContent();
// WAP class가 있으면 WAP class를 통해 컨텐츠 출력
else $oMobile->displayModuleContent();
// 네비게이트 모드가 아니고 WAP 클래스가 아니면 모듈의 결과를 출력
} else if($called_position == 'after_module_proc') {
// 내용 준비
$oMobile->displayContent();
}
?>
<?php
if(!defined('__XE__')) exit();
/**
* @file mobile.addon.php
* @author NHN (developers@xpressengine.com)
* @brief Mobile XE add-on
*
* If a mobile connection is made (see the header information), display contents with WAP tags
*
* Time to call
*
* before_module_proc > call when changing general settings for mobile
*
* after_module_proc > display mobile content
* Condition
**/
// Ignore admin page
if(Context::get('module')=='admin') return;
// Manage when to call it
if($called_position != 'before_module_proc' && $called_position != 'after_module_proc' ) return;
// Ignore if not mobile browser
require_once(_XE_PATH_.'addons/mobile/classes/mobile.class.php');
if(!mobileXE::getBrowserType()) return;
// Generate mobile instance
$oMobile = &mobileXE::getInstance();
if(!$oMobile) return;
// Specify charset on the add-on settings
$oMobile->setCharSet($addon_info->charset);
// Set module information
$oMobile->setModuleInfo($this->module_info);
// Register the current module object
$oMobile->setModuleInstance($this);
// Extract content and display/exit if navigate mode is or if WAP class exists
if($called_position == 'before_module_proc') {
if($oMobile->isLangChange()) {
$oMobile->setLangType();
$oMobile->displayLangSelect();
}
// On navigation mode, display navigation content
if($oMobile->isNavigationMode()) $oMobile->displayNavigationContent();
// If you have a WAP class content output via WAP class
else $oMobile->displayModuleContent();
// If neither navigation mode nor WAP class is, display the module's result
} else if($called_position == 'after_module_proc') {
// Display
$oMobile->displayContent();
}
?>

View file

@ -1,125 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">OpenID delegation ID</title>
<title xml:lang="zh-CN">OpenID</title>
<title xml:lang="en">OpenID Delegation ID</title>
<title xml:lang="vi">OpenID Delegation ID</title>
<title xml:lang="ge">OpenID Delegation ID</title>
<title xml:lang="es">Delegación ID para OpenID</title>
<title xml:lang="jp">OpenIDアドオン</title>
<title xml:lang="ru">Открытый ID(OpenID)</title>
<title xml:lang="zh-TW">OpenID</title>
<description xml:lang="ko">
본인의 도메인을 사용하여 오픈아이디로 활용할 수 있도록 합니다.
꼭 설정을 통해서 openid provider관련 값을 입력후 사용해주세요.
</description>
<description xml:lang="zh-CN">
可以把本人的域名当分散式身份验证系统(OpenID)来使用。
必须在设置中输入openid provider相关值后再使用。
</description>
<description xml:lang="en">
This addon enables you to use your own domain name as an OpenID.
Just be sure to set the values related with openid provider before using.
</description>
<description xml:lang="vi">
Addon này cho phép bạn sử dụng tên miền của mình như một OpenID.
Hãy kiểm tra để đặt giá trị liên quan với OpenID trước khi sử dụng.
</description>
<description xml:lang="ge">
Dieses Addon ermöglicht es Ihnen, mit Ihrem eigenen Domain-Namen als OpenID.
Einfach sicher sein, dass die Werte im Zusammenhang mit OpenID-Provider, bevor Sie.
</description>
<description xml:lang="es">
Utlizando su propio dominio puede usar como OpenID.
Debe utilizar luego de ingresar los valores relacionado con openid provider a través de la configuracion.
</description>
<description xml:lang="jp">
保有しているオリジナルドメインをオープンIDとして活用することが出来ます。
必ず設定にて、OpenIDプロバイダーの関連情報を入力してから使用して下さい。
</description>
<description xml:lang="ru">
Этот аддон позволяет Вам использовать Ваше доменное имя как OpenID.
Прежде, чем использовать, установите значения, имеющие отношение к openid-провайдеру .
</description>
<description xml:lang="zh-TW">
可將原本的域名當做OpenID來使用。
必須在設置中輸入openid provider相關資料後再使用。
</description>
<version>0.1</version>
<date>2007-02-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
<extra_vars>
<var name="server">
<title xml:lang="ko">server</title>
<title xml:lang="zh-CN">server</title>
<title xml:lang="en">server</title>
<title xml:lang="vi">Server</title>
<title xml:lang="ge">server</title>
<title xml:lang="es">Servidor</title>
<title xml:lang="jp">server</title>
<title xml:lang="ru">server</title>
<title xml:lang="zh-TW">server</title>
<description xml:lang="ko">openid.server 값을 입력해 주세요.</description>
<description xml:lang="zh-CN">请输入 openid.server 值。</description>
<description xml:lang="vi">Hãy nhập OpenID Server của bạn.</description>
<description xml:lang="en">Please input your openid.server value.</description>
<description xml:lang="ge">Bitte geben Sie Ihre openid.server Wert.</description>
<description xml:lang="es">Ingrese el valor del openid.server.</description>
<description xml:lang="jp">openid.server値を入力して下さい。</description>
<description xml:lang="ru">Пожалуйста, введите Ваше значение openid.server</description>
<description xml:lang="zh-TW">請輸入 openid.server 值。</description>
</var>
<var name="delegate">
<title xml:lang="ko">delegate</title>
<title xml:lang="en">delegate</title>
<title xml:lang="vi">Delegate</title>
<title xml:lang="ge">delegate</title>
<title xml:lang="zh-CN">delegate</title>
<title xml:lang="es">delegado</title>
<title xml:lang="jp">delegate</title>
<title xml:lang="ru">delegate</title>
<title xml:lang="zh-TW">delegate</title>
<description xml:lang="ko">openid.delegate값을 입력해주세요.</description>
<description xml:lang="zh-CN">请输入 openid.delegate 值。</description>
<description xml:lang="vi">Hãy nhập OpenID Delegate của bạn.</description>
<description xml:lang="en">Please input your openid.delegate value.</description>
<description xml:lang="ge">Bitte geben Sie Ihre openid.delegate Wert.</description>
<description xml:lang="es">Ingresar el valor del openid.delegate</description>
<description xml:lang="jp">openid.delegate値を入力して下さい。</description>
<description xml:lang="ru">Пожалуйста, введите Ваше значение openid.delegate</description>
<description xml:lang="zh-TW">請輸入 openid.delegate 值。</description>
</var>
<var name="xrds">
<title xml:lang="ko">xrds</title>
<title xml:lang="zh-CN">xrds</title>
<title xml:lang="en">xrds</title>
<title xml:lang="vi">xrds</title>
<title xml:lang="ge">xrds</title>
<title xml:lang="es">xrds</title>
<title xml:lang="jp">xrds</title>
<title xml:lang="ru">xrds</title>
<title xml:lang="zh-TW">xrds</title>
<description xml:lang="ko">X-XRDS-Location값을 입력해주세요.</description>
<description xml:lang="zh-CN">请输入 X-XRDS-Location 值。</description>
<description xml:lang="en">Please input your X-XRDS-Location value.</description>
<description xml:lang="vi">Hãy nhập X-XRDS-Location của bạn.</description>
<description xml:lang="ge">Bitte geben Sie Ihre X-XRDS-Standort Wert.</description>
<description xml:lang="es">Ingresar el valor de X-XRDS-Location</description>
<description xml:lang="jp">X-XRDS-Location値を入力して下さい。</description>
<description xml:lang="ru">Пожалуйста, введите Ваше значение X-XRDS-Локации.</description>
<description xml:lang="zh-TW">請輸入 X-XRDS-Location 值。</description>
</var>
</extra_vars>
</addon>
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">OpenID delegation ID</title>
<title xml:lang="zh-CN">OpenID</title>
<title xml:lang="en">OpenID Delegation ID</title>
<title xml:lang="vi">OpenID Delegation ID</title>
<title xml:lang="ge">OpenID Delegation ID</title>
<title xml:lang="es">Delegación ID para OpenID</title>
<title xml:lang="jp">OpenIDアドオン</title>
<title xml:lang="ru">Открытый ID(OpenID)</title>
<title xml:lang="zh-TW">OpenID</title>
<description xml:lang="ko">
본인의 도메인을 사용하여 오픈아이디로 활용할 수 있도록 합니다.
꼭 설정을 통해서 openid provider관련 값을 입력후 사용해주세요.
</description>
<description xml:lang="zh-CN">
可以把本人的域名当分散式身份验证系统(OpenID)来使用。
必须在设置中输入openid provider相关值后再使用。
</description>
<description xml:lang="en">
This addon enables you to use your own domain name as an OpenID.
Just be sure to set the values related with openid provider before using.
</description>
<description xml:lang="vi">
Addon này cho phép bạn sử dụng tên miền của mình như một OpenID.
Hãy kiểm tra để đặt giá trị liên quan với OpenID trước khi sử dụng.
</description>
<description xml:lang="ge">
Dieses Addon ermöglicht es Ihnen, mit Ihrem eigenen Domain-Namen als OpenID.
Einfach sicher sein, dass die Werte im Zusammenhang mit OpenID-Provider, bevor Sie.
</description>
<description xml:lang="es">
Utlizando su propio dominio puede usar como OpenID.
Debe utilizar luego de ingresar los valores relacionado con openid provider a través de la configuracion.
</description>
<description xml:lang="jp">
保有しているオリジナルドメインをオープンIDとして活用することが出来ます。
必ず設定にて、OpenIDプロバイダーの関連情報を入力してから使用して下さい。
</description>
<description xml:lang="ru">
Этот аддон позволяет Вам использовать Ваше доменное имя как OpenID.
Прежде, чем использовать, установите значения, имеющие отношение к openid-провайдеру .
</description>
<description xml:lang="zh-TW">
可將原本的域名當做OpenID來使用。
必須在設置中輸入openid provider相關資料後再使用。
</description>
<version>0.1</version>
<date>2007-02-28</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
<extra_vars>
<var name="server">
<title xml:lang="ko">server</title>
<title xml:lang="zh-CN">server</title>
<title xml:lang="en">server</title>
<title xml:lang="vi">Server</title>
<title xml:lang="ge">server</title>
<title xml:lang="es">Servidor</title>
<title xml:lang="jp">server</title>
<title xml:lang="ru">server</title>
<title xml:lang="zh-TW">server</title>
<description xml:lang="ko">openid.server 값을 입력해 주세요.</description>
<description xml:lang="zh-CN">请输入 openid.server 值。</description>
<description xml:lang="vi">Hãy nhập OpenID Server của bạn.</description>
<description xml:lang="en">Please input your openid.server value.</description>
<description xml:lang="ge">Bitte geben Sie Ihre openid.server Wert.</description>
<description xml:lang="es">Ingrese el valor del openid.server.</description>
<description xml:lang="jp">openid.server値を入力して下さい。</description>
<description xml:lang="ru">Пожалуйста, введите Ваше значение openid.server</description>
<description xml:lang="zh-TW">請輸入 openid.server 值。</description>
</var>
<var name="delegate">
<title xml:lang="ko">delegate</title>
<title xml:lang="en">delegate</title>
<title xml:lang="vi">Delegate</title>
<title xml:lang="ge">delegate</title>
<title xml:lang="zh-CN">delegate</title>
<title xml:lang="es">delegado</title>
<title xml:lang="jp">delegate</title>
<title xml:lang="ru">delegate</title>
<title xml:lang="zh-TW">delegate</title>
<description xml:lang="ko">openid.delegate값을 입력해주세요.</description>
<description xml:lang="zh-CN">请输入 openid.delegate 值。</description>
<description xml:lang="vi">Hãy nhập OpenID Delegate của bạn.</description>
<description xml:lang="en">Please input your openid.delegate value.</description>
<description xml:lang="ge">Bitte geben Sie Ihre openid.delegate Wert.</description>
<description xml:lang="es">Ingresar el valor del openid.delegate</description>
<description xml:lang="jp">openid.delegate値を入力して下さい。</description>
<description xml:lang="ru">Пожалуйста, введите Ваше значение openid.delegate</description>
<description xml:lang="zh-TW">請輸入 openid.delegate 值。</description>
</var>
<var name="xrds">
<title xml:lang="ko">xrds</title>
<title xml:lang="zh-CN">xrds</title>
<title xml:lang="en">xrds</title>
<title xml:lang="vi">xrds</title>
<title xml:lang="ge">xrds</title>
<title xml:lang="es">xrds</title>
<title xml:lang="jp">xrds</title>
<title xml:lang="ru">xrds</title>
<title xml:lang="zh-TW">xrds</title>
<description xml:lang="ko">X-XRDS-Location값을 입력해주세요.</description>
<description xml:lang="zh-CN">请输入 X-XRDS-Location 值。</description>
<description xml:lang="en">Please input your X-XRDS-Location value.</description>
<description xml:lang="vi">Hãy nhập X-XRDS-Location của bạn.</description>
<description xml:lang="ge">Bitte geben Sie Ihre X-XRDS-Standort Wert.</description>
<description xml:lang="es">Ingresar el valor de X-XRDS-Location</description>
<description xml:lang="jp">X-XRDS-Location値を入力して下さい。</description>
<description xml:lang="ru">Пожалуйста, введите Ваше значение X-XRDS-Локации.</description>
<description xml:lang="zh-TW">請輸入 X-XRDS-Location 值。</description>
</var>
</extra_vars>
</addon>

View file

@ -1,29 +1,27 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file openid_delegation_id.addon.php
* @author NHN (developers@xpressengine.com)
* @brief OpenID Delegation ID 애드온
*
* 오픈아이디를 자신의 홈페이지나 블로그 주소로 이용할 있도록 해줍니다.
* 설정을 통해서 사용하시는 오픈아이디 서비스에 해당하는 정보를 입력해주세요.
**/
// called_position이 before_module_init일때만 실행
if($called_position != 'before_module_init') return;
// openid_delegation_id 애드온 설정 정보를 가져옴
if(!$addon_info->server||!$addon_info->delegate||!$addon_info->xrds) return;
$header_script = sprintf(
'<link rel="openid.server" href="%s" />'."\n".
'<link rel="openid.delegate" href="%s" />'."\n".
'<meta http-equiv="X-XRDS-Location" content="%s" />',
$addon_info->server,
$addon_info->delegate,
$addon_info->xrds
);
Context::addHtmlHeader($header_script);
?>
<?php
if(!defined('__XE__')) exit();
/**
* @file openid_delegation_id.addon.php
* @author NHN (developers@xpressengine.com)
* @brief OpenID Delegation ID Add-on
*
* This enables to use openID as user's homepage or blog url.
* Enter your open ID service information on the configuration.
**/
// Execute only wen called_position is before_module_init
if($called_position != 'before_module_init') return;
// Get add-on settings(openid_delegation_id)
if(!$addon_info->server||!$addon_info->delegate||!$addon_info->xrds) return;
$header_script = sprintf(
'<link rel="openid.server" href="%s" />'."\n".
'<link rel="openid.delegate" href="%s" />'."\n".
'<meta http-equiv="X-XRDS-Location" content="%s" />',
$addon_info->server,
$addon_info->delegate,
$addon_info->xrds
);
Context::addHtmlHeader($header_script);
?>

View file

@ -1,62 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">포인트 레벨 아이콘 표시 애드온</title>
<title xml:lang="zh-CN">积分级别图标</title>
<title xml:lang="jp">ポイントレベルアイコン表示アドオン</title>
<title xml:lang="en">Point Level Icon</title>
<title xml:lang="vi">Icon cấp độ của điểm</title>
<title xml:lang="ge">Point-Level-Symbol</title>
<title xml:lang="es">Addon para mostar el nivel del ícono</title>
<title xml:lang="ru">Иконка уровня поинтов</title>
<title xml:lang="zh-TW">點數等級圖案</title>
<description xml:lang="ko">
포인트 시스템을 사용중일 경우 사용자 이름 앞에 레벨 아이콘을 표시하도록 합니다.
레벨 아이콘은 모듈 &gt; 포인트시스템에서 선택 가능합니다.
</description>
<description xml:lang="zh-CN">
使用积分系统时,可以在用户名前显示级别图标。
级别图标可以在模块 &gt; 积分系统中进行选择。
</description>
<description xml:lang="jp">
ポイントシステムを使用する場合、ユーザ名の前にレベルアイコンの表示します。
レベルアイコンは、「モジュール &gt; ポイントシステム」で選択します。
</description>
<description xml:lang="en">
This addon displays level icon in front of the user name when you are using the point system.
You can choose the level icon in Module &gt; Point System.
</description>
<description xml:lang="vi">
Addon này sẽ hiển thị Icon cấp độ trước tên người sử dụng khi bạn sử dụng hệ thống tính điểm.
Bạn có thể chọn Icon cấp độ tại Module &gt; cỉa hệ thống điểm.
</description>
<description xml:lang="ge">
Dieses Addon zeigt Level Icon vor dem Benutzernamen, wenn Sie die Punkte-System.
Sie können wählen, der Level Icon in Modul> Point-System.
</description>
<description xml:lang="es">
Este addon muestra el nivel del ícono delante del nombre del usuario cuando es usado el sistema de puntos.
Tu puedes elegir los icono de cada nivel en el módulo &gt; Sistema de Puntos.
</description>
<description xml:lang="ru">
Этот аддон отображает иконку уровня поинтов напротив имени пользователя, когда используется система поинтов.
Вы можете выбрать иконку уровня в Модуле Системы Поинтов.
</description>
<description xml:lang="zh-TW">
使用點數系統時,可以在用戶名前顯示等級圖案。
等級圖案可以在模組 &gt; 點數系統中進行選擇。
</description>
<version>0.1</version>
<date>2007-07-26</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">포인트 레벨 아이콘 표시 애드온</title>
<title xml:lang="zh-CN">积分级别图标</title>
<title xml:lang="jp">ポイントレベルアイコン表示アドオン</title>
<title xml:lang="en">Point Level Icon</title>
<title xml:lang="vi">Icon cấp độ của điểm</title>
<title xml:lang="ge">Point-Level-Symbol</title>
<title xml:lang="es">Addon para mostar el nivel del ícono</title>
<title xml:lang="ru">Иконка уровня поинтов</title>
<title xml:lang="zh-TW">點數等級圖案</title>
<description xml:lang="ko">
포인트 시스템을 사용중일 경우 사용자 이름 앞에 레벨 아이콘을 표시하도록 합니다.
레벨 아이콘은 모듈 &gt; 포인트시스템에서 선택 가능합니다.
</description>
<description xml:lang="zh-CN">
使用积分系统时,可以在用户名前显示级别图标。
级别图标可以在模块 &gt; 积分系统中进行选择。
</description>
<description xml:lang="jp">
ポイントシステムを使用する場合、ユーザ名の前にレベルアイコンの表示します。
レベルアイコンは、「モジュール &gt; ポイントシステム」で選択します。
</description>
<description xml:lang="en">
This addon displays level icon in front of the user name when you are using the point system.
You can choose the level icon in Module &gt; Point System.
</description>
<description xml:lang="vi">
Addon này sẽ hiển thị Icon cấp độ trước tên người sử dụng khi bạn sử dụng hệ thống tính điểm.
Bạn có thể chọn Icon cấp độ tại Module &gt; cỉa hệ thống điểm.
</description>
<description xml:lang="ge">
Dieses Addon zeigt Level Icon vor dem Benutzernamen, wenn Sie die Punkte-System.
Sie können wählen, der Level Icon in Modul> Point-System.
</description>
<description xml:lang="es">
Este addon muestra el nivel del ícono delante del nombre del usuario cuando es usado el sistema de puntos.
Tu puedes elegir los icono de cada nivel en el módulo &gt; Sistema de Puntos.
</description>
<description xml:lang="ru">
Этот аддон отображает иконку уровня поинтов напротив имени пользователя, когда используется система поинтов.
Вы можете выбрать иконку уровня в Модуле Системы Поинтов.
</description>
<description xml:lang="zh-TW">
使用點數系統時,可以在用戶名前顯示等級圖案。
等級圖案可以在模組 &gt; 點數系統中進行選擇。
</description>
<version>0.1</version>
<date>2007-07-26</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>

View file

@ -1,19 +1,18 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file point.addon.php
* @author NHN (developers@xpressengine.com)
* @brief 포인트 레벨 아이콘 표시 애드온
*
* 포인트 시스템 사용중일때 사용자 이름 앞에 포인트 레벨 아이콘을 표시합니다.
**/
// before_display_content 가 아니면 return
if($called_position != "before_display_content" || Context::get('act')=='dispPageAdminContentModify') return;
require_once('./addons/point_level_icon/point_level_icon.lib.php');
$oPointController = &getController('point');
$output = preg_replace_callback('!<(div|span|a)([^\>]*)member_([0-9\-]+)([^\>]*)>(.*?)\<\/(div|span|a)\>!is', 'pointLevelIconTrans', $output);
?>
<?php
if(!defined('__XE__')) exit();
/**
* @file point.addon.php
* @author NHN (developers@xpressengine.com)
* @brief Icon-on-point level
*
* Display point level icon before user name when point system is enabled.
**/
// return unless before_display_content
if($called_position != "before_display_content" || Context::get('act')=='dispPageAdminContentModify') return;
require_once('./addons/point_level_icon/point_level_icon.lib.php');
$oPointController = &getController('point');
$output = preg_replace_callback('!<(div|span|a)([^\>]*)member_([0-9\-]+)([^\>]*)>(.*?)\<\/(div|span|a)\>!is', 'pointLevelIconTrans', $output);
?>

View file

@ -1,56 +1,52 @@
<?php
/**
* @brief 포인트 아이콘 변경을 위한 함수.
**/
function pointLevelIconTrans($matches) {
$member_srl = $matches[3];
if($member_srl<1) return $matches[0];
/**
* @brief Function to change point icon.
**/
function pointLevelIconTrans($matches) {
$member_srl = $matches[3];
if($member_srl<1) return $matches[0];
$orig_text = preg_replace('/'.preg_quote($matches[5],'/').'<\/'.$matches[6].'>$/', '', $matches[0]);
$orig_text = preg_replace('/'.preg_quote($matches[5],'/').'<\/'.$matches[6].'>$/', '', $matches[0]);
// Check Group Image Mark
$oMemberModel = &getModel('member');
if($oMemberModel->getGroupImageMark($member_srl)) return $orig_text.$matches[5].'</'.$matches[6].'>';
// Check Group Image Mark
$oMemberModel = &getModel('member');
if($oMemberModel->getGroupImageMark($member_srl)) return $orig_text.$matches[5].'</'.$matches[6].'>';
if(!isset($GLOBALS['_pointLevelIcon'][$member_srl])) {
// 포인트 설정을 구해옴
if(!$GLOBALS['_pointConfig']) {
$oModuleModel = &getModel('module');
$GLOBALS['_pointConfig'] = $oModuleModel->getModuleConfig('point');
}
$config = $GLOBALS['_pointConfig'];
if(!isset($GLOBALS['_pointLevelIcon'][$member_srl])) {
// Get point configuration
if(!$GLOBALS['_pointConfig']) {
$oModuleModel = &getModel('module');
$GLOBALS['_pointConfig'] = $oModuleModel->getModuleConfig('point');
}
$config = $GLOBALS['_pointConfig'];
// Get point model
if(!$GLOBALS['_pointModel']) $GLOBALS['_pointModel'] = getModel('point');
$oPointModel = &$GLOBALS['_pointModel'];
// Get points
if(!$oPointModel->isExistsPoint($member_srl)) return $matches[0];
$point = $oPointModel->getPoint($member_srl);
// Get level
$level = $oPointModel->getLevel($point, $config->level_step);
$text = $matches[5];
// Get a path where level icon is
$level_icon = sprintf('%smodules/point/icons/%s/%d.gif', Context::getRequestUri(), $config->level_icon, $level);
// Get per to go to the next level if not a top level
if($level < $config->max_level) {
$next_point = $config->level_step[$level+1];
$present_point = $config->level_step[$level];
if($next_point > 0) {
$per = (int)(($point - $present_point) / ($next_point - $present_point)*100);
$per = $per.'%';
}
}
// 포인트 모델을 구해 놓음
if(!$GLOBALS['_pointModel']) $GLOBALS['_pointModel'] = getModel('point');
$oPointModel = &$GLOBALS['_pointModel'];
$title = sprintf('%s:%s%s%s, %s:%s/%s', Context::getLang('point'), $point, $config->point_name, $per?' ('.$per.')':'', Context::getLang('level'), $level, $config->max_level);
$alt = sprintf('[%s:%s]', Context::getLang('level'), $level);
// 포인트를 구함
$point = $oPointModel->getPoint($member_srl);
$GLOBALS['_pointLevelIcon'][$member_srl] = sprintf('<img src="%s" alt="%s" title="%s" style="vertical-align:middle; margin-right:3px;" />', $level_icon, $alt, $title);
}
$text = $GLOBALS['_pointLevelIcon'][$member_srl];
// 레벨을 구함
$level = $oPointModel->getLevel($point, $config->level_step);
$text = $matches[5];
// 레벨 아이콘의 위치를 구함
$level_icon = sprintf('%smodules/point/icons/%s/%d.gif', Context::getRequestUri(), $config->level_icon, $level);
// 최고 레벨이 아니면 다음 레벨로 가기 위한 per을 구함 :: 주석과 실제 내용이 맞지 않아 실제 내용을 수정
if($level < $config->max_level) {
$next_point = $config->level_step[$level+1];
$present_point = $config->level_step[$level];
if($next_point > 0) {
$per = (int)(($point - $present_point) / ($next_point - $present_point)*100);
$per = $per.'%';
}
}
$title = sprintf('%s:%s%s%s, %s:%s/%s', Context::getLang('point'), $point, $config->point_name, $per?' ('.$per.')':'', Context::getLang('level'), $level, $config->max_level);
$alt = sprintf('[%s:%s]', Context::getLang('level'), $level);
$GLOBALS['_pointLevelIcon'][$member_srl] = sprintf('<img src="%s" alt="%s" title="%s" style="vertical-align:middle; margin-right:3px;" />', $level_icon, $alt, $title);
}
$text = $GLOBALS['_pointLevelIcon'][$member_srl];
return $orig_text.$text.$matches[5].'</'.$matches[6].'>';
}
return $orig_text.$text.$matches[5].'</'.$matches[6].'>';
}
?>

View file

@ -1,53 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">본문내 이미지 조절 애드온</title>
<title xml:lang="jp">本文内イメージリーサイズアドオン</title>
<title xml:lang="zh-CN">内容区图片缩放插件</title>
<title xml:lang="en">Image Resizer</title>
<title xml:lang="vi">Thay đổi cỡ hình ảnh</title>
<title xml:lang="es">Imagen de control add-on bonmunnae</title>
<title xml:lang="ru">Аддон редактирования размера картинки в тексте</title>
<title xml:lang="ge">Image-Add-on bonmunnae</title>
<title xml:lang="zh-TW">圖片縮放</title>
<description xml:lang="ko">
본문내에 삽입된 이미지의 크기를 본문크기에 맞게 하고 클릭시 원본을 보여주는 애드온입니다.
</description>
<description xml:lang="jp">
本文内に挿入されたイメージのサイズを本文の幅サイズに合わせてリーサイズし、クリックした時、オリジナルサイズのイメージを表示します。
</description>
<description xml:lang="zh-CN">
自动调整主题内容区内的图片大小,点击将显示原始大小的插件。
</description>
<description xml:lang="vi">
Addon này sẽ lấy lại kích thước nguyên bản của hình ảnh trong bài viết hoặc bình luận khi bạn bấm vào hình.
</description>
<description xml:lang="en">
This addon resizes images inserted in the article, and shows original image when you click on them.
</description>
<description xml:lang="es">
La imagen corporal se inserta dentro del cuerpo para que se adapte al tamaño de la muestra original cuando hago clic en los add-ons.
</description>
<description xml:lang="ru">
Аддон, изменяющий размер картинки к размеру текста, при клике на картинку, появляется полное изображение.
</description>
<description xml:lang="ge">
Body Bild eingefügt im Inneren des Körpers zu passen die Größe des Originals zeigen, wenn ich darauf klicke auf das Add-ons.
</description>
<description xml:lang="zh-TW">
自動調整文章内的圖片大小,點擊圖片後會顯示原始大小。
</description>
<version>0.1</version>
<date>2008-04-22</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>
<?xml version="1.0" encoding="UTF-8"?>
<addon version="0.2">
<title xml:lang="ko">본문내 이미지 조절 애드온</title>
<title xml:lang="jp">本文内イメージリーサイズアドオン</title>
<title xml:lang="zh-CN">内容区图片缩放插件</title>
<title xml:lang="en">Image Resizer</title>
<title xml:lang="vi">Thay đổi cỡ hình ảnh</title>
<title xml:lang="es">Imagen de control add-on bonmunnae</title>
<title xml:lang="ru">Аддон редактирования размера картинки в тексте</title>
<title xml:lang="ge">Image-Add-on bonmunnae</title>
<title xml:lang="zh-TW">圖片縮放</title>
<description xml:lang="ko">
본문내에 삽입된 이미지의 크기를 본문크기에 맞게 하고 클릭시 원본을 보여주는 애드온입니다.
</description>
<description xml:lang="jp">
本文内に挿入されたイメージのサイズを本文の幅サイズに合わせてリーサイズし、クリックした時、オリジナルサイズのイメージを表示します。
</description>
<description xml:lang="zh-CN">
自动调整主题内容区内的图片大小,点击将显示原始大小的插件。
</description>
<description xml:lang="vi">
Addon này sẽ lấy lại kích thước nguyên bản của hình ảnh trong bài viết hoặc bình luận khi bạn bấm vào hình.
</description>
<description xml:lang="en">
This addon resizes images inserted in the article. When clicked, the original images are shown.
</description>
<description xml:lang="es">
La imagen corporal se inserta dentro del cuerpo para que se adapte al tamaño de la muestra original cuando hago clic en los add-ons.
</description>
<description xml:lang="ru">
Аддон, изменяющий размер картинки к размеру текста, при клике на картинку, появляется полное изображение.
</description>
<description xml:lang="ge">
Body Bild eingefügt im Inneren des Körpers zu passen die Größe des Originals zeigen, wenn ich darauf klicke auf das Add-ons.
</description>
<description xml:lang="zh-TW">
自動調整文章内的圖片大小,點擊圖片後會顯示原始大小。
</description>
<version>0.1</version>
<date>2008-04-22</date>
<author email_address="developers@xpressengine.com" link="http://xpressengine.com/">
<name xml:lang="ko">NHN</name>
<name xml:lang="vi">NHN</name>
<name xml:lang="jp">NHN</name>
<name xml:lang="zh-CN">NHN</name>
<name xml:lang="es">NHN</name>
<name xml:lang="ge">NHN</name>
<name xml:lang="ru">NHN</name>
<name xml:lang="en">NHN</name>
<name xml:lang="zh-TW">NHN</name>
</author>
</addon>

View file

@ -121,21 +121,18 @@ function getScreen() {
prevbtn.css("visibility", (this.index>0)?"visible":"hidden");
nextbtn.css("visibility", (this.index<this.list.size()-1)?"visible":"hidden");
//textyle 이미지 리사이즈 처리
var src = this.list.eq(this.index).attr("rawsrc");
if(!src) src = this.list.eq(this.index).attr("src");
imgframe.attr("src", src).css({
left : Math.round( Math.max( (clientWidth-imgframe.width()-14)/2, 0 ) ) + "px",
top : Math.round( Math.max( (clientHeight-imgframe.height()-14)/2, 0 ) ) + "px"
});
//textyle 이미지 리사이즈 처리
var src = this.list.eq(this.index).attr("rawsrc");
if(!src) src = this.list.eq(this.index).attr("src");
imgframe.attr("src", src).css({
left : Math.round( Math.max( (clientWidth-imgframe.width()-14)/2, 0 ) ) + "px",
top : Math.round( Math.max( (clientHeight-imgframe.height()-14)/2, 0 ) ) + "px"
});
};
// 스크린을 닫는 상황
$(document).scroll(xScreen.xeHide);
$(document).keydown(xScreen.xeHide);
$(window).resize(xScreen.xeHide);
$(window).scroll(xScreen.xeHide);
} else {
controls = $("#xe_gallery_controls");
imgframe = $("#xe_gallery_holder");
@ -149,7 +146,7 @@ function getScreen() {
// 이미지 슬라이드를 보는 함수
function slideshow(event) {
var container = $(this).parents(".xe_content");
var container = $(this).closest('.xe_content');
var imglist = container.find("img[rel=xe_gallery]");
var currentIdx = $.inArray($(this).get(0), imglist.get());
var xScreen = getScreen();
@ -203,8 +200,7 @@ $(function() {
}
$('div.xe_content').each(function() {
dummy.appendTo(this);
var contentWidth = dummy.width();
var contentWidth = dummy.appendTo(this).width();
dummy.remove();
if(!contentWidth) return;

View file

@ -1,9 +1,9 @@
/**
* @brief 화면내에서 상위 영역보다 이미지가 크면 리사이즈를 하고 클릭시 원본을 보여줄수 있도록 변경
**/
(function($){var xScreen=null;function getScreen(){var body=$(document.body);var controls,imgframe,closebtn,prevbtn,nextbtn;if(!xScreen){xScreen=$("<div>").attr("id","xe_gallery_screen").css({position:"absolute",display:"none",backgroundColor:"black",zIndex:500,opacity:0.5});controls=$("<div>").attr("id","xe_gallery_controls").css({position:"absolute",display:"none",overflow:"hidden",zIndex:510});closebtn=$("<img>").attr("id","xe_gallery_closebtn").attr("src",request_uri+"addons/resize_image/iconClose.png").css({top:"10px"}).click(function(){xScreen.xeHide()}).appendTo(controls);prevbtn=$("<img>").attr("id","xe_gallery_prevbtn").attr("src",request_uri+"addons/resize_image/iconLeft.png").css("left","10px").click(function(){xScreen.xePrev()}).appendTo(controls);nextbtn=$("<img>").attr("id","xe_gallery_nextbtn").attr("src",request_uri+"addons/resize_image/iconRight.png").css("right","10px").click(function(){xScreen.xeNext()}).appendTo(controls);controls.find("img").attr({width:60,height:60,className:"iePngFix"}).css({position:"absolute",width:"60px",height:"60px",zIndex:530,cursor:"pointer"});imgframe=$("<img>").attr("id","xe_gallery_holder").css("border","7px solid white").css("zIndex",520).appendTo(controls).draggable();body.append(xScreen).append(controls);xScreen.xeShow=function(){var clientWidth=$(window).width();var clientHeight=$(window).height();$("#xe_gallery_controls,#xe_gallery_screen").css({display:"block",width:clientWidth+"px",height:clientHeight+"px",left:$(document).scrollLeft(),top:$(document).scrollTop()});closebtn.css("left",Math.round((clientWidth-60)/2)+"px");$("#xe_gallery_prevbtn,#xe_gallery_nextbtn").css("top",Math.round((clientHeight-60)/2)+"px");this.xeMove(0);};xScreen.xeHide=function(event){xScreen.css("display","none");controls.css("display","none");};xScreen.xePrev=function(){this.xeMove(-1);};xScreen.xeNext=function(){this.xeMove(1);};xScreen.xeMove=function(val){var clientWidth=$(window).width();var clientHeight=$(window).height();this.index+=val;prevbtn.css("visibility",(this.index>0)?"visible":"hidden");nextbtn.css("visibility",(this.index<this.list.size()-1)?"visible":"hidden");var src=this.list.eq(this.index).attr("rawsrc");if(!src)src=this.list.eq(this.index).attr("src");imgframe.attr("src",src).css({left:Math.round(Math.max((clientWidth-imgframe.width()-14)/2,0))+"px",top:Math.round(Math.max((clientHeight-imgframe.height()-14)/2,0))+"px"});};$(document).scroll(xScreen.xeHide);$(document).keydown(xScreen.xeHide);$(window).resize(xScreen.xeHide);$(window).scroll(xScreen.xeHide);}else{controls=$("#xe_gallery_controls");imgframe=$("#xe_gallery_holder");closebtn=$("#xe_gallery_closebtn");prevbtn=$("#xe_gallery_prevbtn");nextbtn=$("#xe_gallery_nextbtn");}
(function($){var xScreen=null;function getScreen(){var body=$(document.body);var controls,imgframe,closebtn,prevbtn,nextbtn;if(!xScreen){xScreen=$("<div>").attr("id","xe_gallery_screen").css({position:"absolute",display:"none",backgroundColor:"black",zIndex:500,opacity:0.5});controls=$("<div>").attr("id","xe_gallery_controls").css({position:"absolute",display:"none",overflow:"hidden",zIndex:510});closebtn=$("<img>").attr("id","xe_gallery_closebtn").attr("src",request_uri+"addons/resize_image/iconClose.png").css({top:"10px"}).click(function(){xScreen.xeHide()}).appendTo(controls);prevbtn=$("<img>").attr("id","xe_gallery_prevbtn").attr("src",request_uri+"addons/resize_image/iconLeft.png").css("left","10px").click(function(){xScreen.xePrev()}).appendTo(controls);nextbtn=$("<img>").attr("id","xe_gallery_nextbtn").attr("src",request_uri+"addons/resize_image/iconRight.png").css("right","10px").click(function(){xScreen.xeNext()}).appendTo(controls);controls.find("img").attr({width:60,height:60,className:"iePngFix"}).css({position:"absolute",width:"60px",height:"60px",zIndex:530,cursor:"pointer"});imgframe=$("<img>").attr("id","xe_gallery_holder").css("border","7px solid white").css("zIndex",520).appendTo(controls).draggable();body.append(xScreen).append(controls);xScreen.xeShow=function(){var clientWidth=$(window).width();var clientHeight=$(window).height();$("#xe_gallery_controls,#xe_gallery_screen").css({display:"block",width:clientWidth+"px",height:clientHeight+"px",left:$(document).scrollLeft(),top:$(document).scrollTop()});closebtn.css("left",Math.round((clientWidth-60)/2)+"px");$("#xe_gallery_prevbtn,#xe_gallery_nextbtn").css("top",Math.round((clientHeight-60)/2)+"px");this.xeMove(0);};xScreen.xeHide=function(event){xScreen.css("display","none");controls.css("display","none");};xScreen.xePrev=function(){this.xeMove(-1);};xScreen.xeNext=function(){this.xeMove(1);};xScreen.xeMove=function(val){var clientWidth=$(window).width();var clientHeight=$(window).height();this.index+=val;prevbtn.css("visibility",(this.index>0)?"visible":"hidden");nextbtn.css("visibility",(this.index<this.list.size()-1)?"visible":"hidden");var src=this.list.eq(this.index).attr("rawsrc");if(!src)src=this.list.eq(this.index).attr("src");imgframe.attr("src",src).css({left:Math.round(Math.max((clientWidth-imgframe.width()-14)/2,0))+"px",top:Math.round(Math.max((clientHeight-imgframe.height()-14)/2,0))+"px"});};$(document).keydown(xScreen.xeHide);}else{controls=$("#xe_gallery_controls");imgframe=$("#xe_gallery_holder");closebtn=$("#xe_gallery_closebtn");prevbtn=$("#xe_gallery_prevbtn");nextbtn=$("#xe_gallery_nextbtn");}
return xScreen;}
function slideshow(event){var container=$(this).parents(".xe_content");var imglist=container.find("img[rel=xe_gallery]");var currentIdx=$.inArray($(this).get(0),imglist.get());var xScreen=getScreen();xScreen.list=imglist;xScreen.index=currentIdx;xScreen.xeShow();}
function slideshow(event){var container=$(this).closest('.xe_content');var imglist=container.find("img[rel=xe_gallery]");var currentIdx=$.inArray($(this).get(0),imglist.get());var xScreen=getScreen();xScreen.list=imglist;xScreen.index=currentIdx;xScreen.xeShow();}
$(function(){var regx_skip=/(?:(modules|addons|classes|common|layouts|libs|widgets|widgetstyles)\/)/i;var regx_allow_i6pngfix=/(?:common\/tpl\/images\/blank\.gif$)/i;var dummy=$('<div style="height:1; overflow:hidden; opacity:0; display:block; clear:both;"></div>');function doResize(contentWidth,count){if(!count)count=0;if(count>=10)return;var $img=this;var beforSize={'width':$img.width(),'height':$img.height()};if(!beforSize.width||!beforSize.height){setTimeout(function(){doResize.call($img,contentWidth,++count)},200);return;}
if(beforSize.width<=contentWidth)return;var resize_ratio=contentWidth/beforSize.width;$img.removeAttr('width').removeAttr('height').css({'width':contentWidth,'height':parseInt(beforSize.height*resize_ratio,10)});}
$('div.xe_content').each(function(){dummy.appendTo(this);var contentWidth=dummy.width();dummy.remove();if(!contentWidth)return;$('img',this).each(function(){var $img=$(this);var imgSrc=$img.attr('src');if(regx_skip.test(imgSrc)&&!regx_allow_i6pngfix.test(imgSrc))return;$img.attr('rel','xe_gallery');doResize.call($img,contentWidth);});$('img[rel=xe_gallery]',this).live('mouseover',function(){var $img=$(this);if(!$img.parent('a').length&&!$img.attr('onclick')){$img.css('cursor','pointer').click(slideshow);}});});});})(jQuery);

View file

@ -1,18 +1,18 @@
<?php
if(!defined("__ZBXE__")) exit();
/**
* @file resize_image.addon.php
* @author NHN (developers@xpressengine.com)
* @brief 본문내 이미지 조절 애드온
**/
if($called_position == 'after_module_proc' && Context::getResponseMethod()=="HTML") {
if(Mobile::isFromMobilePhone()) {
Context::addCssFile('./addons/resize_image/css/resize_image.mobile.css');
} else {
Context::loadJavascriptPlugin('ui');
Context::addJsFile('./addons/resize_image/js/resize_image.min.js',false, '',null, 'body');
}
}
?>
<?php
if(!defined('__XE__')) exit();
/**
* @file resize_image.addon.php
* @author NHN (developers@xpressengine.com)
* @brief Add-on to resize images in the body
**/
if($called_position == 'after_module_proc' && Context::getResponseMethod()=="HTML") {
if(Mobile::isFromMobilePhone()) {
Context::loadFile('./addons/resize_image/css/resize_image.mobile.css', true);
} else {
Context::loadJavascriptPlugin('ui');
Context::loadFile(array('./addons/resize_image/js/resize_image.min.js', 'body', '', null), true);
}
}
?>

View file

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

View file

@ -1,95 +1,130 @@
<?php
/**
* @class CacheHandler
* @author NHN (developer@xpressengine.com)
* @brief Cache Handler
* @version 0.1
*
**/
class CacheHandler extends Handler {
var $handler = null;
function &getInstance($target='object') {
return new CacheHandler($target);
}
function CacheHandler($target, $info=null) {
if(!$info) $info = Context::getDBInfo();
if($info){
if($target == 'object'){
if($info->use_object_cache =='apc') $type = 'apc';
else if(substr($info->use_object_cache,0,8)=='memcache'){
$type = 'memcache';
$url = $info->use_object_cache;
}
}else if($target == 'template'){
if($info->use_template_cache =='apc') $type = 'apc';
else if(substr($info->use_template_cache,0,8)=='memcache'){
$type = 'memcache';
$url = $info->use_template_cache;
}
}
if($type){
$class = 'Cache' . ucfirst($type);
include_once sprintf('%sclasses/cache/%s.class.php', _XE_PATH_, $class);
$this->handler = call_user_func(array($class,'getInstance'), $url);
}
}
}
function isSupport(){
if($this->handler && $this->handler->isSupport()) return true;
return false;
}
function get($key, $modified_time = 0){
if(!$this->handler) return false;
return $this->handler->get($key, $modified_time);
}
function put($key, $obj, $valid_time = 0){
if(!$this->handler) return false;
return $this->handler->put($key, $obj, $valid_time);
}
function delete($key){
if(!$this->handler) return false;
return $this->handler->delete($key);
}
function isValid($key, $modified_time){
if(!$this->handler) return false;
return $this->handler->isValid($key, $modified_time);
}
function truncate(){
if(!$this->handler) return false;
return $this->handler->truncate();
}
}
class CacheBase{
function get($key, $modified_time = 0){
return false;
}
function put($key, $obj, $valid_time = 0){
return false;
}
function isValid($key, $modified_time = 0){
return false;
}
function isSupport(){
return false;
}
function truncate(){
return false;
}
}
?>
<?php
/**
* @class CacheHandler
* @author NHN (developer@xpressengine.com)
* @brief Cache Handler
* @version 0.1
**/
class CacheHandler extends Handler {
var $handler = null;
var $keyGroupVersions = null;
function &getInstance($target = 'object') {
if(!$GLOBALS['__XE_CACHE_HANDLER__'][$target]) {
$GLOBALS['__XE_CACHE_HANDLER__'][$target] = new CacheHandler($target);
}
return $GLOBALS['__XE_CACHE_HANDLER__'][$target];
}
function CacheHandler($target, $info = null) {
if(!$info) $info = Context::getDBInfo();
if($info){
if($target == 'object'){
if($info->use_object_cache =='apc') $type = 'apc';
else if(substr($info->use_object_cache,0,8)=='memcache'){
$type = 'memcache';
$url = $info->use_object_cache;
}
}else if($target == 'template'){
if($info->use_template_cache =='apc') $type = 'apc';
else if(substr($info->use_template_cache,0,8)=='memcache'){
$type = 'memcache';
$url = $info->use_template_cache;
}
}
if($type){
$class = 'Cache' . ucfirst($type);
include_once sprintf('%sclasses/cache/%s.class.php', _XE_PATH_, $class);
$this->handler = call_user_func(array($class,'getInstance'), $url);
$this->keyGroupVersions = $this->handler->get('key_group_versions', 0);
if(!$this->keyGroupVersions) {
$this->keyGroupVersions = array();
$this->handler->put('key_group_versions', $this->keyGroupVersions, 0);
}
}
}
}
function isSupport(){
if($this->handler && $this->handler->isSupport()) return true;
return false;
}
function get($key, $modified_time = 0){
if(!$this->handler) return false;
return $this->handler->get($key, $modified_time);
}
function put($key, $obj, $valid_time = 0){
if(!$this->handler) return false;
return $this->handler->put($key, $obj, $valid_time);
}
function delete($key){
if(!$this->handler) return false;
return $this->handler->delete($key);
}
function isValid($key, $modified_time){
if(!$this->handler) return false;
return $this->handler->isValid($key, $modified_time);
}
function truncate(){
if(!$this->handler) return false;
return $this->handler->truncate();
}
/**
* Function used for generating keys for similar objects.
*
* Ex: 1:document:123
* 1:document:777
*
* This allows easily removing all object of type "document"
* from cache by simply invalidating the group key.
*
* The new key will be 2:document:123, thus forcing the document
* to be reloaded from the database.
*/
function getGroupKey($keyGroupName, $key){
if(!$this->keyGroupVersions[$keyGroupName]){
$this->keyGroupVersions[$keyGroupName] = 1;
$this->handler->put('key_group_versions', $this->keyGroupVersions, 0);
}
return $this->keyGroupVersions[$keyGroupName] . ':' . $keyGroupName . ':' . $key;
}
function invalidateGroupKey($keyGroupName){
$this->keyGroupVersions[$keyGroupName]++;
$this->handler->put('key_group_versions', $this->keyGroupVersions, 0);
}
}
class CacheBase{
function get($key, $modified_time = 0){
return false;
}
function put($key, $obj, $valid_time = 0){
return false;
}
function isValid($key, $modified_time = 0){
return false;
}
function isSupport(){
return false;
}
function truncate(){
return false;
}
}
/* End of file CacheHandler.class.php */
/* Location: ./classes/cache/CacheHandler.class.php */

View file

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

View file

@ -24,8 +24,7 @@ class Context {
var $ftp_info = NULL; ///< FTP info.
var $ssl_actions = array(); ///< list of actions to be sent via ssl (it is used by javascript xml handler for ajax)
var $js_files_map = array(); ///< hash map of javascript files. The file name is used as a key
var $css_files_map = array(); ///< hash map of css files. The file name is used as a key
var $oFrontEndFileHandler;
var $html_header = NULL; ///< script codes in <head>..</head>
var $body_class = array(); ///< classnames of <body>
@ -57,6 +56,14 @@ class Context {
return $theInstance;
}
/**
* @brief cunstructor
**/
function Context()
{
$this->oFrontEndFileHandler = new FrontEndFileHandler();
}
/**
* @brief initialization, it sets DB information, request arguments and so on.
* @return none
@ -120,19 +127,20 @@ class Context {
$this->loadLang(_XE_PATH_.'modules/module/lang');
// set session handler
if($this->db_info->use_db_session != 'N') {
if(Context::isInstalled() && $this->db_info->use_db_session != 'N') {
$oSessionModel = &getModel('session');
$oSessionController = &getController('session');
session_set_save_handler(
array(&$oSessionController,"open"),
array(&$oSessionController,"close"),
array(&$oSessionModel,"read"),
array(&$oSessionController,"write"),
array(&$oSessionController,"destroy"),
array(&$oSessionController,"gc")
array(&$oSessionController, 'open'),
array(&$oSessionController, 'close'),
array(&$oSessionModel, 'read'),
array(&$oSessionController, 'write'),
array(&$oSessionController, 'destroy'),
array(&$oSessionController, 'gc')
);
}
session_start();
if($sess=$_POST[session_name()]) session_id($sess);
// set authentication information in Context and session
if(Context::isInstalled()) {
@ -166,7 +174,7 @@ class Context {
if($_SERVER['REQUEST_METHOD'] == 'GET') {
if($this->get_vars) {
foreach($this->get_vars as $key=>$val) {
if(!$val) continue;
if(!strlen($val)) continue;
if(is_array($val)&&count($val)) {
foreach($val as $k => $v) {
$url .= ($url?'&':'').$key.'['.$k.']='.urlencode($v);
@ -210,7 +218,28 @@ class Context {
$config_file = $self->getConfigFile();
if(is_readable($config_file)) @include($config_file);
if(!$db_info->time_zone) $db_info->time_zone = date("O");
// If master_db information does not exist, the config file needs to be updated
if(!isset($db_info->master_db)) {
$db_info->master_db = array();
$db_info->master_db["db_type"] = $db_info->db_type; unset($db_info->db_type);
$db_info->master_db["db_port"] = $db_info->db_port; unset($db_info->db_port);
$db_info->master_db["db_hostname"] = $db_info->db_hostname; unset($db_info->db_hostname);
$db_info->master_db["db_password"] = $db_info->db_password; unset($db_info->db_password);
$db_info->master_db["db_database"] = $db_info->db_database; unset($db_info->db_database);
$db_info->master_db["db_userid"] = $db_info->db_userid; unset($db_info->db_userid);
$db_info->master_db["db_table_prefix"] = $db_info->db_table_prefix; unset($db_info->db_table_prefix);
if(substr($db_info->master_db["db_table_prefix"],-1)!='_') $db_info->master_db["db_table_prefix"] .= '_';
$slave_db = $db_info->master_db;
$db_info->slave_db = array($slave_db);
$self->setDBInfo($db_info);
$oInstallController = &getController('install');
$oInstallController->makeConfigFile();
}
if(!$db_info->time_zone) $db_info->time_zone = date('O');
$GLOBALS['_time_zone'] = $db_info->time_zone;
if($db_info->qmail_compatibility != 'Y') $db_info->qmail_compatibility = 'N';
@ -231,7 +260,7 @@ class Context {
**/
function getDBType() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
return $self->db_info->db_type;
return $self->db_info->master_db["db_type"];
}
/**
@ -253,6 +282,16 @@ class Context {
return $self->db_info;
}
/**
* @brief return ssl status
* @return none|always|optional
**/
function getSslStatus()
{
$dbInfo = Context::getDBInfo();
return $dbInfo->use_ssl;
}
/**
* @brief return default URL
* @return default URL string
@ -330,7 +369,7 @@ class Context {
$url_info = parse_url($url);
$url_info['query'].= ($url_info['query']?'&':'').'SSOID='.session_id();
$redirect_url = sprintf('%s://%s%s%s?%s',$url_info['scheme'],$url_info['host'],$url_info['port']?':'.$url_info['port']:'',$url_info['path'], $url_info['query']);
header("location:".$redirect_url);
header('location:'.$redirect_url);
return false;
}
// for sites requesting SSO validation
@ -341,13 +380,13 @@ class Context {
setcookie(session_name(), $session_name);
$url = preg_replace('/([\?\&])$/','',str_replace('SSOID='.$session_name,'',Context::getRequestUrl()));
header("location:".$url);
header('location:'.$url);
return false;
// send SSO request
} else if($_COOKIE['sso']!=md5(Context::getRequestUri()) && !Context::get('SSOID')) {
setcookie('sso',md5(Context::getRequestUri()),0,'/');
$url = sprintf("%s?default_url=%s", $default_url, base64_encode(Context::getRequestUrl()));
header("location:".$url);
header('location:'.$url);
return false;
}
}
@ -413,7 +452,7 @@ class Context {
$oModuleController = &getController('module');
$oModuleController->replaceDefinedLangCode($self->site_title);
return $self->site_title;
return htmlspecialchars($self->site_title);
}
/**
* @deprecated
@ -432,20 +471,61 @@ class Context {
if(!is_object($lang)) $lang = new stdClass;
if(!$self->lang_type) return;
if(substr($path,-1)!='/') $path .= '/';
$path_tpl = $path.'%s.lang.php';
$filename = sprintf($path_tpl, $self->lang_type);
$langs = array('ko','en'); // this will be configurable.
while(!is_readable($filename) && $langs[0]) {
$filename = sprintf($path_tpl, array_shift($langs));
}
if(!is_readable($filename)) return;
$filename = $self->_loadXmlLang($path);
if(!$filename) $filename = $self->_loadPhpLang($path);
if(!is_array($self->loaded_lang_files)) $self->loaded_lang_files = array();
if(in_array($filename, $self->loaded_lang_files)) return;
$self->loaded_lang_files[] = $filename;
@include($filename);
if ($filename && is_readable($filename)){
$self->loaded_lang_files[] = $filename;
@include($filename);
}else{
$self->_evalxmlLang($path);
}
}
function _evalxmlLang($path) {
global $lang;
$_path = 'eval://'.$path;
if(in_array($_path, $this->loaded_lang_files)) return;
if(substr($path,-1)!='/') $path .= '/';
$file = $path.'lang.xml';
$oXmlLangParser = new XmlLangParser($file, $this->lang_type);
$content = $oXmlLangParser->getCompileContent();
if ($content){
$this->loaded_lang_files[] = $_path;
eval($content);
}
}
function _loadXmlLang($path) {
if(substr($path,-1)!='/') $path .= '/';
$file = $path.'lang.xml';
$oXmlLangParser = new XmlLangParser($file, $this->lang_type);
$file = $oXmlLangParser->compile();
return $file;
}
function _loadPhpLang($path) {
if(substr($path,-1)!='/') $path .= '/';
$path_tpl = $path.'%s.lang.php';
$file = sprintf($path_tpl, $this->lang_type);
$langs = array('ko','en'); // this will be configurable.
while(!is_readable($file) && $langs[0]) {
$file = sprintf($path_tpl, array_shift($langs));
}
if(!is_readable($file)) return false;
return $file;
}
/**
@ -564,15 +644,15 @@ class Context {
/**
* @brief determine request method (GET/POST/XMLRPC/JSON)
* @param[in] $type request method
* @param[in] $type request method (optional)
* @return none
**/
function setRequestMethod($type) {
function setRequestMethod($type='') {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
($type && $self->request_method=$type) or
(strpos($_SERVER['CONTENT_TYPE'],'json') && $this->request_method='JSON') or
($GLOBALS['HTTP_RAW_POST_DATA'] && $this->request_method='XMLRPC') or
(strpos($_SERVER['CONTENT_TYPE'],'json') && $self->request_method='JSON') or
($GLOBALS['HTTP_RAW_POST_DATA'] && $self->request_method='XMLRPC') or
($self->request_method = $_SERVER['REQUEST_METHOD']);
}
@ -584,7 +664,7 @@ class Context {
if(!count($_REQUEST)) return;
foreach($_REQUEST as $key => $val) {
if($val === "" || Context::get($key)) continue;
if($val === '' || Context::get($key)) continue;
$val = $this->_filterRequestVar($key, $val);
if($this->getRequestMethod()=='GET'&&isset($_GET[$key])) $set_to_vars = true;
@ -640,15 +720,15 @@ class Context {
* @return filtered value
**/
function _filterRequestVar($key, $val, $do_stripslashes = 1) {
if( ($key == "page" || $key == "cpage" || substr($key,-3)=="srl")) return !preg_match('/^[0-9,]+$/',$val)?(int)$val:$val;
if( ($key == 'page' || $key == 'cpage' || substr($key,-3)=='srl')) return !preg_match('/^[0-9,]+$/',$val)?(int)$val:$val;
if(is_array($val) && count($val) ) {
foreach($val as $k => $v) {
if($do_stripslashes && version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $v = stripslashes($v);
if($do_stripslashes && version_compare(PHP_VERSION, '5.9.0', '<') && get_magic_quotes_gpc()) $v = stripslashes($v);
$v = trim($v);
$val[$k] = $v;
}
} else {
if($do_stripslashes && version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $val = stripslashes($val);
if($do_stripslashes && version_compare(PHP_VERSION, '5.9.0', '<') && get_magic_quotes_gpc()) $val = stripslashes($val);
$val = trim($val);
}
return $val;
@ -669,7 +749,7 @@ class Context {
**/
function _setUploadedArgument() {
if($this->getRequestMethod() != 'POST') return;
if(!preg_match("/multipart\/form-data/i",$_SERVER['CONTENT_TYPE'])) return;
if(!preg_match('/multipart\/form-data/i',$_SERVER['CONTENT_TYPE'])) return;
if(!$_FILES) return;
foreach($_FILES as $key => $val) {
@ -709,7 +789,7 @@ class Context {
* @brief make URL with args_list upon request URL
* @return result URL
**/
function getUrl($num_args=0, $args_list=array(), $domain = null, $encode = true) {
function getUrl($num_args=0, $args_list=array(), $domain = null, $encode = true, $autoEncode = false) {
static $site_module_info = null;
static $current_info = null;
@ -788,7 +868,9 @@ class Context {
// if using rewrite mod
if($self->allow_rewrite) {
$var_keys = array_keys($get_vars);
$target = implode('.', $var_keys);
sort($var_keys);
$target = implode('.', $var_keys);
$act = $get_vars['act'];
$vid = $get_vars['vid'];
@ -817,7 +899,7 @@ class Context {
'act.document_srl.key.vid'=>($act=='trackback')?"$vid/$srl/$key/$act":''
);
$query = $target_map[$target];
$query = $target_map[$target];
}
if(!$query) {
@ -853,18 +935,37 @@ class Context {
else $query = getScriptPath().$query;
}
return $encode?htmlspecialchars($query):$query;
if ($encode){
if($autoEncode){
$parsedUrl = parse_url($query);
parse_str($parsedUrl['query'], $output);
$encode_queries = array();
foreach($output as $key=>$value){
if (preg_match('/&([a-z]{2,}|#\d+);/', urldecode($value))){
$value = urlencode(htmlspecialchars_decode(urldecode($value)));
}
$encode_queries[] = $key.'='.$value;
}
$encode_query = implode('&', $encode_queries);
return htmlspecialchars($parsedUrl['path'].'?'.$encode_query);
}
else{
return htmlspecialchars($query);
}
}else{
return $query;
}
}
/**
* @brief 요청이 들어온 URL에서 argument를 제거하여 return
* @brief Return after removing an argument on the requested URL
**/
function getRequestUri($ssl_mode = FOLLOW_REQUEST_SSL, $domain = null) {
static $url = array();
// HTTP Request가 아니면 패스
if(!isset($_SERVER['SERVER_PROTOCOL'])) return ;
if(Context::get('_use_ssl') == "always") $ssl_mode = ENFORCE_SSL;
if(Context::get('_use_ssl') == 'always') $ssl_mode = ENFORCE_SSL;
if($domain) $domain_key = md5($domain);
else $domain_key = 'default';
@ -903,7 +1004,7 @@ class Context {
elseif($url_info['port']==80) unset($url_info['port']);
}
$url[$ssl_mode][$domain_key] = sprintf("%s://%s%s%s",$use_ssl?'https':$url_info['scheme'], $url_info['host'], $url_info['port']&&$url_info['port']!=80?':'.$url_info['port']:'',$url_info['path']);
$url[$ssl_mode][$domain_key] = sprintf('%s://%s%s%s',$use_ssl?'https':$url_info['scheme'], $url_info['host'], $url_info['port']&&$url_info['port']!=80?':'.$url_info['port']:'',$url_info['path']);
return $url[$ssl_mode][$domain_key];
}
@ -919,17 +1020,19 @@ class Context {
}
/**
* @brief key값에 해당하는 값을 return
* @brief return key value
**/
function get($key) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
if(!isset($self->context->{$key})) return null;
return $self->context->{$key};
}
/**
* @brief 받고자 하는 변수만 object에 입력하여 받음
*
* key1, key2, key3 .. 등의 인자를 주어 여러개의 변수를 object vars로 세팅하여 받을 있음
* @brief get a specified var in object
*
* get one more vars in object vars with given arguments(key1, key2, key3,...)
**/
function gets() {
$num_args = func_num_args();
@ -944,7 +1047,7 @@ class Context {
}
/**
* @brief 모든 데이터를 return
* @brief Return all data
**/
function getAll() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
@ -952,16 +1055,17 @@ class Context {
}
/**
* @brief GET/POST/XMLRPC에서 넘어온 변수값을 return
* @brief Return values from the GET/POST/XMLRPC
**/
function getRequestVars() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
return clone($self->get_vars);
if($self->get_vars) return clone($self->get_vars);
return new stdClass;
}
/**
* @brief SSL로 인증되어야 action이 있을 경우 등록
* common/js/xml_handler.js에서 action들에 대해서 https로 전송되도록
* @brief Register if actions is to be encrypted by SSL
* Those actions are sent to https in common/js/xml_handler.js
**/
function addSSLAction($action) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
@ -982,6 +1086,7 @@ class Context {
/**
* @brief normalize file path
* @return normalized file path
* @deprecated
*/
function normalizeFilePath($file) {
if(strpos($file,'://')===false && $file{0}!='/' && $file{0}!='.') $file = './'.$file;
@ -992,37 +1097,78 @@ class Context {
}
/**
* @brief js file을 추가
* @deprecated
**/
function addJsFile($file, $optimized = false, $targetie = '',$index=0, $type='head') {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
function getAbsFileUrl($file) {
$file = Context::normalizeFilePath($file);
if(strpos($file,'./')===0) $file = dirname($_SERVER['SCRIPT_NAME']).'/'.substr($file,2);
elseif(strpos($file,'../')===0) $file = Context::normalizeFilePath(dirname($_SERVER['SCRIPT_NAME'])."/{$file}");
$avail_types = array('head', 'body');
if(!in_array($type, $avail_types)) $type = $avail_types[0];
$key = $self->normalizeFilePath($file)."\t".$targetie;
$map = &$self->js_files_map;
// Is this file already registered?
if (!is_array($map[$type])) $map[$type] = array();
if (!isset($map[$type][$key]) || (int)$map[$type][$key] > (int)$index) $map[$type][$key] = (int)$index+count($map[$type])/1000-1;
return $file;
}
/**
* @brief js file을 제거
* @brief load front end file
* @params $args array
* case js
* $args[0]: file name
* $args[1]: type (head | body)
* $args[2]: target IE
* $args[3]: index
* case css
* $args[0]: file name
* $args[1]: media
* $args[2]: target IE
* $args[3]: index
**/
function loadFile($args, $useCdn = false, $cdnPrefix = '', $cdnVersion = '')
{
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
if ($useCdn && !$cdnPrefix)
{
$cdnPrefix = __XE_CDN_PREFIX__;
$cdnVersion = __XE_CDN_VERSION__;
}
$self->oFrontEndFileHandler->loadFile($args, $useCdn, $cdnPrefix, $cdnVersion);
}
function unloadFile($file, $targetIe = '', $media = 'all')
{
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$self->oFrontEndFileHandler->unloadFile($file, $targetIe, $media);
}
function unloadAllFiles($type = 'all')
{
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$self->oFrontEndFileHandler->unloadAllFiles($type);
}
/**
* @brief Add the js file
* @deprecated
**/
function addJsFile($file, $optimized = false, $targetie = '',$index=0, $type='head', $isRuleset = false) {
if($isRuleset)
{
$validator = new Validator($file);
$validator->setCacheDir('files/cache');
$file = $validator->getJsPath();
}
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$self->oFrontEndFileHandler->loadFile(array($file, $type, $targetie, $index));
}
/**
* @brief Remove the js file
* @deprecated
**/
function unloadJsFile($file, $optimized = false, $targetie = '') {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$realfile = realpath($file);
foreach($self->js_files_map as $key=>$val) {
list($_file, $_targetie) = explode("\t", $key);
if(realpath($_file)==$realfile && $_targetie == $targetie) {
unset($self->js_files_map[$key]);
return;
}
}
$self->oFrontEndFileHandler->unloadFile($file, $targetie);
}
/**
@ -1030,18 +1176,18 @@ class Context {
**/
function unloadAllJsFiles() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$self->js_files_map = array();
$self->oFrontEndFileHandler->unloadAllJsFiles();
}
/**
* @brief javascript filter 추가
* @brief Add javascript filter
**/
function addJsFilter($path, $filename) {
$oXmlFilter = new XmlJSFilter($path, $filename);
$oXmlFilter->compile();
}
/**
* @brief array_unique와 동작은 동일하나 file 첨자에 대해서만 동작함
* @brief Same as array_unique but works only for file subscript
* @deprecated
**/
function _getUniqueFileList($files) {
@ -1063,49 +1209,25 @@ class Context {
**/
function getJsFile($type='head') {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
if(!is_array($self->js_files_map[$type])) $self->js_files_map[$type] = array();
$ret = array();
$map = &$self->js_files_map[$type];
asort($self->js_files_map[$type]);
foreach($map as $key=>$val) {
list($file, $targetie) = explode("\t", $key);
$ret[] = array('file'=>$file, 'targetie'=>$targetie);
}
return $ret;
return $self->oFrontEndFileHandler->getJsFileList($type);
}
/**
* @brief CSS file 추가
* @brief Add CSS file
* @deprecated
**/
function addCSSFile($file, $optimized=false, $media='all', $targetie='',$index=0) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$key = $self->normalizeFilePath($file)."\t".$targetie."\t".$media;
$map = &$self->css_files_map;
if (!isset($map[$key]) || (int)$map[$key] > (int)$index) $map[$key] = (int)$index+count($map)/100-1;
$self->oFrontEndFileHandler->loadFile(array($file, $media, $targetie, $index));
}
/**
* @brief css file을 제거
* @brief Remove css file
* @deprecated
**/
function unloadCSSFile($file, $optimized = false, $media = 'all', $targetie = '') {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$realfile = realpath($file);
foreach($self->css_files_map as $key => $val) {
list($_file, $_targetie, $_media) = explode("\t", $key);
if(realpath($_file)==$realfile && $_media==$media && $_targetie==$targetie) {
unset($self->css_files_map[$key]);
return;
}
}
$self->oFrontEndFileHandler->unloadFile($file, $targetie, $media);
}
/**
@ -1113,7 +1235,7 @@ class Context {
**/
function unloadAllCSSFiles() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$self->css_files_map = array();
$self->oFrontEndFileHandler->unloadAllCssFiles();
}
/**
@ -1121,16 +1243,7 @@ class Context {
**/
function getCSSFile() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
asort($self->css_files_map);
$ret = array();
foreach($self->css_files_map as $key=>$val) {
list($_file, $_targetie, $_media) = explode("\t", $key);
$ret[] = array('file'=>$_file, 'media'=>$_media, 'targetie'=>$_targetie);
}
return $ret;
return $self->oFrontEndFileHandler->getCssFileList();
}
/**
@ -1145,7 +1258,7 @@ class Context {
if($loaded_plugins[$plugin_name]) return;
$loaded_plugins[$plugin_name] = true;
$plugin_path = "./common/js/plugins/$plugin_name/";
$plugin_path = './common/js/plugins/'.$plugin_name.'/';
$info_file = $plugin_path.'plugin.load';
if(!is_readable($info_file)) return;
@ -1155,15 +1268,15 @@ class Context {
if(!$filename) continue;
if(substr($filename,0,2)=='./') $filename = substr($filename,2);
if(preg_match('/\.js$/i', $filename)) $self->addJsFile($plugin_path.$filename, false, '', 0, 'body');
elseif(preg_match('/\.css$/i', $filename)) $self->addCSSFile($plugin_path.$filename, false, 'all', '', 0);
if(preg_match('/\.js$/i', $filename)) $self->loadFile(array($plugin_path.$filename, 'body', '', 0), true);
elseif(preg_match('/\.css$/i', $filename)) $self->loadFile(array($plugin_path.$filename, 'all', '', 0), true);
}
if(is_dir($plugin_path.'lang')) $self->loadLang($plugin_path.'lang');
}
/**
* @brief HtmlHeader 추가
* @brief Add HtmlHeader
**/
function addHtmlHeader($header) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
@ -1179,7 +1292,7 @@ class Context {
}
/**
* @brief Html Body에 css class 추가
* @brief Add css class to Html Body
**/
function addBodyClass($class_name) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
@ -1187,7 +1300,7 @@ class Context {
}
/**
* @brief Html Body에 css class return
* @brief Return css class to Html Body
**/
function getBodyClass() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
@ -1232,14 +1345,14 @@ class Context {
* @brief returns the path of the config file that contains database settings
**/
function getConfigFile() {
return _XE_PATH_."files/config/db.config.php";
return _XE_PATH_.'files/config/db.config.php';
}
/**
* @brief returns the path of the config file that contains FTP settings
**/
function getFTPConfigFile() {
return _XE_PATH_."files/config/ftp.config.php";
return _XE_PATH_.'files/config/ftp.config.php';
}
/**
@ -1251,7 +1364,7 @@ class Context {
}
/**
* @brief 내용의 위젯이나 기타 기능에 대한 code를 실제 code로 변경
* @brief Transforms codes about widget or other features into the actual code, deprecatred
**/
function transContent($content) {
return $content;
@ -1300,5 +1413,36 @@ class Context {
if(substr($path,-1)!='/') $path .= '/';
return $path;
}
/**
* @brief returns the list of meta tags
**/
function getMetaTag() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
if(!is_array($self->meta_tags)) $self->meta_tags = array();
$ret = array();
$map = &$self->meta_tags;
foreach($map as $key=>$val) {
list($name, $is_http_equiv) = explode("\t", $key);
$ret[] = array('name'=>$name, 'is_http_equiv'=>$is_http_equiv, 'content' => $val);
}
return $ret;
}
/**
* @brief Add the meta tag
**/
function addMetaTag($name, $content, $is_http_equiv = false) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$key = $name."\t".($is_http_equiv ? '1' : '0');
$map = &$self->meta_tags;
$map[$key] = $content;
}
}
?>
?>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,164 +1,152 @@
<?php
require_once('DBMysql.class.php');
/**
* @class DBMysql_innodb
* @author NHN (developers@xpressengine.com)
* @brief MySQL DBMS를 이용하기 위한 class
* @version 0.1
*
* mysql innodb handling class
**/
class DBMysql_innodb extends DBMysql {
/**
* @brief constructor
**/
function DBMysql_innodb() {
$this->_setDBInfo();
$this->_connect();
}
/**
* @brief create an instance of this class
*/
function create()
{
return new DBMysql_innodb;
}
/**
* @brief DB접속 해제
**/
function close() {
if(!$this->isConnected()) return;
$this->_query("commit");
@mysql_close($this->fd);
}
/**
* @brief 트랜잭션 시작
**/
function begin() {
if(!$this->isConnected() || $this->transaction_started) return;
$this->transaction_started = true;
$this->_query("begin");
}
/**
* @brief 롤백
**/
function rollback() {
if(!$this->isConnected() || !$this->transaction_started) return;
$this->_query("rollback");
$this->transaction_started = false;
}
/**
* @brief 커밋
**/
function commit($force = false) {
if(!$force && (!$this->isConnected() || !$this->transaction_started)) return;
$this->_query("commit");
$this->transaction_started = false;
}
/**
* @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 = @mysql_query($query, $this->fd);
// 오류 체크
if(mysql_error($this->fd)) $this->setError(mysql_errno($this->fd), mysql_error($this->fd));
// 쿼리 실행 종료를 알림
$this->actFinish();
// 결과 리턴
return $result;
}
/**
* @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.')':'',
isset($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 = INNODB CHARACTER SET utf8 COLLATE utf8_general_ci");
$output = $this->_query($schema);
if(!$output) return false;
}
}
return new DBMysql_innodb;
?>
<?php
require_once('DBMysql.class.php');
/**
* @class DBMysql_innodb
* @author NHN (developers@xpressengine.com)
* @brief class to use MySQL DBMS
* @version 0.1
*
* mysql innodb handling class
**/
class DBMysql_innodb extends DBMysql {
/**
* @brief constructor
**/
function DBMysql_innodb() {
$this->_setDBInfo();
$this->_connect();
}
/**
* @brief create an instance of this class
*/
function create()
{
return new DBMysql_innodb;
}
/**
* @brief DB disconnection
**/
function _close($connection) {
$this->_query("commit", $connection);
@mysql_close($connection);
}
/**
* @brief Begin transaction
**/
function _begin() {
$connection = $this->_getConnection('master');
$this->_query("begin", $connection);
return true;
}
/**
* @brief Rollback
**/
function _rollback() {
$connection = $this->_getConnection('master');
$this->_query("rollback", $connection);
return true;
}
/**
* @brief Commits
**/
function _commit() {
$connection = $this->_getConnection('master');
$this->_query("commit", $connection);
return true;
}
/**
* @brief : Run a query and fetch the result
*
* query: run a query and return the result \n
* fetch: NULL if no value is returned \n
* array object if rows are returned \n
* object if a row is returned \n
* return\n
**/
function __query($query, $connection) {
// Run the query statement
$result = @mysql_query($query, $connection);
// Error Check
if(mysql_error($connection)) $this->setError(mysql_errno($connection), mysql_error($connection));
// Return result
return $result;
}
/**
* @brief generate a query statement to create a table by using schema xml
*
* 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);
// Create a table 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.')':'',
isset($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 = INNODB CHARACTER SET utf8 COLLATE utf8_general_ci");
$output = $this->_query($schema);
if(!$output) return false;
}
}
return new DBMysql_innodb;
?>

View file

@ -1,123 +1,118 @@
<?php
require_once('DBMysql.class.php');
/**
* @class DBMysqli
* @author NHN (developers@xpressengine.com)
* @brief MySQL DBMS를 mysqli_* 이용하기 위한 class
* @version 0.1
*
* mysql handling class
**/
class DBMysqli extends DBMysql {
/**
* @brief constructor
**/
function DBMysqli() {
$this->_setDBInfo();
$this->_connect();
}
/**
* @brief 설치 가능 여부를 return
**/
function isSupported() {
if(!function_exists('mysqli_connect')) return false;
return true;
}
/**
* @brief create an instance of this class
*/
function create()
{
return new DBMysqli;
}
/**
* @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,mysqli_connect_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 : 쿼리문의 실행 결과의 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;
}
function db_insert_id()
{
return mysqli_insert_id($this->fd);
}
function db_fetch_object(&$result)
{
return mysqli_fetch_object($result);
}
}
return new DBMysqli;
?>
<?php
require_once('DBMysql.class.php');
/**
* @class DBMysqli
* @author NHN (developers@xpressengine.com)
* @brief Class to use MySQL DBMS as mysqli_*
* @version 0.1
*
* mysql handling class
**/
class DBMysqli extends DBMysql {
/**
* @brief constructor
**/
function DBMysqli() {
$this->_setDBInfo();
$this->_connect();
}
/**
* @brief Return if it is installable
**/
function isSupported() {
if(!function_exists('mysqli_connect')) return false;
return true;
}
/**
* @brief create an instance of this class
*/
function create()
{
return new DBMysqli;
}
/**
* @brief DB Connection
**/
function __connect($connection) {
// Attempt to connect
if ($connection["db_port"]) {
$result = @mysqli_connect($connection["db_hostname"]
, $connection["db_userid"]
, $connection["db_password"]
, $connection["db_database"]
, $connection["db_port"]);
} else {
$result = @mysqli_connect($connection["db_hostname"]
, $connection["db_userid"]
, $connection["db_password"]
, $connection["db_database"]);
}
$error = mysqli_connect_errno();
if($error) {
$this->setError($error,mysqli_connect_error());
return;
}
mysqli_set_charset($result,'utf8');
return $result;
}
/**
* @brief DB disconnection
**/
function _close($connection) {
mysqli_close($connection);
}
/**
* @brief Add quotes on the string variables in a query
**/
function addQuotes($string) {
if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string));
if(!is_numeric($string)){
$connection = $this->_getConnection('master');
$string = mysqli_escape_string($connection,$string);
}
return $string;
}
/**
* @brief : Run a query and fetch the result
*
* query: run a query and return the result \n
* fetch: NULL if no value is returned \n
* array object if rows are returned \n
* object if a row is returned \n
* return\n
**/
function __query($query, $connection) {
// Run the query statement
$result = mysqli_query($connection,$query);
// Error Check
$error = mysqli_error($connection);
if($error){
$this->setError(mysqli_errno($connection), $error);
}
// Return result
return $result;
}
function db_insert_id()
{
$connection = $this->_getConnection('master');
return mysqli_insert_id($connection);
}
function db_fetch_object(&$result)
{
return mysqli_fetch_object($result);
}
}
return new DBMysqli;
?>

View file

@ -2,43 +2,39 @@
/**
* @class DBPostgreSQL
* @author ioseph (ioseph@postgresql.kr) updated by yoonjong.joh@gmail.com
* @brief MySQL DBMS를 이용하기 위한 class
* @brief Class to use PostgreSQL DBMS
* @version 0.2
*
* postgresql handling class
* 2009.02.10 update delete query를 실행할때 table 이름에 alias 사용하는 것을 없앰. 지원 안함
* order by clause를 실행할때 함수를 실행 하는 부분을 column alias로 대체.
* 2009.02.11 dropColumn() function이 추가
* 2009.02.13 addColumn() 함수 변경
* 2009.02.10 update and delete query for the table name at runtime, eliminating the alias to use. Not Supported
* when running order by clause column alias to run a function to replace parts.
* 2009.02.11 dropColumn() function added
* 2009.02.13 addColumn() function changes
**/
class DBPostgresql extends DB
{
/**
* @brief PostgreSQL DB접속하기 위한 정보
* @brief Connection information for PostgreSQL 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설치 가능)
var $comment_syntax = '/* %s */';
var $prefix = 'xe'; // / <prefix of a tablename (One or more XEs can be installed in a single DB)
var $comment_syntax = '/* %s */';
/**
* @brief postgresql에서 사용될 column type
* @brief column type used in postgresql
*
* column_type은 schema/query xml에서 공통 선언된 type을 이용하기 때문에
* DBMS에 맞게 replace 해주어야 한다
* Becasue a common column type in schema/query xml is used for colum_type,
* it should be replaced properly for each DBMS
**/
var $column_type = array(
'bignumber' => 'bigint',
'bignumber' => 'bigint',
'number' => 'integer',
'varchar' => 'varchar',
'char' => 'char',
'text' => 'text',
'varchar' => 'varchar',
'char' => 'char',
'text' => 'text',
'bigtext' => 'text',
'date' => 'varchar(14)',
'date' => 'varchar(14)',
'float' => 'real',
);
@ -50,7 +46,7 @@ class DBPostgresql extends DB
$this->_setDBInfo();
$this->_connect();
}
/**
* @brief create an instance of this class
*/
@ -60,7 +56,7 @@ class DBPostgresql extends DB
}
/**
* @brief 설치 가능 여부를 return
* @brief Return if it is installable
**/
function isSupported()
{
@ -70,66 +66,38 @@ class DBPostgresql extends DB
}
/**
* @brief DB정보 설정 connect/ close
* @brief DB Connection
**/
function _setDBInfo()
function __connect($connection)
{
$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()
{
// pg용 connection string
// the connection string for PG
$conn_string = "";
// Create connection string
$conn_string .= ($connection["db_hostname"]) ? ' host='.$connection["db_hostname"] : "";
$conn_string .= ($connection["db_userid"]) ? " user=" . $connection["db_userid"] : "";
$conn_string .= ($connection["db_password"]) ? " password=" . $connection["db_password"] : "";
$conn_string .= ($connection["db_database"]) ? " dbname=" . $connection["db_database"] : "";
$conn_string .= ($connection["db_port"]) ? " port=" . $connection["db_port"] : "";
// db 정보가 없으면 무시
if (!$this->hostname || !$this->userid || !$this->database)
return;
// connection string 만들기
$conn_string .= ($this->hostname) ? " host=$this->hostname" : "";
$conn_string .= ($this->userid) ? " user=$this->userid" : "";
$conn_string .= ($this->password) ? " password=$this->password" : "";
$conn_string .= ($this->database) ? " dbname=$this->database" : "";
$conn_string .= ($this->port) ? " port=$this->port" : "";
// 접속시도
$this->fd = @pg_connect($conn_string);
if (!$this->fd || pg_connection_status($this->fd) != PGSQL_CONNECTION_OK) {
// Attempt to connect
$result = @pg_connect($conn_string);
if (!$result || pg_connection_status($result) != PGSQL_CONNECTION_OK) {
$this->setError(-1, "CONNECTION FAILURE");
return;
}
// 접속체크
$this->is_connected = true;
$this->password = md5($this->password);
// utf8임을 지정
//$this ->_query('set client_encoding to uhc');
return $result;
}
/**
* @brief DB접속 해제
* @brief DB disconnection
**/
function close()
function _close($connection)
{
if (!$this->isConnected())
return;
@pg_close($this->fd);
@pg_close($connection);
}
/**
* @brief 쿼리에서 입력되는 문자열 변수들의 quotation 조절
* @brief Add quotes on the string variables in a query
**/
function addQuotes($string)
{
@ -141,48 +109,43 @@ class DBPostgresql extends DB
}
/**
* @brief 트랜잭션 시작
* @brief Begin transaction
**/
function begin()
function _begin()
{
if (!$this->isConnected() || $this->transaction_started == false)
return;
if ($this->_query($this->fd, 'BEGIN'))
$this->transaction_started = true;
$connection = $this->_getConnection('master');
if (!$this->_query('BEGIN')) return false;
return true;
}
/**
* @brief 롤백
* @brief Rollback
**/
function rollback()
function _rollback()
{
if (!$this->isConnected() || $this->transaction_started == false)
return;
if ($this->_query($this->fd, 'ROLLBACK'))
$this->transaction_started = false;
if (!$this->_query('ROLLBACK')) return false;
return true;
}
/**
* @brief 커밋
* @brief Commits
**/
function commit()
function _commit()
{
if (!$this->isConnected() || $this->transaction_started == false)
return;
if ($this->_query($this->fd, 'COMMIT'))
$this->transaction_started = false;
if (!$this->_query('COMMIT')) return false;
return true;
}
/**
* @brief : 쿼리문의 실행 결과의 fetch 처리
* @brief : Run a query and fetch the result
*
* query : query문 실행하고 result return\n
* fetch : reutrn 값이 없으면 NULL\n
* rows이면 array object\n
* row이면 object\n
* query: run a query and return the result \n
* fetch: NULL if no value is returned \n
* array object if rows are returned \n
* object if a row is returned \n
* return\n
**/
function _query($query)
function __query($query, $connection)
{
if (!$this->isConnected())
return;
@ -198,58 +161,53 @@ class DBPostgresql extends DB
$query = implode(" ",$l_query_array);
}
}
else if ($l_query_array[0] = "delete")
else if ($l_query_array[0] = "delete")
{
if (strtolower($l_query_array[3]) == "as")
{
$l_query_array[3] = "";
$l_query_array[4] = "";
$l_query_array[4] = "";
$query = implode(" ",$l_query_array);
}
}
*/
// 쿼리 시작을 알림
$this->actStart($query);
$arr = array('Hello', 'World!', 'Beautiful', 'Day!');
// 쿼리 문 실행
$result = @pg_query($this->fd, $query);
// 오류 체크
// Notify to start a query execution
// $arr = array('Hello', 'World!', 'Beautiful', 'Day!');
// Run the query statement
$result = @pg_query($connection, $query);
// Error Check
if (!$result) {
// var_dump($l_query_array);
//var_dump($query);
//die("\nin query statement\n");
//var_dump(debug_backtrace());
$this->setError(1, pg_last_error($this->fd));
$this->setError(1, pg_last_error($connection));
}
// 쿼리 실행 종료를 알림
$this->actFinish();
// 결과 리턴
// Return result
return $result;
}
/**
* @brief 결과를 fetch
* @brief Fetch results
**/
function _fetch($result)
// TODO This is duplicate code - maybe we can find away to abastract the driver
function _fetch($result, $arrayIndexEndValue = NULL)
{
if (!$this->isConnected() || $this->isError() || !$result)
return;
while ($tmp = pg_fetch_object($result)) {
$output[] = $tmp;
if($arrayIndexEndValue) $output[$arrayIndexEndValue--] = $tmp;
else $output[] = $tmp;
}
if(count($output)==1){
if(isset($arrayIndexEndValue)) return $output;
else return $output[0];
}
if (count($output) == 1)
return $output[0];
return $output;
}
/**
* @brief 1 증가되는 sequence값을 return (postgresql의 auto_increment는 sequence테이블에서만 사용)
* @brief Return sequence value incremented by 1(in postgresql, auto_increment is used in the sequence table only)
**/
function getNextSequence()
{
@ -260,7 +218,7 @@ class DBPostgresql extends DB
}
/**
* @brief 테이블 기생성 여부 return
* @brief Return if a table already exists
**/
function isTableExists($target_name)
{
@ -277,7 +235,7 @@ class DBPostgresql extends DB
}
/**
* @brief 특정 테이블에 특정 column 추가
* @brief Add a column to a table
**/
function addColumn($table_name, $column_name, $type = 'number', $size = '', $default =
NULL, $notnull = false)
@ -301,7 +259,7 @@ class DBPostgresql extends DB
}
if ($notnull) {
$query = sprintf("update %s%s set %s = %s ", $this->prefix, $table_name, $column_name, $default);
$this->_query($query);
$this->_query($query);
$query = sprintf("alter table %s%s alter %s set not null ", $this->prefix, $table_name, $column_name);
$this->_query($query);
}
@ -309,7 +267,7 @@ class DBPostgresql extends DB
/**
* @brief 특정 테이블의 column의 정보를 return
* @brief Return column information of a table
**/
function isColumnExists($table_name, $column_name)
{
@ -329,7 +287,7 @@ class DBPostgresql extends DB
}
/**
* @brief 특정 테이블에 특정 인덱스 추가
* @brief Add an index to a table
* $target_columns = array(col1, col2)
* $is_unique? unique : none
**/
@ -340,8 +298,7 @@ class DBPostgresql extends DB
if (strpos($table_name, $this->prefix) === false)
$table_name = $this->prefix . $table_name;
// index_name의 경우 앞에 table이름을 붙여줘서 중복을 피함
// Use a tablename before an index name to avoid defining the same index
$index_name = $table_name . $index_name;
$query = sprintf("create %s index %s on %s (%s);", $is_unique ? 'unique' : '', $index_name,
@ -350,7 +307,7 @@ class DBPostgresql extends DB
}
/**
* @brief 특정 테이블에 특정 column 제거
* @brief Delete a column from a table
**/
function dropColumn($table_name, $column_name)
{
@ -359,14 +316,13 @@ class DBPostgresql extends DB
}
/**
* @brief 특정 테이블의 특정 인덱스 삭제
* @brief Drop an index from a table
**/
function dropIndex($table_name, $index_name, $is_unique = false)
{
if (strpos($table_name, $this->prefix) === false)
$table_name = $this->prefix . $table_name;
// index_name의 경우 앞에 table이름을 붙여줘서 중복을 피함
// Use a tablename before an index name to avoid defining the same index
$index_name = $table_name . $index_name;
$query = sprintf("drop index %s", $index_name);
@ -375,14 +331,13 @@ class DBPostgresql extends DB
/**
* @brief 특정 테이블의 index 정보를 return
* @brief Return index information of a table
**/
function isIndexExists($table_name, $index_name)
{
if (strpos($table_name, $this->prefix) === false)
$table_name = $this->prefix . $table_name;
// index_name의 경우 앞에 table이름을 붙여줘서 중복을 피함
// Use a tablename before an index name to avoid defining the same index
$index_name = $table_name . $index_name;
//$query = sprintf("show indexes from %s%s where key_name = '%s' ", $this->prefix, $table_name, $index_name);
@ -402,7 +357,7 @@ class DBPostgresql extends DB
}
/**
* @brief xml 받아서 테이블을 생성
* @brief Create a table by using xml file
**/
function createTableByXml($xml_doc)
{
@ -410,19 +365,19 @@ class DBPostgresql extends DB
}
/**
* @brief xml 받아서 테이블을 생성
* @brief Create a table by using xml file
**/
function createTableByXmlFile($file_name)
{
if (!file_exists($file_name))
return;
// xml 파일을 읽음
// read xml file
$buff = FileHandler::readFile($file_name);
return $this->_createTable($buff);
}
/**
* @brief schema xml을 이용하여 create table query생성
* @brief generate a query statement to create a table by using schema xml
*
* type : number, varchar, text, char, date, \n
* opt : notnull, default, size\n
@ -433,8 +388,7 @@ class DBPostgresql extends DB
// xml parsing
$oXml = new XmlParser();
$xml_obj = $oXml->parse($xml_doc);
// 테이블 생성 schema 작성
// Create a table schema
$table_name = $xml_obj->table->attrs->name;
if ($table_name == 'sequence') {
@ -507,434 +461,140 @@ class DBPostgresql extends DB
}
/**
* @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', 'double', 'array'))) continue;
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 처리
* @brief Handle the insertAct
**/
function _executeInsertAct($output)
function _executeInsertAct($queryObject)
{
// 테이블 정리
foreach ($output->tables as $key => $val) {
$table_list[] = $this->prefix . $val;
}
// 컬럼 정리
foreach ($output->columns as $key => $val) {
$name = $val['name'];
$value = $val['value'];
if ($output->column_type[$name] != 'number') {
$value = "'" . $this->addQuotes($value) . "'";
if (!$value)
$value = 'null';
}
// sql injection 문제로 xml 선언이 number인 경우이면서 넘어온 값이 숫자형이 아니면 숫자형으로 강제 형변환
// elseif (!$value || is_numeric($value)) $value = (int)$value;
else $this->_filterNumber(&$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;
$table_list[] = $this->prefix . $val;
}
// 컬럼 정리
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) . "'";
// sql injection 문제로 xml 선언이 number인 경우이면서 넘어온 값이 숫자형이 아니면 숫자형으로 강제 형변환
else $this->_filterNumber(&$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);
$query = $this->getInsertSql($queryObject);
if(is_a($query, 'Object')) return;
return $this->_query($query);
}
/**
* @brief deleteAct 처리
* @brief Handle updateAct
**/
function _executeDeleteAct($output)
function _executeUpdateAct($queryObject)
{
// 테이블 정리
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);
$query = $this->getUpdateSql($queryObject);
if(is_a($query, 'Object')) return;
return $this->_query($query);
}
/**
* @brief Handle deleteAct
**/
function _executeDeleteAct($queryObject)
{
$query = $this->getDeleteSql($queryObject);
if(is_a($query, 'Object')) return;
return $this->_query($query);
}
/**
* @brief selectAct 처리
*
* select의 경우 특정 페이지의 목록을 가져오는 것을 편하게 하기 위해\n
* navigation이라는 method를 제공
* override
* @param $queryObject
*/
function getSelectSql($query){
$select = $query->getSelectString();
if($select == '') return new Object(-1, "Invalid query");
$select = 'SELECT ' .$select;
$from = $query->getFromString();
if($from == '') return new Object(-1, "Invalid query");
$from = ' FROM '.$from;
$where = $query->getWhereString();
if($where != '') $where = ' WHERE ' . $where;
$groupBy = $query->getGroupByString();
if($groupBy != '') $groupBy = ' GROUP BY ' . $groupBy;
$orderBy = $query->getOrderByString();
if($orderBy != '') $orderBy = ' ORDER BY ' . $orderBy;
$limit = $query->getLimitString();
$limitObject = $query->getLimit();
if($limit != '') $limit = ' LIMIT ' . $limitObject->getLimit() . ' OFFSET ' . $limitObject->getOffset();
return $select . ' ' . $from . ' ' . $where . ' ' . $groupBy . ' ' . $orderBy . ' ' . $limit;
}
/**
* @brief Handle selectAct
*
* In order to get a list of pages easily when selecting \n
* it supports a method as navigation
**/
function _executeSelectAct($output)
function _executeSelectAct($queryObject, $connection)
{
// 테이블 정리
$table_list = array();
foreach ($output->tables as $key => $val) {
$table_list[] = $this->prefix . $val . ' as ' . $key;
}
$query = $this->getSelectSql($queryObject);
$left_join = array();
// why???
$left_tables = (array )$output->left_tables;
if(is_a($query, 'Object')) return;
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 . ')';
}
}
$query .= (__DEBUG_QUERY__&1 && $queryObject->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id):'';
$click_count = array();
if(!$output->columns){
$output->columns = array(array('name'=>'*'));
}
// TODO Add support for click count
// TODO Add code for pagination
$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[$alias] = sprintf('%s as %s', $name, $alias);
else
$column_list[] = sprintf('%s', $name);
} else {
if ($alias)
$column_list[$alias] = sprintf('%s as %s', $name, $alias);
else
$column_list[] = sprintf('%s', $name);
$result = $this->_query ($query, $connection);
if ($this->isError ()) {
if ($limit && $output->limit->isPageHandler()){
$buff = new Object ();
$buff->total_count = 0;
$buff->total_page = 0;
$buff->page = 1;
$buff->data = array ();
$buff->page_navigation = new PageHandler (/*$total_count*/0, /*$total_page*/1, /*$page*/1, /*$page_count*/10);//default page handler values
return $buff;
}else
return;
}
}
$columns = implode(',', $column_list);
$condition = $this->getCondition($output);
$limit = $queryObject->getLimit();
if ($limit && $limit->isPageHandler()) {
// Total count
$temp_where = $queryObject->getWhereString(true, false);
$count_query = sprintf('select count(*) as "count" %s %s', 'FROM ' . $queryObject->getFromString(), ($temp_where === '' ? '' : ' WHERE '. $temp_where));
if ($queryObject->getGroupByString() != '') {
$count_query = sprintf('select count(*) as "count" from (%s) xet', $count_query);
}
$output->column_list = $column_list;
if ($output->list_count && $output->page)
return $this->_getNavigationData($table_list, $columns, $left_join, $condition,
$output);
$count_query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf (' '.$this->comment_syntax, $this->query_id):'';
$result_count = $this->_query($count_query, $connection);
$count_output = $this->_fetch($result_count);
$total_count = (int)$count_output->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);
}
}
}
// Total pages
if ($total_count) {
$total_page = (int) (($total_count - 1) / $limit->list_count) + 1;
} else $total_page = 1;
if (count($output->groups)) {
/*
var_dump("= column output start = ");
var_dump(sizeof ($output->columns) . " = end length == ");
var_dump($output->columns);
var_dump("= column output end = " . "\n");
var_dump($output->groups);
var_dump("=== " . "\n");
var_dump(debug_backtrace());
foreach($output->columns as $key => $val) {
$name = $val['name'];
$alias = $val['alias'];
} */
$group_list = array();
foreach ($output->groups as $gkey => $gval) {
foreach ($output->columns as $key => $val) {
$name = $val['name'];
$alias = $val['alias'];
if (trim($name) == trim($gval)) {
$group_list[] = $alias;
break;
}
}
$virtual_no = $total_count - ($limit->page - 1) * $limit->list_count;
$data = $this->_fetch($result, $virtual_no);
if($column_list[$gval]) $output->arg_columns[] = $column_list[$gval];
$buff = new Object ();
$buff->total_count = $total_count;
$buff->total_page = $total_page;
$buff->page = $limit->page->getValue();
$buff->data = $data;
$buff->page_navigation = new PageHandler($total_count, $total_page, $limit->page->getValue(), $limit->page_count);
}else{
$data = $this->_fetch($result);
$buff = new Object ();
$buff->data = $data;
}
}
$groupby_query = sprintf(' group by %s', implode(',', $group_list));
// var_dump($query);
}
if ($output->order) {
foreach ($output->order as $key => $val) {
$index_list[] = sprintf('%s %s', $val[0], $val[1]);
if(count($output->arg_columns) && $column_list[$val[0]]) $output->arg_columns[] = $column_list[$val[0]];
}
if (count($index_list)) $orderby_query = ' order by ' . implode(',', $index_list);
}
if(count($output->arg_columns))
{
$columns = join(',',$output->arg_columns);
}
$query = sprintf("select %s from %s %s %s %s", $columns, implode(',', $table_list), implode(' ', $left_join), $condition, $groupby_query.$orderby_query);
$query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id):'';
$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;
return $buff;
}
/**
* @brief query xml에 navigation 정보가 있을 경우 페이징 관련 작업을 처리한다
*
* 그닥 좋지는 않은 구조이지만 편리하다.. -_-;
**/
function _getNavigationData($table_list, $columns, $left_join, $condition, $output)
{
require_once (_XE_PATH_ . 'classes/page/PageHandler.class.php');
$column_list = $output->column_list;
/*
// group by 절이 포함된 SELECT 쿼리의 전체 갯수를 구하기 위한 수정
// 정상적인 동작이 확인되면 주석으로 막아둔 부분으로 대체합니다.
//
$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);
}
*/
// 전체 개수를 구함
$count_query = sprintf("select count(*) as count from %s %s %s", implode(',', $table_list), implode(' ', $left_join), $condition);
$count_query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id . ' count(*)'):'';
$result = $this->_query($count_query);
$count_output = $this->_fetch($result);
$total_count = (int)$count_output->count;
$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);
}
}
}
if (count($output->groups)) {
/*
var_dump("= column output start = ");
var_dump(sizeof ($output->columns) . " = end length == ");
var_dump($output->columns);
var_dump("= column output end = " . "\n");
var_dump($output->groups);
var_dump("=== " . "\n");
var_dump(debug_backtrace());
foreach($output->columns as $key => $val) {
$name = $val['name'];
$alias = $val['alias'];
} */
$group_list = array();
foreach ($output->groups as $gkey => $gval) {
foreach ($output->columns as $key => $val) {
$name = $val['name'];
$alias = $val['alias'];
if (trim($name) == trim($gval)) {
$group_list[] = $alias;
break;
}
}
if($column_list[$gval]) $output->arg_columns[] = $column_list[$gval];
}
$groupby_query = sprintf(' group by %s', implode(',', $group_list));
// var_dump($query);
}
if ($output->order) {
foreach ($output->order as $key => $val) {
$index_list[] = sprintf('%s %s', $val[0], $val[1]);
if(count($output->arg_columns) && $column_list[$val[0]]) $output->arg_columns[] = $column_list[$val[0]];
}
if (count($index_list)) $orderby_query = ' order by ' . implode(',', $index_list);
}
if(count($output->arg_columns))
{
$columns = join(',',$output->arg_columns);
}
$query = sprintf("select %s from %s %s %s", $columns, implode(',', $table_list), implode(' ', $left_join), $condition);
$query = sprintf('%s offset %d limit %d', $query, $start_count, $list_count);
$query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id):'';
$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 = pg_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;
function getParser(){
return new DBParser('"', '"', $this->prefix);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,327 @@
<?php
class Query extends Object {
var $queryID;
var $action;
var $priority;
var $columns;
var $tables;
var $conditions;
var $groups;
var $orderby;
var $limit;
var $arguments = null;
var $columnList = null;
var $_orderByString;
function Query($queryID = null
, $action = null
, $columns = null
, $tables = null
, $conditions = null
, $groups = null
, $orderby = null
, $limit = null){
$this->queryID = $queryID;
$this->action = $action;
$this->priority = $priority;
if(!isset($tables)) return;
$this->columns = $this->setColumns($columns);
$this->tables = $this->setTables($tables);
$this->conditions = $this->setConditions($conditions);
$this->groups = $this->setGroups($groups);
$this->orderby = $this->setOrder($orderby);
$this->limit = $this->setLimit($limit);
}
function show(){
return true;
}
function setQueryId($queryID){
$this->queryID = $queryID;
}
function setAction($action){
$this->action = $action;
}
function setPriority($priority){
$this->priority = $priority;
}
function setColumnList($columnList){
$this->columnList = $columnList;
if(count($this->columnList) > 0) {
$selectColumns = array();
$dbParser = DB::getParser();
foreach($this->columnList as $columnName){
$columnName = $dbParser->escapeColumn($columnName);
$selectColumns[] = new SelectExpression($columnName);
}
unset($this->columns);
$this->columns = $selectColumns;
}
}
function setColumns($columns){
if(!isset($columns) || count($columns) === 0){
$this->columns = array(new StarExpression());
return;
}
if(!is_array($columns)) $columns = array($columns);
$this->columns = $columns;
}
function setTables($tables){
if(!isset($tables) || count($tables) === 0){
$this->setError(true);
$this->setMessage("You must provide at least one table for the query.");
return;
}
if(!is_array($tables)) $tables = array($tables);
$this->tables = $tables;
}
function setConditions($conditions){
$this->conditions = array();
if(!isset($conditions) || count($conditions) === 0) return;
if(!is_array($conditions)) $conditions = array($conditions);
foreach($conditions as $conditionGroup){
if($conditionGroup->show()) $this->conditions[] = $conditionGroup;
}
}
function setGroups($groups){
if(!isset($groups) || count($groups) === 0) return;
if(!is_array($groups)) $groups = array($groups);
$this->groups = $groups;
}
function setOrder($order){
if(!isset($order) || count($order) === 0) return;
if(!is_array($order)) $order = array($order);
$this->orderby = $order;
}
function setLimit($limit = NULL){
if(!isset($limit)) return;
$this->limit = $limit;
}
// START Fluent interface
function select($columns= null){
$this->action = 'select';
$this->setColumns($columns);
return $this;
}
function from($tables){
$this->setTables($tables);
return $this;
}
function where($conditions){
$this->setConditions($conditions);
return $this;
}
function groupBy($groups){
$this->setGroups($groups);
return $this;
}
function orderBy($order){
$this->setOrder($order);
return $this;
}
function limit($limit){
$this->setLimit($limit);
return $this;
}
// END Fluent interface
function getAction(){
return $this->action;
}
function getPriority(){
return $this->priority?'LOW_PRIORITY':'';
}
function getSelectString($with_values = true){
foreach($this->columns as $column){
if($column->show())
if($column->isSubquery()){
$select[] = $column->toString($with_values) . ' as '. $column->getAlias();
}
else
$select[] = $column->getExpression($with_values);
}
return trim(implode($select, ', '));
}
function getUpdateString($with_values = true){
foreach($this->columns as $column){
if($column->show())
$update[] = $column->getExpression($with_values);
}
return trim(implode($update, ', '));
}
function getInsertString($with_values = true){
$columnsList = '';
$valuesList = '';
foreach($this->columns as $column){
if($column->show()){
$columnsList .= $column->getColumnName() . ', ';
$valuesList .= $column->getValue($with_values) . ', ';
}
}
$columnsList = substr($columnsList, 0, -2);
$valuesList = substr($valuesList, 0, -2);
return "($columnsList) \n VALUES ($valuesList)";
}
function getTables(){
return $this->tables;
}
// from table_a
// from table_a inner join table_b on x=y
// from (select * from table a) as x
// from (select * from table t) as x inner join table y on y.x
function getFromString($with_values = true){
$from = '';
$simple_table_count = 0;
foreach($this->tables as $table){
if($table->isJoinTable() || !$simple_table_count) $from .= $table->toString($with_values) . ' ';
else $from .= ', '.$table->toString($with_values) . ' ';
if(is_a($table, 'Subquery')) $from .= $table->getAlias() ? ' as ' . $table->getAlias() . ' ' : ' ';
$simple_table_count++;
}
if(trim($from) == '') return '';
return $from;
}
function getWhereString($with_values = true, $with_optimization = true){
$where = '';
$condition_count = 0;
foreach($this->conditions as $conditionGroup){
if($condition_count === 0){
$conditionGroup->setPipe("");
}
$condition_string = $conditionGroup->toString($with_values);
$where .= $condition_string;
$condition_count++;
}
if($with_optimization &&
(strstr($this->getOrderByString(), 'list_order') || strstr($this->getOrderByString(), 'update_order'))){
if($condition_count !== 0) $where = '(' . $where .') ';
foreach($this->orderby as $order){
$colName = $order->getColumnName();
if(strstr($colName, 'list_order') || strstr($colName, 'update_order')){
$opt_condition = new ConditionWithoutArgument($colName, 2100000000, 'less', 'and');
if ($condition_count === 0) $opt_condition->setPipe("");
$where .= $opt_condition->toString($with_values).' ';
$condition_count++;
}
}
}
return trim($where);
}
function getGroupByString(){
$groupBy = '';
if($this->groups) if($this->groups[0] !== "")
$groupBy = implode(', ', $this->groups);
return $groupBy;
}
function getOrderByString(){
if(!$this->_orderByString){
if(count($this->orderby) === 0) return '';
$orderBy = '';
foreach($this->orderby as $order){
$orderBy .= $order->toString() .', ';
}
$orderBy = substr($orderBy, 0, -2);
$this->_orderByString = $orderBy;
}
return $this->_orderByString;
}
function getLimit(){
return $this->limit;
}
function getLimitString(){
$limit = '';
if(count($this->limit) > 0){
$limit = '';
$limit .= $this->limit->toString();
}
return $limit;
}
function getFirstTableName(){
return $this->tables[0]->getName();
}
function getArguments(){
if(!isset($this->arguments)){
$this->arguments = array();
// Column arguments
if(count($this->columns) > 0){ // The if is for delete statements, all others must have columns
foreach($this->columns as $column){
if($column->show()){
$arg = $column->getArgument();
if($arg) $this->arguments[] = $arg;
}
}
}
// Condition arguments
if(count($this->conditions) > 0)
foreach($this->conditions as $conditionGroup){
$args = $conditionGroup->getArguments();
if(count($args) > 0) $this->arguments = array_merge($this->arguments, $args);
}
// Navigation arguments
if(count($this->orderby) > 0)
foreach($this->orderby as $order){
$args = $order->getArguments();
if(count($args) > 0) $this->arguments = array_merge($this->arguments, $args);
}
}
return $this->arguments;
}
}
?>

View file

@ -0,0 +1,42 @@
<?php
class Subquery extends Query {
var $alias;
var $join_type;
function Subquery($alias, $columns, $tables, $conditions, $groups, $orderby, $limit, $join_type = null){
$this->alias = $alias;
$this->queryID = null;
$this->action = "select";
$this->columns = $columns;
$this->tables = $tables;
$this->conditions = $conditions;
$this->groups = $groups;
$this->orderby = $orderby;
$this->limit = $limit;
$this->join_type = $join_type;
}
function getAlias(){
return $this->alias;
}
function isJoinTable(){
if($this->join_type) return true;
return false;
}
function toString($with_values = true){
$oDB = &DB::getInstance();
return '(' .$oDB->getSelectSql($this, $with_values) . ')';
}
function isSubquery(){
return true;
}
}
?>

View file

@ -0,0 +1,152 @@
<?php
class Condition {
var $column_name;
var $argument;
var $operation;
var $pipe;
var $_value;
var $_show;
var $_value_to_string;
function Condition($column_name, $argument, $operation, $pipe){
$this->column_name = $column_name;
$this->argument = $argument;
$this->operation = $operation;
$this->pipe = $pipe;
}
function getArgument(){
return null;
}
function toString($withValue = true){
if(!isset($this->_value_to_string)){
if(!$this->show()) { $this->_value_to_string = ''; }
else if($withValue)
$this->_value_to_string = $this->toStringWithValue();
else $this->_value_to_string = $this->toStringWithoutValue();
}
return $this->_value_to_string;
}
function toStringWithoutValue(){
return $this->pipe . ' ' . $this->getConditionPart($this->_value);
}
function toStringWithValue(){
return $this->pipe . ' ' . $this->getConditionPart($this->_value);
}
function setPipe($pipe){
$this->pipe = $pipe;
}
function show(){
if(!isset($this->_show)){
if(is_array($this->_value) && count($this->_value) === 1 && $this->_value[0] === '') {
$this->_show = false;
}
else {
$this->_show = true;
switch($this->operation) {
case 'equal' :
case 'more' :
case 'excess' :
case 'less' :
case 'below' :
case 'like_tail' :
case 'like_prefix' :
case 'like' :
case 'notlike_tail' :
case 'notlike_prefix' :
case 'notlike' :
case 'in' :
case 'notin' :
case 'and':
case 'or':
case 'xor':
case 'not':
case 'notequal' :
// if variable is not set or is not string or number, return
if(!isset($this->_value)) { $this->_show = false; break;}
if($this->_value === '') { $this->_show = false; break; }
if(!in_array(gettype($this->_value), array('string', 'integer'))) {$this->_show = false; break; }
break;
case 'between' :
if(!is_array($this->_value)) { $this->_show = false; break;}
if(count($this->_value)!=2) {$this->_show = false; break;}
}
}
}
return $this->_show;
}
function getConditionPart($value) {
$name = $this->column_name;
$operation = $this->operation;
switch($operation) {
case 'equal' :
return $name.' = '.$value;
break;
case 'more' :
return $name.' >= '.$value;
break;
case 'excess' :
return $name.' > '.$value;
break;
case 'less' :
return $name.' <= '.$value;
break;
case 'below' :
return $name.' < '.$value;
break;
case 'like_tail' :
case 'like_prefix' :
case 'like' :
return $name.' like '.$value;
break;
case 'notlike_tail' :
case 'notlike_prefix' :
case 'notlike' :
return $name.' not like '.$value;
break;
case 'in' :
return $name.' in '.$value;
break;
case 'notin' :
return $name.' not in '.$value;
break;
case 'notequal' :
return $name.' <> '.$value;
break;
case 'notnull' :
return $name.' is not null';
break;
case 'null' :
return $name.' is null';
break;
case 'and' :
return $name.' & '.$value;
break;
case 'or' :
return $name.' | '.$value;
break;
case 'xor' :
return $name.' ^ '.$value;
break;
case 'not' :
return $name.' ~ '.$value;
break;
case 'between' :
return $name.' between ' . $value[0] . ' and ' . $value[1];
break;
}
}
}
?>

View file

@ -0,0 +1,60 @@
<?php
class ConditionGroup {
var $conditions;
var $pipe;
var $_group;
var $_show;
function ConditionGroup($conditions, $pipe = "") {
$this->conditions = array();
foreach($conditions as $condition){
if($condition->show())
$this->conditions[] = $condition;
}
if(count($this->conditions) === 0) $this->_show = false;
else $this->_show = true;
$this->pipe = $pipe;
}
function show(){
return $this->_show;
}
function setPipe($pipe){
if($this->pipe !== $pipe) $this->_group = null;
$this->pipe = $pipe;
}
function toString($with_value = true){
if(!isset($this->_group)){
$cond_indx = 0;
$group = '';
foreach($this->conditions as $condition){
if($cond_indx === 0) $condition->setPipe("");
$group .= $condition->toString($with_value) . ' ';
$cond_indx++;
}
if($this->pipe !== "" && trim($group) !== ''){
$group = $this->pipe . ' (' . $group . ')';
}
$this->_group = $group;
}
return $this->_group;
}
function getArguments(){
$args = array();
foreach($this->conditions as $condition){
$arg = $condition->getArgument();
if($arg) $args[] = $arg;
}
return $args;
}
}
?>

View file

@ -0,0 +1,11 @@
<?php
class ConditionSubquery extends Condition {
function ConditionSubquery($column_name, $argument, $operation, $pipe = ""){
parent::Condition($column_name, $argument, $operation, $pipe);
$this->_value = $this->argument->toString();
}
}
?>

View file

@ -0,0 +1,41 @@
<?php
class ConditionWithArgument extends Condition {
function ConditionWithArgument($column_name, $argument, $operation, $pipe = ""){
if($argument === null) { $this->_show = false; return; }
parent::Condition($column_name, $argument, $operation, $pipe);
$this->_value = $argument->getValue();
}
function getArgument(){
if(!$this->show()) return;
return $this->argument;
}
function toStringWithoutValue(){
$value = $this->argument->getUnescapedValue();
if(is_array($value)){
$q = '';
foreach ($value as $v) $q .= '?,';
if($q !== '') $q = substr($q, 0, -1);
$q = '(' . $q . ')';
}
else $q = '?';
return $this->pipe . ' ' . $this->getConditionPart($q);
}
function show(){
if(!isset($this->_show)){
if(!$this->argument->isValid()) $this->_show = false;
if($this->_value === '\'\'') $this->_show = false;
if(!isset($this->_show)){
return parent::show();
}
}
return $this->_show;
}
}
?>

View file

@ -0,0 +1,14 @@
<?php
class ConditionWithoutArgument extends Condition {
function ConditionWithoutArgument($column_name, $argument, $operation, $pipe = ""){
parent::Condition($column_name, $argument, $operation, $pipe);
if(in_array($operation, array('in', 'notin')))
$this->_value = '('. $argument .')';
else
$this->_value = $argument;
}
}
?>

View file

@ -0,0 +1,33 @@
<?php
/**
* @class ClickCountExpression
* @author Arnia Software
* @brief
*
*/
class ClickCountExpression extends SelectExpression {
var $click_count;
function ClickCountExpression($column_name, $alias = NULL, $click_count = false){
parent::SelectExpression($column_name, $alias);
if(!is_bool($click_count)){
error_log("Click_count value for $column_name was not boolean", 0);
$this->click_count = false;
return;
}
$this->click_count = $click_count;
}
function show() {
return $this->click_count;
}
function getExpression(){
return "$this->column_name = $this->column_name + 1";
}
}
?>

View file

@ -0,0 +1,35 @@
<?php
/**
* @class DeleteExpression
* @author Arnia Software
* @brief
*
*/
// TODO Fix this class
class DeleteExpression extends Expression {
var $value;
function DeleteExpression($column_name, $value){
parent::Expression($column_name);
$this->value = $value;
}
function getExpression(){
return "$this->column_name = $this->value";
}
function getValue(){
// TODO Escape value according to column type instead of variable type
if(!is_numeric($this->value)) return "'".$this->value."'";
return $this->value;
}
function show(){
if(!$this->value) return false;
return true;
}
}
?>

View file

@ -0,0 +1,30 @@
<?php
/**
* @class Expression
* @author Corina
* @brief Represents an expression used in select/update/insert/delete statements
*
* Examples (expressions are inside double square brackets):
* select [[columnA]], [[columnB as aliasB]] from tableA
* update tableA set [[columnA = valueA]] where columnB = something
*
*/
class Expression {
var $column_name;
function Expression($column_name){
$this->column_name = $column_name;
}
function getColumnName(){
return $this->column_name;
}
function show() {
return false;
}
function getExpression() {
}
}

View file

@ -0,0 +1,36 @@
<?php
/**
* @class InsertExpression
* @author Arnia Software
* @brief
*
*/
class InsertExpression extends Expression {
var $argument;
function InsertExpression($column_name, $argument){
parent::Expression($column_name);
$this->argument = $argument;
}
function getValue($with_values = true){
if($with_values)
return $this->argument->getValue();
return '?';
}
function show(){
if(!$this->argument) return false;
$value = $this->argument->getValue();
if(!isset($value)) return false;
return true;
}
function getArgument(){
return $this->argument;
}
}
?>

View file

@ -0,0 +1,40 @@
<?php
/**
* @class SelectExpression
* @author Arnia Software
* @brief Represents an expresion that appears in the select clause
*
* @remarks
* $column_name can be:
* - a table column name
* - an sql function - like count(*)
* - an sql expression - substr(column_name, 1, 8) or score1 + score2
* $column_name is already escaped
*/
class SelectExpression extends Expression {
var $column_alias;
function SelectExpression($column_name, $alias = NULL){
parent::Expression($column_name);
$this->column_alias = $alias;
}
function getExpression() {
return sprintf("%s%s", $this->column_name, $this->column_alias ? " as ".$this->column_alias : "");
}
function show() {
return true;
}
function getArgument(){
return null;
}
function isSubquery(){
return false;
}
}
?>

View file

@ -0,0 +1,20 @@
<?php
/**
* @class StarExpression
* @author Corina
* @brief Represents the * in 'select * from ...' statements
*
*/
class StarExpression extends SelectExpression {
function StarExpression(){
parent::SelectExpression("*");
}
function getArgument(){
return null;
}
}
?>

View file

@ -0,0 +1,58 @@
<?php
/**
* @class UpdateExpression
* @author Arnia Software
* @brief
*
*/
class UpdateExpression extends Expression {
var $argument;
function UpdateExpression($column_name, $argument){
parent::Expression($column_name);
$this->argument = $argument;
}
function getExpression($with_value = true){
if($with_value)
return $this->getExpressionWithValue();
return $this->getExpressionWithoutValue();
}
function getExpressionWithValue(){
$value = $this->argument->getValue();
$operation = $this->argument->getColumnOperation();
if(isset($operation))
return "$this->column_name = $this->column_name $operation $value";
return "$this->column_name = $value";
}
function getExpressionWithoutValue(){
$operation = $this->argument->getColumnOperation();
if(isset($operation))
return "$this->column_name = $this->column_name $operation ?";
return "$this->column_name = ?";
}
function getValue(){
// TODO Escape value according to column type instead of variable type
$value = $this->argument->getValue();
if(!is_numeric($value)) return "'".$value."'";
return $value;
}
function show(){
if(!$this->argument) return false;
$value = $this->argument->getValue();
if(!isset($value)) return false;
return true;
}
function getArgument(){
return $this->argument;
}
}
?>

View file

@ -0,0 +1,41 @@
<?php
/**
* @class UpdateExpression
* @author Arnia Software
* @brief
*
*/
class UpdateExpressionWithoutArgument extends UpdateExpression {
var $argument;
function UpdateExpressionWithoutArgument($column_name, $argument){
parent::Expression($column_name);
$this->argument = $argument;
}
function getExpression($with_value = true){
return "$this->column_name = $this->argument";
}
function getValue(){
// TODO Escape value according to column type instead of variable type
$value = $this->argument;
if(!is_numeric($value)) return "'".$value."'";
return $value;
}
function show(){
if(!$this->argument) return false;
$value = $this->argument;
if(!isset($value)) return false;
return true;
}
function getArgument(){
return null;
}
}
?>

View file

@ -0,0 +1,37 @@
<?php
class Limit {
var $start;
var $list_count;
var $page_count;
var $page;
function Limit($list_count, $page= NULL, $page_count= NULL){
$this->list_count = $list_count;
if ($page){
$list_count_value = $list_count->getValue();
$page_value = $page->getValue();
$this->start = ($page_value - 1) * $list_count_value;
$this->page_count = $page_count;
$this->page = $page;
}
}
function isPageHandler(){//in case you choose to use query limit in other cases than page select
if ($this->page)return true;
else return false;
}
function getOffset(){
return $this->start;
}
function getLimit(){
return $this->list_count->getValue();
}
function toString(){
if ($this->page) return $this->start . ' , ' . $this->list_count->getValue();
else return $this->list_count->getValue();
}
}
?>

View file

@ -0,0 +1,31 @@
<?php
class OrderByColumn {
var $column_name;
var $sort_order;
function OrderByColumn($column_name, $sort_order){
$this->column_name = $column_name;
$this->sort_order = $sort_order;
}
function toString(){
$result = $this->getColumnName();
$result .= ' ';
$result .= is_a($this->sort_order, 'Argument') ? $this->sort_order->getValue() : $this->sort_order;
return $result;
}
function getColumnName(){
return is_a($this->column_name, 'Argument') ? $this->column_name->getValue() : $this->column_name;
}
function getArguments(){
$args = array();
if(is_a($this->column_name, 'Argument'))
$args[]= $this->column_name;
if(is_a($this->sort_order, 'Argument'))
$args[] = $this->sort_order;
}
}
?>

View file

@ -0,0 +1,35 @@
<?php
class CubridTableWithHint extends Table {
var $name;
var $alias;
var $index_hints_list;
function CubridTableWithHint($name, $alias = NULL, $index_hints_list){
parent::Table($name, $alias);
$this->index_hints_list = $index_hints_list;
}
function getIndexHintString(){
$result = '';
// Retrieve table prefix, to add it to index name
$db_info = Context::getDBInfo();
$prefix = $db_info->master_db["db_table_prefix"];
foreach($this->index_hints_list as $index_hint){
$index_hint_type = $index_hint->getIndexHintType();
if($index_hint_type !== 'IGNORE'){
$result .= $this->alias . '.'
. '"' . $prefix . substr($index_hint->getIndexName(), 1)
. ($index_hint_type == 'FORCE' ? '(+)' : '')
. ', ';
}
}
$result = substr($result, 0, -2);
return $result;
}
}
?>

View file

@ -0,0 +1,21 @@
<?php
class IndexHint {
var $index_name;
var $index_hint_type;
function IndexHint($index_name, $index_hint_type){
$this->index_name = $index_name;
$this->index_hint_type = $index_hint_type;
}
function getIndexName(){
return $this->index_name;
}
function getIndexHintType() {
return $this->index_hint_type;
}
}
?>

View file

@ -0,0 +1,37 @@
<?php
/**
* @class JoinTable
* @author Arnia Software
* @brief
*
* @remarks
* $conditions in an array of Condition objects
*
*/
class JoinTable extends Table {
var $join_type;
var $conditions;
function JoinTable($name, $alias, $join_type, $conditions){
parent::Table($name, $alias);
$this->join_type = $join_type;
$this->conditions = $conditions;
}
function toString($with_value = true){
$part = $this->join_type . ' ' . $this->name ;
$part .= $this->alias ? ' as ' . $this->alias : '';
$part .= ' on ';
foreach($this->conditions as $conditionGroup)
$part .= $conditionGroup->toString($with_value);
return $part;
}
function isJoinTable(){
return true;
}
}
?>

View file

@ -0,0 +1,29 @@
<?php
class MssqlTableWithHint extends Table {
var $name;
var $alias;
var $index_hints_list;
function MssqlTableWithHint($name, $alias = NULL, $index_hints_list){
parent::Table($name, $alias);
$this->index_hints_list = $index_hints_list;
}
function toString(){
$result = parent::toString();
$index_hint_string = '';
foreach($this->index_hints_list as $index_hint){
$index_hint_type = $index_hint->getIndexHintType();
if(in_array($index_hint_type, array('USE', 'FORCE')))
$index_hint_string .= 'INDEX(' . $index_hint->getIndexName() . '), ';
}
if($index_hint_string != ''){
$result .= ' WITH(' . substr($index_hint_string, 0, -2) . ') ';
}
return $result;
}
}
?>

View file

@ -0,0 +1,36 @@
<?php
class MysqlTableWithHint extends Table {
var $name;
var $alias;
var $index_hints_list;
function MysqlTableWithHint($name, $alias = NULL, $index_hints_list){
parent::Table($name, $alias);
$this->index_hints_list = $index_hints_list;
}
function toString(){
$result = parent::toString();
$use_index_hint = ''; $force_index_hint = ''; $ignore_index_hint = '';
foreach($this->index_hints_list as $index_hint){
$index_hint_type = $index_hint->getIndexHintType();
if($index_hint_type == 'USE') $use_index_hint .= $index_hint->getIndexName() . ', ';
else if($index_hint_type == 'FORCE') $force_index_hint .= $index_hint->getIndexName() . ', ';
else if($index_hint_type == 'IGNORE') $ignore_index_hint .= $index_hint->getIndexName() . ', ';
}
if($use_index_hint != ''){
$result .= ' USE INDEX (' . substr($use_index_hint, 0, -2) . ') ';
}
if($force_index_hint != ''){
$result .= ' FORCE INDEX (' . substr($force_index_hint, 0, -2) . ') ';
}
if($ignore_index_hint != ''){
$result .= ' IGNORE INDEX (' . substr($ignore_index_hint, 0, -2) . ') ';
}
return $result;
}
}
?>

View file

@ -0,0 +1,30 @@
<?php
class Table {
var $name;
var $alias;
function Table($name, $alias = NULL){
$this->name = $name;
$this->alias = $alias;
}
function toString(){
//return $this->name;
return sprintf("%s%s", $this->name, $this->alias ? ' as ' . $this->alias : '');
}
function getName(){
return $this->name;
}
function getAlias(){
return $this->alias;
}
function isJoinTable(){
return false;
}
}
?>

View file

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

View file

@ -5,19 +5,35 @@ class HTMLDisplayHandler {
* @brief Produce HTML compliant content given a module object.\n
* @param[in] $oModule the module object
**/
function toDoc(&$oModule)
function toDoc(&$oModule)
{
$oTemplate = &TemplateHandler::getInstance();
// compile module tpl
$template_path = $oModule->getTemplatePath();
if ($oModule->module_info->module == $oModule->module)
$skin = $oModule->origin_module_info->skin;
else
$skin = $oModule->module_config->skin;
if(Context::get('module')!='admin' && strpos(Context::get('act'),'Admin') === false){
if ($skin && is_string($skin)){
$theme_skin = explode('.', $skin);
if (count($theme_skin) == 2)
$template_path = sprintf('./themes/%s/modules/%s/', $theme_skin[0], $theme_skin[1]);
else
$template_path = $oModule->getTemplatePath();
}else{
$template_path = $oModule->getTemplatePath();
}
}else $template_path = $oModule->getTemplatePath();
$tpl_file = $oModule->getTemplateFile();
$output = $oTemplate->compile($template_path, $tpl_file);
// add #xeAdmin div for adminitration pages
// add .x div for adminitration pages
if(Context::getResponseMethod() == 'HTML') {
if(Context::get('module')!='admin' && strpos(Context::get('act'),'Admin')>0) $output = '<div id="xeAdmin">'.$output.'</div>';
if(Context::get('module')!='admin' && strpos(Context::get('act'),'Admin')>0) $output = '<div class="x">'.$output.'</div>';
if(Context::get('layout') != 'none') {
if(__DEBUG__==3) $start = getMicroTime();
@ -28,32 +44,32 @@ class HTMLDisplayHandler {
$edited_layout_file = $oModule->getEditedLayoutFile();
// 현재 요청된 레이아웃 정보를 구함
// get the layout information currently requested
$oLayoutModel = &getModel('layout');
$layout_info = Context::get('layout_info');
$layout_srl = $layout_info->layout_srl;
// 레이아웃과 연결되어 있으면 레이아웃 컴파일
// compile if connected to the layout
if($layout_srl > 0){
// faceoff 레이아웃일 경우 별도 처리
// handle separately if the layout is faceoff
if($layout_info && $layout_info->type == 'faceoff') {
$oLayoutModel->doActivateFaceOff($layout_info);
Context::set('layout_info', $layout_info);
}
// 관리자 레이아웃 수정화면에서 변경된 CSS가 있는지 조사
// search if the changes CSS exists in the admin layout edit window
$edited_layout_css = $oLayoutModel->getUserLayoutCss($layout_srl);
if(file_exists($edited_layout_css)) Context::addCSSFile($edited_layout_css,true,'all','',100);
if(file_exists($edited_layout_css)) Context::loadFile(array($edited_layout_css,'all','',100));
}
if(!$layout_path) $layout_path = "./common/tpl";
if(!$layout_file) $layout_file = "default_layout";
if(!$layout_path) $layout_path = './common/tpl';
if(!$layout_file) $layout_file = 'default_layout';
$output = $oTemplate->compile($layout_path, $layout_file, $edited_layout_file);
if(__DEBUG__==3) $GLOBALS['__layout_compile_elapsed__'] = getMicroTime()-$start;
if(preg_match('/MSIE/i',$_SERVER['HTTP_USER_AGENT']) && (Context::get("_use_ssl")=='optional'||Context::get("_use_ssl")=="always")) {
if(preg_match('/MSIE/i',$_SERVER['HTTP_USER_AGENT']) && (Context::get('_use_ssl') == 'optional' || Context::get('_use_ssl') == 'always')) {
Context::addHtmlFooter('<iframe id="xeTmpIframe" name="xeTmpIframe" style="width:1px;height:1px;position:absolute;top:-2px;left:-2px;"></iframe>');
}
}
@ -63,16 +79,16 @@ class HTMLDisplayHandler {
function prepareToPrint(&$output) {
if(Context::getResponseMethod() != 'HTML') return;
if(__DEBUG__==3) $start = getMicroTime();
// body 내의 <style ..></style>를 header로 이동
// move <style ..></style> in body to the header
$output = preg_replace_callback('!<style(.*?)<\/style>!is', array($this,'_moveStyleToHeader'), $output);
// 메타 파일 변경 (캐싱기능등으로 인해 위젯등에서 <!--Meta:경로--> 태그를 content에 넣는 경우가 있음
// change a meta fine(widget often put the tag like <!--Meta:path--> to the content because of caching)
$output = preg_replace_callback('/<!--(#)?Meta:([a-z0-9\_\/\.\@]+)-->/is', array($this,'_transMeta'), $output);
// rewrite module 사용시 생기는 상대경로에 대한 처리를 함
// handles a relative path generated by using the rewrite module
if(Context::isAllowRewrite()) {
$url = parse_url(Context::getRequestUri());
$real_path = $url['path'];
@ -89,15 +105,31 @@ class HTMLDisplayHandler {
}
}
// 간혹 background-image에 url(none) 때문에 request가 한번 더 일어나는 경우가 생기는 것을 방지
// prevent the 2nd request due to url(none) of the background-image
$output = preg_replace('/url\((["\']?)none(["\']?)\)/is', 'none', $output);
if(is_array(Context::get('INPUT_ERROR')))
{
$INPUT_ERROR = Context::get('INPUT_ERROR');
$keys = array_keys($INPUT_ERROR);
$keys = '('.implode('|', $keys).')';
$output = preg_replace_callback('@(<input)([^>]*?)\sname="'.$keys.'"([^>]*?)/?>@is', array(&$this, '_preserveValue'), $output);
}
if(__DEBUG__==3) $GLOBALS['__trans_content_elapsed__'] = getMicroTime()-$start;
// 불필요한 정보 제거
// Remove unnecessary information
$output = preg_replace('/member\_\-([0-9]+)/s','member_0',$output);
// 최종 레이아웃 변환
// set icon
$oAdminModel = &getAdminModel('admin');
$favicon_url = $oAdminModel->getFaviconUrl();
$mobicon_url = $oAdminModel->getMobileIconUrl();
Context::set('favicon_url', $favicon_url);
Context::set('mobicon_url', $mobicon_url);
// convert the final layout
Context::set('content', $output);
$oTemplate = &TemplateHandler::getInstance();
if(Mobile::isFromMobilePhone()) {
@ -106,14 +138,45 @@ class HTMLDisplayHandler {
else
{
$this->_loadJSCSS();
$this->_addMetaTag();
$output = $oTemplate->compile('./common/tpl', 'common_layout');
}
// 사용자 정의 언어 변환
// replace the user-defined-language
$oModuleController = &getController('module');
$oModuleController->replaceDefinedLangCode($output);
}
function _preserveValue($match)
{
$INPUT_ERROR = Context::get('INPUT_ERROR');
$str = $match[1].$match[2].' name="'.$match[3].'"'.$match[4];
// get type
$type = 'text';
if(preg_match('/\stype="([a-z]+)"/i', $str, $m)) $type = strtolower($m[1]);
switch($type){
case 'text':
case 'hidden':
$str = preg_replace('@\svalue="[^"]*?"@', ' ', $str).' value="'.$INPUT_ERROR[$match[3]].'"';
break;
case 'password':
$str = preg_replace('@\svalue="[^"]*?"@', ' ', $str);
break;
case 'radio':
case 'checkbox':
$str = preg_replace('@\schecked(="[^"]*?")?@', ' ', $str);
if(preg_match('@\s(?i:value)="'.$INPUT_ERROR[$match[3]].'"@', $str)) {
$str .= ' checked="checked"';
}
break;
}
return $str.' />';
}
/**
* @brief add html style code extracted from html body to Context, which will be
* printed inside <header></header> later.
@ -124,33 +187,53 @@ class HTMLDisplayHandler {
}
/**
* @brief add given .css or .js file names in widget code to Context
* @brief add given .css or .js file names in widget code to Context
* @param[in] $oModule the module object
**/
function _transMeta($matches) {
if($matches[1]) return '';
if(substr($matches[2],'-4')=='.css') Context::addCSSFile($matches[2]);
elseif(substr($matches[2],'-3')=='.js') Context::addJSFile($matches[2]);
Context::loadFile($matches[2]);
}
function _loadJSCSS()
{
$oContext =& Context::getInstance();
$oContext =& Context::getInstance();
$lang_type = Context::getLangType();
// add common JS/CSS files
$oContext->addJsFile('./common/js/jquery.js', false, '', -100000);
$oContext->addJsFile('./common/js/x.js', false, '', -100000);
$oContext->addJsFile('./common/js/common.js', false, '', -100000);
$oContext->addJsFile('./common/js/js_app.js', false, '', -100000);
$oContext->addJsFile('./common/js/xml_handler.js', false, '', -100000);
$oContext->addJsFile('./common/js/xml_js_filter.js', false, '', -100000);
$oContext->addCSSFile('./common/css/default.css', false, 'all', '', -100000);
$oContext->addCSSFile('./common/css/button.css', false, 'all', '', -100000);
if(__DEBUG__) {
$oContext->loadFile(array('./common/js/jquery.js', 'head', '', -100000), true);
$oContext->loadFile(array('./common/js/x.js', 'head', '', -100000), true);
$oContext->loadFile(array('./common/js/common.js', 'head', '', -100000), true);
$oContext->loadFile(array('./common/js/js_app.js', 'head', '', -100000), true);
$oContext->loadFile(array('./common/js/xml_handler.js', 'head', '', -100000), true);
$oContext->loadFile(array('./common/js/xml_js_filter.js', 'head', '', -100000), true);
$oContext->loadFile(array('./common/css/xe.css', 'all', '', -100000), true);
} else {
$oContext->loadFile(array('./common/js/jquery.min.js', 'head', '', -100000), true);
$oContext->loadFile(array('./common/js/x.min.js', 'head', '', -100000), true);
$oContext->loadFile(array('./common/js/xe.min.js', 'head', '', -100000), true);
$oContext->loadFile(array('./common/css/xe.min.css', 'all', '', -100000), true);
}
// for admin page, add admin css
if(Context::get('module')=='admin' || strpos(Context::get('act'),'Admin')>0){
$oContext->addCSSFile('./modules/admin/tpl/css/font.css', false, 'all', '',10000);
$oContext->addCSSFile('./modules/admin/tpl/css/pagination.css', false, 'all', '', 100001);
$oContext->addCSSFile('./modules/admin/tpl/css/admin.css', false, 'all', '', 100002);
if(__DEBUG__) {
$oContext->loadFile(array('./modules/admin/tpl/css/admin.css', 'all', '', 100000), true);
$oContext->loadFile(array("./modules/admin/tpl/css/admin_{$lang_type}.css", 'all', '', 100000), true);
$oContext->loadFile('./modules/admin/tpl/js/admin.js', true);
} else {
$oContext->loadFile(array('./modules/admin/tpl/css/admin.min.css', 'all', '', 100000), true);
$oContext->loadFile(array("./modules/admin/tpl/css/admin_{$lang_type}.css", 'all', '',10000), true);
$oContext->loadFile('./modules/admin/tpl/js/admin.min.js', true);
}
}
}
function _addMetaTag()
{
$oContext =& Context::getInstance();
$oContext->addMetaTag('Content-Type', 'text/html; charset=UTF-8', true);
$oContext->addMetaTag('imagetoolbar', 'no');
}
}

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