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 RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(.+)/files/(member_extra_info|attach|cache|faceOff)/(.*) ./files/$2/$3 [L] RewriteRule ^(.+)/files/(member_extra_info|attach|cache|faceOff)/(.*) ./files/$2/$3 [L]
RewriteCond %{SCRIPT_FILENAME} !-f 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 # rss , blogAPI
RewriteRule ^(rss|atom)$ ./index.php?module=rss&act=$1 [L] 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] RewriteRule ^admin/?$ ./index.php?module=admin [L]
# document permanent link # document permanent link
RewriteRule ^([0-9]+)$ ./index.php?document_srl=$1 [L] RewriteRule ^([0-9]+)$ ./index.php?document_srl=$1 [L,QSA]
# mid link # mid link
RewriteCond %{SCRIPT_FILENAME} !-d 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 # 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 # vid + mid link
RewriteCond %{SCRIPT_FILENAME} !-d 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 # 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 # 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 # 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 <?php
if(!defined("__ZBXE__")) exit(); if(!defined('__XE__')) exit();
/** /**
* @file autolink.addon.php * @file autolink.addon.php
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief 자동 링크 애드온 * @brief Automatic link add-on
**/ **/
if($called_position == 'after_module_proc' && Context::getResponseMethod()!="XMLRPC") { if($called_position == 'after_module_proc' && Context::getResponseMethod()!="XMLRPC") {
Context::addJsFile('./addons/autolink/autolink.js', false ,'', null, 'body'); Context::loadFile(array('./addons/autolink/autolink.js', 'body', '', null), true);
} }
?> ?>

View file

@ -2,11 +2,11 @@
<addon version="0.2"> <addon version="0.2">
<title xml:lang="ko">자동 링크 애드온</title> <title xml:lang="ko">자동 링크 애드온</title>
<title xml:lang="jp">自動リンクアドオン</title> <title xml:lang="jp">自動リンクアドオン</title>
<title xml:lang="en">Auto Link</title> <title xml:lang="en">Auto Link Addon</title>
<title xml:lang="vi">Auto Link</title> <title xml:lang="vi">Auto Link</title>
<title xml:lang="zh-CN">自动链接插件</title> <title xml:lang="zh-CN">自动链接插件</title>
<title xml:lang="es">auto vínculo addon</title> <title xml:lang="es">auto vínculo addon</title>
<title xml:lang="ru">авто ссылка аддон</title> <title xml:lang="ru">Аддон авто-ссылки</title>
<title xml:lang="ge">Auto-Link Addon</title> <title xml:lang="ge">Auto-Link Addon</title>
<title xml:lang="zh-TW">自動連結</title> <title xml:lang="zh-TW">自動連結</title>
<description xml:lang="ko"> <description xml:lang="ko">
@ -16,7 +16,7 @@
書き込み本文とコメントに登録された内容の中、httpで始まる一般文字列に自動にリンクを貼り付け、そのリンクにマウスオーバすると、別ウィンドウ、または同一ウィンドウに開くメニュが現れるアドオンです。 書き込み本文とコメントに登録された内容の中、httpで始まる一般文字列に自動にリンクを貼り付け、そのリンクにマウスオーバすると、別ウィンドウ、または同一ウィンドウに開くメニュが現れるアドオンです。
</description> </description>
<description xml:lang="en"> <description xml:lang="en">
This addon makes a link to a string that starts with http. This addon automatically transforms text URLs encountered in posts and comments into linkable URLs.
</description> </description>
<description xml:lang="vi"> <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. 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.
@ -28,7 +28,7 @@
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. 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>
<description xml:lang="ru"> <description xml:lang="ru">
Комментарии, которые начинаются с http naeyongjung темой общей строки автоматически ссылку повесить мышь над каждой ссылке и saechang Сити и появляться на меню добавить-на украшения. Этот аддон-дополнение переводит все неактивные ссылки, которые встречаются в статьях и комментариях, в рабочие ссылки.
</description> </description>
<description xml:lang="ge"> <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. 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.

View file

@ -1,454 +1,421 @@
<?php <?php
if(!defined("__ZBXE__")) exit(); if(!defined('__XE__')) exit();
/** /**
* @file blogapicounter.addon.php * @file blogapicounter.addon.php
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief blogAPI 애드온 * @brief Add blogAPI
* *
* ms live writer, 파이어폭스의 performancing, zoundry 등의 외부 툴을 이용하여 글을 입력할 있게 합니다. * It enables to write a post by using an external tool such as ms live writer, firefox performancing, zoundry and so on.
* 모듈 실행 이전(before_module_proc) 호출이 되어야 하며 정상동작후에는 강제 종료를 한다. * 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();
// called_position가 after_module_proc일때 rsd 태그 삽입 $method_name = $xmlDoc->methodcall->methodname->body;
if($called_position == 'after_module_proc') { $params = $xmlDoc->methodcall->params->param;
// 현재 모듈의 rsd주소를 만듬 if($params && !is_array($params)) $params = array($params);
$site_module_info = Context::get('site_module_info'); // Compatible with some of methodname
$rsd_url = getFullSiteUrl($site_module_info->domain, '', 'mid',$site_module_info->mid, 'act','api'); 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);
// 헤더에 rsd태그 삽입 switch($method_name) {
Context::addHtmlHeader(" ".'<link rel="EditURI" type="application/rsd+xml" title="RSD" href="'.$rsd_url.'" />'); // Blog information
} case 'blogger.getUsersBlogs' :
$obj->url = getFullSiteUrl('');
$obj->blogid = $this->mid;
$obj->blogName = $this->module_info->browser_title;
$blog_list = array($obj);
// act가 api가 아니면 그냥 리턴~ $content = getXmlRpcResponse($blog_list);
if($_REQUEST['act']!='api') return; 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;
}
}
// 관련 func 파일 읽음 $content = getXmlRpcResponse($category_obj_list);
require_once('./addons/blogapi/blogapi.func.php'); 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') );
}
}
// xmlprc 파싱 $fileinfo = $params[3]->value->struct->member;
// 요청된 xmlrpc를 파싱 foreach($fileinfo as $key => $val) {
$oXmlParser = new XmlParser(); $nodename = $val->name->body;
$xmlDoc = $oXmlParser->parse(); if($nodename == 'bits') $filedata = base64_decode($val->value->base64->body);
elseif($nodename == 'name') $filename = $val->value->string->body;
}
$method_name = $xmlDoc->methodcall->methodname->body; $tmp_arr = explode('/',$filename);
$params = $xmlDoc->methodcall->params->param; $filename = array_pop($tmp_arr);
if($params && !is_array($params)) $params = array($params);
// 일부 methodname에 대한 호환 if(!is_dir($tmp_uploaded_path)) FileHandler::makeDir($tmp_uploaded_path);
if(in_array($method_name, array('metaWeblog.deletePost', 'metaWeblog.getUsersBlogs', 'metaWeblog.getUserInfo'))) {
$method_name = str_replace('metaWeblog.', 'blogger.', $method_name);
}
// blogger.deletePost일 경우 첫번째 인자 값 삭제 $target_filename = sprintf('%s%s', $tmp_uploaded_path, $filename);
if($method_name == 'blogger.deletePost') array_shift($params); FileHandler::writeFile($target_filename, $filedata);
$obj->url = Context::getRequestUri().$target_filename;
// user_id, password를 구해서 로그인 시도 $content = getXmlRpcResponse($obj);
$user_id = trim($params[1]->value->string->body); printContent($content);
$password = trim($params[2]->value->string->body); 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(
if($called_position == 'before_module_init') { '<?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;
}
// member controller을 이용해서 로그인 시도 }
if($user_id && $password) { // Set document srl
$oMemberController = &getController('member'); $document_srl = getNextSequence();
$output = $oMemberController->doLogin($user_id, $password); $obj->document_srl = $document_srl;
// 로그인 실패시 에러 메시지 출력 $obj->module_srl = $this->module_srl;
if(!$output->toBool()) { // Attachment
$content = getXmlRpcFailure(1, $output->getMessage()); if(is_dir($tmp_uploaded_path)) {
printContent($content); $file_list = FileHandler::readDir($tmp_uploaded_path);
} $file_count = count($file_list);
} else { if($file_count) {
$content = getXmlRpcFailure(1, 'not logged'); $oFileController = &getController('file');
printContent($content); 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;
}
}
// 모듈에서 무언가 작업을 하기 전에 blogapi tool의 요청에 대한 처리를 하고 강제 종료한다. $obj->content = str_replace($uploaded_target_path,sprintf('/files/attach/images/%s/%s%s', $this->module_srl, getNumberingPath($document_srl,3), $filename), $obj->content);
if($called_position == 'before_module_proc') {
// 글쓰기 권한 체크 (권한명의 경우 약속이 필요할듯..) $oDocumentController = &getController('document');
if(!$this->grant->write_document) { $obj->commentStatus = 'ALLOW';
printContent( getXmlRpcFailure(1, 'no permission') ); $obj->allow_trackback = 'Y';
} $output = $oDocumentController->insertDocument($obj);
// 카테고리의 정보를 구해옴 if(!$output->toBool()) {
$oDocumentModel = &getModel('document'); $content = getXmlRpcFailure(1, $output->getMessage());
$category_list = $oDocumentModel->getCategoryList($this->module_srl); } else {
$content = getXmlRpcResponse(strval($document_srl));
}
FileHandler::removeDir($tmp_uploaded_path);
// 임시 파일 저장 장소 지정 printContent($content);
$tmp_uploaded_path = sprintf('./files/cache/blogapi/%s/%s/', $this->mid, $user_id); break;
$uploaded_target_path = sprintf('/files/cache/blogapi/%s/%s/', $this->mid, $user_id); // 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;
}
switch($method_name) { $oDocumentModel = &getModel('document');
// 블로그 정보 $oDocument = $oDocumentModel->getDocument($document_srl);
case 'blogger.getUsersBlogs' : // Check if a permission to modify a document is granted
$obj->url = getFullSiteUrl(''); if(!$oDocument->isGranted()) {
$obj->blogid = $this->mid; $content = getXmlRpcFailure(1, 'no permission');
$obj->blogName = $this->module_info->browser_title; break;
$blog_list = array($obj); }
$content = getXmlRpcResponse($blog_list); $obj = $oDocument->getObjectVars();
printContent($content);
break;
// 카테고리 목록 return $info = $params[3];
case 'metaWeblog.getCategories' : // Get information of post, title, and category
$category_obj_list = array(); for($i=0;$i<count($info->value->struct->member);$i++) {
if($category_list) { $val = $info->value->struct->member[$i];
foreach($category_list as $category_srl => $category_info) { switch($val->name->body) {
unset($obj); case 'title' :
$obj->description = $category_info->title; $obj->title = $val->value->string->body;
//$obj->htmlUrl = Context::getRequestUri().$this->mid.'/1'; break;
//$obj->rssUrl= Context::getRequestUri().'rss/'.$this->mid.'/1'; case 'description' :
$obj->title = $category_info->title; $obj->content = $val->value->string->body;
$obj->categoryid = $category_srl; break;
$category_obj_list[] = $obj; 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;
}
$content = getXmlRpcResponse($category_obj_list); }
printContent($content); // Document srl
break; $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']);
case 'metaWeblog.newMediaObject' : if(file_exists($moved_filename)) continue;
// 파일 업로드 권한 체크
$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; $oFileController->insertFile($file_info, $this->module_srl, $document_srl, 0, true);
foreach($fileinfo as $key => $val) { }
$nodename = $val->name->body; $obj->uploaded_count += $file_count;
if($nodename == 'bits') $filedata = base64_decode($val->value->base64->body); }
elseif($nodename == 'name') $filename = $val->value->string->body; }
}
$tmp_arr = explode('/',$filename); $obj->content = str_replace($uploaded_target_path,sprintf('/files/attach/images/%s/%s%s', $this->module_srl, getNumberingPath($document_srl,3), $filename), $obj->content);
$filename = array_pop($tmp_arr);
if(!is_dir($tmp_uploaded_path)) FileHandler::makeDir($tmp_uploaded_path); $oDocumentController = &getController('document');
$output = $oDocumentController->updateDocument($oDocument,$obj);
$target_filename = sprintf('%s%s', $tmp_uploaded_path, $filename); if(!$output->toBool()) {
FileHandler::writeFile($target_filename, $filedata); $content = getXmlRpcFailure(1, $output->getMessage());
$obj->url = Context::getRequestUri().$target_filename; } else {
$content = getXmlRpcResponse(true);
FileHandler::removeDir($tmp_uploaded_path);
}
$content = getXmlRpcResponse($obj); printContent($content);
printContent($content); break;
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);
case 'metaWeblog.getPost' : break;
$document_srl = $params[0]->value->string->body; // Get recent posts
if(!$document_srl) { case 'metaWeblog.getRecentPosts' :
printContent( getXmlRpcFailure(1, 'no permission') ); // Options to get a list
} else { $args->module_srl = $this->module_srl; // /< module_srl of the current module
$oDocumentModel = &getModel('document'); $args->page = 1;
$oDocument = $oDocumentModel->getDocument($document_srl); $args->list_count = 20;
if(!$oDocument->isExists() || !$oDocument->isGranted()) { $args->sort_index = 'list_order'; // /< Sorting values
printContent( getXmlRpcFailure(1, 'no permission') ); $logged_info = Context::get('logged_info');
} else { $args->search_target = 'member_srl';
// 카테고리를 사용하는지 확인후 사용시 카테고리 목록을 구해와서 Context에 세팅 $args->search_keyword = $logged_info->member_srl;
$category = ""; $output = $oDocumentModel->getDocumentList($args);
if($oDocument->get('category_srl')) { if(!$output->toBool() || !$output->data) {
$oDocumentModel = &getModel('document'); $content = getXmlRpcFailure(1, 'post not founded');
$category_list = $oDocumentModel->getCategoryList($oDocument->get('module_srl')); printContent($content);
if($category_list[$oDocument->get('category_srl')]) { } else {
$category = $category_list[$oDocument->get('category_srl')]->title; $oEditorController = &getController('editor');
}
}
$content = sprintf( $posts = array();
'<?xml version="1.0" encoding="utf-8"?>'. foreach($output->data as $key => $oDocument) {
'<methodResponse>'. $post = null;
'<params>'. $post->categories = array();
'<param>'. $post->dateCreated = date("Ymd", $oDocument->getRegdateTime()).'T'.date("H:i:s", $oDocument->getRegdateTime());
'<value>'. $post->description = htmlspecialchars($oEditorController->transComponent($oDocument->getContent(false,false,true,false)));
'<struct>'. $post->link = $post->permaLink = getFullUrl('','document_srl',$oDocument->document_srl);
'<member><name>categories</name><value><array><data><value><![CDATA[%s]]></value></data></array></value></member>'. $post->postid = $oDocument->document_srl;
'<member><name>dateCreated</name><value><dateTime.iso8601>%s</dateTime.iso8601></value></member>'. $post->title = htmlspecialchars($oDocument->get('title'));
'<member><name>description</name><value><![CDATA[%s]]></value></member>'. $post->publish = 1;
'<member><name>link</name><value>%s</value></member>'. $post->userid = $oDocument->get('user_id');
'<member><name>postid</name><value><string>%s</string></value></member>'. $post->mt_allow_pings = 0;
'<member><name>title</name><value><![CDATA[%s]]></value></member>'. $post->mt_allow_comments = $oDocument->allowComment()?1:0;
'<member><name>publish</name><value><boolean>1</boolean></value></member>'. $posts[] = $post;
'</struct>'. }
'</value>'. $content = getXmlRpcResponse($posts);
'</param>'. printContent($content);
'</params>'. }
'</methodResponse>', break;
$category, // Display RSD if there is no request
date("Ymd", $oDocument->getRegdateTime()).'T'.date("H:i:s", $oDocument->getRegdateTime()), default :
$oDocument->getContent(false, false, true,false), $homepagelink = getUrl('','mid',$this->mid);
getFullUrl('','document_srl', $oDocument->document_srl), $site_module_info = Context::get('site_module_info');
$oDocument->document_srl, $api_url = getFullSiteUrl($site_module_info->domain, '', 'mid',$site_module_info->mid, 'act','api');
$oDocument->getTitleText() $content = <<<RSDContent
);
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" ?> <?xml version="1.0" ?>
<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd" > <rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd" >
<service> <service>
@ -461,8 +428,8 @@
</service> </service>
</rsd> </rsd>
RSDContent; RSDContent;
printContent($content); printContent($content);
break; break;
} }
} }
?> ?>

View file

@ -1,13 +1,13 @@
<?php <?php
if(!defined("__ZBXE__")) exit(); if(!defined('__XE__')) exit();
/** /**
* @file ./addons/blogapi/blogapi.func.php * @file ./addons/blogapi/blogapi.func.php
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief blogapi구현을 위한 함수 모음집 * @brief Function collections for the implementation of blogapi
**/ **/
// 오류 표시 // Error messages
function getXmlRpcFailure($error, $message) { function getXmlRpcFailure($error, $message) {
return return
sprintf( sprintf(
@ -16,8 +16,7 @@
htmlspecialchars($message) htmlspecialchars($message)
); );
} }
// Display results
// 결과 표시
function getXmlRpcResponse($params) { function getXmlRpcResponse($params) {
$buff = '<?xml version="1.0" encoding="utf-8"?>'."\n<methodResponse><params>"; $buff = '<?xml version="1.0" encoding="utf-8"?>'."\n<methodResponse><params>";
$buff .= _getEncodedVal($params); $buff .= _getEncodedVal($params);
@ -25,8 +24,7 @@
return $buff; return $buff;
} }
// Encoding
// 인코딩 처리
function _getEncodedVal($val, $is_sub_set = false) { function _getEncodedVal($val, $is_sub_set = false) {
if(is_int($val)) $buff = sprintf("<value><i4>%d</i4></value>", $val); if(is_int($val)) $buff = sprintf("<value><i4>%d</i4></value>", $val);
elseif(is_string($val)&&preg_match('/^([0-9]+)T([0-9\:]+)$/', $val)) $buff = sprintf("<value><dateTime.iso8601>%s</dateTime.iso8601></value>\n", $val); elseif(is_string($val)&&preg_match('/^([0-9]+)T([0-9\:]+)$/', $val)) $buff = sprintf("<value><dateTime.iso8601>%s</dateTime.iso8601></value>\n", $val);
@ -53,8 +51,7 @@
if(!$is_sub_set) return sprintf("<param>\n%s</param>", $buff); if(!$is_sub_set) return sprintf("<param>\n%s</param>", $buff);
return $buff; return $buff;
} }
// Display the result
// 결과 출력
function printContent($content) { function printContent($content) {
header("Content-Type: text/xml; charset=UTF-8"); header("Content-Type: text/xml; charset=UTF-8");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");

View file

@ -28,10 +28,10 @@
把状态设置为"使用"时才会激活RSD标签及api。 把状态设置为"使用"时才会激活RSD标签及api。
</description> </description>
<description xml:lang="en"> <description xml:lang="en">
This blogApi addon supports metaWeblog. This blogAPI addon supports metaWeblog.
By using this option, it lets the RSD tag to be exposed to each module. 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. URL to the API is http://setup_path/module_name/api.
RSD tag and the api will work only if u use this addon. RSD tag and the api will work only if you use this addon.
</description> </description>
<description xml:lang="vi"> <description xml:lang="vi">
Addon BlogAPI này hỗ trợ metaWeblog.. Addon BlogAPI này hỗ trợ metaWeblog..

View file

@ -4,8 +4,8 @@
/** /**
* @file captcha.addon.php * @file captcha.addon.php
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief 특정 action을 실행할때 captcha를 띄우도록 * @brief Captcha for a particular action
* 영어 알파벳을 입력, 음성기능 추가 * English alphabets and voice verification added
**/ **/
if(!class_exists('AddonCaptcha')) if(!class_exists('AddonCaptcha'))
@ -33,6 +33,8 @@
if($this->addon_info->target != 'all' && Context::get('is_logged')) return false; if($this->addon_info->target != 'all' && Context::get('is_logged')) return false;
if($_SESSION['captcha_authed']) return false; if($_SESSION['captcha_authed']) return false;
$type = Context::get('captchaType');
$target_acts = array('procBoardInsertDocument','procBoardInsertComment','procIssuetrackerInsertIssue','procIssuetrackerInsertHistory','procTextyleInsertComment'); $target_acts = array('procBoardInsertDocument','procBoardInsertComment','procIssuetrackerInsertIssue','procIssuetrackerInsertHistory','procTextyleInsertComment');
if($this->addon_info->apply_find_account=='apply') $target_acts[] = 'procMemberFindAccount'; 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_resend_auth_mail=='apply') $target_acts[] = 'procMemberResendAuthMail';
@ -40,11 +42,15 @@
if(Context::getRequestMethod()!='XMLRPC' && Context::getRequestMethod()!=='JSON') if(Context::getRequestMethod()!='XMLRPC' && Context::getRequestMethod()!=='JSON')
{ {
Context::addHtmlHeader('<script type="text/javascript"> var captchaTargetAct = new Array("'.implode('","',$target_acts).'"); </script>'); if($type == 'inline') {
Context::addJsFile('./addons/captcha/captcha.js',false, '', null, 'body'); $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)) { if(!$_SESSION['captcha_authed'] && in_array(Context::get('act'), $target_acts)) {
Context::loadLang('./addons/captcha/lang'); Context::loadLang('./addons/captcha/lang');
$ModuleHandler->error = "captcha_denied"; $ModuleHandler->error = "captcha_denied";
@ -53,18 +59,26 @@
return true; return true;
} }
function before_module_init_setCaptchaSession() function createKeyword()
{ {
if($_SESSION['captcha_authed']) return false; $type = Context::get('captchaType');
if ($type == 'inline' && $_SESSION['captcha_keyword']) return;
// 언어파일 로드
Context::loadLang(_XE_PATH_.'addons/captcha/lang');
// 키워드 생성
$arr = range('A','Y'); $arr = range('A','Y');
shuffle($arr); shuffle($arr);
$arr = array_slice($arr,0,6); $arr = array_slice($arr,0,6);
$_SESSION['captcha_keyword'] = join('', $arr); $_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'); $target = Context::getLang('target_captcha');
header("Content-Type: text/xml; charset=UTF-8"); header("Content-Type: text/xml; charset=UTF-8");
@ -87,6 +101,7 @@
function before_module_init_captchaImage() function before_module_init_captchaImage()
{ {
if($_SESSION['captcha_authed']) return false; if($_SESSION['captcha_authed']) return false;
if(Context::get('renew')) $this->createKeyword();
$keyword = $_SESSION['captcha_keyword']; $keyword = $_SESSION['captcha_keyword'];
$im = $this->createCaptchaImage($keyword); $im = $this->createCaptchaImage($keyword);
@ -106,31 +121,31 @@
{ {
$arr = array(); $arr = array();
for($i=0,$c=strlen($string);$i<$c;$i++) $arr[] = $string{$i}; for($i=0,$c=strlen($string);$i<$c;$i++) $arr[] = $string{$i};
// Font site
// 글자 하나 사이즈
$w = 18; $w = 18;
$h = 25; $h = 25;
// Character length
// 글자 수
$c = count($arr); $c = count($arr);
// Character image
// 글자 이미지
$im = array(); $im = array();
// Create an image by total size
// 총사이즈로 바탕 이미지 생성
$im[] = imagecreate(($w+2)*count($arr), $h); $im[] = imagecreate(($w+2)*count($arr), $h);
$deg = range(-30,30); $deg = range(-30,30);
shuffle($deg); shuffle($deg);
// Create an image for each letter
// 글자별 이미지 생성
foreach($arr as $i => $str) foreach($arr as $i => $str)
{ {
$im[$i+1] = @imagecreate($w, $h); $im[$i+1] = @imagecreate($w, $h);
$background_color = imagecolorallocate($im[$i+1], 255, 255, 255); $background_color = imagecolorallocate($im[$i+1], 255, 255, 255);
$text_color = imagecolorallocate($im[$i+1], 0, 0, 0); $text_color = imagecolorallocate($im[$i+1], 0, 0, 0);
// Control font size
// 글자폰트(사이즈) 조절
$ran = range(1,20); $ran = range(1,20);
shuffle($ran); shuffle($ran);
@ -148,22 +163,23 @@
} }
} }
// 각글자 이미지를 합침 // Combine images of each character
for($i=1;$i<count($im);$i++) for($i=1;$i<count($im);$i++)
{ {
imagecopy($im[0],$im[$i],(($w+2)*($i-1)),0,0,0,$w,$h); imagecopy($im[0],$im[$i],(($w+2)*($i-1)),0,0,0,$w,$h);
imagedestroy($im[$i]); imagedestroy($im[$i]);
} }
// Larger image
// 이미지 확대
$big_count = 2; $big_count = 2;
$big = imagecreatetruecolor(($w+2)*$big_count*$c, $h*$big_count); $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); imagecopyresized($big, $im[0], 0, 0, 0, 0, ($w+2)*$big_count*$c, $h*$big_count, ($w+2)*$c, $h);
imagedestroy($im[0]); imagedestroy($im[0]);
if(function_exists('imageantialias')) imageantialias($big,true); if(function_exists('imageantialias')) imageantialias($big,true);
// Background line
// 배경 라인 및 점찍기
$line_color = imagecolorallocate($big, 0, 0, 0); $line_color = imagecolorallocate($big, 0, 0, 0);
$w = ($w+2)*$big_count*$c; $w = ($w+2)*$big_count*$c;
@ -207,8 +223,8 @@
{ {
$_data = FileHandler::readFile(sprintf($_audio, $string{$i})); $_data = FileHandler::readFile(sprintf($_audio, $string{$i}));
$start = rand(5, 68); // 해더 4바이트, 데이터 영역 64바이트 정도 랜덤하게 시작 $start = rand(5, 68); // Random start in 4-byte header and 64 byte data
$datalen = strlen($_data) - $start - 256; // 마지막 unchanged 256 바이트 $datalen = strlen($_data) - $start - 256; // Last unchanged 256 bytes
for($j=$start;$j<$datalen;$j+=64) for($j=$start;$j<$datalen;$j+=64)
{ {
@ -223,12 +239,23 @@
return $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() function before_module_init_captchaCompare()
{ {
if($_SESSION['captcha_authed']) return false; if(!$this->compareCaptcha()) 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("Content-Type: text/xml; charset=UTF-8");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
@ -241,23 +268,59 @@
Context::close(); Context::close();
exit(); 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__'] = new AddonCaptcha;
$GLOBALS['__AddonCaptcha__']->setInfo($addon_info); $GLOBALS['__AddonCaptcha__']->setInfo($addon_info);
Context::set('oCaptcha', &$GLOBALS['__AddonCaptcha__']);
} }
$oAddonCaptcha = &$GLOBALS['__AddonCaptcha__']; $oAddonCaptcha = &$GLOBALS['__AddonCaptcha__'];
if(method_exists(&$oAddonCaptcha, $called_position)) if(method_exists($oAddonCaptcha, $called_position))
{ {
if(!call_user_func(array(&$oAddonCaptcha, $called_position), &$this)) return false; if(!call_user_func_array(array(&$oAddonCaptcha, $called_position), array(&$this))) return false;
} }
$addon_act = Context::get('captcha_action'); $addon_act = Context::get('captcha_action');
if($addon_act && method_exists(&$oAddonCaptcha, $called_position.'_'.$addon_act)) if($addon_act && method_exists($oAddonCaptcha, $called_position.'_'.$addon_act))
{ {
if(!call_user_func(array(&$oAddonCaptcha, $called_position.'_'.$addon_act), &$this)) return false; if(!call_user_func_array(array(&$oAddonCaptcha, $called_position.'_'.$addon_act), array(&$this))) return false;
} }
?> ?>

View file

@ -12,8 +12,7 @@
로그인하지 않은 경우에만 해당됩니다. 로그인하지 않은 경우에만 해당됩니다.
</description> </description>
<description xml:lang="en"> <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 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.
This addon applies only to not-logged-in users.
</description> </description>
<description xml:lang="vi"> <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 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.
@ -60,7 +59,7 @@
<description xml:lang="zh-CN">可以指定验证码应用对象(管理员除外)。</description> <description xml:lang="zh-CN">可以指定验证码应用对象(管理员除外)。</description>
<description xml:lang="jp">管理者を除き、書き込み・コメントを入力する際にcaptchaイメージを見せる対象を設定します。</description> <description xml:lang="jp">管理者を除き、書き込み・コメントを入力する際にcaptchaイメージを見せる対象を設定します。</description>
<description xml:lang="zh-TW">除了管理員,可以選擇圖形驗證應用的對象。</description> <description xml:lang="zh-TW">除了管理員,可以選擇圖形驗證應用的對象。</description>
<description xml:lang="en">You may specify targets CAPTCHA work. It's not applied when administrator writes.</description> <description xml:lang="en">You 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="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> <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=""> <options value="">

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

@ -22,8 +22,8 @@
把状态设置为"使用"时,才会记录网站访问信息. 把状态设置为"使用"时,才会记录网站访问信息.
</description> </description>
<description xml:lang="en"> <description xml:lang="en">
This addon logs access information based on the basic counter module within XE. 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. The access information will be collected only if you enable this addon.
</description> </description>
<description xml:lang="vi"> <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. 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.

View file

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

View file

@ -20,7 +20,7 @@
此插件可激活短信箱及添加好友功能。 此插件可激活短信箱及添加好友功能。
</description> </description>
<description xml:lang="en"> <description xml:lang="en">
This addon enables communication module in order to use message or friend function. 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. Please enable this addon in case you want to use those functions.
</description> </description>
<description xml:lang="vi"> <description xml:lang="vi">

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 <?php
if(!defined("__ZBXE__")) exit(); if(!defined('__XE__')) exit();
/** /**
* @file member_communication.addon.php * @file member_communication.addon.php
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief 사용자의 커뮤니케이션 기능을 활성화 * @brief Promote user communication
* *
* - 새로운 쪽지가 왔을 경우 팝업으로 띄움 * - Pop-up the message if new message comes in
* - MemberModel::getMemberMenu 호출시 대상이 회원일 경우 쪽지 보내기 기능 추가합니다. * - When calling MemberModel::getMemberMenu, feature to send a message is added
* - MemberModel::getMemberMenu 호출시 친구 등록 메뉴를 추가합니다. * - 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;
// 비로그인 사용자면 중지 /**
$logged_info = Context::get('logged_info'); * Message/Friend munus are added on the pop-up window and member profile. Check if a new message is received
if(!$logged_info) return; **/
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);
if($called_position == 'before_module_init' && $this->module != 'member') { 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')));
Context::loadLang('./modules/communication/lang'); $link = Context::getRequestUri().'?module=communication&act=dispCommunicationNewMessage';
$script = "<script type=\"text/javascript\">jQuery(function(){ xeNotifyMessage('{$text}','{$new_message_count}'); });</script>";
// 회원 로그인 정보중에서 쪽지등의 메뉴를 추가 Context::addHtmlFooter($script);
$oMemberController = &getController('member'); }
$oMemberController->addMemberMenu('dispCommunicationFriend', 'cmd_view_friend'); } elseif($called_position == 'before_module_proc' && $this->act == 'getMemberMenu') {
$oMemberController->addMemberMenu('dispCommunicationMessages', 'cmd_view_message_box'); $oMemberController = &getController('member');
$member_srl = Context::get('target_srl');
// 새로운 쪽지에 대한 플래그가 있으면 쪽지 보기 팝업 띄움 $mid = Context::get('cur_mid');
$flag_path = './files/member_extra_info/new_message_flags/'.getNumberingPath($logged_info->member_srl); // Creates communication model object
$flag_file = sprintf('%s%s', $flag_path, $logged_info->member_srl); $oCommunicationModel = &getModel('communication');
// Add a feature to display own message box.
if(file_exists($flag_file)) { if($logged_info->member_srl == $member_srl) {
$new_message_count = FileHandler::readFile($flag_file); // Add your own viewing Note Template
FileHandler::removeFile($flag_file); $oMemberController->addMemberPopupMenu(getUrl('','mid',$mid,'act','dispCommunicationMessages'), 'cmd_view_message_box', '', 'self');
Context::loadLang('./addons/member_communication/lang'); // Display a list of friends
$oMemberController->addMemberPopupMenu(getUrl('','mid',$mid,'act','dispCommunicationFriend'), 'cmd_view_friend', '', 'self');
$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'); // If not, Add menus to send message and to add friends
} else {
Context::addHtmlHeader( $script ); // 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');
} elseif($called_position == 'before_module_proc' && $this->act == 'getMemberMenu') { // 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 = &getController('member'); $oMemberController->addMemberPopupMenu(getUrl('','module','communication','act','dispCommunicationSendMessage','receiver_srl',$member_srl), 'cmd_send_message', '', 'popup');
$member_srl = Context::get('target_srl'); // Add a menu for listing friends (if a friend is new)
$mid = Context::get('cur_mid'); if(!$oCommunicationModel->isAddedFriend($member_srl))
$oMemberController->addMemberPopupMenu(getUrl('','module','communication','act','dispCommunicationAddFriend','target_srl',$member_srl), 'cmd_add_friend', '', 'popup');
// 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');
}
}
?> ?>

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,23 +1,21 @@
<?php <?php
if(!defined("__ZBXE__")) exit(); if(!defined('__XE__')) exit();
/** /**
* @file image_name.addon.php * @file image_name.addon.php
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief 사용자의 이미지이름/ 이미지마크등을 출력 * @brief Display user image name/image mark
* *
* <div class="member_회원번호">....</div> 정의가 부분을 찾아 회원번호를 구해서 * 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; if($called_position != "before_display_content" || Context::get('act')=='dispPageAdminContentModify') return;
// Include a file having functions to replace member image name/mark
// 회원 이미지이름/ 마크/ 찾아서 대체할 함수를 담고 있는 파일을 include require_once('./addons/member_extra_info/member_extra_info.lib.php');
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);
// 1. 출력문서중에서 <div class="member_번호">content</div>를 찾아 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 <?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) { function memberTransImageName($matches) {
// If member_srl < 0, then return text only in the body
// 회원번호를 추출하여 0보다 찾으면 본문중 text만 return
$member_srl = $matches[3]; $member_srl = $matches[3];
if($member_srl<0) return $matches[5]; if($member_srl<0) return $matches[5];
$site_module_info = Context::get('site_module_info'); $site_module_info = Context::get('site_module_info');
$oMemberModel = &getModel('member'); $oMemberModel = &getModel('member');
$group_image = $oMemberModel->getGroupImageMark($member_srl,$site_module_info->site_srl); $group_image = $oMemberModel->getGroupImageMark($member_srl,$site_module_info->site_srl);
// If member_srl=o(not a member), return the entire body
// 회원이 아닐경우(member_srl = 0) 본문 전체를 return
$nick_name = $matches[5]; $nick_name = $matches[5];
if(!$member_srl) return $matches[0]; if(!$member_srl) return $matches[0];
// If pre-defined data in the global variablesm return it
// 전역변수에 미리 설정한 데이터가 있다면 그걸 return
if(!$GLOBALS['_transImageNameList'][$member_srl]->cached) { if(!$GLOBALS['_transImageNameList'][$member_srl]->cached) {
$GLOBALS['_transImageNameList'][$member_srl]->cached = true; $GLOBALS['_transImageNameList'][$member_srl]->cached = true;
$image_name_file = sprintf('files/member_extra_info/image_name/%s%d.gif', getNumberingPath($member_srl), $member_srl); $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_name_file = $GLOBALS['_transImageNameList'][$member_srl]->image_name_file;
$image_mark_file = $GLOBALS['_transImageNameList'][$member_srl]->image_mark_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 && !$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)); // check member_config
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);
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); $config = $oMemberModel->getMemberConfig();
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]); $orig_text = preg_replace('/'.preg_quote($matches[5],'/').'<\/'.$matches[6].'>$/', '', $matches[0]);

View file

@ -13,7 +13,7 @@
} }
/** /**
* @brief hdml 헤더 출력 * @brief hdml header output
**/ **/
function printHeader() { function printHeader() {
header("Content-Type:text/x-hdml; charset=".$this->charset); header("Content-Type:text/x-hdml; charset=".$this->charset);
@ -33,7 +33,7 @@
} }
/** /**
* @brief 제목을 출력 * @brief Output title
**/ **/
function printTitle() { function printTitle() {
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage); if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
@ -41,8 +41,8 @@
} }
/** /**
* @brief 내용을 출력 * @brief Output information
* hasChilds() 있으면 목록형을 그렇지 않으면 컨텐츠를 출력 * hasChilds() if there is a list of content types, otherwise output
**/ **/
function printContent() { function printContent() {
if($this->hasChilds()) { if($this->hasChilds()) {
@ -56,10 +56,10 @@
} }
/** /**
* @brief 버튼을 출력함 * @brief Button to output
**/ **/
function printBtn() { function printBtn() {
// 메뉴 형식 // Menu Types
if($this->hasChilds()) { if($this->hasChilds()) {
if($this->nextUrl) { if($this->nextUrl) {
$url = $this->nextUrl; $url = $this->nextUrl;
@ -73,7 +73,7 @@
$url = $this->homeUrl; $url = $this->homeUrl;
printf('<ce task=go label="%s" dest="%s">%s%s', $url->text, $url->url, $url->text, "\n"); printf('<ce task=go label="%s" dest="%s">%s%s', $url->text, $url->url, $url->text, "\n");
} }
// 컨텐츠 형식 // Content Types
} else { } else {
if($this->nextUrl) { if($this->nextUrl) {
$url = $this->nextUrl; $url = $this->nextUrl;
@ -91,7 +91,7 @@
} }
/** /**
* @brief 푸터 정보를 출력 * @brief Footer information output
**/ **/
function printFooter() { function printFooter() {
print $this->hasChilds()?'</choice>':'</display>'; print $this->hasChilds()?'</choice>':'</display>';

View file

@ -13,23 +13,22 @@
} }
/** /**
* @brief hdml 헤더 출력 * @brief hdml header output
**/ **/
function printHeader() { function printHeader() {
print("<html><head>\n"); print("<html><head>\n");
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage); 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)); printf("<title>%s%s</title></head><body>\n", htmlspecialchars($this->title),htmlspecialchars($titlePageStr));
} }
// Output title
// 제목을 출력
function printTitle() { function printTitle() {
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage); 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"); printf('&lt;%s%s&gt;<br>%s', htmlspecialchars($this->title),htmlspecialchars($titlePageStr),"\n");
} }
/** /**
* @brief 내용을 출력 * @brief Output information
* hasChilds() 있으면 목록형을 그렇지 않으면 컨텐츠를 출력 * hasChilds() if there is a list of content types, otherwise output
**/ **/
function printContent() { function printContent() {
if($this->hasChilds()) { if($this->hasChilds()) {
@ -45,7 +44,7 @@
} }
/** /**
* @brief 버튼을 출력함 * @brief Button to output
**/ **/
function printBtn() { function printBtn() {
if($this->nextUrl) { if($this->nextUrl) {
@ -56,7 +55,7 @@
$url = $this->prevUrl; $url = $this->prevUrl;
printf('<a href="%s">%s</a><br>%s', $url->url, $url->text, "\n"); printf('<a href="%s">%s</a><br>%s', $url->url, $url->text, "\n");
} }
// 언어선택 // Select Language
if(!parent::isLangChange()){ if(!parent::isLangChange()){
$url = getUrl('','lcm','1','sel_lang',Context::getLangType(),'return_uri',Context::get('current_url')); $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"); printf('<a href="%s">%s</a><br>%s', $url, 'Language : '.Context::getLang('select_lang'), "\n");
@ -73,8 +72,7 @@
printf('<a btn="%s" href="%s">%s</a><br>%s', $url->text, $url->url, $url->text, "\n"); printf('<a btn="%s" href="%s">%s</a><br>%s', $url->text, $url->url, $url->text, "\n");
} }
} }
// Footer information output
// 푸터 정보를 출력
function printFooter() { function printFooter() {
print("</body></html>\n"); print("</body></html>\n");
} }

View file

@ -2,48 +2,40 @@
/** /**
* Mobile XE Library Class ver 0.1 * Mobile XE Library Class ver 0.1
* @author NHN (developers@xpressengine.com) / lang_select : misol * @author NHN (developers@xpressengine.com) / lang_select : misol
* @brief WAP 태그 출력을 위한 XE 라이브러리 * @brief XE library for WAP tag output
**/ **/
class mobileXE { class mobileXE {
// Base url
// 기본 url
var $homeUrl = NULL; var $homeUrl = NULL;
var $upperUrl = NULL; var $upperUrl = NULL;
var $nextUrl = NULL; var $nextUrl = NULL;
var $prevUrl = NULL; var $prevUrl = NULL;
var $etcBtn = NULL; var $etcBtn = NULL;
// Variable for menu navigation
// 메뉴 네비게이션을 위한 변수
var $childs = null; var $childs = null;
// Basic variable
// 기본 변수
var $title = NULL; var $title = NULL;
var $content = NULL; var $content = NULL;
var $mobilePage = 0; var $mobilePage = 0;
var $totalPage = 1; var $totalPage = 1;
var $charset = 'UTF-8'; var $charset = 'UTF-8';
var $no = 0; var $no = 0;
// Navigation-related variables
// 네비게이션 관련 변수
var $menu = null; var $menu = null;
var $listed_items = null; var $listed_items = null;
var $node_list = null; var $node_list = null;
var $index_mid = null; var $index_mid = null;
// Navigation On/Off status value
// Navigation On/ Off 상태 값
var $navigationMode = 0; var $navigationMode = 0;
// XE module information currently requested
// 현재 요청된 XE 모듈 정보
var $module_info = null; var $module_info = null;
// Currently running instance of the module
// 현재 실행중인 모듈의 instance
var $oModule = null; var $oModule = null;
// Deck size // Deck size
var $deckSize = 1024; var $deckSize = 1024;
// Changing the language setting
// 언어 설정 변경
var $languageMode = 0; var $languageMode = 0;
var $lang = null; var $lang = null;
/** /**
@ -59,8 +51,7 @@
$class_file = sprintf('%saddons/mobile/classes/%s.class.php', _XE_PATH_, $browserType); $class_file = sprintf('%saddons/mobile/classes/%s.class.php', _XE_PATH_, $browserType);
require_once($class_file); require_once($class_file);
// Download mobile language settings (cookies, not willing to come up when you click create cache file ...- is initialized ..)
// 모바일 언어설정 로드(쿠키가 안되어 생각해낸 방법...-캐시파일 재생성을 클릭하면 초기화된다..)
$this->lang = FileHandler::readFile('./files/cache/addons/mobile/setLangType/personal_settings/'.md5(trim($_SERVER['HTTP_USER_AGENT']).trim($_SERVER['HTTP_PHONE_NUMBER']).trim($_SERVER['HTTP_HTTP_PHONE_NUMBER'])).'.php'); $this->lang = FileHandler::readFile('./files/cache/addons/mobile/setLangType/personal_settings/'.md5(trim($_SERVER['HTTP_USER_AGENT']).trim($_SERVER['HTTP_PHONE_NUMBER']).trim($_SERVER['HTTP_HTTP_PHONE_NUMBER'])).'.php');
if($this->lang) { if($this->lang) {
$lang_supported = Context::get('lang_supported'); $lang_supported = Context::get('lang_supported');
@ -85,7 +76,7 @@
* @brief constructor * @brief constructor
**/ **/
function mobileXE() { function mobileXE() {
// navigation mode 체크 // Check navigation mode
if(Context::get('nm')) { if(Context::get('nm')) {
$this->navigationMode = 1; $this->navigationMode = 1;
$this->cmid = (int)Context::get('cmid'); $this->cmid = (int)Context::get('cmid');
@ -98,16 +89,16 @@
} }
/** /**
* @brief navigation mode 체크 * @brief Check navigation mode
* navigationMode 세팅과 모듈 정보의 menu_srl이 있어야 navigation mode = true로 return * navigationMode settings and modules of information must be menu_srl return to navigation mode = true
**/ **/
function isNavigationMode() { function isNavigationMode() {
return ($this->navigationMode && $this->module_info->menu_srl)?true:false; return ($this->navigationMode && $this->module_info->menu_srl)?true:false;
} }
/** /**
* @brief langchange mode 체크 * @brief Check langchange mode
* languageMode 세팅 있어야 true return * true return should be set languageMode
**/ **/
function isLangChange() { function isLangChange() {
if($this->languageMode) return true; if($this->languageMode) return true;
@ -115,12 +106,12 @@
} }
/** /**
* @brief 언어 설정 * @brief Language settings
* 쿠키가 안되기 때문에 휴대전화마다 고유한 파일로 언어설정을 저장하는 파일 생성 * Cookies Since you set your phone to store language-specific file, file creation
**/ **/
function setLangType() { function setLangType() {
$lang_supported = Context::get('lang_supported'); $lang_supported = Context::get('lang_supported');
// 언어 변수가 있는지 확인하고 변수가 유효한지 확인 // Make sure that the language variables and parameters are valid
if($this->lang && isset($lang_supported[$this->lang])) { if($this->lang && isset($lang_supported[$this->lang])) {
$langbuff = FileHandler::readFile('./files/cache/addons/mobile/setLangType/personal_settings/'.md5(trim($_SERVER['HTTP_USER_AGENT']).trim($_SERVER['HTTP_PHONE_NUMBER']).trim($_SERVER['HTTP_HTTP_PHONE_NUMBER'])).'.php'); $langbuff = FileHandler::readFile('./files/cache/addons/mobile/setLangType/personal_settings/'.md5(trim($_SERVER['HTTP_USER_AGENT']).trim($_SERVER['HTTP_PHONE_NUMBER']).trim($_SERVER['HTTP_HTTP_PHONE_NUMBER'])).'.php');
if($langbuff) FileHandler::removeFile('./files/cache/addons/mobile/setLangType/personal_settings/'.md5(trim($_SERVER['HTTP_USER_AGENT']).trim($_SERVER['HTTP_PHONE_NUMBER']).trim($_SERVER['HTTP_HTTP_PHONE_NUMBER'])).'.php'); if($langbuff) FileHandler::removeFile('./files/cache/addons/mobile/setLangType/personal_settings/'.md5(trim($_SERVER['HTTP_USER_AGENT']).trim($_SERVER['HTTP_PHONE_NUMBER']).trim($_SERVER['HTTP_HTTP_PHONE_NUMBER'])).'.php');
@ -130,7 +121,7 @@
} }
/** /**
* @brief 현재 요청된 모듈 정보 세팅 * @brief Information currently requested module settings
**/ **/
function setModuleInfo(&$module_info) { function setModuleInfo(&$module_info) {
if($this->module_info) return; if($this->module_info) return;
@ -138,21 +129,18 @@
} }
/** /**
* @brief 현재 실행중인 모듈 instance 세팅 * @brief Set the module instance is currently running
**/ **/
function setModuleInstance(&$oModule) { function setModuleInstance(&$oModule) {
if($this->oModule) return; if($this->oModule) return;
// Save instance
// instance 저장
$this->oModule = $oModule; $this->oModule = $oModule;
// Of the current module if there is a menu by menu
// 현재 모듈의 메뉴가 설정되어 있으면 메뉴 정리
$menu_cache_file = sprintf(_XE_PATH_.'files/cache/menu/%d.php', $this->module_info->menu_srl); $menu_cache_file = sprintf(_XE_PATH_.'files/cache/menu/%d.php', $this->module_info->menu_srl);
if(!file_exists($menu_cache_file)) return; if(!file_exists($menu_cache_file)) return;
include $menu_cache_file; include $menu_cache_file;
// One-dimensional arrangement of menu changes
// 정리된 menu들을 1차원으로 변경
$this->getListedItems($menu->list, $listed_items, $node_list); $this->getListedItems($menu->list, $listed_items, $node_list);
$this->listed_items = $listed_items; $this->listed_items = $listed_items;
@ -162,8 +150,7 @@
$k = array_keys($node_list); $k = array_keys($node_list);
$v = array_values($node_list); $v = array_values($node_list);
$this->index_mid = $k[0]; $this->index_mid = $k[0];
// The depth of the current menu, the top button to specify if one or more
// 현재 메뉴의 depth가 1이상이면 상위 버튼을 지정
$cur_menu_item = $listed_items[$node_list[$this->module_info->mid]]; $cur_menu_item = $listed_items[$node_list[$this->module_info->mid]];
if($cur_menu_item['parent_srl']) { if($cur_menu_item['parent_srl']) {
$parent_srl = $cur_menu_item['parent_srl']; $parent_srl = $cur_menu_item['parent_srl'];
@ -177,39 +164,38 @@
} }
/** /**
* @brief 접속 브라우저의 헤더를 판단하여 브라우저 타입을 return * @brief Access the browser's header to determine the return type of the browser
* 모바일 브라우저가 아닐 경우 null return * Mobile browser, if not null return
**/ **/
function getBrowserType() { function getBrowserType() {
if(Context::get('smartphone')) return null; if(Context::get('smartphone')) return null;
// 브라우저 타입을 판별 // Determine the type of browser
$browserAccept = $_SERVER['HTTP_ACCEPT']; $browserAccept = $_SERVER['HTTP_ACCEPT'];
$userAgent = $_SERVER['HTTP_USER_AGENT']; $userAgent = $_SERVER['HTTP_USER_AGENT'];
$wap_sid = $_SERVER['HTTP_X_UP_SUBNO']; $wap_sid = $_SERVER['HTTP_X_UP_SUBNO'];
if(eregi("SKT11", $userAgent) || eregi("skt", $browserAccept)) { if(preg_match("/SKT11/i", $userAgent) || preg_match("/skt/i", $browserAccept)) {
Context::set('mobile_skt',1); Context::set('mobile_skt',1);
return "wml"; return "wml";
} }
elseif(eregi("hdml", $browserAccept)) return "hdml"; elseif(preg_match("/hdml/i", $browserAccept)) return "hdml";
elseif(eregi("CellPhone", $userAgent)) return "mhtml"; elseif(preg_match("/CellPhone/i", $userAgent)) return "mhtml";
return null; return null;
} }
/** /**
* @brief charset 지정 * @brief Specify charset
**/ **/
function setCharSet($charset = 'UTF-8') { function setCharSet($charset = 'UTF-8') {
if(!$charset) $charset = 'UTF-8'; if(!$charset) $charset = 'UTF-8';
// SKT supports the euc-kr
//SKT는 euc-kr만 지원
if(Context::get('mobile_skt')==1) $charset = 'euc-kr'; if(Context::get('mobile_skt')==1) $charset = 'euc-kr';
$this->charset = $charset; $this->charset = $charset;
} }
/** /**
* @brief 모바일 기기의 용량 제한에 다른 가상 페이지 지정 * @brief Limited capacity of mobile devices, specifying a different virtual page
**/ **/
function setMobilePage($page=1) { function setMobilePage($page=1) {
if(!$page) $page = 1; if(!$page) $page = 1;
@ -217,10 +203,10 @@
} }
/** /**
* @brief 목록형 데이터 설정을 위한 child menu지정 * @brief Mokrokhyeong child menu for specifying the data set
**/ **/
function setChilds($childs) { function setChilds($childs) {
// menu개수가 9개 이상일 경우 자체 페이징 처리 // If more than nine the number of menu paging processing itself
$menu_count = count($childs); $menu_count = count($childs);
if($menu_count>9) { if($menu_count>9) {
$startNum = ($this->mobilePage-1)*9; $startNum = ($this->mobilePage-1)*9;
@ -235,8 +221,7 @@
$childs = $new_childs; $childs = $new_childs;
$this->totalPage = (int)(($menu_count-1)/9)+1; $this->totalPage = (int)(($menu_count-1)/9)+1;
// next/prevUrl specify
// next/prevUrl 지정
if($this->mobilePage>1) { if($this->mobilePage>1) {
$url = getUrl('mid',$_GET['mid'],'mpage',$this->mobilePage-1); $url = getUrl('mid',$_GET['mid'],'mpage',$this->mobilePage-1);
$text = sprintf('%s (%d/%d)', Context::getLang('cmd_prev'), $this->mobilePage-1, $this->totalPage); $text = sprintf('%s (%d/%d)', Context::getLang('cmd_prev'), $this->mobilePage-1, $this->totalPage);
@ -253,21 +238,21 @@
} }
/** /**
* @brief menu 출력대상이 있는지 확인 * @brief Check the menu to be output
**/ **/
function hasChilds() { function hasChilds() {
return count($this->childs)?true:0; return count($this->childs)?true:0;
} }
/** /**
* @brief child menu반환 * @brief Returns the child menu
**/ **/
function getChilds() { function getChilds() {
return $this->childs; return $this->childs;
} }
/** /**
* @brief title 지정 * @brief Specify title
**/ **/
function setTitle($title) { function setTitle($title) {
$oModuleController = &getController('module'); $oModuleController = &getController('module');
@ -276,28 +261,24 @@
} }
/** /**
* @brief title 반환 * @brief return title
**/ **/
function getTitle() { function getTitle() {
return $this->title; return $this->title;
} }
/** /**
* @brief 컨텐츠 정리 * @brief Content Cleanup
* HTML 컨텐츠에서 텍스트와 링크만 추출하는 기능 * In HTML content, the ability to extract text and links
**/ **/
function setContent($content) { function setContent($content) {
$oModuleController = &getController('module'); $oModuleController = &getController('module');
$allow_tag_array = array('<a>','<br>','<p>','<b>','<i>','<u>','<em>','<small>','<strong>','<big>','<table>','<tr>','<td>'); $allow_tag_array = array('<a>','<br>','<p>','<b>','<i>','<u>','<em>','<small>','<strong>','<big>','<table>','<tr>','<td>');
// Links/wrap, remove all tags except gangjoman
// 링크/ 줄바꿈, 강조만 제외하고 모든 태그 제거
$content = strip_tags($content, implode($allow_tag_array)); $content = strip_tags($content, implode($allow_tag_array));
// Margins tab removed
// 탭 여백 제거
$content = str_replace("\t", "", $content); $content = str_replace("\t", "", $content);
// Repeat two more times the space and remove julnanumeul
// 2번 이상 반복되는 공백과 줄나눔을 제거
$content = preg_replace('/( ){2,}/s', '', $content); $content = preg_replace('/( ){2,}/s', '', $content);
$content = preg_replace("/([\r\n]+)/s", "\r\n", $content); $content = preg_replace("/([\r\n]+)/s", "\r\n", $content);
$content = preg_replace(array("/<a/i","/<\/a/i","/<b/i","/<\/b/i","/<br/i"),array('<a','</a','<b','</b','<br'),$content); $content = preg_replace(array("/<a/i","/<\/a/i","/<b/i","/<\/b/i","/<br/i"),array('<a','</a','<b','</b','<br'),$content);
@ -306,8 +287,7 @@
while(strpos($content, '<br/><br/>')) { while(strpos($content, '<br/><br/>')) {
$content = str_replace('<br/><br/>','<br/>',$content); $content = str_replace('<br/><br/>','<br/>',$content);
} }
// If the required size of a deck of mobile content to write down all the dividing pages
// 모바일의 경우 한 덱에 필요한 사이즈가 적어서 내용을 모두 페이지로 나눔
$contents = array(); $contents = array();
while($content) { while($content) {
$tmp = $this->cutStr($content, $this->deckSize, ''); $tmp = $this->cutStr($content, $this->deckSize, '');
@ -335,8 +315,7 @@
} }
$this->totalPage = count($contents); $this->totalPage = count($contents);
// next/prevUrl specify
// next/prevUrl 지정
if($this->mobilePage>1) { if($this->mobilePage>1) {
$url = getUrl('mid',$_GET['mid'],'mpage',$this->mobilePage-1); $url = getUrl('mid',$_GET['mid'],'mpage',$this->mobilePage-1);
$text = sprintf('%s (%d/%d)', Context::getLang('cmd_prev'), $this->mobilePage-1, $this->totalPage); $text = sprintf('%s (%d/%d)', Context::getLang('cmd_prev'), $this->mobilePage-1, $this->totalPage);
@ -355,21 +334,21 @@
} }
/** /**
* @brief byte수로 자르는 함수 * @brief cutting the number of byte functions
**/ **/
function cutStr($string, $cut_size) { function cutStr($string, $cut_size) {
return preg_match('/.{'.$cut_size.'}/su', $string, $arr) ? $arr[0] : $string; return preg_match('/.{'.$cut_size.'}/su', $string, $arr) ? $arr[0] : $string;
} }
/** /**
* @brief 컨텐츠 반환 * @brief Return content
**/ **/
function getContent() { function getContent() {
return $this->content; return $this->content;
} }
/** /**
* @brief home url 지정 * @brief Specifies the home url
**/ **/
function setHomeUrl($url, $text) { function setHomeUrl($url, $text) {
if(!$url) $url = '#'; if(!$url) $url = '#';
@ -378,7 +357,7 @@
} }
/** /**
* @brief upper url 지정 * @brief Specify upper url
**/ **/
function setUpperUrl($url, $text) { function setUpperUrl($url, $text) {
if(!$url) $url = '#'; if(!$url) $url = '#';
@ -387,7 +366,7 @@
} }
/** /**
* @brief prev url 지정 * @brief Specify prev url
**/ **/
function setPrevUrl($url, $text) { function setPrevUrl($url, $text) {
if(!$url) $url = '#'; if(!$url) $url = '#';
@ -396,7 +375,7 @@
} }
/** /**
* @brief next url 지정 * @brief Specify next url
**/ **/
function setNextUrl($url, $text) { function setNextUrl($url, $text) {
if(!$url) $url = '#'; if(!$url) $url = '#';
@ -405,7 +384,7 @@
} }
/** /**
* @brief 다음, 이전, 상위 이외에 기타 버튼 지정 * @brief Next, Previous, Top button assignments other than
**/ **/
function setEtcBtn($url, $text) { function setEtcBtn($url, $text) {
if(!$url) $url = '#'; if(!$url) $url = '#';
@ -418,32 +397,25 @@
* @brief display * @brief display
**/ **/
function display() { function display() {
// 홈버튼 지정 // Home button assignments
$this->setHomeUrl(getUrl(), Context::getLang('cmd_go_home')); $this->setHomeUrl(getUrl(), Context::getLang('cmd_go_home'));
// Specify the title
// 제목 지정
if(!$this->title) $this->setTitle(Context::getBrowserTitle()); if(!$this->title) $this->setTitle(Context::getBrowserTitle());
ob_start(); ob_start();
// Output header
// 헤더를 출력
$this->printHeader(); $this->printHeader();
// Output title
// 제목을 출력
$this->printTitle(); $this->printTitle();
// Information output
// 내용 출력
$this->printContent(); $this->printContent();
// Button output
// 버튼 출력
$this->printBtn(); $this->printBtn();
// Footer output
// 푸터를 출력
$this->printFooter(); $this->printFooter();
$content = ob_get_clean(); $content = ob_get_clean();
// After conversion output
// 변환 후 출력
if(strtolower($this->charset) == 'utf-8') print $content; if(strtolower($this->charset) == 'utf-8') print $content;
else print iconv('UTF-8',$this->charset."//TRANSLIT//IGNORE", $content); else print iconv('UTF-8',$this->charset."//TRANSLIT//IGNORE", $content);
@ -451,7 +423,7 @@
} }
/** /**
* @brief 페이지 이동 * @brief Move page
**/ **/
function movepage($url) { function movepage($url) {
header("location:$url"); header("location:$url");
@ -459,7 +431,7 @@
} }
/** /**
* @brief 목록등에서 일련 번호를 리턴한다 * @brief And returns a list of serial numbers in
**/ **/
function getNo() { function getNo() {
$this->no++; $this->no++;
@ -468,7 +440,7 @@
} }
/** /**
* @brief XEMenu 모듈이 값을 사용하기 쉽게 정리해주는 함수 * @brief XE is easy to use Menu module is relieved during the function, value
**/ **/
function getListedItems($menu, &$listed_items, &$node_list) { function getListedItems($menu, &$listed_items, &$node_list) {
if(!count($menu)) return; if(!count($menu)) return;
@ -486,7 +458,7 @@
} }
/** /**
* @brief XE 네비게이션 출력 * @brief XE navigation output
**/ **/
function displayNavigationContent() { function displayNavigationContent() {
$childs = array(); $childs = array();
@ -523,13 +495,12 @@
} }
$this->setChilds($childs); $this->setChilds($childs);
} }
// Output
// 출력
$this->display(); $this->display();
} }
/** /**
* @brief 언어설정 메뉴 출력 * @brief Language Settings menu, the output
**/ **/
function displayLangSelect() { function displayLangSelect() {
$childs = array(); $childs = array();
@ -561,37 +532,33 @@
} }
/** /**
* @brief 모듈의 WAP 클래스 객체 생성하여 WAP 준비 * @brief Module to create a class object of the WAP WAP ready
**/ **/
function displayModuleContent() { function displayModuleContent() {
// 선택된 모듈의 WAP class 객체 생성 // Create WAP class objects of the selected module
$oModule = &getWap($this->module_info->module); $oModule = &getWap($this->module_info->module);
if(!$oModule || !method_exists($oModule, 'procWAP') ) return; if(!$oModule || !method_exists($oModule, 'procWAP') ) return;
$vars = get_object_vars($this->oModule); $vars = get_object_vars($this->oModule);
if(count($vars)) foreach($vars as $key => $val) $oModule->{$key} = $val; if(count($vars)) foreach($vars as $key => $val) $oModule->{$key} = $val;
// Run
// 실행
$oModule->procWAP($this); $oModule->procWAP($this);
// Output
// 출력
$this->display(); $this->display();
} }
/** /**
* @brief WAP 컨텐츠를 별도로 구할 없으면 최종 결과물을 출력 * @brief WAP content is available as a separate output if the final results
**/ **/
function displayContent() { function displayContent() {
Context::set('layout','none'); Context::set('layout','none');
// Compile a template
// 템플릿 컴파일
$oTemplate = new TemplateHandler(); $oTemplate = new TemplateHandler();
$oContext = &Context::getInstance(); $oContext = &Context::getInstance();
$content = $oTemplate->compile($this->oModule->getTemplatePath(), $this->oModule->getTemplateFile()); $content = $oTemplate->compile($this->oModule->getTemplatePath(), $this->oModule->getTemplateFile());
$this->setContent($content); $this->setContent($content);
// Output
// 출력
$this->display(); $this->display();
} }
} }

View file

@ -13,19 +13,19 @@
} }
/** /**
* @brief wml 헤더 출력 * @brief wml header output
**/ **/
function printHeader() { function printHeader() {
header("Content-Type: text/vnd.wap.wml"); header("Content-Type: text/vnd.wap.wml");
header("charset: ".$this->charset); header("charset: ".$this->charset);
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage); 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"); 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)); printf("<wml>\n<card title=\"%s%s\">\n<p>\n",htmlspecialchars($this->title),htmlspecialchars($titlePageStr));
} }
/** /**
* @brief 제목을 출력 * @brief Output title
**/ **/
function printTitle() { function printTitle() {
if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage); if($this->totalPage > $this->mobilePage) $titlePageStr = sprintf("(%d/%d)",$this->mobilePage, $this->totalPage);
@ -33,8 +33,8 @@
} }
/** /**
* @brief 내용을 출력 * @brief Output information
* hasChilds() 있으면 목록형을 그렇지 않으면 컨텐츠를 출력 * hasChilds() if there is a list of content types, otherwise output
**/ **/
function printContent() { function printContent() {
if($this->hasChilds()) { if($this->hasChilds()) {
@ -50,7 +50,7 @@
} }
/** /**
* @brief 버튼을 출력함 * @brief Button to output
**/ **/
function printBtn() { function printBtn() {
if($this->nextUrl) { if($this->nextUrl) {
@ -61,7 +61,7 @@
$url = $this->prevUrl; $url = $this->prevUrl;
printf('<do type="vnd.prev" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n"); printf('<do type="vnd.prev" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n");
} }
// 기타 해당사항 없는 버튼 출력 담당 (array로 전달) type?? // Others are not applicable in charge of the button output (array passed) type??
if($this->etcBtn) { if($this->etcBtn) {
if(is_array($this->etcBtn)) { if(is_array($this->etcBtn)) {
foreach($this->etcBtn as $key=>$val) { foreach($this->etcBtn as $key=>$val) {
@ -69,7 +69,7 @@
} }
} }
} }
// 언어선택 // Select Language
if(!parent::isLangChange()){ if(!parent::isLangChange()){
$url = getUrl('','lcm','1','sel_lang',Context::getLangType(),'return_uri',Context::get('current_url')); $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"); printf('<do type="vnd.lang" label="%s"><go href="%s"/></do>%s', 'Language : '.Context::getLang('select_lang'), $url, "\n");
@ -86,13 +86,11 @@
printf('<do type="vnd.up" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n"); printf('<do type="vnd.up" label="%s"><go href="%s"/></do>%s', $url->text, $url->url, "\n");
} }
} }
// Footer information output
// 푸터 정보를 출력
function printFooter() { function printFooter() {
print("</p>\n</card>\n</wml>"); print("</p>\n</card>\n</wml>");
} }
// And returns a list of serial numbers in
// 목록등에서 일련 번호를 리턴한다
function getNo() { function getNo() {
if(Context::get('mobile_skt')==1) { if(Context::get('mobile_skt')==1) {
return "vnd.skmn".parent::getNo(); return "vnd.skmn".parent::getNo();

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 <?php
if(!defined("__ZBXE__")) exit(); if(!defined('__XE__')) exit();
/** /**
* @file mobile.addon.php * @file mobile.addon.php
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief 모바일XE 애드온 * @brief Mobile XE add-on
* *
* 헤더정보를 가로채서 모바일에서의 접속일 경우 WAP 태그로 컨텐츠를 출력함 * If a mobile connection is made (see the header information), display contents with WAP tags
* *
* 동작 시점 * Time to call
* *
* before_module_proc > 모바일 처리를 위해 모듈의 일반 설정을 변경해야 경우 호출 * before_module_proc > call when changing general settings for mobile
* *
* after_module_proc > 모바일 컨텐츠 출력 * 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()) {
if(Context::get('module')=='admin') return; $oMobile->setLangType();
$oMobile->displayLangSelect();
// 동작 시점 관리 }
if($called_position != 'before_module_proc' && $called_position != 'after_module_proc' ) return; // On navigation mode, display navigation content
if($oMobile->isNavigationMode()) $oMobile->displayNavigationContent();
// 모바일 브라우저가 아니라면 무시 // If you have a WAP class content output via WAP class
require_once(_XE_PATH_.'addons/mobile/classes/mobile.class.php'); else $oMobile->displayModuleContent();
if(!mobileXE::getBrowserType()) return; // If neither navigation mode nor WAP class is, display the module's result
} else if($called_position == 'after_module_proc') {
// mobile instance 생성 // Display
$oMobile = &mobileXE::getInstance(); $oMobile->displayContent();
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();
}
?> ?>

View file

@ -1,29 +1,27 @@
<?php <?php
if(!defined("__ZBXE__")) exit(); if(!defined('__XE__')) exit();
/** /**
* @file openid_delegation_id.addon.php * @file openid_delegation_id.addon.php
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief OpenID Delegation ID 애드온 * @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;
// called_position이 before_module_init일때만 실행 $header_script = sprintf(
if($called_position != 'before_module_init') return; '<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
);
// openid_delegation_id 애드온 설정 정보를 가져옴 Context::addHtmlHeader($header_script);
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,19 +1,18 @@
<?php <?php
if(!defined("__ZBXE__")) exit(); if(!defined('__XE__')) exit();
/** /**
* @file point.addon.php * @file point.addon.php
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief 포인트 레벨 아이콘 표시 애드온 * @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;
// before_display_content 가 아니면 return require_once('./addons/point_level_icon/point_level_icon.lib.php');
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);
$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 <?php
/** /**
* @brief 포인트 아이콘 변경을 위한 함수. * @brief Function to change point icon.
**/ **/
function pointLevelIconTrans($matches) { function pointLevelIconTrans($matches) {
$member_srl = $matches[3]; $member_srl = $matches[3];
if($member_srl<1) return $matches[0]; 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 // Check Group Image Mark
$oMemberModel = &getModel('member'); $oMemberModel = &getModel('member');
if($oMemberModel->getGroupImageMark($member_srl)) return $orig_text.$matches[5].'</'.$matches[6].'>'; if($oMemberModel->getGroupImageMark($member_srl)) return $orig_text.$matches[5].'</'.$matches[6].'>';
if(!isset($GLOBALS['_pointLevelIcon'][$member_srl])) { if(!isset($GLOBALS['_pointLevelIcon'][$member_srl])) {
// 포인트 설정을 구해옴 // Get point configuration
if(!$GLOBALS['_pointConfig']) { if(!$GLOBALS['_pointConfig']) {
$oModuleModel = &getModel('module'); $oModuleModel = &getModel('module');
$GLOBALS['_pointConfig'] = $oModuleModel->getModuleConfig('point'); $GLOBALS['_pointConfig'] = $oModuleModel->getModuleConfig('point');
} }
$config = $GLOBALS['_pointConfig']; $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.'%';
}
}
// 포인트 모델을 구해 놓음 $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);
if(!$GLOBALS['_pointModel']) $GLOBALS['_pointModel'] = getModel('point'); $alt = sprintf('[%s:%s]', Context::getLang('level'), $level);
$oPointModel = &$GLOBALS['_pointModel'];
// 포인트를 구함 $GLOBALS['_pointLevelIcon'][$member_srl] = sprintf('<img src="%s" alt="%s" title="%s" style="vertical-align:middle; margin-right:3px;" />', $level_icon, $alt, $title);
$point = $oPointModel->getPoint($member_srl); }
$text = $GLOBALS['_pointLevelIcon'][$member_srl];
// 레벨을 구함 return $orig_text.$text.$matches[5].'</'.$matches[6].'>';
$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].'>';
}
?> ?>

View file

@ -22,7 +22,7 @@
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. 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>
<description xml:lang="en"> <description xml:lang="en">
This addon resizes images inserted in the article, and shows original image when you click on them. This addon resizes images inserted in the article. When clicked, the original images are shown.
</description> </description>
<description xml:lang="es"> <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. 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.

View file

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

View file

@ -1,9 +1,9 @@
/** /**
* @brief 화면내에서 상위 영역보다 이미지가 크면 리사이즈를 하고 클릭시 원본을 보여줄수 있도록 변경 * @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;} 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;} $(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)});} 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); $('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 <?php
if(!defined("__ZBXE__")) exit(); if(!defined('__XE__')) exit();
/** /**
* @file resize_image.addon.php * @file resize_image.addon.php
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief 본문내 이미지 조절 애드온 * @brief Add-on to resize images in the body
**/ **/
if($called_position == 'after_module_proc' && Context::getResponseMethod()=="HTML") { if($called_position == 'after_module_proc' && Context::getResponseMethod()=="HTML") {
if(Mobile::isFromMobilePhone()) { if(Mobile::isFromMobilePhone()) {
Context::addCssFile('./addons/resize_image/css/resize_image.mobile.css'); Context::loadFile('./addons/resize_image/css/resize_image.mobile.css', true);
} else { } else {
Context::loadJavascriptPlugin('ui'); Context::loadJavascriptPlugin('ui');
Context::addJsFile('./addons/resize_image/js/resize_image.min.js',false, '',null, 'body'); Context::loadFile(array('./addons/resize_image/js/resize_image.min.js', 'body', '', null), true);
} }
} }
?> ?>

View file

@ -1,72 +1,72 @@
<?php <?php
/** /**
* @class CacheApc * @class CacheApc
* @author NHN (developer@xpressengine.com) * @author NHN (developer@xpressengine.com)
* @brief APC Handler * @brief APC Handler
* @version 0.1 * @version 0.1
* **/
**/
class CacheApc extends CacheBase {
var $valid_time = 36000;
class CacheApc extends CacheBase { function getInstance($opt=null){
var $valid_time = 36000; if(!$GLOBALS['__CacheApc__']) {
$GLOBALS['__CacheApc__'] = new CacheApc();
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');
} }
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 <?php
/** /**
* @class CacheHandler * @class CacheHandler
* @author NHN (developer@xpressengine.com) * @author NHN (developer@xpressengine.com)
* @brief Cache Handler * @brief Cache Handler
* @version 0.1 * @version 0.1
* **/
**/
class CacheHandler extends Handler { class CacheHandler extends Handler {
var $handler = null;
var $keyGroupVersions = null;
var $handler = 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 &getInstance($target='object') { function CacheHandler($target, $info = null) {
return new CacheHandler($target); if(!$info) $info = Context::getDBInfo();
} if($info){
if($target == 'object'){
function CacheHandler($target, $info=null) { if($info->use_object_cache =='apc') $type = 'apc';
if(!$info) $info = Context::getDBInfo(); else if(substr($info->use_object_cache,0,8)=='memcache'){
if($info){ $type = 'memcache';
if($target == 'object'){ $url = $info->use_object_cache;
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;
}
} }
}else if($target == 'template'){
if($type){ if($info->use_template_cache =='apc') $type = 'apc';
$class = 'Cache' . ucfirst($type); else if(substr($info->use_template_cache,0,8)=='memcache'){
include_once sprintf('%sclasses/cache/%s.class.php', _XE_PATH_, $class); $type = 'memcache';
$this->handler = call_user_func(array($class,'getInstance'), $url); $url = $info->use_template_cache;
} }
} }
}
function isSupport(){ if($type){
if($this->handler && $this->handler->isSupport()) return true; $class = 'Cache' . ucfirst($type);
return false; 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);
function get($key, $modified_time = 0){ if(!$this->keyGroupVersions) {
if(!$this->handler) return false; $this->keyGroupVersions = array();
return $this->handler->get($key, $modified_time); $this->handler->put('key_group_versions', $this->keyGroupVersions, 0);
} }
}
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;
} }
} }
?>
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 <?php
/** /**
* @class CacheMemcache * @class CacheMemcache
* @author NHN (developer@xpressengine.com) * @author NHN (developer@xpressengine.com)
* @brief Memcache Handler * @brief Memcache Handler
* @version 0.1 * @version 0.1
* **/
**/
class CacheMemcache extends CacheBase { class CacheMemcache extends CacheBase {
var $valid_time = 36000;
var $Memcache;
var $valid_time = 36000; function getInstance($url){
var $Memcache; if(!$GLOBALS['__CacheMemcache__']) {
$GLOBALS['__CacheMemcache__'] = new CacheMemcache($url);
function getInstance($url){
if(!$GLOBALS['__CacheMemcache__']) {
$GLOBALS['__CacheMemcache__'] = new CacheMemcache($url);
}
return $GLOBALS['__CacheMemcache__'];
} }
return $GLOBALS['__CacheMemcache__'];
}
function CacheMemcache($url){ function CacheMemcache($url){
//$config['url'] = array('memcache://localhost:11211'); //$config['url'] = array('memcache://localhost:11211');
$config['url'] = is_array($url)?$url:array($url); $config['url'] = is_array($url)?$url:array($url);
$this->Memcache = new Memcache; $this->Memcache = new Memcache;
foreach($config['url'] as $url) { foreach($config['url'] as $url) {
$info = parse_url($url); $info = parse_url($url);
$this->Memcache->addServer($info['host'], $info['port']); $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;
} }
} }
?>
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 $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 $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 $oFrontEndFileHandler;
var $css_files_map = array(); ///< hash map of css files. The file name is used as a key
var $html_header = NULL; ///< script codes in <head>..</head> var $html_header = NULL; ///< script codes in <head>..</head>
var $body_class = array(); ///< classnames of <body> var $body_class = array(); ///< classnames of <body>
@ -57,6 +56,14 @@ class Context {
return $theInstance; return $theInstance;
} }
/**
* @brief cunstructor
**/
function Context()
{
$this->oFrontEndFileHandler = new FrontEndFileHandler();
}
/** /**
* @brief initialization, it sets DB information, request arguments and so on. * @brief initialization, it sets DB information, request arguments and so on.
* @return none * @return none
@ -120,19 +127,20 @@ class Context {
$this->loadLang(_XE_PATH_.'modules/module/lang'); $this->loadLang(_XE_PATH_.'modules/module/lang');
// set session handler // set session handler
if($this->db_info->use_db_session != 'N') { if(Context::isInstalled() && $this->db_info->use_db_session != 'N') {
$oSessionModel = &getModel('session'); $oSessionModel = &getModel('session');
$oSessionController = &getController('session'); $oSessionController = &getController('session');
session_set_save_handler( session_set_save_handler(
array(&$oSessionController,"open"), array(&$oSessionController, 'open'),
array(&$oSessionController,"close"), array(&$oSessionController, 'close'),
array(&$oSessionModel,"read"), array(&$oSessionModel, 'read'),
array(&$oSessionController,"write"), array(&$oSessionController, 'write'),
array(&$oSessionController,"destroy"), array(&$oSessionController, 'destroy'),
array(&$oSessionController,"gc") array(&$oSessionController, 'gc')
); );
} }
session_start(); session_start();
if($sess=$_POST[session_name()]) session_id($sess);
// set authentication information in Context and session // set authentication information in Context and session
if(Context::isInstalled()) { if(Context::isInstalled()) {
@ -166,7 +174,7 @@ class Context {
if($_SERVER['REQUEST_METHOD'] == 'GET') { if($_SERVER['REQUEST_METHOD'] == 'GET') {
if($this->get_vars) { if($this->get_vars) {
foreach($this->get_vars as $key=>$val) { foreach($this->get_vars as $key=>$val) {
if(!$val) continue; if(!strlen($val)) continue;
if(is_array($val)&&count($val)) { if(is_array($val)&&count($val)) {
foreach($val as $k => $v) { foreach($val as $k => $v) {
$url .= ($url?'&':'').$key.'['.$k.']='.urlencode($v); $url .= ($url?'&':'').$key.'['.$k.']='.urlencode($v);
@ -210,7 +218,28 @@ class Context {
$config_file = $self->getConfigFile(); $config_file = $self->getConfigFile();
if(is_readable($config_file)) @include($config_file); 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; $GLOBALS['_time_zone'] = $db_info->time_zone;
if($db_info->qmail_compatibility != 'Y') $db_info->qmail_compatibility = 'N'; if($db_info->qmail_compatibility != 'Y') $db_info->qmail_compatibility = 'N';
@ -231,7 +260,7 @@ class Context {
**/ **/
function getDBType() { function getDBType() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); 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; 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 * @brief return default URL
* @return default URL string * @return default URL string
@ -330,7 +369,7 @@ class Context {
$url_info = parse_url($url); $url_info = parse_url($url);
$url_info['query'].= ($url_info['query']?'&':'').'SSOID='.session_id(); $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']); $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; return false;
} }
// for sites requesting SSO validation // for sites requesting SSO validation
@ -341,13 +380,13 @@ class Context {
setcookie(session_name(), $session_name); setcookie(session_name(), $session_name);
$url = preg_replace('/([\?\&])$/','',str_replace('SSOID='.$session_name,'',Context::getRequestUrl())); $url = preg_replace('/([\?\&])$/','',str_replace('SSOID='.$session_name,'',Context::getRequestUrl()));
header("location:".$url); header('location:'.$url);
return false; return false;
// send SSO request // send SSO request
} else if($_COOKIE['sso']!=md5(Context::getRequestUri()) && !Context::get('SSOID')) { } else if($_COOKIE['sso']!=md5(Context::getRequestUri()) && !Context::get('SSOID')) {
setcookie('sso',md5(Context::getRequestUri()),0,'/'); setcookie('sso',md5(Context::getRequestUri()),0,'/');
$url = sprintf("%s?default_url=%s", $default_url, base64_encode(Context::getRequestUrl())); $url = sprintf("%s?default_url=%s", $default_url, base64_encode(Context::getRequestUrl()));
header("location:".$url); header('location:'.$url);
return false; return false;
} }
} }
@ -413,7 +452,7 @@ class Context {
$oModuleController = &getController('module'); $oModuleController = &getController('module');
$oModuleController->replaceDefinedLangCode($self->site_title); $oModuleController->replaceDefinedLangCode($self->site_title);
return $self->site_title; return htmlspecialchars($self->site_title);
} }
/** /**
* @deprecated * @deprecated
@ -432,20 +471,61 @@ class Context {
if(!is_object($lang)) $lang = new stdClass; if(!is_object($lang)) $lang = new stdClass;
if(!$self->lang_type) return; if(!$self->lang_type) return;
if(substr($path,-1)!='/') $path .= '/'; $filename = $self->_loadXmlLang($path);
$path_tpl = $path.'%s.lang.php'; if(!$filename) $filename = $self->_loadPhpLang($path);
$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;
if(!is_array($self->loaded_lang_files)) $self->loaded_lang_files = array(); if(!is_array($self->loaded_lang_files)) $self->loaded_lang_files = array();
if(in_array($filename, $self->loaded_lang_files)) return; 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) * @brief determine request method (GET/POST/XMLRPC/JSON)
* @param[in] $type request method * @param[in] $type request method (optional)
* @return none * @return none
**/ **/
function setRequestMethod($type) { function setRequestMethod($type='') {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
($type && $self->request_method=$type) or ($type && $self->request_method=$type) or
(strpos($_SERVER['CONTENT_TYPE'],'json') && $this->request_method='JSON') or (strpos($_SERVER['CONTENT_TYPE'],'json') && $self->request_method='JSON') or
($GLOBALS['HTTP_RAW_POST_DATA'] && $this->request_method='XMLRPC') or ($GLOBALS['HTTP_RAW_POST_DATA'] && $self->request_method='XMLRPC') or
($self->request_method = $_SERVER['REQUEST_METHOD']); ($self->request_method = $_SERVER['REQUEST_METHOD']);
} }
@ -584,7 +664,7 @@ class Context {
if(!count($_REQUEST)) return; if(!count($_REQUEST)) return;
foreach($_REQUEST as $key => $val) { foreach($_REQUEST as $key => $val) {
if($val === "" || Context::get($key)) continue; if($val === '' || Context::get($key)) continue;
$val = $this->_filterRequestVar($key, $val); $val = $this->_filterRequestVar($key, $val);
if($this->getRequestMethod()=='GET'&&isset($_GET[$key])) $set_to_vars = true; if($this->getRequestMethod()=='GET'&&isset($_GET[$key])) $set_to_vars = true;
@ -640,15 +720,15 @@ class Context {
* @return filtered value * @return filtered value
**/ **/
function _filterRequestVar($key, $val, $do_stripslashes = 1) { 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) ) { if(is_array($val) && count($val) ) {
foreach($val as $k => $v) { 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); $v = trim($v);
$val[$k] = $v; $val[$k] = $v;
} }
} else { } 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); $val = trim($val);
} }
return $val; return $val;
@ -669,7 +749,7 @@ class Context {
**/ **/
function _setUploadedArgument() { function _setUploadedArgument() {
if($this->getRequestMethod() != 'POST') return; 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; if(!$_FILES) return;
foreach($_FILES as $key => $val) { foreach($_FILES as $key => $val) {
@ -709,7 +789,7 @@ class Context {
* @brief make URL with args_list upon request URL * @brief make URL with args_list upon request URL
* @return result 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 $site_module_info = null;
static $current_info = null; static $current_info = null;
@ -788,7 +868,9 @@ class Context {
// if using rewrite mod // if using rewrite mod
if($self->allow_rewrite) { if($self->allow_rewrite) {
$var_keys = array_keys($get_vars); $var_keys = array_keys($get_vars);
$target = implode('.', $var_keys); sort($var_keys);
$target = implode('.', $var_keys);
$act = $get_vars['act']; $act = $get_vars['act'];
$vid = $get_vars['vid']; $vid = $get_vars['vid'];
@ -817,7 +899,7 @@ class Context {
'act.document_srl.key.vid'=>($act=='trackback')?"$vid/$srl/$key/$act":'' 'act.document_srl.key.vid'=>($act=='trackback')?"$vid/$srl/$key/$act":''
); );
$query = $target_map[$target]; $query = $target_map[$target];
} }
if(!$query) { if(!$query) {
@ -853,18 +935,37 @@ class Context {
else $query = getScriptPath().$query; 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) { function getRequestUri($ssl_mode = FOLLOW_REQUEST_SSL, $domain = null) {
static $url = array(); static $url = array();
// HTTP Request가 아니면 패스 // HTTP Request가 아니면 패스
if(!isset($_SERVER['SERVER_PROTOCOL'])) return ; 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); if($domain) $domain_key = md5($domain);
else $domain_key = 'default'; else $domain_key = 'default';
@ -903,7 +1004,7 @@ class Context {
elseif($url_info['port']==80) unset($url_info['port']); 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]; return $url[$ssl_mode][$domain_key];
} }
@ -919,17 +1020,19 @@ class Context {
} }
/** /**
* @brief key값에 해당하는 값을 return * @brief return key value
**/ **/
function get($key) { function get($key) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
if(!isset($self->context->{$key})) return null;
return $self->context->{$key}; return $self->context->{$key};
} }
/** /**
* @brief 받고자 하는 변수만 object에 입력하여 받음 * @brief get a specified var in object
* *
* key1, key2, key3 .. 등의 인자를 주어 여러개의 변수를 object vars로 세팅하여 받을 있음 * get one more vars in object vars with given arguments(key1, key2, key3,...)
**/ **/
function gets() { function gets() {
$num_args = func_num_args(); $num_args = func_num_args();
@ -944,7 +1047,7 @@ class Context {
} }
/** /**
* @brief 모든 데이터를 return * @brief Return all data
**/ **/
function getAll() { function getAll() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); 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() { function getRequestVars() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); 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이 있을 경우 등록 * @brief Register if actions is to be encrypted by SSL
* common/js/xml_handler.js에서 action들에 대해서 https로 전송되도록 * Those actions are sent to https in common/js/xml_handler.js
**/ **/
function addSSLAction($action) { function addSSLAction($action) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
@ -982,6 +1086,7 @@ class Context {
/** /**
* @brief normalize file path * @brief normalize file path
* @return normalized file path * @return normalized file path
* @deprecated
*/ */
function normalizeFilePath($file) { function normalizeFilePath($file) {
if(strpos($file,'://')===false && $file{0}!='/' && $file{0}!='.') $file = './'.$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') { function getAbsFileUrl($file) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); $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'); return $file;
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;
} }
/** /**
* @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 = '') { function unloadJsFile($file, $optimized = false, $targetie = '') {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$self->oFrontEndFileHandler->unloadFile($file, $targetie);
$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;
}
}
} }
/** /**
@ -1030,18 +1176,18 @@ class Context {
**/ **/
function unloadAllJsFiles() { function unloadAllJsFiles() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); 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) { function addJsFilter($path, $filename) {
$oXmlFilter = new XmlJSFilter($path, $filename); $oXmlFilter = new XmlJSFilter($path, $filename);
$oXmlFilter->compile(); $oXmlFilter->compile();
} }
/** /**
* @brief array_unique와 동작은 동일하나 file 첨자에 대해서만 동작함 * @brief Same as array_unique but works only for file subscript
* @deprecated * @deprecated
**/ **/
function _getUniqueFileList($files) { function _getUniqueFileList($files) {
@ -1063,49 +1209,25 @@ class Context {
**/ **/
function getJsFile($type='head') { function getJsFile($type='head') {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
return $self->oFrontEndFileHandler->getJsFileList($type);
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;
} }
/** /**
* @brief CSS file 추가 * @brief Add CSS file
* @deprecated
**/ **/
function addCSSFile($file, $optimized=false, $media='all', $targetie='',$index=0) { function addCSSFile($file, $optimized=false, $media='all', $targetie='',$index=0) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$self->oFrontEndFileHandler->loadFile(array($file, $media, $targetie, $index));
$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;
} }
/** /**
* @brief css file을 제거 * @brief Remove css file
* @deprecated
**/ **/
function unloadCSSFile($file, $optimized = false, $media = 'all', $targetie = '') { function unloadCSSFile($file, $optimized = false, $media = 'all', $targetie = '') {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
$self->oFrontEndFileHandler->unloadFile($file, $targetie, $media);
$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;
}
}
} }
/** /**
@ -1113,7 +1235,7 @@ class Context {
**/ **/
function unloadAllCSSFiles() { function unloadAllCSSFiles() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); 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() { function getCSSFile() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); is_a($this,'Context')?$self=&$this:$self=&Context::getInstance();
return $self->oFrontEndFileHandler->getCssFileList();
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;
} }
/** /**
@ -1145,7 +1258,7 @@ class Context {
if($loaded_plugins[$plugin_name]) return; if($loaded_plugins[$plugin_name]) return;
$loaded_plugins[$plugin_name] = true; $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'; $info_file = $plugin_path.'plugin.load';
if(!is_readable($info_file)) return; if(!is_readable($info_file)) return;
@ -1155,15 +1268,15 @@ class Context {
if(!$filename) continue; if(!$filename) continue;
if(substr($filename,0,2)=='./') $filename = substr($filename,2); if(substr($filename,0,2)=='./') $filename = substr($filename,2);
if(preg_match('/\.js$/i', $filename)) $self->addJsFile($plugin_path.$filename, false, '', 0, 'body'); if(preg_match('/\.js$/i', $filename)) $self->loadFile(array($plugin_path.$filename, 'body', '', 0), true);
elseif(preg_match('/\.css$/i', $filename)) $self->addCSSFile($plugin_path.$filename, false, 'all', '', 0); 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'); if(is_dir($plugin_path.'lang')) $self->loadLang($plugin_path.'lang');
} }
/** /**
* @brief HtmlHeader 추가 * @brief Add HtmlHeader
**/ **/
function addHtmlHeader($header) { function addHtmlHeader($header) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); 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) { function addBodyClass($class_name) {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); 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() { function getBodyClass() {
is_a($this,'Context')?$self=&$this:$self=&Context::getInstance(); 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 * @brief returns the path of the config file that contains database settings
**/ **/
function getConfigFile() { 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 * @brief returns the path of the config file that contains FTP settings
**/ **/
function getFTPConfigFile() { 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) { function transContent($content) {
return $content; return $content;
@ -1300,5 +1413,36 @@ class Context {
if(substr($path,-1)!='/') $path .= '/'; if(substr($path,-1)!='/') $path .= '/';
return $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;
}
} }
?> ?>

View file

@ -13,6 +13,38 @@
* queryid = module_name.query_name * queryid = module_name.query_name
**/ **/
if(!defined('__XE_LOADED_DB_CLASS__')){
define('__XE_LOADED_DB_CLASS__', 1);
require(_XE_PATH_.'classes/xml/xmlquery/DBParser.class.php');
require(_XE_PATH_.'classes/xml/xmlquery/QueryParser.class.php');
require(_XE_PATH_.'classes/xml/xmlquery/argument/Argument.class.php');
require(_XE_PATH_.'classes/xml/xmlquery/argument/SortArgument.class.php');
require(_XE_PATH_.'classes/xml/xmlquery/argument/ConditionArgument.class.php');
require(_XE_PATH_.'classes/db/queryparts/expression/Expression.class.php');
require(_XE_PATH_.'classes/db/queryparts/expression/SelectExpression.class.php');
require(_XE_PATH_.'classes/db/queryparts/expression/InsertExpression.class.php');
require(_XE_PATH_.'classes/db/queryparts/expression/UpdateExpression.class.php');
require(_XE_PATH_.'classes/db/queryparts/expression/UpdateExpressionWithoutArgument.class.php');
require(_XE_PATH_.'classes/db/queryparts/table/Table.class.php');
require(_XE_PATH_.'classes/db/queryparts/table/JoinTable.class.php');
require(_XE_PATH_.'classes/db/queryparts/table/CubridTableWithHint.class.php');
require(_XE_PATH_.'classes/db/queryparts/table/MysqlTableWithHint.class.php');
require(_XE_PATH_.'classes/db/queryparts/table/MssqlTableWithHint.class.php');
require(_XE_PATH_.'classes/db/queryparts/table/IndexHint.class.php');
require(_XE_PATH_.'classes/db/queryparts/condition/ConditionGroup.class.php');
require(_XE_PATH_.'classes/db/queryparts/condition/Condition.class.php');
require(_XE_PATH_.'classes/db/queryparts/condition/ConditionWithArgument.class.php');
require(_XE_PATH_.'classes/db/queryparts/condition/ConditionWithoutArgument.class.php');
require(_XE_PATH_.'classes/db/queryparts/condition/ConditionSubquery.class.php');
require(_XE_PATH_.'classes/db/queryparts/expression/StarExpression.class.php');
require(_XE_PATH_.'classes/db/queryparts/order/OrderByColumn.class.php');
require(_XE_PATH_.'classes/db/queryparts/limit/Limit.class.php');
require(_XE_PATH_.'classes/db/queryparts/Query.class.php');
require(_XE_PATH_.'classes/db/queryparts/Subquery.class.php');
}
class DB { class DB {
var $count_cache_path = 'files/cache/db'; var $count_cache_path = 'files/cache/db';
@ -28,14 +60,17 @@
'null' => 'is null', 'null' => 'is null',
); );
var $fd = NULL; ///< connector resource or file description var $master_db = NULL; // master database connection string
var $slave_db = NULL; // array of slave databases connection strings
var $result = NULL; ///< result var $result = NULL; ///< result
var $errno = 0; ///< error code (0 means no error) var $errno = 0; ///< error code (0 means no error)
var $errstr = ''; ///< error message var $errstr = ''; ///< error message
var $query = ''; ///< query string of latest executed query var $query = ''; ///< query string of latest executed query
var $connection = '';
var $elapsed_time = 0; ///< elapsed time of latest executed query var $elapsed_time = 0; ///< elapsed time of latest executed query
var $elapsed_dbclass_time = 0; ///< elapsed time of latest executed query
var $transaction_started = false; ///< transaction flag var $transaction_started = false; ///< transaction flag
@ -45,6 +80,8 @@
var $cache_file = 'files/cache/queries/'; ///< location of query cache var $cache_file = 'files/cache/queries/'; ///< location of query cache
var $db_type; ///< stores database type: 'mysql','cubrid','mssql' etc. or 'db' when database is not yet set
/** /**
* @brief returns instance of certain db type * @brief returns instance of certain db type
* @param[in] $db_type type of db * @param[in] $db_type type of db
@ -54,7 +91,8 @@
if(!$db_type) $db_type = Context::getDBType(); if(!$db_type) $db_type = Context::getDBType();
if(!$db_type && Context::isInstalled()) return new Object(-1, 'msg_db_not_setted'); if(!$db_type && Context::isInstalled()) return new Object(-1, 'msg_db_not_setted');
if(!$GLOBALS['__DB__']) { if(!isset($GLOBALS['__DB__'])) $GLOBALS['__DB__'] = array();
if(!isset($GLOBALS['__DB__'][$db_type])) {
$class_name = 'DB'.ucfirst($db_type); $class_name = 'DB'.ucfirst($db_type);
$class_file = _XE_PATH_."classes/db/$class_name.class.php"; $class_file = _XE_PATH_."classes/db/$class_name.class.php";
if(!file_exists($class_file)) return new Object(-1, 'msg_db_not_setted'); if(!file_exists($class_file)) return new Object(-1, 'msg_db_not_setted');
@ -62,6 +100,7 @@
// get a singletone instance of the database driver class // get a singletone instance of the database driver class
require_once($class_file); require_once($class_file);
$GLOBALS['__DB__'][$db_type] = call_user_func(array($class_name, 'create')); $GLOBALS['__DB__'][$db_type] = call_user_func(array($class_name, 'create'));
$GLOBALS['__DB__'][$db_type]->db_type = $db_type;
} }
return $GLOBALS['__DB__'][$db_type]; return $GLOBALS['__DB__'][$db_type];
@ -89,6 +128,48 @@
return $oDB->_getSupportedList(); return $oDB->_getSupportedList();
} }
/**
* @brief returns list of enable in supported db
* @return list of enable in supported db
**/
function getEnableList()
{
if(!$this->supported_list)
{
$oDB = new DB();
$this->supported_list = $oDB->_getSupportedList();
}
$enableList = array();
if(is_array($this->supported_list))
{
foreach($this->supported_list AS $key=>$value)
if($value->enable) array_push($enableList, $value);
}
return $enableList;
}
/**
* @brief returns list of disable in supported db
* @return list of disable in supported db
**/
function getDisableList()
{
if(!$this->supported_list)
{
$oDB = new DB();
$this->supported_list = $oDB->_getSupportedList();
}
$disableList = array();
if(is_array($this->supported_list))
{
foreach($this->supported_list AS $key=>$value)
if(!$value->enable) array_push($disableList, $value);
}
return $disableList;
}
/** /**
* @brief returns list of supported db * @brief returns list of supported db
* @return list of supported db * @return list of supported db
@ -140,8 +221,9 @@
* @brief check if is connected * @brief check if is connected
* @return true: connected, false: not connected * @return true: connected, false: not connected
**/ **/
function isConnected() { function isConnected($type = 'master', $indx = 0) {
return $this->is_connected ? true : false; if($type == 'master') return $this->master_db["is_connected"] ? true : false;
else return $this->slave_db[$indx]["is_connected"] ? true : false;
} }
/** /**
@ -168,6 +250,7 @@
$log['query'] = $this->query; $log['query'] = $this->query;
$log['elapsed_time'] = $elapsed_time; $log['elapsed_time'] = $elapsed_time;
$log['connection'] = $this->connection;
// leave error log if an error occured (if __DEBUG_DB_OUTPUT__ is defined) // leave error log if an error occured (if __DEBUG_DB_OUTPUT__ is defined)
if($this->isError()) { if($this->isError()) {
@ -241,7 +324,7 @@
} }
/** /**
* @brief query xml 파일을 실행하여 결과를 return * @brief Run the result of the query xml file
* @param[in] $query_id query id (module.queryname * @param[in] $query_id query id (module.queryname
* @param[in] $args arguments for query * @param[in] $args arguments for query
* @return result of query * @return result of query
@ -249,7 +332,11 @@
**/ **/
function executeQuery($query_id, $args = NULL, $arg_columns = NULL) { function executeQuery($query_id, $args = NULL, $arg_columns = NULL) {
if(!$query_id) return new Object(-1, 'msg_invalid_queryid'); if(!$query_id) return new Object(-1, 'msg_invalid_queryid');
$this->query_id = $query_id; if(!$this->db_type) return;
$this->actDBClassStart();
$this->query_id = $query_id;
$id_args = explode('.', $query_id); $id_args = explode('.', $query_id);
if(count($id_args) == 2) { if(count($id_args) == 2) {
@ -258,20 +345,31 @@
$id = $id_args[1]; $id = $id_args[1];
} elseif(count($id_args) == 3) { } elseif(count($id_args) == 3) {
$target = $id_args[0]; $target = $id_args[0];
if(!in_array($target, array('addons','widgets'))) return; if(!in_array($target, array('addons','widgets'))){
$this->actDBClassFinish();
return;
}
$module = $id_args[1]; $module = $id_args[1];
$id = $id_args[2]; $id = $id_args[2];
} }
if(!$target || !$module || !$id) return new Object(-1, 'msg_invalid_queryid'); if(!$target || !$module || !$id){
$this->actDBClassFinish();
return new Object(-1, 'msg_invalid_queryid');
}
$xml_file = sprintf('%s%s/%s/queries/%s.xml', _XE_PATH_, $target, $module, $id); $xml_file = sprintf('%s%s/%s/queries/%s.xml', _XE_PATH_, $target, $module, $id);
if(!file_exists($xml_file)) return new Object(-1, 'msg_invalid_queryid'); if(!file_exists($xml_file)){
$this->actDBClassFinish();
return new Object(-1, 'msg_invalid_queryid');
}
// look for cache file // look for cache file
$cache_file = $this->checkQueryCacheFile($query_id, $xml_file); $cache_file = $this->checkQueryCacheFile($query_id, $xml_file);
$result = $this->_executeQuery($cache_file, $args, $query_id, $arg_columns);
$this->actDBClassFinish();
// execute query // execute query
return $this->_executeQuery($cache_file, $args, $query_id, $arg_columns); return $result;
} }
@ -284,14 +382,14 @@
function checkQueryCacheFile($query_id,$xml_file){ function checkQueryCacheFile($query_id,$xml_file){
// first try finding cache file // first try finding cache file
$cache_file = sprintf('%s%s%s.cache.php', _XE_PATH_, $this->cache_file, $query_id); $cache_file = sprintf('%s%s%s.%s.%s.cache.php', _XE_PATH_, $this->cache_file, $query_id, __ZBXE_VERSION__, $this->db_type);
if(file_exists($cache_file)) $cache_time = filemtime($cache_file); if(file_exists($cache_file)) $cache_time = filemtime($cache_file);
else $cache_time = -1; else $cache_time = -1;
// if there is no cache file or is not new, find original xml query file and parse it // if there is no cache file or is not new, find original xml query file and parse it
if($cache_time < filemtime($xml_file) || $cache_time < filemtime(_XE_PATH_.'classes/db/DB.class.php') || $cache_time < filemtime(_XE_PATH_.'classes/xml/XmlQueryParser.class.php')) { if($cache_time < filemtime($xml_file) || $cache_time < filemtime(_XE_PATH_.'classes/db/DB.class.php') || $cache_time < filemtime(_XE_PATH_.'classes/xml/XmlQueryParser.150.class.php')) {
require_once(_XE_PATH_.'classes/xml/XmlQueryParser.class.php'); require_once(_XE_PATH_.'classes/xml/XmlQueryParser.150.class.php');
$oParser = new XmlQueryParser(); $oParser = new XmlQueryParser();
$oParser->parse($query_id, $xml_file, $cache_file); $oParser->parse($query_id, $xml_file, $cache_file);
} }
@ -314,13 +412,12 @@
if($source_args) $args = @clone($source_args); if($source_args) $args = @clone($source_args);
$output = @include($cache_file); $output = include($cache_file);
if( (is_a($output, 'Object') || is_subclass_of($output, 'Object')) && !$output->toBool()) return $output; if( (is_a($output, 'Object') || is_subclass_of($output, 'Object')) && !$output->toBool()) return $output;
$output->_tables = ($output->_tables && is_array($output->_tables)) ? $output->_tables : array();
// execute appropriate query // execute appropriate query
switch($output->action) { switch($output->getAction()) {
case 'insert' : case 'insert' :
$this->resetCountCache($output->tables); $this->resetCountCache($output->tables);
$output = $this->_executeInsertAct($output); $output = $this->_executeInsertAct($output);
@ -334,8 +431,10 @@
$output = $this->_executeDeleteAct($output); $output = $this->_executeDeleteAct($output);
break; break;
case 'select' : case 'select' :
$output->arg_columns = is_array($arg_columns)?$arg_columns:array(); $arg_columns = is_array($arg_columns)?$arg_columns:array();
$output = $this->_executeSelectAct($output); $output->setColumnList($arg_columns);
$connection = $this->_getConnection('slave');
$output = $this->_executeSelectAct($output, $connection);
break; break;
} }
@ -347,233 +446,6 @@
return $output; return $output;
} }
/**
* @brief check $val with $filter_type
* @param[in] $key key value
* @param[in] $val value of $key
* @param[in] $filter_type type of filter to check $val
* @return object
* @remarks this function is to be used from XmlQueryParser
**/
function checkFilter($key, $val, $filter_type) {
global $lang;
switch($filter_type) {
case 'email' :
case 'email_address' :
if(!preg_match('/^[_0-9a-z-]+(\.[_0-9a-z-]+)*@[0-9a-z-]+(\.[0-9a-z-]+)*$/is', $val)) return new Object(-1, sprintf($lang->filter->invalid_email, $lang->{$key} ? $lang->{$key} : $key));
break;
case 'homepage' :
if(!preg_match('/^(http|https)+(:\/\/)+[0-9a-z_-]+\.[^ ]+$/is', $val)) return new Object(-1, sprintf($lang->filter->invalid_homepage, $lang->{$key} ? $lang->{$key} : $key));
break;
case 'userid' :
case 'user_id' :
if(!preg_match('/^[a-zA-Z]+([_0-9a-zA-Z]+)*$/is', $val)) return new Object(-1, sprintf($lang->filter->invalid_userid, $lang->{$key} ? $lang->{$key} : $key));
break;
case 'number' :
case 'numbers' :
if(is_array($val)) $val = join(',', $val);
if(!preg_match('/^(-?)[0-9]+(,\-?[0-9]+)*$/is', $val)) return new Object(-1, sprintf($lang->filter->invalid_number, $lang->{$key} ? $lang->{$key} : $key));
break;
case 'alpha' :
if(!preg_match('/^[a-z]+$/is', $val)) return new Object(-1, sprintf($lang->filter->invalid_alpha, $lang->{$key} ? $lang->{$key} : $key));
break;
case 'alpha_number' :
if(!preg_match('/^[0-9a-z]+$/is', $val)) return new Object(-1, sprintf($lang->filter->invalid_alpha_number, $lang->{$key} ? $lang->{$key} : $key));
break;
}
return new Object();
}
/**
* @brief returns type of column
* @param[in] $column_type_list list of column type
* @param[in] $name name of column type
* @return column type of $name
* @remarks columns are usually like a.b, so it needs another function
**/
function getColumnType($column_type_list, $name) {
if(strpos($name, '.') === false) return $column_type_list[$name];
list($prefix, $name) = explode('.', $name);
return $column_type_list[$name];
}
/**
* @brief returns the value of condition
* @param[in] $name name of condition
* @param[in] $value value of condition
* @param[in] $operation operation this is used in condition
* @param[in] $type type of condition
* @param[in] $column_type type of column
* @return well modified $value
* @remarks if $operation is like or like_prefix, $value itself will be modified
* @remarks if $type is not 'number', call addQuotes() and wrap with ' '
**/
function getConditionValue($name, $value, $operation, $type, $column_type) {
if(!in_array($operation,array('in','notin','between')) && $type == 'number') {
if(is_array($value)){
$value = join(',',$value);
}
if(strpos($value, ',') === false && strpos($value, '(') === false) return (int)$value;
return $value;
}
if(!is_array($value) && strpos($name, '.') !== false && strpos($value, '.') !== false) {
list($table_name, $column_name) = explode('.', $value);
if($column_type[$column_name]) return $value;
}
switch($operation) {
case 'like_prefix' :
if(!is_array($value)) $value = preg_replace('/(^\'|\'$){1}/', '', $value);
$value = $value.'%';
break;
case 'like_tail' :
if(!is_array($value)) $value = preg_replace('/(^\'|\'$){1}/', '', $value);
$value = '%'.$value;
break;
case 'like' :
if(!is_array($value)) $value = preg_replace('/(^\'|\'$){1}/', '', $value);
$value = '%'.$value.'%';
break;
case 'notin' :
if(is_array($value))
{
$value = $this->addQuotesArray($value);
if($type=='number') return join(',',$value);
else return "'". join("','",$value)."'";
}
else
{
return $value;
}
break;
case 'in' :
if(is_array($value))
{
$value = $this->addQuotesArray($value);
if($type=='number') return join(',',$value);
else return "'". join("','",$value)."'";
}
else
{
return $value;
}
break;
case 'between' :
if(!is_array($value)) $value = array($value);
$value = $this->addQuotesArray($value);
if($type!='number')
{
foreach($value as $k=>$v)
{
$value[$k] = "'".$v."'";
}
}
return $value;
break;
default:
if(!is_array($value)) $value = preg_replace('/(^\'|\'$){1}/', '', $value);
}
return "'".$this->addQuotes($value)."'";
}
/**
* @brief returns part of condition
* @param[in] $name name of condition
* @param[in] $value value of condition
* @param[in] $operation operation that is used in condition
* @return detail condition
**/
function getConditionPart($name, $value, $operation) {
switch($operation) {
case 'equal' :
case 'more' :
case 'excess' :
case 'less' :
case 'below' :
case 'like_tail' :
case 'like_prefix' :
case 'like' :
case 'in' :
case 'notin' :
case 'notequal' :
// if variable is not set or is not string or number, return
if(!isset($value)) return;
if($value === '') return;
if(!in_array(gettype($value), array('string', 'integer'))) return;
break;
case 'between' :
if(!is_array($value)) return;
if(count($value)!=2) return;
}
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 '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 'between' :
return $name.' between ' . $value[0] . ' and ' . $value[1];
break;
}
}
/**
* @brief returns condition key
* @param[in] $output result of query
* @return array of conditions of $output
**/
function getConditionList($output) {
$conditions = array();
if(count($output->conditions)) {
foreach($output->conditions as $key => $val) {
if($val['condition']) {
foreach($val['condition'] as $k => $v) {
$conditions[] = $v['column'];
}
}
}
}
return $conditions;
}
/** /**
* @brief returns counter cache data * @brief returns counter cache data
@ -678,31 +550,297 @@
$this->_query($query); $this->_query($query);
} }
function addQuotesArray($arr) function getSelectSql($query, $with_values = true){
{ $select = $query->getSelectString($with_values);
if(is_array($arr)) if($select == '') return new Object(-1, "Invalid query");
{ $select = 'SELECT ' .$select;
foreach($arr as $k => $v)
{
$arr[$k] = $this->addQuotes($v);
}
}
else
{
$arr = $this->addQuotes($arr);
}
return $arr; $from = $query->getFromString($with_values);
if($from == '') return new Object(-1, "Invalid query");
$from = ' FROM '.$from;
$where = $query->getWhereString($with_values);
if($where != '') $where = ' WHERE ' . $where;
$tableObjects = $query->getTables();
$index_hint_list = '';
foreach($tableObjects as $tableObject){
if(is_a($tableObject, 'CubridTableWithHint'))
$index_hint_list .= $tableObject->getIndexHintString() . ', ';
}
$index_hint_list = substr($index_hint_list, 0, -2);
if($index_hint_list != '')
$index_hint_list = 'USING INDEX ' . $index_hint_list;
$groupBy = $query->getGroupByString();
if($groupBy != '') $groupBy = ' GROUP BY ' . $groupBy;
$orderBy = $query->getOrderByString();
if($orderBy != '') $orderBy = ' ORDER BY ' . $orderBy;
$limit = $query->getLimitString();
if($limit != '') $limit = ' LIMIT ' . $limit;
return $select . ' ' . $from . ' ' . $where . ' ' . $index_hint_list . ' ' . $groupBy . ' ' . $orderBy . ' ' . $limit;
} }
function getDeleteSql($query, $with_values = true, $with_priority = false){
$sql = 'DELETE ';
$sql .= $with_priority?$query->getPriority():'';
$tables = $query->getTables();
$sql .= $tables[0]->getAlias();
$from = $query->getFromString($with_values);
if($from == '') return new Object(-1, "Invalid query");
$sql .= ' FROM '.$from;
$where = $query->getWhereString($with_values);
if($where != '') $sql .= ' WHERE ' . $where;
return $sql;
}
function getUpdateSql($query, $with_values = true, $with_priority = false){
$columnsList = $query->getUpdateString($with_values);
if($columnsList == '') return new Object(-1, "Invalid query");
$tables = $query->getFromString($with_values);
if($tables == '') return new Object(-1, "Invalid query");
$where = $query->getWhereString($with_values);
if($where != '') $where = ' WHERE ' . $where;
$priority = $with_priority?$query->getPriority():'';
return "UPDATE $priority $tables SET $columnsList ".$where;
}
function getInsertSql($query, $with_values = true, $with_priority = false){
$tableName = $query->getFirstTableName();
$values = $query->getInsertString($with_values);
$priority = $with_priority?$query->getPriority():'';
return "INSERT $priority INTO $tableName \n $values";
}
function _getSlaveConnectionStringIndex() {
$max = count($this->slave_db);
$indx = rand(0, $max - 1);
return $indx;
}
function _getConnection($type = 'master', $indx = NULL){
if($type == master){
if(!$this->master_db['is_connected'])
$this->_connect($type);
$this->connection = 'Master ' . $this->master_db['db_hostname'];
return $this->master_db["resource"];
}
if($indx === NULL)
$indx = $this->_getSlaveConnectionStringIndex($type);
if(!$this->slave_db[$indx]['is_connected'])
$this->_connect($type, $indx);
$this->connection = 'Slave ' . $this->slave_db[$indx]['db_hostname'];
return $this->slave_db[$indx]["resource"];
}
function _dbInfoExists() {
if (!$this->master_db)
return false;
if (count($this->slave_db) === 0)
return false;
return true;
}
function _close($connection){
}
/** /**
* @brief Just like numbers, and operations needed to remove the rest * @brief DB disconnection
* */
function close($type = 'master', $indx = 0) {
if (!$this->isConnected($type, $indx))
return;
if ($type == 'master')
$connection = &$this->master_db;
else
$connection = &$this->slave_db[$indx];
$this->_close($connection["resource"]);
$connection["is_connected"] = false;
}
function _begin(){
return true;
}
/**
* @brief Begin transaction
* */
function begin() {
if (!$this->isConnected() || $this->transaction_started)
return;
if($this->_begin())
$this->transaction_started = true;
}
function _rollback(){
return true;
}
/**
* @brief Rollback
* */
function rollback() {
if (!$this->isConnected() || !$this->transaction_started)
return;
if($this->_rollback())
$this->transaction_started = false;
}
function _commit(){
return true;
}
/**
* @brief Commits
* */
function commit($force = false) {
if (!$force && (!$this->isConnected() || !$this->transaction_started))
return;
if($this->_commit())
$this->transaction_started = false;
}
function __query($query, $connection){
}
/**
* @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 = null) {
if($connection == null)
$connection = $this->_getConnection('master');
// Notify to start a query execution
$this->actStart($query);
// Run the query statement
$result = $this->__query($query, $connection);
// Notify to complete a query execution
$this->actFinish();
// Return result
return $result;
}
/**
* @brief DB settings and connect/close
* */
function _setDBInfo(){
$db_info = Context::getDBInfo();
$this->master_db = $db_info->master_db;
if($db_info->master_db["db_hostname"] == $db_info->slave_db[0]["db_hostname"]
&& $db_info->master_db["db_port"] == $db_info->slave_db[0]["db_port"]
&& $db_info->master_db["db_userid"] == $db_info->slave_db[0]["db_userid"]
&& $db_info->master_db["db_password"] == $db_info->slave_db[0]["db_password"]
&& $db_info->master_db["db_database"] == $db_info->slave_db[0]["db_database"]
)
$this->slave_db[0] = &$this->master_db;
else
$this->slave_db = $db_info->slave_db;
$this->prefix = $db_info->master_db["db_table_prefix"];
}
function __connect(){
}
function _afterConnect($connection){
}
/**
* @brief DB Connection
* */
function _connect($type = 'master', $indx = 0) {
if ($this->isConnected($type, $indx))
return;
// Ignore if no DB information exists
if (!$this->_dbInfoExists())
return;
if ($type == 'master')
$connection = &$this->master_db;
else
$connection = &$this->slave_db[$indx];
$result = $this->__connect($connection);
if($result === NULL || $result === false) {
$connection["is_connected"] = false;
return;
}
// Check connections
$connection["resource"] = $result;
$connection["is_connected"] = true;
// Save connection info for db logs
$this->connection = ucfirst($type) . ' ' . $connection["db_hostname"];
$this->_afterConnect($result);
}
/**
* @brief start recording DBClass log
* @return none
**/ **/
function _filterNumber(&$value) function actDBClassStart() {
{ $this->setError(0, 'success');
$value = preg_replace('/[^\d\w\+\-\*\/\.\(\)]/', '', $value); $this->act_dbclass_start = getMicroTime();
$value = preg_replace('@\b(?:select|update|delete)\b|[/+\*]{2,}|(-){2,}@i', '$1', $value); $this->elapsed_dbclass_time = 0;
if(!$value) $value = 0; }
}
/**
* @brief finish recording DBClass log
* @return none
**/
function actDBClassFinish() {
if(!$this->query) return;
$this->act_dbclass_finish = getMicroTime();
$elapsed_dbclass_time = $this->act_dbclass_finish - $this->act_dbclass_start;
$this->elapsed_dbclass_time = $elapsed_dbclass_time;
$GLOBALS['__dbclass_elapsed_time__'] += $elapsed_dbclass_time;
}
/**
* Returns a database specific parser class
* used for escaping expressions and table/column identifiers
*
* Requires an implementation of the DB class (won't work if database is not set)
*
* @remarks singleton
*/
function &getParser($force = false){
static $dbParser = null;
if(!$dbParser || $force) {
$oDB = &DB::getInstance();
$dbParser = $oDB->getParser();
}
return $dbParser;
}
} }
?> ?>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -3,26 +3,24 @@
/** /**
* @class DBMSSQL * @class DBMSSQL
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief MSSQL driver로 수정 sol (sol@ngleader.com) * @brief Modified to use MSSQL driver by sol (sol@ngleader.com)
* @version 0.1 * @version 0.1
**/ **/
class DBMssql extends DB { class DBMssql extends DB {
/** /**
* DB를 이용하기 위한 정보 * information to connect to DB
**/ **/
var $conn = NULL; var $prefix = 'xe'; // / <prefix of XE tables(One more XE can be installed on a single DB)
var $database = NULL; ///< database var $param = array();
var $prefix = 'xe'; ///< XE에서 사용할 테이블들의 prefix (한 DB에서 여러개의 XE 설치 가능) var $comment_syntax = '/* %s */';
var $param = array();
var $comment_syntax = '/* %s */';
/** /**
* @brief mssql 에서 사용될 column type * @brief column type used in mssql
* *
* column_typeschema/query xml에서 공통 선언된 type을 이용하기 때문에 * column_type should be replaced for each DBMS's type
* DBMS에 맞게 replace 해주어야 한다 * becasue it uses commonly defined type in the schema/query xml
**/ **/
var $column_type = array( var $column_type = array(
'bignumber' => 'bigint', 'bignumber' => 'bigint',
@ -52,7 +50,7 @@
} }
/** /**
* @brief 설치 가능 여부를 return * @brief Return if installable
**/ **/
function isSupported() { function isSupported() {
if (!extension_loaded("sqlsrv")) return false; if (!extension_loaded("sqlsrv")) return false;
@ -60,58 +58,35 @@
} }
/** /**
* @brief DB정보 설정 connect/ close * @brief DB Connection
**/ **/
function _setDBInfo() { function __connect($connection) {
$db_info = Context::getDBInfo(); //sqlsrv_configure( 'WarningsReturnAsErrors', 0 );
$this->hostname = $db_info->db_hostname; //sqlsrv_configure( 'LogSeverity', SQLSRV_LOG_SEVERITY_ALL );
$this->port = $db_info->db_port; //sqlsrv_configure( 'LogSubsystems', SQLSRV_LOG_SYSTEM_ALL );
$this->userid = $db_info->db_userid; $result = @sqlsrv_connect($connection["db_hostname"], array('Database' => $connection["db_database"], 'UID' => $connection["db_userid"], 'PWD' => $connection["db_password"]));
$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 .= '_'; if(!$result)
{
$errors = print_r(sqlsrv_errors(), true);
$this->setError (-1, 'database connect fail' . PHP_EOL . $errors);
return;
}
return $result;
} }
/** /**
* @brief DB 접속 * @brief DB disconnect
**/ **/
function _connect() { function _close($connection) {
// db 정보가 없으면 무시
if(!$this->hostname || !$this->database) return;
//sqlsrv_configure( 'WarningsReturnAsErrors', 0 );
//sqlsrv_configure( 'LogSeverity', SQLSRV_LOG_SEVERITY_ALL );
//sqlsrv_configure( 'LogSubsystems', SQLSRV_LOG_SYSTEM_ALL );
$this->conn = sqlsrv_connect( $this->hostname,
array( 'Database' => $this->database,'UID'=>$this->userid,'PWD'=>$this->password ));
// 접속체크
if($this->conn){
$this->is_connected = true;
$this->password = md5($this->password);
}else{
$this->is_connected = false;
}
}
/**
* @brief DB접속 해제
**/
function close() {
if($this->is_connected == false) return;
$this->commit(); $this->commit();
sqlsrv_close($this->conn); sqlsrv_close($connection);
$this->conn = null;
} }
/** /**
* @brief 쿼리에서 입력되는 문자열 변수들의 quotation 조절 * @brief handles quatation of the string variables from the query
**/ **/
// TODO See what to do about this
function addQuotes($string) { function addQuotes($string) {
if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string)); if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string));
//if(!is_numeric($string)) $string = str_replace("'","''",$string); //if(!is_numeric($string)) $string = str_replace("'","''",$string);
@ -120,84 +95,81 @@
} }
/** /**
* @brief 트랜잭션 시작 * @brief Begin transaction
**/ **/
function begin() { function _begin() {
if($this->is_connected == false || $this->transaction_started) return; $connection = $this->_getConnection('master');
if(sqlsrv_begin_transaction( $this->conn ) === false) return; if(sqlsrv_begin_transaction($connection) === false) return;
return true;
$this->transaction_started = true;
} }
/** /**
* @brief 롤백 * @brief Rollback
**/ **/
function rollback() { function _rollback() {
if($this->is_connected == false || !$this->transaction_started) return; $connection = $this->_getConnection('master');
sqlsrv_rollback($connection);
$this->transaction_started = false; return true;
sqlsrv_rollback( $this->conn );
} }
/** /**
* @brief 커밋 * @brief Commit
**/ **/
function commit($force = false) { function _commit() {
if(!$force && ($this->is_connected == false || !$this->transaction_started)) return; $connection = $this->_getConnection('master');
sqlsrv_commit($connection);
$this->transaction_started = false; return true;
sqlsrv_commit( $this->conn );
} }
/** /**
* @brief : 쿼리문의 실행 결과의 fetch 처리 * @brief : executing the query and fetching the result
* *
* query : query문 실행하고 result return\n * query: run a query and return the result\n
* fetch : reutrn 값이 없으면 NULL\n * fetch: NULL if no value returned \n
* rows이면 array object\n * array object if rows returned \n
* row이면 object\n * object if a row returned \n
* return\n * return\n
**/ **/
function _query($query) { function __query($query, $connection) {
if($this->is_connected == false || !$query) return; $_param = array();
$_param = array(); if(count($this->param)){
foreach($this->param as $k => $o){
if($o->getType() == 'number'){
$value = $o->getUnescapedValue();
if(is_array($value)) $_param = array_merge($_param, $value);
else $_param[] = $o->getUnescapedValue();
}else{
$value = $o->getUnescapedValue();
if(is_array($value)) {
foreach($value as $v)
$_param[] = array($v, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'));
}
else $_param[] = array($value, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'));
}
}
}
if(count($this->param)){ // Run the query statement
foreach($this->param as $k => $o){
if($o['type'] == 'number'){
$_param[] = &$o['value'];
}else{
$_param[] = array(&$o['value'], SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'));
}
}
}
// 쿼리 시작을 알림
$this->actStart($query);
// 쿼리 문 실행
$result = false; $result = false;
if(count($_param)){ if(count($_param)){
$result = @sqlsrv_query($this->conn, $query, $_param); $result = @sqlsrv_query($connection, $query, $_param);
}else{ }else{
$result = @sqlsrv_query($this->conn, $query); $result = @sqlsrv_query($connection, $query);
} }
// Error Check
// 오류 체크
if(!$result) $this->setError(print_r(sqlsrv_errors(),true)); if(!$result) $this->setError(print_r(sqlsrv_errors(),true));
// 쿼리 실행 종료를 알림 $this->param = array();
$this->actFinish();
$this->param = array();
return $result; return $result;
} }
/** /**
* @brief 결과를 fetch * @brief Fetch results
**/ **/
function _fetch($result) { function _fetch($result, $arrayIndexEndValue = NULL) {
if(!$this->isConnected() || $this->isError() || !$result) return; if(!$this->isConnected() || $this->isError() || !$result) return;
$c = sqlsrv_num_fields($result); $c = sqlsrv_num_fields($result);
@ -210,16 +182,20 @@
for($i=0;$i<$c;$i++){ for($i=0;$i<$c;$i++){
$row->{$m[$i]['Name']} = sqlsrv_get_field( $result, $i, SQLSRV_PHPTYPE_STRING( 'utf-8' )); $row->{$m[$i]['Name']} = sqlsrv_get_field( $result, $i, SQLSRV_PHPTYPE_STRING( 'utf-8' ));
} }
$output[] = $row; if($arrayIndexEndValue) $output[$arrayIndexEndValue--] = $row;
else $output[] = $row;
} }
if(count($output)==1) return $output[0]; if(count($output)==1) {
if(isset($arrayIndexEndValue)) return $output;
else return $output[0];
}
return $output; return $output;
} }
/** /**
* @brief 1 증가되는 sequence값을 return (mssql의 auto_increment는 sequence테이블에서만 사용) * @brief Return sequence value incremented by 1(auto_increment is usd in the sequence table only)
**/ **/
function getNextSequence() { function getNextSequence() {
$query = sprintf("insert into %ssequence (seq) values (ident_incr('%ssequence'))", $this->prefix, $this->prefix); $query = sprintf("insert into %ssequence (seq) values (ident_incr('%ssequence'))", $this->prefix, $this->prefix);
@ -234,7 +210,7 @@
} }
/** /**
* @brief 테이블 기생성 여부 return * @brief Return if a table already exists
**/ **/
function isTableExists($target_name) { function isTableExists($target_name) {
$query = sprintf("select name from sysobjects where name = '%s%s' and xtype='U'", $this->prefix, $this->addQuotes($target_name)); $query = sprintf("select name from sysobjects where name = '%s%s' and xtype='U'", $this->prefix, $this->addQuotes($target_name));
@ -246,7 +222,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 column 추가 * @brief Add a column to a table
**/ **/
function addColumn($table_name, $column_name, $type='number', $size='', $default = '', $notnull=false) { function addColumn($table_name, $column_name, $type='number', $size='', $default = '', $notnull=false) {
if($this->isColumnExists($table_name, $column_name)) return; if($this->isColumnExists($table_name, $column_name)) return;
@ -263,7 +239,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 column 제거 * @brief Delete a column from a table
**/ **/
function dropColumn($table_name, $column_name) { function dropColumn($table_name, $column_name) {
if(!$this->isColumnExists($table_name, $column_name)) return; if(!$this->isColumnExists($table_name, $column_name)) return;
@ -272,7 +248,7 @@
} }
/** /**
* @brief 특정 테이블의 column의 정보를 return * @brief Return column information of a table
**/ **/
function isColumnExists($table_name, $column_name) { function isColumnExists($table_name, $column_name) {
$query = sprintf("select syscolumns.name as name from syscolumns, sysobjects where sysobjects.name = '%s%s' and sysobjects.id = syscolumns.id and syscolumns.name = '%s'", $this->prefix, $table_name, $column_name); $query = sprintf("select syscolumns.name as name from syscolumns, sysobjects where sysobjects.name = '%s%s' and sysobjects.id = syscolumns.id and syscolumns.name = '%s'", $this->prefix, $table_name, $column_name);
@ -284,7 +260,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 인덱스 추가 * @brief Add an index to a table
* $target_columns = array(col1, col2) * $target_columns = array(col1, col2)
* $is_unique? unique : none * $is_unique? unique : none
**/ **/
@ -297,7 +273,7 @@
} }
/** /**
* @brief 특정 테이블의 특정 인덱스 삭제 * @brief Drop an index from a table
**/ **/
function dropIndex($table_name, $index_name, $is_unique = false) { function dropIndex($table_name, $index_name, $is_unique = false) {
if(!$this->isIndexExists($table_name, $index_name)) return; if(!$this->isIndexExists($table_name, $index_name)) return;
@ -306,7 +282,7 @@
} }
/** /**
* @brief 특정 테이블의 index 정보를 return * @brief Return index information of a table
**/ **/
function isIndexExists($table_name, $index_name) { function isIndexExists($table_name, $index_name) {
$query = sprintf("select sysindexes.name as name from sysindexes, sysobjects where sysobjects.name = '%s%s' and sysobjects.id = sysindexes.id and sysindexes.name = '%s'", $this->prefix, $table_name, $index_name); $query = sprintf("select sysindexes.name as name from sysindexes, sysobjects where sysobjects.name = '%s%s' and sysobjects.id = sysindexes.id and sysindexes.name = '%s'", $this->prefix, $table_name, $index_name);
@ -320,24 +296,24 @@
} }
/** /**
* @brief xml 받아서 테이블을 생성 * @brief Create a table by using xml file
**/ **/
function createTableByXml($xml_doc) { function createTableByXml($xml_doc) {
return $this->_createTable($xml_doc); return $this->_createTable($xml_doc);
} }
/** /**
* @brief xml 받아서 테이블을 생성 * @brief Create a table by using xml file
**/ **/
function createTableByXmlFile($file_name) { function createTableByXmlFile($file_name) {
if(!file_exists($file_name)) return; if(!file_exists($file_name)) return;
// xml 파일을 읽음 // read xml file
$buff = FileHandler::readFile($file_name); $buff = FileHandler::readFile($file_name);
return $this->_createTable($buff); 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 * type : number, varchar, text, char, date, \n
* opt : notnull, default, size\n * opt : notnull, default, size\n
@ -347,8 +323,7 @@
// xml parsing // xml parsing
$oXml = new XmlParser(); $oXml = new XmlParser();
$xml_obj = $oXml->parse($xml_doc); $xml_obj = $oXml->parse($xml_doc);
// Create a table schema
// 테이블 생성 schema 작성
$table_name = $xml_obj->table->attrs->name; $table_name = $xml_obj->table->attrs->name;
if($this->isTableExists($table_name)) return; if($this->isTableExists($table_name)) return;
@ -408,500 +383,162 @@
} }
} }
/**
* @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'))) continue;
$name = $v['column'];
if(preg_match('/^substr\(/i',$name)) $name = preg_replace('/^substr\(/i','substring(',$name);
$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;
}
function getConditionValue($name, $value, $operation, $type, $column_type) {
if($type == 'number') {
if(strpos($value,',')===false && strpos($value,'(')===false){
if(is_integer($value)){
$this->param[] = array('type'=>'number','value'=>(int)$value);
return '?';
}else{
return $value;
}
}
}
if(strpos($name,'.')!==false&&strpos($value,'.')!==false) {
list($table_name, $column_name) = explode('.',$value);
if($column_type[$column_name]){
return $value;
}
}
switch($operation) {
case 'like_prefix' :
$value = preg_replace('/(^\'|\'$){1}/','',$value);
$this->param[] = array('type'=>$column_type[$name],'value'=>$value);
$value = "? + '%'";
break;
case 'like_tail' :
$value = preg_replace('/(^\'|\'$){1}/','',$value);
$this->param[] = array('type'=>$column_type[$name],'value'=>$value);
$value = "'%' + ?";
break;
case 'like' :
$value = preg_replace('/(^\'|\'$){1}/','',$value);
$this->param[] = array('type'=>$column_type[$name],'value'=>$value);
$value = "'%' + ? + '%'";
break;
case 'notin' :
preg_match_all('/,?\'([^\']*)\'/',$value,$match);
$val = array();
foreach($match[1] as $k => $v){
$this->param[] = array('type'=>$column_type[$name],'value'=>trim($v));
$val[] ='?';
}
$value = join(',',$val);
break;
case 'in' :
preg_match_all('/,?\'([^\']*)\'/',$value,$match);
$val = array();
foreach($match[1] as $k => $v){
$this->param[] = array('type'=>$column_type[$name],'value'=>trim($v));
$val[] ='?';
}
$value = join(',',$val);
break;
default:
$value = preg_replace('/(^\'|\'$){1}/','',$value);
$this->param[] = array('type'=>$column_type[$name],'value'=>$value);
$value = '?';
break;
}
return $value;
}
/** /**
* @brief insertAct 처리 * @brief Handle the insertAct
**/ **/
function _executeInsertAct($output) { // TODO Lookup _filterNumber against sql injection - see if it is still needed and how to integrate
function _executeInsertAct($queryObject) {
// 테이블 정리 $query = $this->getInsertSql($queryObject, false);
foreach($output->tables as $key => $val) { $this->param = $queryObject->getArguments();
$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 = '';
} elseif(is_numeric($value)){
if(!$value) $value = '';
$value = (int)$value;
} elseif(!$value){
$value = '';
}
// sql injection 문제로 xml 선언이 number인 경우이면서 넘어온 값이 숫자형이 아니면 숫자형으로 강제 형변환
else $this->_filterNumber(&$value);
$column_list[] = '['.$name.']';
$value_list[] = '?';
$this->param[] = array('type'=>$output->column_type[$name], 'value'=>$value);
}
$query = sprintf("insert into %s (%s) values (%s);", implode(',',$table_list), implode(',',$column_list), implode(',', $value_list));
return $this->_query($query); return $this->_query($query);
} }
/** /**
* @brief updateAct 처리 * @brief Handle updateAct
**/ **/
function _executeUpdateAct($output) { function _executeUpdateAct($queryObject) {
// 테이블 정리 $query = $this->getUpdateSql($queryObject, false);
foreach($output->tables as $key => $val) { $this->param = $queryObject->getArguments();
$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);
if(!$value) $value = '';
$this->param[] = array('type'=>$output->column_type[$name], 'value'=>$value);
$column_list[] = sprintf("[%s] = ?", $name);
}elseif(!$value || is_numeric($value)){
$value = (int)$value;
$this->param[] = array('type'=>$output->column_type[$name], 'value'=>$value);
$column_list[] = sprintf("[%s] = ?", $name);
}else{
if(!$value) $value = '';
$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);
return $this->_query($query); return $this->_query($query);
} }
/** /**
* @brief deleteAct 처리 * @brief Handle deleteAct
**/ **/
function _executeDeleteAct($output) { function _executeDeleteAct($queryObject) {
// 테이블 정리 $query = $this->getDeleteSql($queryObject, false);
foreach($output->tables as $key => $val) { $this->param = $queryObject->getArguments();
$table_list[] = '['.$this->prefix.$val.']';
}
// 조건절 정리
$condition = $this->getCondition($output);
$query = sprintf("delete from %s %s", implode(',',$table_list), $condition);
return $this->_query($query); return $this->_query($query);
} }
function getSelectSql($query){
$with_value = false;
//$limitOffset = $query->getLimit()->getOffset();
//if($limitOffset)
// TODO Implement Limit with offset with subquery
$limit = '';$limitCount = '';
$limitQueryPart = $query->getLimit();
if($limitQueryPart)
$limitCount = $limitQueryPart->getLimit();
if($limitCount != '') $limit = 'SELECT TOP ' . $limitCount;
$select = $query->getSelectString($with_values);
if($select == '') return new Object(-1, "Invalid query");
if($limit != '')
$select = $limit.' '.$select;
else
$select = 'SELECT ' .$select;
$from = $query->getFromString($with_values);
if($from == '') return new Object(-1, "Invalid query");
$from = ' FROM '.$from;
$where = $query->getWhereString($with_values);
if($where != '') $where = ' WHERE ' . $where;
$groupBy = $query->getGroupByString();
if($groupBy != '') $groupBy = ' GROUP BY ' . $groupBy;
$orderBy = $query->getOrderByString();
if($orderBy != '') $orderBy = ' ORDER BY ' . $orderBy;
return $select . ' ' . $from . ' ' . $where . ' ' . $groupBy . ' ' . $orderBy;
}
/** /**
* @brief selectAct 처리 * @brief Handle selectAct
* *
* select의 경우 특정 페이지의 목록을 가져오는 것을 편하게 하기 위해\n * In order to get a list of pages easily when selecting \n
* navigation이라는 method를 제공 * it supports a method as navigation
**/ **/
function _executeSelectAct($output) { function _executeSelectAct($queryObject, $connection = null) {
// 테이블 정리 $query = $this->getSelectSql($queryObject);
$table_list = array();
foreach($output->tables as $key => $val) {
$table_list[] = '['.$this->prefix.$val.'] as '.$key;
}
$left_join = array(); if(strpos($query, "substr")) $query = str_replace ("substr", "substring", $query);
// why???
$left_tables= (array)$output->left_tables;
foreach($left_tables as $key => $val) { // TODO Decide if we continue to pass parameters like this
$condition = $this->_getCondition($output->left_conditions[$key],$output->column_type); $this->param = $queryObject->getArguments();
if($condition){
$left_join[] = $val . ' ['.$this->prefix.$output->_tables[$key].'] as '.$key . ' on (' . $condition . ')';
}
}
$click_count = array(); $query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id):'';
if(!$output->columns){ $result = $this->_query($query, $connection);
$output->columns = array(array('name'=>'*'));
}
$column_list = array(); if ($this->isError ()) return $this->queryError($queryObject);
foreach($output->columns as $key => $val) { else return $this->queryPageLimit($queryObject, $result, $connection);
$name = $val['name'];
if(preg_match('/^substr\(/i',$name)) $name = preg_replace('/^substr\(/i','substring(',$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);
}
}
$columns = implode(',',$column_list);
$condition = $this->getCondition($output);
$output->column_list = $column_list;
if($output->list_count && $output->page) return $this->_getNavigationData($table_list, $columns, $left_join, $condition, $output);
// list_order, update_order 로 정렬시에 인덱스 사용을 위해 condition에 쿼리 추가
if($output->order) {
$conditions = $this->getConditionList($output);
if(!in_array('list_order', $conditions) && !in_array('update_order', $conditions)) {
foreach($output->order as $key => $val) {
$col = $val[0];
if(!in_array($col, array('list_order','update_order'))) continue;
if($condition) $condition .= sprintf(' and %s < 2100000000 ', $col);
else $condition = sprintf(' where %s < 2100000000 ', $col);
}
}
}
if(count($output->groups)){
foreach($output->groups as $k => $v ){
if(preg_match('/^substr\(/i',$v)) $output->groups[$k] = preg_replace('/^substr\(/i','substring(',$v);
if($column_list[$v]) $output->arg_columns[] = $column_list[$v];
}
$groupby_query = sprintf(' group by %s', implode(',',$output->groups));
}
if($output->order && !preg_match('/count\(\*\)/i',$columns) ) {
foreach($output->order as $key => $val) {
if(preg_match('/^substr\(/i',$val[0])) $name = preg_replace('/^substr\(/i','substring(',$val[0]);
$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 = array();
foreach($output->arg_columns as $col){
if(strpos($col,'[')===false && strpos($col,' ')==false) $columns[] = '['.$col.']';
else $columns[] = $col;
}
$columns = join(',',$columns);
}
$query = sprintf("%s from %s %s %s %s", $columns, implode(',',$table_list),implode(' ',$left_join), $condition, $groupby_query.$orderby_query);
// list_count를 사용할 경우 적용
if($output->list_count['value']) $query = sprintf('select top %d %s', $output->list_count['value'], $query);
else $query = "select ".$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;
} }
/** function getParser(){
* @brief query xml에 navigation 정보가 있을 경우 페이징 관련 작업을 처리한다 return new DBParser("[", "]", $this->prefix);
* }
* 그닥 좋지는 않은 구조이지만 편리하다.. -_-;
**/
function _getNavigationData($table_list, $columns, $left_join, $condition, $output) {
require_once(_XE_PATH_.'classes/page/PageHandler.class.php');
$column_list = $output->column_list; function queryError($queryObject){
$limit = $queryObject->getLimit();
if ($limit && $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;
}
// 전체 개수를 구함 function queryPageLimit($queryObject, $result, $connection){
if(count($output->groups)){ $limit = $queryObject->getLimit();
foreach($output->groups as $k => $v ){ if ($limit && $limit->isPageHandler()) {
if(preg_match('/^substr\(/i',$v)) $output->groups[$k] = preg_replace('/^substr\(/i','substring(',$v); // Total count
if($column_list[$v]) $output->arg_columns[] = $column_list[$v]; $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);
} }
$count_condition = sprintf('%s group by %s', $condition, implode(', ', $output->groups));
$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_count = $limit->list_count->getValue();
if (!$list_count) $list_count = 20;
$page_count = $limit->page_count->getValue();
if (!$page_count) $page_count = 10;
$page = $limit->page->getValue();
if (!$page) $page = 1;
// Total pages
if ($total_count) {
$total_page = (int) (($total_count - 1) / $list_count) + 1;
} else $total_page = 1;
// check the page variables
if ($page > $total_page) $page = $total_page;
$start_count = ($page - 1) * $list_count;
$query .= (__DEBUG_QUERY__&1 && $queryObject->query_id)?sprintf (' '.$this->comment_syntax, $this->query_id):'';
$result = $this->_query ($query, $connection);
if ($this->isError ())
return $this->queryError($queryObject);
$virtual_no = $total_count - ($page - 1) * $list_count;
$data = $this->_fetch($result, $virtual_no);
$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);
}else{ }else{
$count_condition = $condition; $data = $this->_fetch($result);
$buff = new Object ();
$buff->data = $data;
} }
return $buff;
$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);
$param = $this->param;
$count_query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id . ' count(*)'):'';
$result = $this->_query($count_query);
$this->param = $param;
$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에 쿼리 추가
$conditions = $this->getConditionList($output);
if($output->order) {
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(' %s < 2100000000 ', $col);
}
}
}
// group by 절 추가
if(count($output->groups)){
foreach($output->groups as $k => $v ){
if(preg_match('/^substr\(/i',$v)) $output->groups[$k] = preg_replace('/^substr\(/i','substring(',$v);
if($column_list[$v]) $output->arg_columns[] = $column_list[$v];
}
$group = sprintf('group by %s', implode(',',$output->groups));
}
// order 절 추가
$order_targets = array();
if($output->order) {
foreach($output->order as $key => $val) {
if(preg_match('/^substr\(/i',$val[0])) $name = preg_replace('/^substr\(/i','substring(',$val[0]);
$order_targets[$val[0]] = $val[1];
$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)) $order .= 'order by '.implode(',',$index_list);
}
if(!count($order_targets)) {
if(in_array('list_order',$conditions)) $order_targets['list_order'] = 'asc';
else $order_targets['xe_seq'] = 'desc';
}
if(count($output->arg_columns))
{
$columns = array();
foreach($output->arg_columns as $col){
if(strpos($col,'[')===false && strpos($col,' ')==false) $columns[] = '['.$col.']';
else $columns[] = $col;
}
$columns = join(',',$columns);
}
if($start_count<1) {
$query = sprintf('select top %d %s from %s %s %s %s %s', $list_count, $columns, implode(',',$table_list), implode(' ',$left_join), $condition, $group, $order);
} else {
foreach($order_targets as $k => $v) {
$first_columns[] = sprintf('%s(%s) as %s', $v=='asc'?'max':'min', $k, $k);
$first_sub_columns[] = $k;
}
// 1차로 order 대상에 해당 하는 값을 가져옴
$param = $this->param;
$first_query = sprintf("select %s from (select top %d %s from %s %s %s %s %s) xet", implode(',',$first_columns), $start_count, implode(',',$first_sub_columns), implode(',',$table_list), implode(' ',$left_join), $condition, $group, $order);
$result = $this->_query($first_query);
$this->param = $param;
$tmp = $this->_fetch($result);
// 1차에서 나온 값을 이용 다시 쿼리 실행
$sub_cond = array();
foreach($order_targets as $k => $v) {
$sub_cond[] = sprintf("%s %s '%s'", $k, $v=='asc'?'>':'<', $tmp->{$k});
}
$sub_condition = ' and( '.implode(' and ',$sub_cond).' )';
if($condition) $condition .= $sub_condition;
else $condition = ' where '.$sub_condition;
$query = sprintf('select top %d %s from %s %s %s %s %s', $list_count, $columns, implode(',',$table_list), implode(' ',$left_join), $condition, $group, $order);
}
$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;
$output = $this->_fetch($result);
if(!is_array($output)) $output = array($output);
foreach($output as $k => $v) {
$data[$virtual_no--] = $v;
}
$buff = new Object();
$buff->total_count = $total_count;
$buff->total_page = $total_page;
$buff->page = $page;
$buff->data = $data;
$buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count);
return $buff;
}
} }

View file

@ -2,7 +2,7 @@
/** /**
* @class DBMysql * @class DBMysql
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief MySQL DBMS이용하기 위한 class * @brief Class to use MySQL DBMS
* @version 0.1 * @version 0.1
* *
* mysql handling class * mysql handling class
@ -11,20 +11,16 @@
class DBMysql extends DB { class DBMysql extends DB {
/** /**
* @brief Mysql DB에 접속하기 위한 정보 * @brief Connection information for Mysql DB
**/ **/
var $hostname = '127.0.0.1'; ///< hostname var $prefix = 'xe_'; // / <prefix of a tablename (One or more XEs can be installed in a single DB)
var $userid = NULL; ///< user id var $comment_syntax = '/* %s */';
var $password = NULL; ///< password
var $database = NULL; ///< database
var $prefix = 'xe'; ///< XE에서 사용할 테이블들의 prefix (한 DB에서 여러개의 XE 설치 가능)
var $comment_syntax = '/* %s */';
/** /**
* @brief mysql에서 사용될 column type * @brief Column type used in MySQL
* *
* column_type은 schema/query xml에서 공통 선언된 type을 이용하기 때문에 * Becasue a common column type in schema/query xml is used for colum_type,
* DBMS에 맞게 replace 해주어야 한다 * it should be replaced properly for each DBMS
**/ **/
var $column_type = array( var $column_type = array(
'bignumber' => 'bigint', 'bignumber' => 'bigint',
@ -41,7 +37,7 @@
* @brief constructor * @brief constructor
**/ **/
function DBMysql() { function DBMysql() {
$this->_setDBInfo(); $this->_setDBInfo();
$this->_connect(); $this->_connect();
} }
@ -50,7 +46,7 @@
} }
/** /**
* @brief 설치 가능 여부를 return * @brief Return if it is installable
**/ **/
function isSupported() { function isSupported() {
if(!function_exists('mysql_connect')) return false; if(!function_exists('mysql_connect')) return false;
@ -58,133 +54,114 @@
} }
/** /**
* @brief DB정보 설정 connect/ close * @brief DB Connection
**/ **/
function _setDBInfo() { function __connect($connection) {
$db_info = Context::getDBInfo(); // Ignore if no DB information exists
$this->hostname = $db_info->db_hostname; if (strpos($connection["db_hostname"], ':') === false && $connection["db_port"])
$this->port = $db_info->db_port; $connection["db_hostname"] .= ':' . $connection["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 .= '_';
}
/** // Attempt to connect
* @brief DB 접속 $result = @mysql_connect($connection["db_hostname"], $connection["db_userid"], $connection["db_password"]);
**/
function _connect() {
// db 정보가 없으면 무시
if(!$this->hostname || !$this->userid || !$this->password || !$this->database) return;
if(strpos($this->hostname, ':')===false && $this->port) $this->hostname .= ':'.$this->port;
// 접속시도
$this->fd = @mysql_connect($this->hostname, $this->userid, $this->password);
if(mysql_error()) { if(mysql_error()) {
$this->setError(mysql_errno(), mysql_error()); $this->setError(mysql_errno(), mysql_error());
return; return;
} }
// Error appears if the version is lower than 4.1
// 버전 확인후 4.1 이하면 오류 표시 if(mysql_get_server_info($result)<"4.1") {
if(mysql_get_server_info($this->fd)<"4.1") {
$this->setError(-1, "XE cannot be installed under the version of mysql 4.1. Current mysql version is ".mysql_get_server_info()); $this->setError(-1, "XE cannot be installed under the version of mysql 4.1. Current mysql version is ".mysql_get_server_info());
return; return;
} }
// select db
// db 선택 @mysql_select_db($connection["db_database"], $result);
@mysql_select_db($this->database, $this->fd);
if(mysql_error()) { if(mysql_error()) {
$this->setError(mysql_errno(), mysql_error()); $this->setError(mysql_errno(), mysql_error());
return; return;
} }
// 접속체크 return $result;
$this->is_connected = true; }
$this->password = md5($this->password);
// mysql의 경우 utf8임을 지정 function _afterConnect($connection){
$this->_query("set names 'utf8'"); // Set utf8 if a database is MySQL
$this->_query("set names 'utf8'", $connection);
} }
/** /**
* @brief DB접속 해제 * @brief DB disconnection
**/ **/
function close() { function _close($connection) {
if(!$this->isConnected()) return; @mysql_close($connection);
@mysql_close($this->fd);
} }
/** /**
* @brief 쿼리에서 입력되는 문자열 변수들의 quotation 조절 * @brief Add quotes on the string variables in a query
**/ **/
function addQuotes($string) { function addQuotes($string) {
if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string)); if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string));
if(!is_numeric($string)) $string = @mysql_escape_string($string); if(!is_numeric($string)) $string = @mysql_real_escape_string($string);
return $string; return $string;
} }
/** /**
* @brief 트랜잭션 시작 * @brief Begin transaction
**/ **/
function begin() { function _begin() {
return true;
} }
/** /**
* @brief 롤백 * @brief Rollback
**/ **/
function rollback() { function _rollback() {
return true;
} }
/** /**
* @brief 커밋 * @brief Commits
**/ **/
function commit() { function _commit() {
return true;
} }
/** /**
* @brief : 쿼리문의 실행 결과의 fetch 처리 * @brief : Run a query and fetch the result
* *
* query : query문 실행하고 result return\n * query: run a query and return the result \n
* fetch : reutrn 값이 없으면 NULL\n * fetch: NULL if no value is returned \n
* rows이면 array object\n * array object if rows are returned \n
* row이면 object\n * object if a row is returned \n
* return\n * return\n
**/ **/
function _query($query) { function __query($query, $connection) {
if(!$this->isConnected()) return; // Run the query statement
$result = mysql_query($query, $connection);
// 쿼리 시작을 알림 // Error Check
$this->actStart($query); if(mysql_error($connection)) $this->setError(mysql_errno($connection), mysql_error($connection));
// Return result
// 쿼리 문 실행
$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; return $result;
} }
/** /**
* @brief 결과를 fetch * @brief Fetch results
**/ **/
function _fetch($result) { function _fetch($result, $arrayIndexEndValue = NULL) {
if(!$this->isConnected() || $this->isError() || !$result) return; if(!$this->isConnected() || $this->isError() || !$result) return;
while($tmp = $this->db_fetch_object($result)) { while($tmp = $this->db_fetch_object($result)) {
$output[] = $tmp; if($arrayIndexEndValue) $output[$arrayIndexEndValue--] = $tmp;
else $output[] = $tmp;
} }
if(count($output)==1) return $output[0]; if(count($output)==1){
if(isset($arrayIndexEndValue)) return $output;
else return $output[0];
}
mysql_free_result($result);
return $output; return $output;
} }
/** /**
* @brief 1 증가되는 sequence값을 return (mysql의 auto_increment는 sequence테이블에서만 사용) * @brief Return sequence value incremented by 1(auto_increment is used in sequence table only in MySQL)
**/ **/
function getNextSequence() { function getNextSequence() {
$query = sprintf("insert into `%ssequence` (seq) values ('0')", $this->prefix); $query = sprintf("insert into `%ssequence` (seq) values ('0')", $this->prefix);
@ -199,7 +176,7 @@
} }
/** /**
* @brief mysql old password를 가져오는 함수 (mysql에서만 사용) * @brief Function to obtain mysql old password(mysql only)
**/ **/
function isValidOldPassword($password, $saved_password) { function isValidOldPassword($password, $saved_password) {
$query = sprintf("select password('%s') as password, old_password('%s') as old_password", $this->addQuotes($password), $this->addQuotes($password)); $query = sprintf("select password('%s') as password, old_password('%s') as old_password", $this->addQuotes($password), $this->addQuotes($password));
@ -210,7 +187,7 @@
} }
/** /**
* @brief 테이블 기생성 여부 return * @brief Return if a table already exists
**/ **/
function isTableExists($target_name) { function isTableExists($target_name) {
$query = sprintf("show tables like '%s%s'", $this->prefix, $this->addQuotes($target_name)); $query = sprintf("show tables like '%s%s'", $this->prefix, $this->addQuotes($target_name));
@ -221,7 +198,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 column 추가 * @brief Add a column to a table
**/ **/
function addColumn($table_name, $column_name, $type='number', $size='', $default = '', $notnull=false) { function addColumn($table_name, $column_name, $type='number', $size='', $default = '', $notnull=false) {
$type = $this->column_type[$type]; $type = $this->column_type[$type];
@ -237,7 +214,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 column 제거 * @brief Delete a column from a table
**/ **/
function dropColumn($table_name, $column_name) { function dropColumn($table_name, $column_name) {
$query = sprintf("alter table `%s%s` drop `%s` ", $this->prefix, $table_name, $column_name); $query = sprintf("alter table `%s%s` drop `%s` ", $this->prefix, $table_name, $column_name);
@ -245,7 +222,7 @@
} }
/** /**
* @brief 특정 테이블의 column의 정보를 return * @brief Return column information of a table
**/ **/
function isColumnExists($table_name, $column_name) { function isColumnExists($table_name, $column_name) {
$query = sprintf("show fields from `%s%s`", $this->prefix, $table_name); $query = sprintf("show fields from `%s%s`", $this->prefix, $table_name);
@ -263,7 +240,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 인덱스 추가 * @brief Add an index to a table
* $target_columns = array(col1, col2) * $target_columns = array(col1, col2)
* $is_unique? unique : none * $is_unique? unique : none
**/ **/
@ -275,7 +252,7 @@
} }
/** /**
* @brief 특정 테이블의 특정 인덱스 삭제 * @brief Drop an index from a table
**/ **/
function dropIndex($table_name, $index_name, $is_unique = false) { function dropIndex($table_name, $index_name, $is_unique = false) {
$query = sprintf("alter table `%s%s` drop index `%s`", $this->prefix, $table_name, $index_name); $query = sprintf("alter table `%s%s` drop index `%s`", $this->prefix, $table_name, $index_name);
@ -284,7 +261,7 @@
/** /**
* @brief 특정 테이블의 index 정보를 return * @brief Return index information of a table
**/ **/
function isIndexExists($table_name, $index_name) { function isIndexExists($table_name, $index_name) {
//$query = sprintf("show indexes from %s%s where key_name = '%s' ", $this->prefix, $table_name, $index_name); //$query = sprintf("show indexes from %s%s where key_name = '%s' ", $this->prefix, $table_name, $index_name);
@ -302,24 +279,24 @@
} }
/** /**
* @brief xml 받아서 테이블을 생성 * @brief Create a table by using xml file
**/ **/
function createTableByXml($xml_doc) { function createTableByXml($xml_doc) {
return $this->_createTable($xml_doc); return $this->_createTable($xml_doc);
} }
/** /**
* @brief xml 받아서 테이블을 생성 * @brief Create a table by using xml file
**/ **/
function createTableByXmlFile($file_name) { function createTableByXmlFile($file_name) {
if(!file_exists($file_name)) return; if(!file_exists($file_name)) return;
// xml 파일을 읽음 // read xml file
$buff = FileHandler::readFile($file_name); $buff = FileHandler::readFile($file_name);
return $this->_createTable($buff); 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 * type : number, varchar, text, char, date, \n
* opt : notnull, default, size\n * opt : notnull, default, size\n
@ -329,8 +306,7 @@
// xml parsing // xml parsing
$oXml = new XmlParser(); $oXml = new XmlParser();
$xml_obj = $oXml->parse($xml_doc); $xml_obj = $oXml->parse($xml_doc);
// Create a table schema
// 테이블 생성 schema 작성
$table_name = $xml_obj->table->attrs->name; $table_name = $xml_obj->table->attrs->name;
if($this->isTableExists($table_name)) return; if($this->isTableExists($table_name)) return;
$table_name = $this->prefix.$table_name; $table_name = $this->prefix.$table_name;
@ -386,396 +362,175 @@
} }
/** /**
* @brief 조건문 작성하여 return * @brief Handle the insertAct
**/ **/
function getCondition($output) { function _executeInsertAct($queryObject) {
if(!$output->conditions) return; // TODO See what priority does
$condition = $this->_getCondition($output->conditions,$output->column_type); //priority setting
if($condition) $condition = ' where '.$condition; //$priority = '';
return $condition; //if($output->priority) $priority = $output->priority['type'].'_priority';
}
function getLeftCondition($conditions,$column_type){ $query = $this->getInsertSql($queryObject, true, true);
return $this->_getCondition($conditions,$column_type); if(is_a($query, 'Object')) return;
}
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;
$name = $v['column'];
$operation = $v['operation'];
$value = $v['value'];
$type = $this->getColumnType($column_type,$name);
$pipe = $v['pipe'];
$value = $this->getConditionValue($name, $value, $operation, $type, $column_type);
if(!$value) $value = $v['value'];
$str = $this->getConditionPart($name, $value, $operation);
if($sub_condition) $sub_condition .= ' '.$pipe.' ';
$sub_condition .= $str;
}
if($sub_condition) {
if($condition && $val['pipe']) $condition .= ' '.$val['pipe'].' ';
$condition .= '('.$sub_condition.')';
}
}
return $condition;
}
/**
* @brief insertAct 처리
**/
function _executeInsertAct($output) {
// 테이블 정리
foreach($output->tables as $key => $val) {
$table_list[] = '`'.$this->prefix.$val.'`';
}
// 컬럼 정리
foreach($output->columns as $key => $val) {
$name = $val['name'];
$value = $val['value'];
if($output->column_type[$name]!='number') {
if(!is_null($value)){
$value = "'" . $this->addQuotes($value) ."'";
}else{
if($val['notnull']=='notnull') {
$value = "''";
} else {
//$value = 'null';
$value = "''";
}
}
}
//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); return $this->_query($query);
} }
/** /**
* @brief updateAct 처리 * @brief Handle updateAct
**/ **/
function _executeUpdateAct($output) { function _executeUpdateAct($queryObject) {
// 테이블 정리 // TODO See what proiority does
foreach($output->tables as $key => $val) { //priority setting
$table_list[] = '`'.$this->prefix.$val.'` as '.$key; //$priority = '';
} //if($output->priority) $priority = $output->priority['type'].'_priority';
// 컬럼 정리
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)."'";
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->getUpdateSql($queryObject, true, true);
if(is_a($query, 'Object')) return;
return $this->_query($query); return $this->_query($query);
} }
/** /**
* @brief deleteAct 처리 * @brief Handle deleteAct
**/ **/
function _executeDeleteAct($output) { function _executeDeleteAct($queryObject) {
// 테이블 정리 $query = $this->getDeleteSql($queryObject, true, true);
foreach($output->tables as $key => $val) {
$table_list[] = '`'.$this->prefix.$val.'`';
}
// 조건절 정리 if(is_a($query, 'Object')) return;
$condition = $this->getCondition($output);
$query = sprintf("delete from %s %s", implode(',',$table_list), $condition);
//priority setting
// TODO Check what priority does
//$priority = '';
//if($output->priority) $priority = $output->priority['type'].'_priority';
return $this->_query($query); return $this->_query($query);
} }
/** /**
* @brief selectAct 처리 * @brief Handle selectAct
* *
* select의 경우 특정 페이지의 목록을 가져오는 것을 편하게 하기 위해\n * In order to get a list of pages easily when selecting \n
* navigation이라는 method를 제공 * it supports a method as navigation
**/ **/
function _executeSelectAct($output) { function _executeSelectAct($queryObject, $connection = null) {
// 테이블 정리 $limit = $queryObject->getLimit();
$table_list = array(); if ($limit && $limit->isPageHandler())
foreach($output->tables as $key => $val) { return $this->queryPageLimit($queryObject, $result, $connection);
$table_list[] = '`'.$this->prefix.$val.'` as '.$key; else {
} $query = $this->getSelectSql($queryObject);
if(is_a($query, 'Object')) return;
$query .= (__DEBUG_QUERY__&1 && $queryObject->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id):'';
$left_join = array(); $result = $this->_query ($query, $connection);
// why??? if ($this->isError ()) return $this->queryError($queryObject);
$left_tables= (array)$output->left_tables;
foreach($left_tables as $key => $val) { $data = $this->_fetch($result);
$condition = $this->_getCondition($output->left_conditions[$key],$output->column_type); $buff = new Object ();
if($condition){ $buff->data = $data;
$left_join[] = $val . ' `'.$this->prefix.$output->_tables[$key].'` as '.$key . ' on (' . $condition . ')';
}
}
$click_count = array();
if(!$output->columns){
$output->columns = array(array('name'=>'*'));
}
$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;
}
else if(strpos($name,'.')===false && strpos($name,'(')===false)
{
if($alias)
{
$col = sprintf('`%s` as `%s`', $name, $alias);
$column_list[$alias] = $col;
}
else
{
$column_list[] = sprintf('`%s`',$name);
}
}
else
{
if($alias)
{
$col = sprintf('%s as `%s`', $name, $alias);
$column_list[$alias] = $col;
}
else
{
$column_list[] = sprintf('%s',$name);
}
}
}
$columns = implode(',',$column_list);
$output->column_list = $column_list;
$condition = $this->getCondition($output);
if($output->list_count && $output->page) return $this->_getNavigationData($table_list, $columns, $left_join, $condition, $output);
// list_order, update_order 로 정렬시에 인덱스 사용을 위해 condition에 쿼리 추가
if($output->order) {
$conditions = $this->getConditionList($output);
if(!in_array('list_order', $conditions) && !in_array('update_order', $conditions)) {
foreach($output->order as $key => $val) {
$col = $val[0];
if(!in_array($col, array('list_order','update_order'))) continue;
if($condition) $condition .= sprintf(' and %s < 2100000000 ', $col);
else $condition = sprintf(' where %s < 2100000000 ', $col);
}
}
}
if(count($output->groups))
{
$groupby_query = sprintf(' group by %s', implode(',',$output->groups));
if(count($output->arg_columns))
{
foreach($output->groups as $group)
{
if($column_list[$group]) $output->arg_columns[] = $column_list[$group];
}
}
}
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 = array();
foreach($output->arg_columns as $col){
if(strpos($col,'`')===false && strpos($col,' ')==false) $columns[] = '`'.$col.'`';
else $columns[] = $col;
}
$columns = join(',',$columns);
}
$query = sprintf("select %s from %s %s %s %s", $columns, implode(',',$table_list),implode(' ',$left_join), $condition, $groupby_query.$orderby_query);
// list_count를 사용할 경우 적용
if($output->list_count['value']) $query = sprintf('%s limit %d', $query, $output->list_count['value']);
$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) && count($output->conditions)){
$_query = '';
foreach($click_count as $k => $c) $_query .= sprintf(',%s=%s+1 ',$c,$c);
$_query = sprintf('update %s set %s %s',implode(',',$table_list), substr($_query,1), $condition);
$this->_query($_query);
}
$data = $this->_fetch($result);
$buff = new Object();
$buff->data = $data;
return $buff;
}
/**
* @brief query xml에 navigation 정보가 있을 경우 페이징 관련 작업을 처리한다
*
* 그닥 좋지는 않은 구조이지만 편리하다.. -_-;
**/
function _getNavigationData($table_list, $columns, $left_join, $condition, $output) {
require_once(_XE_PATH_.'classes/page/PageHandler.class.php');
$column_list = $output->column_list;
// 전체 개수를 구함
$count_condition = count($output->groups) ? sprintf('%s group by %s', $condition, implode(', ', $output->groups)) : $condition;
$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);
$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)){
$groupby_query = sprintf(' group by %s', implode(',',$output->groups));
if(count($output->arg_columns))
{
foreach($output->groups as $group)
{
if($column_list[$group]) $output->arg_columns[] = $column_list[$group];
}
}
}
if(count($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 = array();
foreach($output->arg_columns as $col){
if(strpos($col,'`')===false && strpos($col,' ')==false) $columns[] = '`'.$col.'`';
else $columns[] = $col;
}
$columns = join(',',$columns);
}
$query = sprintf("select %s from %s %s %s %s", $columns, implode(',',$table_list), implode(' ',$left_join), $condition, $groupby_query.$orderby_query);
$query = sprintf('%s limit %d, %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; return $buff;
} }
}
$virtual_no = $total_count - ($page-1)*$list_count; function db_insert_id()
$data = array(); {
while($tmp = $this->db_fetch_object($result)) { $connection = $this->_getConnection('master');
$data[$virtual_no--] = $tmp; return mysql_insert_id($connection);
}
function db_fetch_object(&$result)
{
return mysql_fetch_object($result);
}
function getParser(){
return new DBParser('`', '`', $this->prefix);
}
function queryError($queryObject){
$limit = $queryObject->getLimit();
if ($limit && $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;
}
function queryPageLimit($queryObject, $result, $connection){
$limit = $queryObject->getLimit();
// 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);
} }
$buff = new Object();
$count_query .= (__DEBUG_QUERY__&1 && $queryObject->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_count = $limit->list_count->getValue();
if (!$list_count) $list_count = 20;
$page_count = $limit->page_count->getValue();
if (!$page_count) $page_count = 10;
$page = $limit->page->getValue();
if (!$page) $page = 1;
// total pages
if ($total_count)
$total_page = (int) (($total_count - 1) / $list_count) + 1;
else
$total_page = 1;
// check the page variables
if ($page > $total_page) $page = $total_page;
$start_count = ($page - 1) * $list_count;
$query = $this->getSelectPageSql($queryObject, true, $start_count, $list_count);
$query .= (__DEBUG_QUERY__&1 && $queryObject->query_id)?sprintf (' '.$this->comment_syntax, $this->query_id):'';
$result = $this->_query ($query, $connection);
if ($this->isError ())
return $this->queryError($queryObject);
$virtual_no = $total_count - ($page - 1) * $list_count;
$data = $this->_fetch($result, $virtual_no);
$buff = new Object ();
$buff->total_count = $total_count; $buff->total_count = $total_count;
$buff->total_page = $total_page; $buff->total_page = $total_page;
$buff->page = $page; $buff->page = $page;
$buff->data = $data; $buff->data = $data;
$buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count); $buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count);
return $buff; return $buff;
} }
function db_insert_id() function getSelectPageSql($query, $with_values = true, $start_count = 0, $list_count = 0) {
{ $select = $query->getSelectString($with_values);
return mysql_insert_id($this->fd); if($select == '') return new Object(-1, "Invalid query");
} $select = 'SELECT ' .$select;
function db_fetch_object(&$result) $from = $query->getFromString($with_values);
{ if($from == '') return new Object(-1, "Invalid query");
return mysql_fetch_object($result); $from = ' FROM '.$from;
}
$where = $query->getWhereString($with_values);
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();
if ($limit != '') $limit = sprintf (' LIMIT %d, %d', $start_count, $list_count);
return $select . ' ' . $from . ' ' . $where . ' ' . $groupBy . ' ' . $orderBy . ' ' . $limit;
}
} }
return new DBMysql; return new DBMysql;

View file

@ -4,7 +4,7 @@
/** /**
* @class DBMysql_innodb * @class DBMysql_innodb
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief MySQL DBMS이용하기 위한 class * @brief class to use MySQL DBMS
* @version 0.1 * @version 0.1
* *
* mysql innodb handling class * mysql innodb handling class
@ -29,71 +29,60 @@
} }
/** /**
* @brief DB접속 해제 * @brief DB disconnection
**/ **/
function close() { function _close($connection) {
if(!$this->isConnected()) return; $this->_query("commit", $connection);
$this->_query("commit"); @mysql_close($connection);
@mysql_close($this->fd);
} }
/** /**
* @brief 트랜잭션 시작 * @brief Begin transaction
**/ **/
function begin() { function _begin() {
if(!$this->isConnected() || $this->transaction_started) return; $connection = $this->_getConnection('master');
$this->transaction_started = true; $this->_query("begin", $connection);
$this->_query("begin"); return true;
} }
/** /**
* @brief 롤백 * @brief Rollback
**/ **/
function rollback() { function _rollback() {
if(!$this->isConnected() || !$this->transaction_started) return; $connection = $this->_getConnection('master');
$this->_query("rollback"); $this->_query("rollback", $connection);
$this->transaction_started = false; return true;
} }
/** /**
* @brief 커밋 * @brief Commits
**/ **/
function commit($force = false) { function _commit() {
if(!$force && (!$this->isConnected() || !$this->transaction_started)) return; $connection = $this->_getConnection('master');
$this->_query("commit"); $this->_query("commit", $connection);
$this->transaction_started = false; return true;
} }
/** /**
* @brief : 쿼리문의 실행 결과의 fetch 처리 * @brief : Run a query and fetch the result
* *
* query : query문 실행하고 result return\n * query: run a query and return the result \n
* fetch : reutrn 값이 없으면 NULL\n * fetch: NULL if no value is returned \n
* rows이면 array object\n * array object if rows are returned \n
* row이면 object\n * object if a row is returned \n
* return\n * return\n
**/ **/
function _query($query) { function __query($query, $connection) {
if(!$this->isConnected()) return; // Run the query statement
$result = @mysql_query($query, $connection);
// 쿼리 시작을 알림 // Error Check
$this->actStart($query); if(mysql_error($connection)) $this->setError(mysql_errno($connection), mysql_error($connection));
// Return result
// 쿼리 문 실행
$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; return $result;
} }
/** /**
* @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 * type : number, varchar, text, char, date, \n
* opt : notnull, default, size\n * opt : notnull, default, size\n
@ -103,8 +92,7 @@
// xml parsing // xml parsing
$oXml = new XmlParser(); $oXml = new XmlParser();
$xml_obj = $oXml->parse($xml_doc); $xml_obj = $oXml->parse($xml_doc);
// Create a table schema
// 테이블 생성 schema 작성
$table_name = $xml_obj->table->attrs->name; $table_name = $xml_obj->table->attrs->name;
if($this->isTableExists($table_name)) return; if($this->isTableExists($table_name)) return;
$table_name = $this->prefix.$table_name; $table_name = $this->prefix.$table_name;

View file

@ -3,7 +3,7 @@
/** /**
* @class DBMysqli * @class DBMysqli
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief MySQL DBMS를 mysqli_* 이용하기 위한 class * @brief Class to use MySQL DBMS as mysqli_*
* @version 0.1 * @version 0.1
* *
* mysql handling class * mysql handling class
@ -21,7 +21,7 @@
} }
/** /**
* @brief 설치 가능 여부를 return * @brief Return if it is installable
**/ **/
function isSupported() { function isSupported() {
if(!function_exists('mysqli_connect')) return false; if(!function_exists('mysqli_connect')) return false;
@ -37,80 +37,75 @@
} }
/** /**
* @brief DB 접속 * @brief DB Connection
**/ **/
function _connect() { function __connect($connection) {
// db 정보가 없으면 무시 // Attempt to connect
if(!$this->hostname || !$this->userid || !$this->password || !$this->database) return; if ($connection["db_port"]) {
$result = @mysqli_connect($connection["db_hostname"]
// 접속시도 , $connection["db_userid"]
if($this->port){ , $connection["db_password"]
$this->fd = @mysqli_connect($this->hostname, $this->userid, $this->password, $this->database, $this->port); , $connection["db_database"]
}else{ , $connection["db_port"]);
$this->fd = @mysqli_connect($this->hostname, $this->userid, $this->password, $this->database); } else {
} $result = @mysqli_connect($connection["db_hostname"]
, $connection["db_userid"]
, $connection["db_password"]
, $connection["db_database"]);
}
$error = mysqli_connect_errno(); $error = mysqli_connect_errno();
if($error) { if($error) {
$this->setError($error,mysqli_connect_error()); $this->setError($error,mysqli_connect_error());
return; return;
} }
mysqli_set_charset($this->fd,'utf8'); mysqli_set_charset($result,'utf8');
return $result;
// 접속체크
$this->is_connected = true;
$this->password = md5($this->password);
} }
/** /**
* @brief DB접속 해제 * @brief DB disconnection
**/ **/
function close() { function _close($connection) {
if(!$this->isConnected()) return; mysqli_close($connection);
mysqli_close($this->fd);
} }
/** /**
* @brief 쿼리에서 입력되는 문자열 변수들의 quotation 조절 * @brief Add quotes on the string variables in a query
**/ **/
function addQuotes($string) { function addQuotes($string) {
if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$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); if(!is_numeric($string)){
$connection = $this->_getConnection('master');
$string = mysqli_escape_string($connection,$string);
}
return $string; return $string;
} }
/** /**
* @brief : 쿼리문의 실행 결과의 fetch 처리 * @brief : Run a query and fetch the result
* *
* query : query문 실행하고 result return\n * query: run a query and return the result \n
* fetch : reutrn 값이 없으면 NULL\n * fetch: NULL if no value is returned \n
* rows이면 array object\n * array object if rows are returned \n
* row이면 object\n * object if a row is returned \n
* return\n * return\n
**/ **/
function _query($query) { function __query($query, $connection) {
if(!$this->isConnected()) return; // Run the query statement
$result = mysqli_query($connection,$query);
// 쿼리 시작을 알림 // Error Check
$this->actStart($query); $error = mysqli_error($connection);
// 쿼리 문 실행
$result = mysqli_query($this->fd,$query);
// 오류 체크
$error = mysqli_error($this->fd);
if($error){ if($error){
$this->setError(mysqli_errno($this->fd), $error); $this->setError(mysqli_errno($connection), $error);
} }
// Return result
// 쿼리 실행 종료를 알림
$this->actFinish();
// 결과 리턴
return $result; return $result;
} }
function db_insert_id() function db_insert_id()
{ {
return mysqli_insert_id($this->fd); $connection = $this->_getConnection('master');
return mysqli_insert_id($connection);
} }
function db_fetch_object(&$result) function db_fetch_object(&$result)

View file

@ -2,34 +2,30 @@
/** /**
* @class DBPostgreSQL * @class DBPostgreSQL
* @author ioseph (ioseph@postgresql.kr) updated by yoonjong.joh@gmail.com * @author ioseph (ioseph@postgresql.kr) updated by yoonjong.joh@gmail.com
* @brief MySQL DBMS를 이용하기 위한 class * @brief Class to use PostgreSQL DBMS
* @version 0.2 * @version 0.2
* *
* postgresql handling class * postgresql handling class
* 2009.02.10 update delete query를 실행할때 table 이름에 alias 사용하는 것을 없앰. 지원 안함 * 2009.02.10 update and delete query for the table name at runtime, eliminating the alias to use. Not Supported
* order by clause를 실행할때 함수를 실행 하는 부분을 column alias로 대체. * when running order by clause column alias to run a function to replace parts.
* 2009.02.11 dropColumn() function이 추가 * 2009.02.11 dropColumn() function added
* 2009.02.13 addColumn() 함수 변경 * 2009.02.13 addColumn() function changes
**/ **/
class DBPostgresql extends DB class DBPostgresql extends DB
{ {
/** /**
* @brief PostgreSQL DB접속하기 위한 정보 * @brief Connection information for PostgreSQL DB
**/ **/
var $hostname = '127.0.0.1'; ///< hostname var $prefix = 'xe'; // / <prefix of a tablename (One or more XEs can be installed in a single DB)
var $userid = null; ///< user id var $comment_syntax = '/* %s */';
var $password = null; ///< password
var $database = null; ///< database
var $prefix = 'xe'; ///< XE에서 사용할 테이블들의 prefix (한 DB에서 여러개의 XE설치 가능)
var $comment_syntax = '/* %s */';
/** /**
* @brief postgresql에서 사용될 column type * @brief column type used in postgresql
* *
* column_type은 schema/query xml에서 공통 선언된 type을 이용하기 때문에 * Becasue a common column type in schema/query xml is used for colum_type,
* DBMS에 맞게 replace 해주어야 한다 * it should be replaced properly for each DBMS
**/ **/
var $column_type = array( var $column_type = array(
'bignumber' => 'bigint', 'bignumber' => 'bigint',
@ -60,7 +56,7 @@ class DBPostgresql extends DB
} }
/** /**
* @brief 설치 가능 여부를 return * @brief Return if it is installable
**/ **/
function isSupported() 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(); // the connection string for PG
$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
$conn_string = ""; $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 정보가 없으면 무시 // Attempt to connect
if (!$this->hostname || !$this->userid || !$this->database) $result = @pg_connect($conn_string);
return; if (!$result || pg_connection_status($result) != PGSQL_CONNECTION_OK) {
// 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) {
$this->setError(-1, "CONNECTION FAILURE"); $this->setError(-1, "CONNECTION FAILURE");
return; return;
} }
return $result;
// 접속체크
$this->is_connected = true;
$this->password = md5($this->password);
// utf8임을 지정
//$this ->_query('set client_encoding to uhc');
} }
/** /**
* @brief DB접속 해제 * @brief DB disconnection
**/ **/
function close() function _close($connection)
{ {
if (!$this->isConnected()) @pg_close($connection);
return;
@pg_close($this->fd);
} }
/** /**
* @brief 쿼리에서 입력되는 문자열 변수들의 quotation 조절 * @brief Add quotes on the string variables in a query
**/ **/
function addQuotes($string) 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) $connection = $this->_getConnection('master');
return; if (!$this->_query('BEGIN')) return false;
if ($this->_query($this->fd, 'BEGIN')) return true;
$this->transaction_started = true;
} }
/** /**
* @brief 롤백 * @brief Rollback
**/ **/
function rollback() function _rollback()
{ {
if (!$this->isConnected() || $this->transaction_started == false) if (!$this->_query('ROLLBACK')) return false;
return; return true;
if ($this->_query($this->fd, 'ROLLBACK'))
$this->transaction_started = false;
} }
/** /**
* @brief 커밋 * @brief Commits
**/ **/
function commit() function _commit()
{ {
if (!$this->isConnected() || $this->transaction_started == false) if (!$this->_query('COMMIT')) return false;
return; return true;
if ($this->_query($this->fd, 'COMMIT'))
$this->transaction_started = false;
} }
/** /**
* @brief : 쿼리문의 실행 결과의 fetch 처리 * @brief : Run a query and fetch the result
* *
* query : query문 실행하고 result return\n * query: run a query and return the result \n
* fetch : reutrn 값이 없으면 NULL\n * fetch: NULL if no value is returned \n
* rows이면 array object\n * array object if rows are returned \n
* row이면 object\n * object if a row is returned \n
* return\n * return\n
**/ **/
function _query($query) function __query($query, $connection)
{ {
if (!$this->isConnected()) if (!$this->isConnected())
return; return;
@ -208,48 +171,43 @@ class DBPostgresql extends DB
} }
} }
*/ */
// Notify to start a query execution
// 쿼리 시작을 알림 // $arr = array('Hello', 'World!', 'Beautiful', 'Day!');
$this->actStart($query); // Run the query statement
$arr = array('Hello', 'World!', 'Beautiful', 'Day!'); $result = @pg_query($connection, $query);
// Error Check
// 쿼리 문 실행
$result = @pg_query($this->fd, $query);
// 오류 체크
if (!$result) { if (!$result) {
// var_dump($l_query_array); // var_dump($l_query_array);
//var_dump($query); //var_dump($query);
//die("\nin query statement\n"); //die("\nin query statement\n");
//var_dump(debug_backtrace()); //var_dump(debug_backtrace());
$this->setError(1, pg_last_error($this->fd)); $this->setError(1, pg_last_error($connection));
} }
// Return result
// 쿼리 실행 종료를 알림
$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) if (!$this->isConnected() || $this->isError() || !$result)
return; return;
while ($tmp = pg_fetch_object($result)) { 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; 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() function getNextSequence()
{ {
@ -260,7 +218,7 @@ class DBPostgresql extends DB
} }
/** /**
* @brief 테이블 기생성 여부 return * @brief Return if a table already exists
**/ **/
function isTableExists($target_name) 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 = function addColumn($table_name, $column_name, $type = 'number', $size = '', $default =
NULL, $notnull = false) NULL, $notnull = false)
@ -309,7 +267,7 @@ class DBPostgresql extends DB
/** /**
* @brief 특정 테이블의 column의 정보를 return * @brief Return column information of a table
**/ **/
function isColumnExists($table_name, $column_name) 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) * $target_columns = array(col1, col2)
* $is_unique? unique : none * $is_unique? unique : none
**/ **/
@ -340,8 +298,7 @@ class DBPostgresql extends DB
if (strpos($table_name, $this->prefix) === false) if (strpos($table_name, $this->prefix) === false)
$table_name = $this->prefix . $table_name; $table_name = $this->prefix . $table_name;
// Use a tablename before an index name to avoid defining the same index
// index_name의 경우 앞에 table이름을 붙여줘서 중복을 피함
$index_name = $table_name . $index_name; $index_name = $table_name . $index_name;
$query = sprintf("create %s index %s on %s (%s);", $is_unique ? 'unique' : '', $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) 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) function dropIndex($table_name, $index_name, $is_unique = false)
{ {
if (strpos($table_name, $this->prefix) === false) if (strpos($table_name, $this->prefix) === false)
$table_name = $this->prefix . $table_name; $table_name = $this->prefix . $table_name;
// Use a tablename before an index name to avoid defining the same index
// index_name의 경우 앞에 table이름을 붙여줘서 중복을 피함
$index_name = $table_name . $index_name; $index_name = $table_name . $index_name;
$query = sprintf("drop index %s", $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) function isIndexExists($table_name, $index_name)
{ {
if (strpos($table_name, $this->prefix) === false) if (strpos($table_name, $this->prefix) === false)
$table_name = $this->prefix . $table_name; $table_name = $this->prefix . $table_name;
// Use a tablename before an index name to avoid defining the same index
// index_name의 경우 앞에 table이름을 붙여줘서 중복을 피함
$index_name = $table_name . $index_name; $index_name = $table_name . $index_name;
//$query = sprintf("show indexes from %s%s where key_name = '%s' ", $this->prefix, $table_name, $index_name); //$query = sprintf("show indexes from %s%s 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) 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) function createTableByXmlFile($file_name)
{ {
if (!file_exists($file_name)) if (!file_exists($file_name))
return; return;
// xml 파일을 읽음 // read xml file
$buff = FileHandler::readFile($file_name); $buff = FileHandler::readFile($file_name);
return $this->_createTable($buff); 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 * type : number, varchar, text, char, date, \n
* opt : notnull, default, size\n * opt : notnull, default, size\n
@ -433,8 +388,7 @@ class DBPostgresql extends DB
// xml parsing // xml parsing
$oXml = new XmlParser(); $oXml = new XmlParser();
$xml_obj = $oXml->parse($xml_doc); $xml_obj = $oXml->parse($xml_doc);
// Create a table schema
// 테이블 생성 schema 작성
$table_name = $xml_obj->table->attrs->name; $table_name = $xml_obj->table->attrs->name;
if ($table_name == 'sequence') { 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)
{ {
// 테이블 정리 $query = $this->getInsertSql($queryObject);
foreach ($output->tables as $key => $val) { if(is_a($query, 'Object')) return;
$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);
return $this->_query($query); return $this->_query($query);
} }
/** /**
* @brief deleteAct 처리 * @brief Handle updateAct
**/ **/
function _executeDeleteAct($output) function _executeUpdateAct($queryObject)
{ {
// 테이블 정리 $query = $this->getUpdateSql($queryObject);
foreach ($output->tables as $key => $val) { if(is_a($query, 'Object')) return;
$table_list[] = $this->prefix . $val; return $this->_query($query);
} }
// 조건절 정리 /**
$condition = $this->getCondition($output); * @brief Handle deleteAct
**/
$query = sprintf("delete from %s %s", implode(',', $table_list), $condition); function _executeDeleteAct($queryObject)
{
$query = $this->getDeleteSql($queryObject);
if(is_a($query, 'Object')) return;
return $this->_query($query); return $this->_query($query);
} }
/** /**
* @brief selectAct 처리
* *
* select의 경우 특정 페이지의 목록을 가져오는 것을 편하게 하기 위해\n * override
* navigation이라는 method를 제공 * @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)
{ {
// 테이블 정리 $query = $this->getSelectSql($queryObject);
$table_list = array();
foreach ($output->tables as $key => $val) {
$table_list[] = $this->prefix . $val . ' as ' . $key;
}
$left_join = array(); if(is_a($query, 'Object')) return;
// why???
$left_tables = (array )$output->left_tables;
foreach ($left_tables as $key => $val) { $query .= (__DEBUG_QUERY__&1 && $queryObject->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id):'';
$condition = $this->_getCondition($output->left_conditions[$key], $output->
column_type);
if ($condition) {
$left_join[] = $val . ' ' . $this->prefix . $output->_tables[$key] . ' as ' . $key .
' on (' . $condition . ')';
}
}
$click_count = array(); // TODO Add support for click count
if(!$output->columns){ // TODO Add code for pagination
$output->columns = array(array('name'=>'*'));
}
$column_list = array(); $result = $this->_query ($query, $connection);
foreach ($output->columns as $key => $val) { if ($this->isError ()) {
$name = $val['name']; if ($limit && $output->limit->isPageHandler()){
$alias = $val['alias']; $buff = new Object ();
if($val['click_count']) $click_count[] = $val['name']; $buff->total_count = 0;
$buff->total_page = 0;
if (substr($name, -1) == '*') { $buff->page = 1;
$column_list[] = $name; $buff->data = array ();
} elseif (strpos($name, '.') === false && strpos($name, '(') === false) { $buff->page_navigation = new PageHandler (/*$total_count*/0, /*$total_page*/1, /*$page*/1, /*$page_count*/10);//default page handler values
if ($alias) return $buff;
$column_list[$alias] = sprintf('%s as %s', $name, $alias); }else
else return;
$column_list[] = sprintf('%s', $name);
} else {
if ($alias)
$column_list[$alias] = sprintf('%s as %s', $name, $alias);
else
$column_list[] = sprintf('%s', $name);
} }
}
$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; $count_query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf (' '.$this->comment_syntax, $this->query_id):'';
if ($output->list_count && $output->page) $result_count = $this->_query($count_query, $connection);
return $this->_getNavigationData($table_list, $columns, $left_join, $condition, $count_output = $this->_fetch($result_count);
$output); $total_count = (int)$count_output->count;
// list_order, update_order 로 정렬시에 인덱스 사용을 위해 condition에 쿼리 추가 // Total pages
if ($output->order) { if ($total_count) {
$conditions = $this->getConditionList($output); $total_page = (int) (($total_count - 1) / $limit->list_count) + 1;
if (!in_array('list_order', $conditions) && !in_array('update_order', $conditions)) { } else $total_page = 1;
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)) { $virtual_no = $total_count - ($limit->page - 1) * $limit->list_count;
/* $data = $this->_fetch($result, $virtual_no);
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) { $buff = new Object ();
$name = $val['name']; $buff->total_count = $total_count;
$alias = $val['alias']; $buff->total_page = $total_page;
} */ $buff->page = $limit->page->getValue();
$group_list = array(); $buff->data = $data;
foreach ($output->groups as $gkey => $gval) { $buff->page_navigation = new PageHandler($total_count, $total_page, $limit->page->getValue(), $limit->page_count);
foreach ($output->columns as $key => $val) { }else{
$name = $val['name']; $data = $this->_fetch($result);
$alias = $val['alias']; $buff = new Object ();
if (trim($name) == trim($gval)) { $buff->data = $data;
$group_list[] = $alias; }
break;
}
}
if($column_list[$gval]) $output->arg_columns[] = $column_list[$gval]; return $buff;
}
$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;
} }
/** function getParser(){
* @brief query xml에 navigation 정보가 있을 경우 페이징 관련 작업을 처리한다 return new DBParser('"', '"', $this->prefix);
*
* 그닥 좋지는 않은 구조이지만 편리하다.. -_-;
**/
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;
} }
} }

View file

@ -2,7 +2,7 @@
/** /**
* @class DBSqlite2 * @class DBSqlite2
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief SQLite ver 2.x 이용하기 위한 class * @brief Class for using SQLite ver 2.x
* @version 0.1 * @version 0.1
* *
* sqlite handling class (sqlite ver 2.x) * sqlite handling class (sqlite ver 2.x)
@ -11,17 +11,17 @@
class DBSqlite2 extends DB { class DBSqlite2 extends DB {
/** /**
* DB이용하기 위한 정보 * DB information
**/ **/
var $database = NULL; ///< database var $database = NULL; ///< database
var $prefix = 'xe'; ///< XE에서 사용할 테이블들의 prefix (한 DB에서 여러개의 XE설치 가능) var $prefix = 'xe'; // / <prefix of a tablename (One or more XEs can be installed in a single DB)
var $comment_syntax = '/* %s */'; var $comment_syntax = '/* %s */';
/** /**
* @brief sqlite 에서 사용될 column type * @brief sqlite column type used in
* *
* column_type은 schema/query xml에서 공통 선언된 type을 이용하기 때문에 * Becasue a common column type in schema/query xml is used for colum_type,
* DBMS에 맞게 replace 해주어야 한다 * it should be replaced properly for each DBMS
**/ **/
var $column_type = array( var $column_type = array(
'bignumber' => 'INTEGER', 'bignumber' => 'INTEGER',
@ -51,7 +51,7 @@
} }
/** /**
* @brief 설치 가능 여부를 return * @brief Return if it is installable
**/ **/
function isSupported() { function isSupported() {
if(!function_exists('sqlite_open')) return false; if(!function_exists('sqlite_open')) return false;
@ -59,7 +59,7 @@
} }
/** /**
* @brief DB정보 설정 connect/ close * @brief DB settings and connect/close
**/ **/
function _setDBInfo() { function _setDBInfo() {
$db_info = Context::getDBInfo(); $db_info = Context::getDBInfo();
@ -69,27 +69,25 @@
} }
/** /**
* @brief DB 접속 * @brief DB Connection
**/ **/
function _connect() { function _connect() {
// db 정보가 없으면 무시 // Ignore if no DB information exists
if(!$this->database) return; if(!$this->database) return;
// Attempt to access the database file
// 데이터 베이스 파일 접속 시도
$this->fd = sqlite_open($this->database, 0666, $error); $this->fd = sqlite_open($this->database, 0666, $error);
if(!file_exists($this->database) || $error) { if(!file_exists($this->database) || $error) {
$this->setError(-1,$error); $this->setError(-1,$error);
$this->is_connected = false; $this->is_connected = false;
return; return;
} }
// Check connections
// 접속체크
$this->is_connected = true; $this->is_connected = true;
$this->password = md5($this->password); $this->password = md5($this->password);
} }
/** /**
* @brief DB접속 해제 * @brief DB disconnection
**/ **/
function close() { function close() {
if(!$this->isConnected()) return; if(!$this->isConnected()) return;
@ -97,7 +95,7 @@
} }
/** /**
* @brief 트랜잭션 시작 * @brief Begin transaction
**/ **/
function begin() { function begin() {
if(!$this->is_connected || $this->transaction_started) return; if(!$this->is_connected || $this->transaction_started) return;
@ -105,7 +103,7 @@
} }
/** /**
* @brief 롤백 * @brief Rollback
**/ **/
function rollback() { function rollback() {
if(!$this->is_connected || !$this->transaction_started) return; if(!$this->is_connected || !$this->transaction_started) return;
@ -114,7 +112,7 @@
} }
/** /**
* @brief 커밋 * @brief Commits
**/ **/
function commit($force = false) { function commit($force = false) {
if(!$force && (!$this->isConnected() || !$this->transaction_started)) return; if(!$force && (!$this->isConnected() || !$this->transaction_started)) return;
@ -124,7 +122,7 @@
} }
/** /**
* @brief 쿼리에서 입력되는 문자열 변수들의 quotation 조절 * @brief Add quotes on the string variables in a query
**/ **/
function addQuotes($string) { function addQuotes($string) {
if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string)); if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string));
@ -133,34 +131,30 @@
} }
/** /**
* @brief : 쿼리문의 실행 결과의 fetch 처리 * @brief : Run a query and fetch the result
* *
* query : query문 실행하고 result return\n * query: run a query and return the result \n
* fetch : reutrn 값이 없으면 NULL\n * fetch: NULL if no value is returned \n
* rows이면 array object\n * array object if rows are returned \n
* row이면 object\n * object if a row is returned \n
* return\n * return\n
**/ **/
function _query($query) { function _query($query) {
if(!$this->isConnected()) return; if(!$this->isConnected()) return;
// Notify to start a query execution
// 쿼리 시작을 알림
$this->actStart($query); $this->actStart($query);
// Run the query statement
// 쿼리 문 실행
$result = @sqlite_query($query, $this->fd); $result = @sqlite_query($query, $this->fd);
// Error Check
// 오류 체크
if(sqlite_last_error($this->fd)) $this->setError(sqlite_last_error($this->fd), sqlite_error_string(sqlite_last_error($this->fd))); if(sqlite_last_error($this->fd)) $this->setError(sqlite_last_error($this->fd), sqlite_error_string(sqlite_last_error($this->fd)));
// Notify to complete a query execution
// 쿼리 실행 알림
$this->actFinish(); $this->actFinish();
return $result; return $result;
} }
/** /**
* @brief 결과를 fetch * @brief Fetch results
**/ **/
function _fetch($result) { function _fetch($result) {
if($this->isError() || !$result) return; if($this->isError() || !$result) return;
@ -180,7 +174,7 @@
} }
/** /**
* @brief 1 증가되는 sequence값을 return * @brief Return the sequence value is incremented by 1
**/ **/
function getNextSequence() { function getNextSequence() {
$query = sprintf("insert into %ssequence (seq) values ('')", $this->prefix); $query = sprintf("insert into %ssequence (seq) values ('')", $this->prefix);
@ -195,7 +189,7 @@
} }
/** /**
* @brief 테이블 기생성 여부 return * @brief Return if a table already exists
**/ **/
function isTableExists($target_name) { function isTableExists($target_name) {
$query = sprintf('pragma table_info(%s%s)', $this->prefix, $this->addQuotes($target_name)); $query = sprintf('pragma table_info(%s%s)', $this->prefix, $this->addQuotes($target_name));
@ -205,7 +199,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 column 추가 * @brief Add a column to a table
**/ **/
function addColumn($table_name, $column_name, $type='number', $size='', $default = '', $notnull=false) { function addColumn($table_name, $column_name, $type='number', $size='', $default = '', $notnull=false) {
$type = $this->column_type[$type]; $type = $this->column_type[$type];
@ -221,7 +215,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 column 제거 * @brief Delete a column from a table
**/ **/
function dropColumn($table_name, $column_name) { function dropColumn($table_name, $column_name) {
$query = sprintf("alter table %s%s drop column %s ", $this->prefix, $table_name, $column_name); $query = sprintf("alter table %s%s drop column %s ", $this->prefix, $table_name, $column_name);
@ -229,7 +223,7 @@
} }
/** /**
* @brief 특정 테이블의 column의 정보를 return * @brief Return column information of a table
**/ **/
function isColumnExists($table_name, $column_name) { function isColumnExists($table_name, $column_name) {
$query = sprintf("pragma table_info(%s%s)", $this->prefix, $table_name); $query = sprintf("pragma table_info(%s%s)", $this->prefix, $table_name);
@ -246,7 +240,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 인덱스 추가 * @brief Add an index to a table
* $target_columns = array(col1, col2) * $target_columns = array(col1, col2)
* $is_unique? unique : none * $is_unique? unique : none
**/ **/
@ -261,7 +255,7 @@
} }
/** /**
* @brief 특정 테이블의 특정 인덱스 삭제 * @brief Drop an index from a table
**/ **/
function dropIndex($table_name, $index_name, $is_unique = false) { function dropIndex($table_name, $index_name, $is_unique = false) {
$key_name = sprintf('%s%s_%s', $this->prefix, $table_name, $index_name); $key_name = sprintf('%s%s_%s', $this->prefix, $table_name, $index_name);
@ -270,7 +264,7 @@
} }
/** /**
* @brief 특정 테이블의 index 정보를 return * @brief Return index information of a table
**/ **/
function isIndexExists($table_name, $index_name) { function isIndexExists($table_name, $index_name) {
$key_name = sprintf('%s%s_%s', $this->prefix, $table_name, $index_name); $key_name = sprintf('%s%s_%s', $this->prefix, $table_name, $index_name);
@ -282,24 +276,24 @@
} }
/** /**
* @brief xml 받아서 테이블을 생성 * @brief Create a table by using xml file
**/ **/
function createTableByXml($xml_doc) { function createTableByXml($xml_doc) {
return $this->_createTable($xml_doc); return $this->_createTable($xml_doc);
} }
/** /**
* @brief xml 받아서 테이블을 생성 * @brief Create a table by using xml file
**/ **/
function createTableByXmlFile($file_name) { function createTableByXmlFile($file_name) {
if(!file_exists($file_name)) return; if(!file_exists($file_name)) return;
// xml 파일을 읽음 // read xml file
$buff = FileHandler::readFile($file_name); $buff = FileHandler::readFile($file_name);
return $this->_createTable($buff); 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 * type : number, varchar, text, char, date, \n
* opt : notnull, default, size\n * opt : notnull, default, size\n
@ -309,8 +303,7 @@
// xml parsing // xml parsing
$oXml = new XmlParser(); $oXml = new XmlParser();
$xml_obj = $oXml->parse($xml_doc); $xml_obj = $oXml->parse($xml_doc);
// Create a table schema
// 테이블 생성 schema 작성
$table_name = $xml_obj->table->attrs->name; $table_name = $xml_obj->table->attrs->name;
if($this->isTableExists($table_name)) return; if($this->isTableExists($table_name)) return;
$table_name = $this->prefix.$table_name; $table_name = $this->prefix.$table_name;
@ -371,7 +364,7 @@
} }
/** /**
* @brief 조건문 작성하여 return * @brief Return conditional clause
**/ **/
function getCondition($output) { function getCondition($output) {
if(!$output->conditions) return; if(!$output->conditions) return;
@ -415,15 +408,14 @@
} }
/** /**
* @brief insertAct 처리 * @brief Handle the insertAct
**/ **/
function _executeInsertAct($output) { function _executeInsertAct($output) {
// 테이블 정리 // List tables
foreach($output->tables as $key => $val) { foreach($output->tables as $key => $val) {
$table_list[] = $this->prefix.$val; $table_list[] = $this->prefix.$val;
} }
// List columns
// 컬럼 정리
foreach($output->columns as $key => $val) { foreach($output->columns as $key => $val) {
$name = $val['name']; $name = $val['name'];
$value = $val['value']; $value = $val['value'];
@ -444,18 +436,16 @@
} }
/** /**
* @brief updateAct 처리 * @brief Handle updateAct
**/ **/
function _executeUpdateAct($output) { function _executeUpdateAct($output) {
$table_count = count(array_values($output->tables)); $table_count = count(array_values($output->tables));
// If one day the destination table
// 대상 테이블이 1개일 경우
if($table_count == 1) { if($table_count == 1) {
// 테이블 정리 // List tables
list($target_table) = array_values($output->tables); list($target_table) = array_values($output->tables);
$target_table = $this->prefix.$target_table; $target_table = $this->prefix.$target_table;
// List columns
// 컬럼 정리
foreach($output->columns as $key => $val) { foreach($output->columns as $key => $val) {
if(!isset($val['value'])) continue; if(!isset($val['value'])) continue;
$name = $val['name']; $name = $val['name'];
@ -469,27 +459,23 @@
$column_list[] = sprintf("%s = %s", $name, $value); $column_list[] = sprintf("%s = %s", $name, $value);
} }
} }
// List the conditional clause
// 조건절 정리
$condition = $this->getCondition($output); $condition = $this->getCondition($output);
$query = sprintf("update %s set %s %s", $target_table, implode(',',$column_list), $condition); $query = sprintf("update %s set %s %s", $target_table, implode(',',$column_list), $condition);
// trick to handle if targt table to update is more than one (sqlite doesn't support update to multi-tables)
// 대상 테이블이 2개일 경우 (sqlite에서 update 테이블을 1개 이상 지정 못해서 이렇게 꽁수로... 다른 방법이 있으려나..)
} elseif($table_count == 2) { } elseif($table_count == 2) {
// 테이블 정리 // List tables
foreach($output->tables as $key => $val) { foreach($output->tables as $key => $val) {
$table_list[$val] = $this->prefix.$key; $table_list[$val] = $this->prefix.$key;
} }
list($source_table, $target_table) = array_values($table_list); list($source_table, $target_table) = array_values($table_list);
// List the conditional clause
// 조건절 정리
$condition = $this->getCondition($output); $condition = $this->getCondition($output);
foreach($table_list as $key => $val) { foreach($table_list as $key => $val) {
$condition = eregi_replace($key.'\\.', $val.'.', $condition); $condition = eregi_replace($key.'\\.', $val.'.', $condition);
} }
// List columns
// 컬럼 정리
foreach($output->columns as $key => $val) { foreach($output->columns as $key => $val) {
if(!isset($val['value'])) continue; if(!isset($val['value'])) continue;
$name = $val['name']; $name = $val['name'];
@ -511,15 +497,14 @@
} }
/** /**
* @brief deleteAct 처리 * @brief Handle deleteAct
**/ **/
function _executeDeleteAct($output) { function _executeDeleteAct($output) {
// 테이블 정리 // List tables
foreach($output->tables as $key => $val) { foreach($output->tables as $key => $val) {
$table_list[] = $this->prefix.$val; $table_list[] = $this->prefix.$val;
} }
// List the conditional clause
// 조건절 정리
$condition = $this->getCondition($output); $condition = $this->getCondition($output);
$query = sprintf("delete from %s %s", implode(',',$table_list), $condition); $query = sprintf("delete from %s %s", implode(',',$table_list), $condition);
@ -528,13 +513,13 @@
} }
/** /**
* @brief selectAct 처리 * @brief Handle selectAct
* *
* select의 경우 특정 페이지의 목록을 가져오는 것을 편하게 하기 위해\n * In order to get a list of pages easily when selecting \n
* navigation이라는 method를 제공 * it supports a method as navigation
**/ **/
function _executeSelectAct($output) { function _executeSelectAct($output) {
// 테이블 정리 // List tables
$table_list = array(); $table_list = array();
foreach($output->tables as $key => $val) { foreach($output->tables as $key => $val) {
$table_list[] = $this->prefix.$val.' as '.$key; $table_list[] = $this->prefix.$val.' as '.$key;
@ -577,8 +562,7 @@
$output->column_list = $column_list; $output->column_list = $column_list;
if($output->list_count && $output->page) return $this->_getNavigationData($table_list, $columns, $left_join, $condition, $output); if($output->list_count && $output->page) return $this->_getNavigationData($table_list, $columns, $left_join, $condition, $output);
// Add a condition to use an index when sorting in order by list_order, update_order
// list_order, update_order 로 정렬시에 인덱스 사용을 위해 condition에 쿼리 추가
if($output->order) { if($output->order) {
$conditions = $this->getConditionList($output); $conditions = $this->getConditionList($output);
if(!in_array('list_order', $conditions) && !in_array('update_order', $conditions)) { if(!in_array('list_order', $conditions) && !in_array('update_order', $conditions)) {
@ -601,8 +585,7 @@
} }
if(count($index_list)) $query .= ' order by '.implode(',',$index_list); if(count($index_list)) $query .= ' order by '.implode(',',$index_list);
} }
// Apply when using list_count
// list_count를 사용할 경우 적용
if($output->list_count['value']) $query = sprintf('%s limit %d', $query, $output->list_count['value']); if($output->list_count['value']) $query = sprintf('%s limit %d', $query, $output->list_count['value']);
$query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id):''; $query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id):'';
@ -624,17 +607,17 @@
} }
/** /**
* @brief query xml에 navigation 정보가 있을 경우 페이징 관련 작업을 처리한다 * @brief Paging is handled if navigation information exists in the query xml
* *
* 그닥 좋지는 않은 구조이지만 편리하다.. -_-; * It is quite convenient although its structure is not good at all .. -_-;
**/ **/
function _getNavigationData($table_list, $columns, $left_join, $condition, $output) { function _getNavigationData($table_list, $columns, $left_join, $condition, $output) {
require_once(_XE_PATH_.'classes/page/PageHandler.class.php'); require_once(_XE_PATH_.'classes/page/PageHandler.class.php');
$column_list = $output->column_list; $column_list = $output->column_list;
/* /*
// group by 절이 포함된 SELECT 쿼리의 전체 갯수를 구하기 위한 수정 // Modified to find total number of SELECT queries having group by clause
// 정상적인 동작이 확인되면 주석으로 막아둔 부분으로 대체합니다. // If it works correctly, uncomment the following codes
// //
$count_condition = count($output->groups) ? sprintf('%s group by %s', $condition, implode(', ', $output->groups)) : $condition; $count_condition = count($output->groups) ? sprintf('%s group by %s', $condition, implode(', ', $output->groups)) : $condition;
$total_count = $this->getCountCache($output->tables, $count_condition); $total_count = $this->getCountCache($output->tables, $count_condition);
@ -648,8 +631,7 @@
$this->putCountCache($output->tables, $count_condition, $total_count); $this->putCountCache($output->tables, $count_condition, $total_count);
} }
*/ */
// Get a total count
// 전체 개수를 구함
$count_query = sprintf("select count(*) as count from %s %s %s", implode(',',$table_list),implode(' ',$left_join), $condition); $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(*)'):''; $count_query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id . ' count(*)'):'';
$result = $this->_query($count_query); $result = $this->_query($count_query);
@ -662,16 +644,13 @@
if(!$page_count) $page_count = 10; if(!$page_count) $page_count = 10;
$page = $output->page['value']; $page = $output->page['value'];
if(!$page) $page = 1; if(!$page) $page = 1;
// Get a total page
// 전체 페이지를 구함
if($total_count) $total_page = (int)( ($total_count-1) / $list_count) + 1; if($total_count) $total_page = (int)( ($total_count-1) / $list_count) + 1;
else $total_page = 1; else $total_page = 1;
// Check Page variables
// 페이지 변수를 체크
if($page > $total_page) $page = $total_page; if($page > $total_page) $page = $total_page;
$start_count = ($page-1)*$list_count; $start_count = ($page-1)*$list_count;
// Add a condition to use an index when sorting in order by list_order, update_order
// list_order, update_order 로 정렬시에 인덱스 사용을 위해 condition에 쿼리 추가
if($output->order) { if($output->order) {
$conditions = $this->getConditionList($output); $conditions = $this->getConditionList($output);
if(!in_array('list_order', $conditions) && !in_array('update_order', $conditions)) { if(!in_array('list_order', $conditions) && !in_array('update_order', $conditions)) {

View file

@ -2,21 +2,21 @@
/** /**
* @class DBSqlite3_pdo * @class DBSqlite3_pdo
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief SQLite3를 PDO로 이용하여 class * @brief class to use SQLite3 with PDO
* @version 0.1 * @version 0.1
**/ **/
class DBSqlite3_pdo extends DB { class DBSqlite3_pdo extends DB {
/** /**
* DB이용하기 위한 정보 * DB information
**/ **/
var $database = NULL; ///< database var $database = NULL; ///< database
var $prefix = 'xe'; ///< XE에서 사용할 테이블들의 prefix (한 DB에서 여러개의 XE 설치 가능) var $prefix = 'xe'; // /< prefix of a tablename (many XEs can be installed in a single DB)
var $comment_syntax = '/* %s */'; var $comment_syntax = '/* %s */';
/** /**
* PDO 사용시 필요한 변수들 * Variables for using PDO
**/ **/
var $handler = NULL; var $handler = NULL;
var $stmt = NULL; var $stmt = NULL;
@ -24,10 +24,10 @@
var $bind_vars = array(); var $bind_vars = array();
/** /**
* @brief sqlite3 에서 사용될 column type * @brief column type used in sqlite3
* *
* column_typeschema/query xml에서 공통 선언된 type을 이용하기 때문에 * column_type should be replaced for each DBMS properly
* DBMS에 맞게 replace 해주어야 한다 * because column_type uses a commonly defined type in schema/query xml files
**/ **/
var $column_type = array( var $column_type = array(
'bignumber' => 'INTEGER', 'bignumber' => 'INTEGER',
@ -57,47 +57,51 @@
} }
/** /**
* @brief 설치 가능 여부를 return * @brief Return if installable
**/ **/
function isSupported() { function isSupported() {
return class_exists('PDO'); return class_exists('PDO');
} }
function isConnected() {
return $this->is_connected;
}
/** /**
* @brief DB정보 설정 connect/ close * @brief DB settings and connect/close
**/ **/
function _setDBInfo() { function _setDBInfo() {
$db_info = Context::getDBInfo(); $db_info = Context::getDBInfo();
$this->database = $db_info->db_database; $this->database = $db_info->master_db["db_database"];
$this->prefix = $db_info->db_table_prefix; $this->prefix = $db_info->master_db["db_table_prefix"];
if(!substr($this->prefix,-1)!='_') $this->prefix .= '_'; //if(!substr($this->prefix,-1)!='_') $this->prefix .= '_';
} }
/** /**
* @brief DB 접속 * @brief DB Connection
**/ **/
function _connect() { function _connect() {
// db 정보가 없으면 무시 // override if db information not exists
if(!$this->database) return; if(!$this->database) return;
// 데이터 베이스 파일 접속 시도 // Attempt to access the database file
try { try {
// PDO is only supported with PHP5, // PDO is only supported with PHP5,
// so it is allowed to use try~catch statment in this class. // so it is allowed to use try~catch statment in this class.
$this->handler = new PDO('sqlite:'.$this->database); $this->handler = new PDO('sqlite:'.$this->database);
} catch (PDOException $e) { } catch (PDOException $e) {
$this->setError(-1, 'Connection failed: '.$e->getMessage()); $this->setError(-1, 'Connection failed: '.$e->getMessage());
$this->is_connected = false; $this->is_connected = false;
return; return;
} }
// 접속체크 // Check connections
$this->is_connected = true; $this->is_connected = true;
$this->password = md5($this->password); $this->password = md5($this->password);
} }
/** /**
* @brief DB접속 해제 * @brief disconnect to DB
**/ **/
function close() { function close() {
if(!$this->is_connected) return; if(!$this->is_connected) return;
@ -105,7 +109,7 @@
} }
/** /**
* @brief 트랜잭션 시작 * @brief Begin a transaction
**/ **/
function begin() { function begin() {
if(!$this->is_connected || $this->transaction_started) return; if(!$this->is_connected || $this->transaction_started) return;
@ -113,7 +117,7 @@
} }
/** /**
* @brief 롤백 * @brief Rollback
**/ **/
function rollback() { function rollback() {
if(!$this->is_connected || !$this->transaction_started) return; if(!$this->is_connected || !$this->transaction_started) return;
@ -122,16 +126,22 @@
} }
/** /**
* @brief 커밋 * @brief Commit
**/ **/
function commit($force = false) { function commit($force = false) {
if(!$force && (!$this->is_connected || !$this->transaction_started)) return; if(!$force && (!$this->is_connected || !$this->transaction_started)) return;
$this->handler->commit(); try {
$this->handler->commit();
}
catch(PDOException $e){
// There was no transaction started, so just continue.
error_log($e->getMessage());
}
$this->transaction_started = false; $this->transaction_started = false;
} }
/** /**
* @brief 쿼리에서 입력되는 문자열 변수들의 quotation 조절 * @brief Add or change quotes to the query string variables
**/ **/
function addQuotes($string) { function addQuotes($string) {
if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string)); if(version_compare(PHP_VERSION, "5.9.0", "<") && get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string));
@ -140,12 +150,12 @@
} }
/** /**
* @brief : 쿼리문의 prepare * @brief : Prepare a query statement
**/ **/
function _prepare($query) { function _prepare($query) {
if(!$this->is_connected) return; if(!$this->is_connected) return;
// 쿼리 시작을 알림 // notify to start a query execution
$this->actStart($query); $this->actStart($query);
$this->stmt = $this->handler->prepare($query); $this->stmt = $this->handler->prepare($query);
@ -159,7 +169,7 @@
} }
/** /**
* @brief : stmt에 binding params * @brief : Binding params in stmt
**/ **/
function _bind($val) { function _bind($val) {
if(!$this->is_connected || !$this->stmt) return; if(!$this->is_connected || !$this->stmt) return;
@ -170,7 +180,7 @@
} }
/** /**
* @brief : prepare된 쿼리의 execute * @brief : execute the prepared statement
**/ **/
function _execute() { function _execute() {
if(!$this->is_connected || !$this->stmt) return; if(!$this->is_connected || !$this->stmt) return;
@ -200,7 +210,7 @@
} }
/** /**
* @brief 1 증가되는 sequence값을 return * @brief Return the sequence value incremented by 1
**/ **/
function getNextSequence() { function getNextSequence() {
$query = sprintf("insert into %ssequence (seq) values (NULL)", $this->prefix); $query = sprintf("insert into %ssequence (seq) values (NULL)", $this->prefix);
@ -217,7 +227,7 @@
} }
/** /**
* @brief 테이블 기생성 여부 return * @brief return if the table already exists
**/ **/
function isTableExists($target_name) { function isTableExists($target_name) {
$query = sprintf('pragma table_info(%s%s)', $this->prefix, $target_name); $query = sprintf('pragma table_info(%s%s)', $this->prefix, $target_name);
@ -227,7 +237,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 column 추가 * @brief Add a column to a table
**/ **/
function addColumn($table_name, $column_name, $type='number', $size='', $default = '', $notnull=false) { function addColumn($table_name, $column_name, $type='number', $size='', $default = '', $notnull=false) {
$type = $this->column_type[$type]; $type = $this->column_type[$type];
@ -244,7 +254,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 column 제거 * @brief Remove a column from a table
**/ **/
function dropColumn($table_name, $column_name) { function dropColumn($table_name, $column_name) {
$query = sprintf("alter table %s%s drop column %s ", $this->prefix, $table_name, $column_name); $query = sprintf("alter table %s%s drop column %s ", $this->prefix, $table_name, $column_name);
@ -252,7 +262,7 @@
} }
/** /**
* @brief 특정 테이블의 column의 정보를 return * @brief Return column information of a table
**/ **/
function isColumnExists($table_name, $column_name) { function isColumnExists($table_name, $column_name) {
$query = sprintf("pragma table_info(%s%s)", $this->prefix, $table_name); $query = sprintf("pragma table_info(%s%s)", $this->prefix, $table_name);
@ -270,7 +280,7 @@
} }
/** /**
* @brief 특정 테이블에 특정 인덱스 추가 * @brief Add an index to a table
* $target_columns = array(col1, col2) * $target_columns = array(col1, col2)
* $is_unique? unique : none * $is_unique? unique : none
**/ **/
@ -285,7 +295,7 @@
} }
/** /**
* @brief 특정 테이블의 특정 인덱스 삭제 * @brief Drop an index from a table
**/ **/
function dropIndex($table_name, $index_name, $is_unique = false) { function dropIndex($table_name, $index_name, $is_unique = false) {
$key_name = sprintf('%s%s_%s', $this->prefix, $table_name, $index_name); $key_name = sprintf('%s%s_%s', $this->prefix, $table_name, $index_name);
@ -294,7 +304,7 @@
} }
/** /**
* @brief 특정 테이블의 index 정보를 return * @brief Return index information of a table
**/ **/
function isIndexExists($table_name, $index_name) { function isIndexExists($table_name, $index_name) {
$key_name = sprintf('%s%s_%s', $this->prefix, $table_name, $index_name); $key_name = sprintf('%s%s_%s', $this->prefix, $table_name, $index_name);
@ -307,24 +317,24 @@
} }
/** /**
* @brief xml 받아서 테이블을 생성 * @brief create a table from xml file
**/ **/
function createTableByXml($xml_doc) { function createTableByXml($xml_doc) {
return $this->_createTable($xml_doc); return $this->_createTable($xml_doc);
} }
/** /**
* @brief xml 받아서 테이블을 생성 * @brief create a table from xml file
**/ **/
function createTableByXmlFile($file_name) { function createTableByXmlFile($file_name) {
if(!file_exists($file_name)) return; if(!file_exists($file_name)) return;
// xml 파일을 읽음 // read xml file
$buff = FileHandler::readFile($file_name); $buff = FileHandler::readFile($file_name);
return $this->_createTable($buff); return $this->_createTable($buff);
} }
/** /**
* @brief schema xml을 이용하여 create table query생성 * @brief generate a query to create a table using the schema xml
* *
* type : number, varchar, text, char, date, \n * type : number, varchar, text, char, date, \n
* opt : notnull, default, size\n * opt : notnull, default, size\n
@ -334,8 +344,7 @@
// xml parsing // xml parsing
$oXml = new XmlParser(); $oXml = new XmlParser();
$xml_obj = $oXml->parse($xml_doc); $xml_obj = $oXml->parse($xml_doc);
// Create a table schema
// 테이블 생성 schema 작성
$table_name = $xml_obj->table->attrs->name; $table_name = $xml_obj->table->attrs->name;
if($this->isTableExists($table_name)) return; if($this->isTableExists($table_name)) return;
$table_name = $this->prefix.$table_name; $table_name = $this->prefix.$table_name;
@ -400,420 +409,220 @@
} }
} }
/** function _getConnection($type = null){
* @brief 조건문 작성하여 return return null;
**/ }
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); * @brief insertAct
} * */
function _executeInsertAct($queryObject) {
$query = $this->getInsertSql($queryObject);
if (is_a($query, 'Object'))
return;
$this->_prepare($query);
function _getCondition($conditions,$column_type) { $val_count = count($val_list);
$condition = ''; for ($i = 0; $i < $val_count; $i++)
foreach($conditions as $val) { $this->_bind($val_list[$i]);
$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;
$name = $v['column']; return $this->_execute();
$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']; * @brief updateAct
$str = $this->getConditionPart($name, $value, $operation); * */
if($sub_condition) $sub_condition .= ' '.$pipe.' '; function _executeUpdateAct($queryObject) {
$sub_condition .= $str; $query = $this->getUpdateSql($queryObject);
} if (is_a($query, 'Object'))
if($sub_condition) { return;
if($condition && $val['pipe']) $condition .= ' '.$val['pipe'].' ';
$condition .= '('.$sub_condition.')';
}
}
return $condition;
}
/** $this->_prepare($query);
* @brief insertAct 처리 return $this->_execute();
**/ }
function _executeInsertAct($output) {
// 테이블 정리
foreach($output->tables as $key => $val) {
$table_list[] = $this->prefix.$val;
}
// 컬럼 정리 /**
foreach($output->columns as $key => $val) { * @brief deleteAct
$name = $val['name']; * */
$value = $val['value']; function _executeDeleteAct($queryObject) {
$query = $this->getDeleteSql($queryObject);
if (is_a($query, 'Object'))
return;
$key_list[] = $name; $this->_prepare($query);
return $this->_execute();
}
if($output->column_type[$name]!='number') $val_list[] = $this->addQuotes($value); /**
else { * @brief selectAct
$this->_filterNumber(&$value); *
$val_list[] = $value; * To fetch a list of the page conveniently when selecting, \n
} * navigation method supported
* */
function _executeSelectAct($queryObject) {
$query = $this->getSelectSql($queryObject);
if (is_a($query, 'Object'))
return;
$prepare_list[] = '?'; $this->_prepare($query);
} $data = $this->_execute();
// TODO isError is called twice
if ($this->isError())
return;
$query = sprintf("INSERT INTO %s (%s) VALUES (%s);", implode(',',$table_list), implode(',',$key_list), implode(',',$prepare_list)); if ($this->isError())
return $this->queryError($queryObject);
else
return $this->queryPageLimit($queryObject, $data);
}
$this->_prepare($query); function queryError($queryObject) {
if ($queryObject->getLimit() && $queryObject->getLimit()->isPageHandler()) {
$val_count = count($val_list); $buff = new Object ();
for($i=0;$i<$val_count;$i++) $this->_bind($val_list[$i]);
return $this->_execute();
}
/**
* @brief updateAct 처리
**/
function _executeUpdateAct($output) {
$table_count = count(array_values($output->tables));
// 대상 테이블이 1개일 경우
if($table_count == 1) {
// 테이블 정리
list($target_table) = array_values($output->tables);
$target_table = $this->prefix.$target_table;
// 컬럼 정리
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)."'";
else $this->_filterNumber(&$value);
$column_list[] = sprintf("%s = %s", $name, $value);
}
}
// 조건절 정리
$condition = $this->getCondition($output);
$query = sprintf("update %s set %s %s", $target_table, implode(',',$column_list), $condition);
// 대상 테이블이 2개일 경우 (sqlite에서 update 테이블을 1개 이상 지정 못해서 이렇게 꽁수로... 다른 방법이 있으려나..)
} elseif($table_count == 2) {
// 테이블 정리
foreach($output->tables as $key => $val) {
$table_list[$val] = $this->prefix.$key;
}
list($source_table, $target_table) = array_values($table_list);
// 조건절 정리
$condition = $this->getCondition($output);
foreach($table_list as $key => $val) {
$condition = eregi_replace($key.'\\.', $val.'.', $condition);
}
// 컬럼 정리
foreach($output->columns as $key => $val) {
if(!isset($val['value'])) continue;
$name = $val['name'];
$value = $val['value'];
list($s_prefix, $s_column) = explode('.',$name);
list($t_prefix, $t_column) = explode('.',$value);
$s_table = $table_list[$s_prefix];
$t_table = $table_list[$t_prefix];
$column_list[] = sprintf(' %s = (select %s from %s %s) ', $s_column, $t_column, $t_table, $condition);
}
$query = sprintf('update %s set %s where exists(select * from %s %s)', $source_table, implode(',', $column_list), $target_table, $condition);
} else {
return;
}
$this->_prepare($query);
return $this->_execute();
}
/**
* @brief deleteAct 처리
**/
function _executeDeleteAct($output) {
// 테이블 정리
foreach($output->tables as $key => $val) {
$table_list[] = $this->prefix.$val;
}
// 조건절 정리
$condition = $this->getCondition($output);
$query = sprintf("delete from %s %s", implode(',',$table_list), $condition);
$this->_prepare($query);
return $this->_execute();
}
/**
* @brief selectAct 처리
*
* select의 경우 특정 페이지의 목록을 가져오는 것을 편하게 하기 위해\n
* navigation이라는 method를 제공
**/
function _executeSelectAct($output) {
// 테이블 정리
$table_list = array();
foreach($output->tables as $key => $val) {
$table_list[] = $this->prefix.$val.' as '.$key;
}
$left_join = array();
// why???
$left_tables= (array)$output->left_tables;
foreach($left_tables as $key => $val) {
$condition = $this->_getCondition($output->left_conditions[$key],$output->column_type);
if($condition){
$left_join[] = $val . ' '.$this->prefix.$output->_tables[$key].' as '.$key . ' on (' . $condition . ')';
}
}
$click_count = array();
if(!$output->columns){
$output->columns = array(array('name'=>'*'));
}
$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);
}
}
$columns = implode(',',$column_list);
$condition = $this->getCondition($output);
$output->column_list = $column_list;
if($output->list_count && $output->page) return $this->_getNavigationData($table_list, $columns, $left_join, $condition, $output);
// list_order, update_order 로 정렬시에 인덱스 사용을 위해 condition에 쿼리 추가
if($output->order) {
$conditions = $this->getConditionList($output);
if(!in_array('list_order', $conditions) && !in_array('update_order', $conditions)) {
foreach($output->order as $key => $val) {
$col = $val[0];
if(!in_array($col, array('list_order','update_order'))) continue;
if($condition) $condition .= sprintf(' and %s < 2100000000 ', $col);
else $condition = sprintf(' where %s < 2100000000 ', $col);
}
}
}
if(count($output->groups)){
$groupby_query = sprintf(' group by %s', implode(',',$output->groups));
if(count($output->arg_columns))
{
foreach($output->groups as $group)
{
if($column_list[$group]) $output->arg_columns[] = $column_list[$group];
}
}
}
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);
// list_count를 사용할 경우 적용
if($output->list_count['value']) $query = sprintf('%s limit %d', $query, $output->list_count['value']);
$query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id):'';
$this->_prepare($query);
$data = $this->_execute();
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);
}
$buff = new Object();
$buff->data = $data;
return $buff;
}
/**
* @brief query xml에 navigation 정보가 있을 경우 페이징 관련 작업을 처리한다
*
* 그닥 좋지는 않은 구조이지만 편리하다.. -_-;
**/
function _getNavigationData($table_list, $columns, $left_join, $condition, $output) {
require_once(_XE_PATH_.'classes/page/PageHandler.class.php');
$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(*)'):'';
$this->_prepare($count_query);
$count_output = $this->_execute();
$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)){
$groupby_query = sprintf(' group by %s', implode(',',$output->groups));
if(count($output->arg_columns))
{
foreach($output->groups as $group)
{
if($column_list[$group]) $output->arg_columns[] = $column_list[$group];
}
}
}
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);
}
// return 결과물 생성
$buff = new Object();
$buff->total_count = 0; $buff->total_count = 0;
$buff->total_page = 0; $buff->total_page = 0;
$buff->page = 1; $buff->page = 1;
$buff->data = array(); $buff->data = array();
$buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count); $buff->page_navigation = new PageHandler(/* $total_count */0, /* $total_page */1, /* $page */1, /* $page_count */10); //default page handler values
return $buff;
}else
return;
}
// 쿼리 실행 function queryPageLimit($queryObject, $data) {
$query = sprintf("select %s from %s %s %s %s", $columns, implode(',',$table_list),implode(' ',$left_join), $condition, $groupby_query.$orderby_query); if ($queryObject->getLimit() && $queryObject->getLimit()->isPageHandler()) {
$query = sprintf('%s limit %d, %d', $query, $start_count, $list_count); // Total count
$query .= (__DEBUG_QUERY__&1 && $output->query_id)?sprintf(' '.$this->comment_syntax,$this->query_id):''; $temp_where = $queryObject->getWhereString(true, false);
$count_query = sprintf('select count(*) as "count" %s %s', 'FROM ' . $queryObject->getFromString(), ($temp_where === '' ? '' : ' WHERE ' . $temp_where));
$this->_prepare($query); if ($queryObject->getGroupByString() != '') {
$count_query = sprintf('select count(*) as "count" from (%s) xet', $count_query);
if($this->isError()) {
$this->setError($this->handler->errorCode(), print_r($this->handler->errorInfo(),true));
$this->actFinish();
return $buff;
} }
$this->stmt->execute(); $count_query .= ( __DEBUG_QUERY__ & 1 && $output->query_id) ? sprintf(' ' . $this->comment_syntax, $this->query_id) : '';
$this->_prepare($count_query);
$count_output = $this->_execute();
$total_count = (int) $count_output->count;
if($this->stmt->errorCode() != '00000') { $list_count = $queryObject->getLimit()->list_count->getValue();
$this->setError($this->stmt->errorCode(), print_r($this->stmt->errorInfo(),true)); if (!$list_count) $list_count = 20;
$page_count = $queryObject->getLimit()->page_count->getValue();
if (!$page_count) $page_count = 10;
$page = $queryObject->getLimit()->page->getValue();
if (!$page) $page = 1;
// Total pages
if ($total_count) {
$total_page = (int) (($total_count - 1) / $list_count) + 1;
} else
$total_page = 1;
// check the page variables
if ($page > $total_page) $page = $total_page;
$start_count = ($page - 1) * $list_count;
$this->_prepare($this->getSelectPageSql($queryObject, true, $start_count, $list_count));
$this->stmt->execute();
if ($this->stmt->errorCode() != '00000') {
$this->setError($this->stmt->errorCode(), print_r($this->stmt->errorInfo(), true));
$this->actFinish(); $this->actFinish();
return $buff; return $buff;
} }
$output = null; $output = null;
$virtual_no = $total_count - ($page-1)*$list_count; $virtual_no = $total_count - ($page - 1) * $list_count;
while($tmp = $this->stmt->fetch(PDO::FETCH_ASSOC)) { //$data = $this->_fetch($result, $virtual_no);
while ($tmp = $this->stmt->fetch(PDO::FETCH_ASSOC)) {
unset($obj); unset($obj);
foreach($tmp as $key => $val) { foreach ($tmp as $key => $val) {
$pos = strpos($key, '.'); $pos = strpos($key, '.');
if($pos) $key = substr($key, $pos+1); if ($pos)
$key = substr($key, $pos + 1);
$obj->{$key} = $val; $obj->{$key} = $val;
} }
$data[$virtual_no--] = $obj; $datatemp[$virtual_no--] = $obj;
} }
$this->stmt = null; $this->stmt = null;
$this->actFinish(); $this->actFinish();
$buff = new Object(); $buff = new Object ();
$buff->total_count = $total_count; $buff->total_count = $total_count;
$buff->total_page = $total_page; $buff->total_page = $total_page;
$buff->page = $page; $buff->page = $page;
$buff->data = $data; $buff->data = $datatemp;
$buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count); $buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count);
return $buff; }else {
//$data = $this->_fetch($result);
$buff = new Object ();
$buff->data = $data;
} }
return $buff;
} }
function getSelectPageSql($query, $with_values = true, $start_count = 0, $list_count = 0) {
$select = $query->getSelectString($with_values);
if ($select == '')
return new Object(-1, "Invalid query");
$select = 'SELECT ' . $select;
$from = $query->getFromString($with_values);
if ($from == '')
return new Object(-1, "Invalid query");
$from = ' FROM ' . $from;
$where = $query->getWhereString($with_values);
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();
if ($limit != '' && $query->getLimit()) {
$limit = sprintf(' LIMIT %d, %d',$start_count, $list_count);
}
return $select . ' ' . $from . ' ' . $where . ' ' . $groupBy . ' ' . $orderBy . ' ' . $limit;
}
function getParser() {
return new DBParser('"', '"', $this->prefix);
}
function getUpdateSql($query, $with_values = true, $with_priority = false){
$columnsList = $query->getUpdateString($with_values);
if($columnsList == '') return new Object(-1, "Invalid query");
$tableName = $query->getFirstTableName();
if($tableName == '') return new Object(-1, "Invalid query");
$where = $query->getWhereString($with_values);
if($where != '') $where = ' WHERE ' . $where;
$priority = $with_priority?$query->getPriority():'';
return "UPDATE $priority $tableName SET $columnsList ".$where;
}
function getDeleteSql($query, $with_values = true, $with_priority = false){
$sql = 'DELETE ';
$tables = $query->getTables();
$from = $tables[0]->getName();
$sql .= ' FROM '.$from;
$where = $query->getWhereString($with_values);
if($where != '') $sql .= ' WHERE ' . $where;
return $sql;
}
}
return new DBSqlite3_pdo; return new DBSqlite3_pdo;
?> ?>

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

@ -10,9 +10,9 @@
class DisplayHandler extends Handler { class DisplayHandler extends Handler {
var $content_size = 0; ///< 출력하는 컨텐츠의 사이즈 var $content_size = 0; // /< The size of displaying contents
var $gz_enabled = false; ///< gzip 압축하여 컨텐츠 호출할 것인지에 대한 flag변수 var $gz_enabled = false; // / <a flog variable whether to call contents after compressing by gzip
var $handler = null; var $handler = null;
/** /**
@ -22,16 +22,14 @@
* @param[in] $oModule the module object * @param[in] $oModule the module object
**/ **/
function printContent(&$oModule) { function printContent(&$oModule) {
// Check if the gzip encoding supported
// gzip encoding 지원 여부 체크
if( if(
(defined('__OB_GZHANDLER_ENABLE__') && __OB_GZHANDLER_ENABLE__ == 1) && (defined('__OB_GZHANDLER_ENABLE__') && __OB_GZHANDLER_ENABLE__ == 1) &&
strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')!==false && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')!==false &&
function_exists('ob_gzhandler') && function_exists('ob_gzhandler') &&
extension_loaded('zlib') extension_loaded('zlib')
) $this->gz_enabled = true; ) $this->gz_enabled = true;
// Extract contents to display by the request method
// request method에 따른 컨텐츠 결과물 추출
if(Context::get('xeVirtualRequestMethod')=='xml') { if(Context::get('xeVirtualRequestMethod')=='xml') {
require_once("./classes/display/VirtualXMLDisplayHandler.php"); require_once("./classes/display/VirtualXMLDisplayHandler.php");
$handler = new VirtualXMLDisplayHandler(); $handler = new VirtualXMLDisplayHandler();
@ -51,34 +49,35 @@
} }
$output = $handler->toDoc($oModule); $output = $handler->toDoc($oModule);
// call a trigger before display
// 출력하기 전에 trigger 호출 (before) ModuleHandler::triggerCall('display', 'before', $output);
ModuleHandler::triggerCall('display', 'before', $output); // execute add-on
$called_position = 'before_display_content';
// 애드온 실행 $oAddonController = &getController('addon');
$called_position = 'before_display_content'; $addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone()?"mobile":"pc");
$oAddonController = &getController('addon'); @include($addon_file);
$addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone()?"mobile":"pc");
@include($addon_file);
if(method_exists($handler, "prepareToPrint")) $handler->prepareToPrint($output); if(method_exists($handler, "prepareToPrint")) $handler->prepareToPrint($output);
// header output
if($this->gz_enabled) header("Content-Encoding: gzip");
// header 출력 $httpStatusCode = $oModule->getHttpStatusCode();
if($this->gz_enabled) header("Content-Encoding: gzip"); if($httpStatusCode && $httpStatusCode != 200) $this->_printHttpStatusCode($httpStatusCode);
if(Context::getResponseMethod() == 'JSON') $this->_printJSONHeader(); else
else if(Context::getResponseMethod() != 'HTML') $this->_printXMLHeader(); {
else $this->_printHTMLHeader(); if(Context::getResponseMethod() == 'JSON') $this->_printJSONHeader();
else if(Context::getResponseMethod() != 'HTML') $this->_printXMLHeader();
else $this->_printHTMLHeader();
}
// debugOutput 출력 // debugOutput output
$this->content_size = strlen($output); $this->content_size = strlen($output);
$output .= $this->_debugOutput(); $output .= $this->_debugOutput();
// results directly output
// 결과물 직접 출력 if($this->gz_enabled) print ob_gzhandler($output, 5);
if($this->gz_enabled) print ob_gzhandler($output, 5); else print $output;
else print $output; // call a trigger after display
ModuleHandler::triggerCall('display', 'after', $content);
// 출력 후 trigger 호출 (after)
ModuleHandler::triggerCall('display', 'after', $content);
} }
@ -91,8 +90,7 @@
if(!__DEBUG__) return; if(!__DEBUG__) return;
$end = getMicroTime(); $end = getMicroTime();
// Firebug console output
// Firebug 콘솔 출력
if(__DEBUG_OUTPUT__ == 2 && version_compare(PHP_VERSION, '6.0.0') === -1) { if(__DEBUG_OUTPUT__ == 2 && version_compare(PHP_VERSION, '6.0.0') === -1) {
static $firephp; static $firephp;
if(!isset($firephp)) $firephp = FirePHP::getInstance(true); if(!isset($firephp)) $firephp = FirePHP::getInstance(true);
@ -101,8 +99,7 @@
$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.'); $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; return;
} }
// display total execution time and Request/Response info
// 전체 실행 시간 출력, Request/Response info 출력
if(__DEBUG__ & 2) { if(__DEBUG__ & 2) {
$firephp->fb( $firephp->fb(
array('Request / Response info >>> '.$_SERVER['REQUEST_METHOD'].' / '.Context::getResponseMethod(), array('Request / Response info >>> '.$_SERVER['REQUEST_METHOD'].' / '.Context::getResponseMethod(),
@ -135,8 +132,7 @@
'TABLE' 'TABLE'
); );
} }
// display DB query history
// DB 쿼리 내역 출력
if((__DEBUG__ & 4) && $GLOBALS['__db_queries__']) { if((__DEBUG__ & 4) && $GLOBALS['__db_queries__']) {
$queries_output = array(array('Query', 'Elapsed time', 'Result')); $queries_output = array(array('Query', 'Elapsed time', 'Result'));
foreach($GLOBALS['__db_queries__'] as $query) { foreach($GLOBALS['__db_queries__'] as $query) {
@ -150,43 +146,35 @@
'TABLE' 'TABLE'
); );
} }
// dislpay the file and HTML comments
// 파일 및 HTML 주석으로 출력
} else { } else {
// display total execution time and Request/Response info
// 전체 실행 시간 출력, Request/Response info 출력
if(__DEBUG__ & 2) { if(__DEBUG__ & 2) {
if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) { if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
return; return;
} }
// Request/Response information
// Request/Response 정보 작성
$buff .= "\n- Request/ Response info\n"; $buff .= "\n- Request/ Response info\n";
$buff .= sprintf("\tRequest URI \t\t\t: %s:%s%s%s%s\n", $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['PHP_SELF'], $_SERVER['QUERY_STRING']?'?':'', $_SERVER['QUERY_STRING']); $buff .= sprintf("\tRequest 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("\tRequest method \t\t\t: %s\n", $_SERVER['REQUEST_METHOD']);
$buff .= sprintf("\tResponse method \t\t: %s\n", Context::getResponseMethod()); $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("\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("\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("\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("\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("\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("\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__']); $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__']); $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__']); $buff .= sprintf("\n\tTrans Content \t\t\t: %0.5f sec\n", $GLOBALS['__trans_content_elapsed__']);
} }
// DB Logging
// DB 로그 작성
if(__DEBUG__ & 4) { if(__DEBUG__ & 4) {
if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) { if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) {
return; return;
@ -203,11 +191,11 @@
} else { } else {
$buff .= sprintf("Query $s : %d\n\t\t\t %s\n", $query['result'], $query['errno'], $query['errstr']); $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
// HTML 주석으로 출력
if($buff && __DEBUG_OUTPUT__ == 1 && Context::getResponseMethod() == 'HTML') { if($buff && __DEBUG_OUTPUT__ == 1 && Context::getResponseMethod() == 'HTML') {
$buff = sprintf("[%s %s:%d]\n%s\n", date('Y-m-d H:i:s'), $file_name, $line_num, print_r($buff, true)); $buff = sprintf("[%s %s:%d]\n%s\n", date('Y-m-d H:i:s'), $file_name, $line_num, print_r($buff, true));
@ -217,8 +205,7 @@
return "<!--\r\n".$buff."\r\n-->"; return "<!--\r\n".$buff."\r\n-->";
} }
// Output to a file
// 파일에 출력
if($buff && __DEBUG_OUTPUT__ == 0) { if($buff && __DEBUG_OUTPUT__ == 0) {
$debug_file = _XE_PATH_.'files/_debug_message.php'; $debug_file = _XE_PATH_.'files/_debug_message.php';
$buff = sprintf("[%s %s:%d]\n%s\n", date('Y-m-d H:i:s'), $file_name, $line_num, print_r($buff, true)); $buff = sprintf("[%s %s:%d]\n%s\n", date('Y-m-d H:i:s'), $file_name, $line_num, print_r($buff, true));
@ -272,7 +259,12 @@
} }
/**
* @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

@ -10,13 +10,29 @@ class HTMLDisplayHandler {
$oTemplate = &TemplateHandler::getInstance(); $oTemplate = &TemplateHandler::getInstance();
// compile module tpl // 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(); $tpl_file = $oModule->getTemplateFile();
$output = $oTemplate->compile($template_path, $tpl_file); $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::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(Context::get('layout') != 'none') {
if(__DEBUG__==3) $start = getMicroTime(); if(__DEBUG__==3) $start = getMicroTime();
@ -28,32 +44,32 @@ class HTMLDisplayHandler {
$edited_layout_file = $oModule->getEditedLayoutFile(); $edited_layout_file = $oModule->getEditedLayoutFile();
// 현재 요청된 레이아웃 정보를 구함 // get the layout information currently requested
$oLayoutModel = &getModel('layout'); $oLayoutModel = &getModel('layout');
$layout_info = Context::get('layout_info'); $layout_info = Context::get('layout_info');
$layout_srl = $layout_info->layout_srl; $layout_srl = $layout_info->layout_srl;
// 레이아웃과 연결되어 있으면 레이아웃 컴파일 // compile if connected to the layout
if($layout_srl > 0){ if($layout_srl > 0){
// faceoff 레이아웃일 경우 별도 처리 // handle separately if the layout is faceoff
if($layout_info && $layout_info->type == 'faceoff') { if($layout_info && $layout_info->type == 'faceoff') {
$oLayoutModel->doActivateFaceOff($layout_info); $oLayoutModel->doActivateFaceOff($layout_info);
Context::set('layout_info', $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); $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_path) $layout_path = './common/tpl';
if(!$layout_file) $layout_file = "default_layout"; if(!$layout_file) $layout_file = 'default_layout';
$output = $oTemplate->compile($layout_path, $layout_file, $edited_layout_file); $output = $oTemplate->compile($layout_path, $layout_file, $edited_layout_file);
if(__DEBUG__==3) $GLOBALS['__layout_compile_elapsed__'] = getMicroTime()-$start; 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>'); Context::addHtmlFooter('<iframe id="xeTmpIframe" name="xeTmpIframe" style="width:1px;height:1px;position:absolute;top:-2px;left:-2px;"></iframe>');
} }
} }
@ -66,13 +82,13 @@ class HTMLDisplayHandler {
if(__DEBUG__==3) $start = getMicroTime(); 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); $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); $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()) { if(Context::isAllowRewrite()) {
$url = parse_url(Context::getRequestUri()); $url = parse_url(Context::getRequestUri());
$real_path = $url['path']; $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); $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; if(__DEBUG__==3) $GLOBALS['__trans_content_elapsed__'] = getMicroTime()-$start;
// 불필요한 정보 제거 // Remove unnecessary information
$output = preg_replace('/member\_\-([0-9]+)/s','member_0',$output); $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); Context::set('content', $output);
$oTemplate = &TemplateHandler::getInstance(); $oTemplate = &TemplateHandler::getInstance();
if(Mobile::isFromMobilePhone()) { if(Mobile::isFromMobilePhone()) {
@ -106,14 +138,45 @@ class HTMLDisplayHandler {
else else
{ {
$this->_loadJSCSS(); $this->_loadJSCSS();
$this->_addMetaTag();
$output = $oTemplate->compile('./common/tpl', 'common_layout'); $output = $oTemplate->compile('./common/tpl', 'common_layout');
} }
// 사용자 정의 언어 변환 // replace the user-defined-language
$oModuleController = &getController('module'); $oModuleController = &getController('module');
$oModuleController->replaceDefinedLangCode($output); $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 * @brief add html style code extracted from html body to Context, which will be
* printed inside <header></header> later. * printed inside <header></header> later.
@ -129,28 +192,48 @@ class HTMLDisplayHandler {
**/ **/
function _transMeta($matches) { function _transMeta($matches) {
if($matches[1]) return ''; if($matches[1]) return '';
if(substr($matches[2],'-4')=='.css') Context::addCSSFile($matches[2]); Context::loadFile($matches[2]);
elseif(substr($matches[2],'-3')=='.js') Context::addJSFile($matches[2]);
} }
function _loadJSCSS() function _loadJSCSS()
{ {
$oContext =& Context::getInstance(); $oContext =& Context::getInstance();
$lang_type = Context::getLangType();
// add common JS/CSS files // add common JS/CSS files
$oContext->addJsFile('./common/js/jquery.js', false, '', -100000); if(__DEBUG__) {
$oContext->addJsFile('./common/js/x.js', false, '', -100000); $oContext->loadFile(array('./common/js/jquery.js', 'head', '', -100000), true);
$oContext->addJsFile('./common/js/common.js', false, '', -100000); $oContext->loadFile(array('./common/js/x.js', 'head', '', -100000), true);
$oContext->addJsFile('./common/js/js_app.js', false, '', -100000); $oContext->loadFile(array('./common/js/common.js', 'head', '', -100000), true);
$oContext->addJsFile('./common/js/xml_handler.js', false, '', -100000); $oContext->loadFile(array('./common/js/js_app.js', 'head', '', -100000), true);
$oContext->addJsFile('./common/js/xml_js_filter.js', false, '', -100000); $oContext->loadFile(array('./common/js/xml_handler.js', 'head', '', -100000), true);
$oContext->addCSSFile('./common/css/default.css', false, 'all', '', -100000); $oContext->loadFile(array('./common/js/xml_js_filter.js', 'head', '', -100000), true);
$oContext->addCSSFile('./common/css/button.css', false, 'all', '', -100000); $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 // for admin page, add admin css
if(Context::get('module')=='admin' || strpos(Context::get('act'),'Admin')>0){ if(Context::get('module')=='admin' || strpos(Context::get('act'),'Admin')>0){
$oContext->addCSSFile('./modules/admin/tpl/css/font.css', false, 'all', '',10000); if(__DEBUG__) {
$oContext->addCSSFile('./modules/admin/tpl/css/pagination.css', false, 'all', '', 100001); $oContext->loadFile(array('./modules/admin/tpl/css/admin.css', 'all', '', 100000), true);
$oContext->addCSSFile('./modules/admin/tpl/css/admin.css', false, 'all', '', 100002); $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');
}
} }

View file

@ -2,15 +2,15 @@
/** /**
* @class EditorHandler * @class EditorHandler
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief edit component상위 클래스임 * @brief superclass of the edit component
* *
* 주로 하는 일은 컴포넌트 요청시 컴포넌트에서 필요로 하는 변수를 세팅해준다 * set up the component variables
**/ **/
class EditorHandler extends Object { class EditorHandler extends Object {
/** /**
* @brief 컴포넌트의 xml및 관련 정보들을 설정 * @brief set the xml and other information of the component
**/ **/
function setInfo($info) { function setInfo($info) {
Context::set('component_info', $info); Context::set('component_info', $info);

View file

@ -2,7 +2,7 @@
/** /**
* @class ExtraVar * @class ExtraVar
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief 게시글, 회원등에서 사용하는 확장변수를 핸들링하는 클래스 * @brief a class to handle extra variables used in posts, member and others
* *
**/ **/
class ExtraVar { class ExtraVar {
@ -25,7 +25,7 @@
} }
/** /**
* @brief 확장변수 키를 등록 * @brief register a key of extra variable
* @param module_srl, idx, name, type, default, desc, is_required, search, value * @param module_srl, idx, name, type, default, desc, is_required, search, value
**/ **/
function setExtraVarKeys($extra_keys) { function setExtraVarKeys($extra_keys) {
@ -38,7 +38,7 @@
} }
/** /**
* @brief 확장변수 객체 배열 return * @brief Return an array of extra vars
**/ **/
function getExtraVars() { function getExtraVars() {
return $this->keys; return $this->keys;
@ -48,7 +48,7 @@
/** /**
* @class ExtraItem * @class ExtraItem
* @author NHN (developers@xpressengine.com) * @author NHN (developers@xpressengine.com)
* @brief 확장변수의 개별 * @brief each value of the extra vars
**/ **/
class ExtraItem { class ExtraItem {
var $module_srl = 0; var $module_srl = 0;
@ -80,14 +80,14 @@
} }
/** /**
* @brief 지정 * @brief Values
**/ **/
function setValue($value) { function setValue($value) {
$this->value = $value; $this->value = $value;
} }
/** /**
* @brief type에 따라서 주어진 값을 변형하여 원형 값을 return * @brief return a given value converted based on its type
**/ **/
function _getTypeValue($type, $value) { function _getTypeValue($type, $value) {
$value = trim($value); $value = trim($value);
@ -134,8 +134,8 @@
} }
/** /**
* @brief 값을 return * @brief Return value
* 원형 값을 HTML 결과물로 return * return the original values for HTML result
**/ **/
function getValueHTML() { function getValueHTML() {
$value = $this->_getTypeValue($this->type, $this->value); $value = $this->_getTypeValue($this->type, $this->value);
@ -174,7 +174,7 @@
} }
/** /**
* @brief type에 따른 form을 리턴 * @brief return a form based on its type
**/ **/
function getFormHTML() { function getFormHTML() {
static $id_num = 1000; static $id_num = 1000;
@ -188,17 +188,15 @@
$buff = ''; $buff = '';
switch($type) { switch($type) {
// 홈페이지 주소 // Homepage
case 'homepage' : case 'homepage' :
$buff .= '<input type="text" name="'.$column_name.'" value="'.$value.'" class="homepage" />'; $buff .= '<input type="text" name="'.$column_name.'" value="'.$value.'" class="homepage" />';
break; break;
// Email Address
// Email 주소
case 'email_address' : case 'email_address' :
$buff .= '<input type="text" name="'.$column_name.'" value="'.$value.'" class="email_address" />'; $buff .= '<input type="text" name="'.$column_name.'" value="'.$value.'" class="email_address" />';
break; break;
// Phone Number
// 전화번호
case 'tel' : case 'tel' :
$buff .= $buff .=
'<input type="text" name="'.$column_name.'" value="'.$value[0].'" size="4" class="tel" />'. '<input type="text" name="'.$column_name.'" value="'.$value[0].'" size="4" class="tel" />'.
@ -210,8 +208,7 @@
case 'textarea' : case 'textarea' :
$buff .= '<textarea name="'.$column_name.'" class="textarea">'.$value.'</textarea>'; $buff .= '<textarea name="'.$column_name.'" class="textarea">'.$value.'</textarea>';
break; break;
// multiple choice
// 다중 선택
case 'checkbox' : case 'checkbox' :
$buff .= '<ul>'; $buff .= '<ul>';
foreach($default as $v) { foreach($default as $v) {
@ -225,8 +222,7 @@
} }
$buff .= '</ul>'; $buff .= '</ul>';
break; break;
// single choice
// 단일 선택
case 'select' : case 'select' :
$buff .= '<select name="'.$column_name.'" class="select">'; $buff .= '<select name="'.$column_name.'" class="select">';
foreach($default as $v) { foreach($default as $v) {
@ -251,19 +247,18 @@
} }
$buff .= '</ul>'; $buff .= '</ul>';
break; break;
// date
// 날짜 입력
case 'date' : case 'date' :
// datepicker javascript plugin load // datepicker javascript plugin load
Context::loadJavascriptPlugin('ui.datepicker'); Context::loadJavascriptPlugin('ui.datepicker');
$buff .= $buff .=
'<input type="hidden" name="'.$column_name.'" value="'.$value.'" />'. '<input type="hidden" name="'.$column_name.'" value="'.$value.'" />'.
'<input type="text" id="date_'.$column_name.'" value="'.zdate($value,'Y-m-d').'" readonly="readonly" class="date" />'."\n". '<input type="text" id="date_'.$column_name.'" value="'.zdate($value,'Y-m-d').'" class="date" />'."\n".
'<script type="text/javascript">'."\n". '<script type="text/javascript">'."\n".
'(function($){'."\n". '(function($){'."\n".
' $(function(){'."\n". ' $(function(){'."\n".
' var option = { changeMonth:true, changeYear:true, gotoCurrent: false,yearRange:\'-100:+10\', onSelect:function(){'."\n". ' var option = { dateFormat: "yy-mm-dd", changeMonth:true, changeYear:true, gotoCurrent: false,yearRange:\'-100:+10\', onSelect:function(){'."\n".
' $(this).prev(\'input[type="hidden"]\').val(this.value.replace(/-/g,""))}'."\n". ' $(this).prev(\'input[type="hidden"]\').val(this.value.replace(/-/g,""))}'."\n".
' };'."\n". ' };'."\n".
' $.extend(option,$.datepicker.regional[\''.Context::getLangType().'\']);'."\n". ' $.extend(option,$.datepicker.regional[\''.Context::getLangType().'\']);'."\n".
@ -272,8 +267,7 @@
'})(jQuery);'."\n". '})(jQuery);'."\n".
'</script>'; '</script>';
break; break;
// address
// 주소 입력
case "kr_zip" : case "kr_zip" :
// krzip address javascript plugin load // krzip address javascript plugin load
Context::loadJavascriptPlugin('ui.krzip'); Context::loadJavascriptPlugin('ui.krzip');
@ -298,8 +292,7 @@
'<input type="text" name="'.$column_name.'" value="'.htmlspecialchars($value[1]).'" class="address" />'. '<input type="text" name="'.$column_name.'" value="'.htmlspecialchars($value[1]).'" class="address" />'.
''; '';
break; break;
// General text
// 일반 text
default : default :
$buff .=' <input type="text" name="'.$column_name.'" value="'.$value.'" class="text" />'; $buff .=' <input type="text" name="'.$column_name.'" value="'.$value.'" class="text" />';
break; break;

File diff suppressed because it is too large Load diff

View file

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

View file

@ -0,0 +1,262 @@
<?php
/**
* @class FrontEndFileHandler
* @author NHN (developers@xpressengine.com)
**/
class FrontEndFileHandler extends Handler
{
var $cssMap = array();
var $jsHeadMap = array();
var $jsBodyMap = array();
var $cssMapIndex = array();
var $jsHeadMapIndex = array();
var $jsBodyMapIndex = array();
function isSsl()
{
if ($GLOBAL['__XE_IS_SSL__']) return $GLOBAL['__XE_IS_SSL__'];
$url_info = parse_url(Context::getRequestUrl());
if ($url_info['scheme'] == 'https')
$GLOBAL['__XE_IS_SSL__'] = true;
else
$GLOBAL['__XE_IS_SSL__'] = false;
return $GLOBAL['__XE_IS_SSL__'];
}
/**
* @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 = '')
{
if (!is_array($args)) $args = array($args);
$pathInfo = pathinfo($args[0]);
$file->fileName = $pathInfo['basename'];
$file->filePath = $this->_getAbsFileUrl($pathInfo['dirname']);
$file->fileExtension = strtolower($pathInfo['extension']);
if (strpos($file->filePath, '://') == false)
{
$file->useCdn = $useCdn;
$file->cdnPath = $this->_normalizeFilePath($pathInfo['dirname']);
$file->cdnPrefix = $cdnPrefix;
$file->cdnVersion = $cdnVersion;
}
$availableExtension = array('css', 'js');
if (!in_array($file->fileExtension, $availableExtension)) return;
$file->targetIe = $args[2];
$file->index = (int)$args[3];
if ($file->fileExtension == 'css')
{
$file->media = $args[1];
if (!$file->media) $file->media = 'all';
$map = &$this->cssMap;
$mapIndex = &$this->cssMapIndex;
$key = $file->filePath . $file->fileName . "\t" . $file->targetIe . "\t" . $file->media;
}
else if ($file->fileExtension == 'js')
{
$type = $args[1];
if ($type == 'body')
{
$map = &$this->jsBodyMap;
$mapIndex = &$this->jsBodyMapIndex;
}
else
{
$map = &$this->jsHeadMap;
$mapIndex = &$this->jsHeadMapIndex;
}
$key = $file->filePath . $file->fileName . "\t" . $file->targetIe;
}
if (!isset($map[$key]) || $mapIndex[$key] != $file->index)
{
$this->unloadFile($args[0], $args[2], $args[1]);
$map[$file->index][$key] = $file;
$mapIndex[$key] = $file->index;
}
}
function unloadFile($fileName, $targetIe = '', $media = 'all')
{
$pathInfo = pathinfo($fileName);
$fileName = $pathInfo['basename'];
$filePath = $this->_getAbsFileUrl($pathInfo['dirname']);
$fileExtension = strtolower($pathInfo['extension']);
$key = $filePath . $fileName . "\t" . $targetIe;
if ($fileExtension == 'css')
{
$key .= "\t" . $media;
if (isset($this->cssMapIndex[$key]))
{
$index = $this->cssMapIndex[$key];
unset($this->cssMap[$index][$key]);
unset($this->cssMapIndex[$key]);
}
}
else
{
if (isset($this->jsHeadMapIndex[$key]))
{
$index = $this->jsHeadMapIndex[$key];
unset($this->jsHeadMap[$index][$key]);
unset($this->jsHeadMapIndex[$key]);
}
if (isset($this->jsBodyMapIndex[$key]))
{
$index = $this->jsBodyMapIndex[$key];
unset($this->jsBodyMap[$index][$key]);
unset($this->jsBodyMapIndex[$key]);
}
}
}
function unloadAllFiles($type = 'all')
{
if ($type == 'css' || $type == 'all')
{
$cssMap = array();
$cssMapIndex = array();
}
if ($type == 'js' || $type == 'all')
{
$jsHeadMap = array();
$jsBodyMap = array();
$jsHeadMapIndex = array();
$jsBodyMapIndex = array();
}
}
function getCssFileList()
{
$map = &$this->cssMap;
$mapIndex = &$this->cssMapIndex;
$this->_sortMap($map, $mapIndex);
$dbInfo = Context::getDBInfo();
$useCdn = $dbInfo->use_cdn;
$result = array();
foreach($map as $indexedMap)
{
foreach($indexedMap as $file)
{
if ($this->isSsl() == false && $useCdn == 'Y' && $file->useCdn && $file->cdnVersion != '%__XE_CDN_VERSION__%')
{
$fullFilePath = $file->cdnPrefix . $file->cdnVersion . '/' . substr($file->cdnPath, 2) . '/' . $file->fileName;
}
else
{
$fullFilePath = $file->filePath . '/' . $file->fileName;
}
$result[] = array('file' => $fullFilePath, 'media' => $file->media, 'targetie' => $file->targetIe);
}
}
return $result;
}
function getJsFileList($type = 'head')
{
if ($type == 'head')
{
$map = &$this->jsHeadMap;
$mapIndex = &$this->jsHeadMapIndex;
}
else
{
$map = &$this->jsBodyMap;
$mapIndex = &$this->jsBodyMapIndex;
}
$this->_sortMap($map, $mapIndex);
$dbInfo = Context::getDBInfo();
$useCdn = $dbInfo->use_cdn;
$result = array();
foreach($map as $indexedMap)
{
foreach($indexedMap as $file)
{
if ($this->isSsl() == false && $useCdn == 'Y' && $file->useCdn && $file->cdnVersion != '%__XE_CDN_VERSION__%')
{
$fullFilePath = $file->cdnPrefix . $file->cdnVersion . '/' . substr($file->cdnPath, 2) . '/' . $file->fileName;
}
else
{
$fullFilePath = $file->filePath . '/' . $file->fileName;
}
$result[] = array('file' => $fullFilePath, 'targetie' => $file->targetIe);
}
}
return $result;
}
function _sortMap(&$map, &$index)
{
ksort($map);
}
function _normalizeFilePath($path)
{
if (strpos($path, '://') === false && $path{0} != '/' && $path{0} != '.')
{
$path = './' . $path;
}
$path = preg_replace('@/\./|(?<!:)\/\/@', '/', $path);
while(strpos($path, '/../'))
{
$path = preg_replace('/\/([^\/]+)\/\.\.\//s', '/', $path, 1);
}
return $path;
}
function _getAbsFileUrl($path)
{
$path = $this->_normalizeFilePath($path);
if(strpos($path, './') === 0)
{
if (dirname($_SERVER['SCRIPT_NAME']) == '/' || dirname($_SERVER['SCRIPT_NAME']) == '\\')
{
$path = '/' . substr($path, 2);
}
else
{
$path = dirname($_SERVER['SCRIPT_NAME']) . '/' . substr($path, 2);
}
}
else if(strpos($file, '../') === 0)
{
$path= $this->_normalizeFilePath(dirname($_SERVER['SCRIPT_NAME']) . "/{$path}");
}
return $path;
}
}

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