openid_delegation_id 등 일부 애드온 및 레이아웃, 위젯 스킨을 배포본에서 제거

xpressengine/xe-core#2037
This commit is contained in:
Kijin Sung 2018-06-11 23:29:13 +09:00
parent 43732495fe
commit 15eb5c3715
153 changed files with 0 additions and 2426 deletions

View file

@ -1,602 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
if(!defined('__XE__'))
exit();
/**
* @file blogapicounter.addon.php
* @author NAVER (developers@xpressengine.com)
* @brief Add blogAPI
*
* It enables to write a post by using an external tool such as ms live writer, firefox performancing, zoundry and so on.
* It should be called before executing the module(before_module_proc). If not, it is forced to shut down.
* */
// Insert a rsd tag when called_position is after_module_proc
if($called_position == 'after_module_proc')
{
// Create rsd address of the current module
$site_module_info = Context::get('site_module_info');
$rsd_url = getFullSiteUrl($site_module_info->domain, '', 'mid', $this->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(_XE_PATH_ . 'addons/blogapi/blogapi.func.php');
$xml = $GLOBALS['HTTP_RAW_POST_DATA'];
// If HTTP_RAW_POST_DATA is NULL, Print error message
if(!$xml)
{
$content = getXmlRpcFailure(1, 'Invalid Method Call');
printContent($content);
}
// xmlprc parsing
// Parse the requested xmlrpc
if(Security::detectingXEE($xml))
{
header("HTTP/1.0 400 Bad Request");
exit;
}
if(version_compare(PHP_VERSION, '5.2.11', '<=')) libxml_disable_entity_loader(true);
$xml = new SimpleXMLElement($xml, LIBXML_NONET | LIBXML_NOENT);
$method_name = (string)$xml->methodName;
$params = $xml->params->param;
// Compatible with some of methodname
if(in_array($method_name, array('metaWeblog.deletePost', 'metaWeblog.getUsersBlogs', 'metaWeblog.getUserInfo')))
{
$method_name = str_replace('metaWeblog.', 'blogger.', $method_name);
}
// Get user_id, password and attempt log-in
$user_id = trim((string)$params[1]->value->string);
$password = trim((string)$params[2]->value->string);
// 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
$logged_info = Context::get('logged_info');
$mediaPath = sprintf('files/cache/blogapi/%s/%s/', $this->mid, $logged_info->member_srl);
$mediaAbsPath = _XE_PATH_ . $mediaPath;
$mediaUrlPath = Context::getRequestUri() . $mediaPath;
switch($method_name)
{
// Blog information
case 'blogger.getUsersBlogs' :
$obj = new stdClass();
$obj->url = getFullSiteUrl('');
$obj->blogid = $this->mid;
$obj->blogName = $this->module_info->browser_title;
$blog_list = array($obj);
$content = getXmlRpcResponse($blog_list);
printContent($content);
break;
// Return a list of categories
case 'metaWeblog.getCategories' :
$category_obj_list = array();
if($category_list)
{
foreach($category_list as $category_srl => $category_info)
{
$obj = new stdClass();
$obj->description = $category_info->title;
//$obj->htmlUrl = Context::getRequestUri().$this->mid.'/1';
//$obj->rssUrl= Context::getRequestUri().'rss/'.$this->mid.'/1';
$obj->title = $category_info->title;
$obj->categoryid = $category_srl;
$category_obj_list[] = $obj;
}
}
$content = getXmlRpcResponse($category_obj_list);
printContent($content);
break;
// Upload file
case 'metaWeblog.newMediaObject' :
// Check a file upload permission
$oFileModel = getModel('file');
$file_module_config = $oFileModel->getFileModuleConfig($this->module_srl);
if(is_array($file_module_config->download_grant) && count($file_module_config->download_grant) > 0)
{
$logged_info = Context::get('logged_info');
if($logged_info->is_admin != 'Y')
{
$is_permitted = false;
for($i = 0; $i < count($file_module_config->download_grant); $i++)
{
$group_srl = $file_module_config->download_grant[$i];
if($logged_info->group_list[$group_srl])
{
$is_permitted = true;
break;
}
}
if(!$is_permitted){
printContent(getXmlRpcFailure(1, 'no permission'));
}
}
}
$fileinfo = $params[3]->value->struct->member;
foreach($fileinfo as $key => $val)
{
$nodename = (string)$val->name;
if($nodename === 'bits')
{
$filedata = base64_decode((string)$val->value->base64);
}
else if($nodename === 'name')
{
$filename = pathinfo((string)$val->value->string, PATHINFO_BASENAME);
}
}
if($logged_info->is_admin != 'Y')
{
// check file type
if(isset($file_module_config->allowed_filetypes) && $file_module_config->allowed_filetypes !== '*.*')
{
$filetypes = explode(';', $file_module_config->allowed_filetypes);
$ext = array();
foreach($filetypes as $item)
{
$item = explode('.', $item);
$ext[] = strtolower(array_pop($item));
}
$uploaded_ext = explode('.', $filename);
$uploaded_ext = strtolower(array_pop($uploaded_ext));
if(!in_array($uploaded_ext, $ext))
{
printContent(getXmlRpcFailure(1, 'Not allowed file type'));
break;
}
}
$allowed_filesize = $file_module_config->allowed_filesize * 1024 * 1024;
if($allowed_filesize < strlen($filedata))
{
printContent(getXmlRpcFailure(1, 'This file exceeds the attachment limit'));
break;
}
}
$temp_filename = Password::createSecureSalt(12, 'alnum');
$target_filename = sprintf('%s%s', $mediaAbsPath, $temp_filename);
FileHandler::makeDir($mediaAbsPath);
FileHandler::writeFile($target_filename, $filedata);
FileHandler::writeFile($target_filename . '_source_filename', $filename);
$obj = new stdClass();
$obj->url = Context::getRequestUri() . $mediaPath . $temp_filename;
$content = getXmlRpcResponse($obj);
printContent($content);
break;
// Get posts
case 'metaWeblog.getPost' :
$document_srl = (string)$params[0]->value->string;
if(!$document_srl)
{
printContent(getXmlRpcFailure(1, 'no permission'));
}
else
{
$oDocumentModel = getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl);
if(!$oDocument->isGranted())
{
printContent(getXmlRpcFailure(1, 'no permission'));
}
else
{
// Get a list of categories and set Context
$category = "";
if($oDocument->get('category_srl'))
{
$oDocumentModel = getModel('document');
$category_list = $oDocumentModel->getCategoryList($oDocument->get('module_srl'));
if($category_list[$oDocument->get('category_srl')])
{
$category = $category_list[$oDocument->get('category_srl')]->title;
}
}
$content = sprintf(
'<?xml version="1.0" encoding="utf-8"?>' .
'<methodResponse>' .
'<params>' .
'<param>' .
'<value>' .
'<struct>' .
'<member><name>categories</name><value><array><data><value><![CDATA[%s]]></value></data></array></value></member>' .
'<member><name>dateCreated</name><value><dateTime.iso8601>%s</dateTime.iso8601></value></member>' .
'<member><name>description</name><value><![CDATA[%s]]></value></member>' .
'<member><name>link</name><value>%s</value></member>' .
'<member><name>postid</name><value><string>%s</string></value></member>' .
'<member><name>title</name><value><![CDATA[%s]]></value></member>' .
'<member><name>publish</name><value><boolean>1</boolean></value></member>' .
'</struct>' .
'</value>' .
'</param>' .
'</params>' .
'</methodResponse>',
$category,
date("Ymd", $oDocument->getRegdateTime()) . 'T' . date("H:i:s", $oDocument->getRegdateTime()),
$oDocument->getContent(false, false, true, false),
getFullUrl('', 'document_srl', $oDocument->document_srl),
$oDocument->document_srl,
$oDocument->getTitleText()
);
printContent($content);
}
}
break;
// Write a new post
case 'metaWeblog.newPost' :
$obj = new stdClass();
$info = $params[3];
// Get information of post, title, and category
foreach($info->value->struct->member as $val)
{
switch((string)$val->name)
{
case 'title' :
$obj->title = (string)$val->value->string;
break;
case 'description' :
$obj->content = (string)$val->value->string;
break;
case 'categories' :
$categories = $val->value->array->data->value;
$category = (string)$categories[0]->string;
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;
foreach($tags as $tag)
{
$tag_list[] = (string)$tag->string;
}
if(count($tag_list))
$obj->tags = implode(',', $tag_list);
break;
}
}
// Set document srl
$document_srl = getNextSequence();
$obj->document_srl = $document_srl;
$obj->module_srl = $this->module_srl;
// Attachment
if(is_dir($mediaAbsPath))
{
$file_list = FileHandler::readDir($mediaAbsPath, '/(_source_filename)$/is');
$file_count = count($file_list);
if($file_count)
{
$oFileController = getController('file');
$oFileModel = getModel('file');
foreach($file_list as $file)
{
$filename = FileHandler::readFile($mediaAbsPath . $file);
$temp_filename = str_replace('_source_filename', '', $file);
$file_info = array();
$file_info['tmp_name'] = sprintf('%s%s', $mediaAbsPath, $temp_filename);
$file_info['name'] = $filename;
$fileOutput = $oFileController->insertFile($file_info, $this->module_srl, $document_srl, 0, true);
if($fileOutput->get('direct_download') === 'N')
{
$replace_url = Context::getRequestUri() . $oFileModel->getDownloadUrl($fileOutput->file_srl, $fileOutput->sid, $this->module_srl);
}
else
{
$replace_url = Context::getRequestUri() . $fileOutput->get('uploaded_filename');
}
$obj->content = str_replace($mediaUrlPath . $temp_filename, $replace_url, $obj->content);
}
$obj->uploaded_count = $file_count;
}
}
$oDocumentController = getController('document');
$obj->commentStatus = 'ALLOW';
$obj->allow_trackback = 'Y';
$logged_info = Context::get('logged_info');
$obj->member_srl = $logged_info->member_srl;
$obj->user_id = $logged_info->user_id;
$obj->user_name = $logged_info->user_name;
$obj->nick_name = $logged_info->nick_name;
$obj->email_address = $logged_info->email_address;
$obj->homepage = $logged_info->homepage;
$output = $oDocumentController->insertDocument($obj, TRUE);
if(!$output->toBool())
{
$content = getXmlRpcFailure(1, $output->getMessage());
}
else
{
$content = getXmlRpcResponse(strval($document_srl));
}
FileHandler::removeDir($mediaAbsPath);
printContent($content);
break;
// Edit post
case 'metaWeblog.editPost' :
$tmp_val = (string)$params[0]->value->string;
if(!$tmp_val)
$tmp_val = (string)$params[0]->value->i4;
if(!$tmp_val)
{
$content = getXmlRpcFailure(1, 'no permission');
break;
}
$tmp_arr = explode('/', $tmp_val);
$document_srl = array_pop($tmp_arr);
if(!$document_srl)
{
$content = getXmlRpcFailure(1, 'no permission');
break;
}
$oDocumentModel = getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl);
// Check if a permission to modify a document is granted
if(!$oDocument->isGranted())
{
$content = getXmlRpcFailure(1, 'no permission');
break;
}
$obj = $oDocument->getObjectVars();
$info = $params[3];
// Get information of post, title, and category
foreach($info->value->struct->member as $val)
{
switch((string)$val->name)
{
case 'title' :
$obj->title = (string)$val->value->string;
break;
case 'description' :
$obj->content = (string)$val->value->string;
break;
case 'categories' :
$categories = $val->value->array->data->value;
$category = (string)$categories[0]->string;
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;
foreach($tags as $tag)
{
$tag_list[] = (string)$tag->string;
}
if(count($tag_list))
$obj->tags = implode(',', $tag_list);
break;
}
}
// Document srl
$obj->document_srl = $document_srl;
$obj->module_srl = $this->module_srl;
// Attachment
if(is_dir($mediaAbsPath))
{
$file_list = FileHandler::readDir($mediaAbsPath, '/(_source_filename)$/is');
$file_count = count($file_list);
if($file_count)
{
$oFileController = getController('file');
$oFileModel = getModel('file');
foreach($file_list as $file)
{
$filename = FileHandler::readFile($mediaAbsPath . $file);
$temp_filename = str_replace('_source_filename', '', $file);
$file_info = array();
$file_info['tmp_name'] = sprintf('%s%s', $mediaAbsPath, $temp_filename);
$file_info['name'] = $filename;
$fileOutput = $oFileController->insertFile($file_info, $this->module_srl, $document_srl, 0, true);
if($fileOutput->get('direct_download') === 'N')
{
$replace_url = Context::getRequestUri() . $oFileModel->getDownloadUrl($fileOutput->file_srl, $fileOutput->sid, $this->module_srl);
}
else
{
$replace_url = Context::getRequestUri() . $fileOutput->get('uploaded_filename');
}
$obj->content = str_replace($mediaUrlPath . $temp_filename, $replace_url, $obj->content);
}
$obj->uploaded_count += $file_count;
}
}
$oDocumentController = getController('document');
$output = $oDocumentController->updateDocument($oDocument, $obj, TRUE);
if(!$output->toBool())
{
$content = getXmlRpcFailure(1, $output->getMessage());
}
else
{
$content = getXmlRpcResponse(true);
FileHandler::removeDir($mediaAbsPath);
}
printContent($content);
break;
// Delete the post
case 'blogger.deletePost' :
$tmp_val = (string)$params[1]->value->string;
$tmp_arr = explode('/', $tmp_val);
$document_srl = array_pop($tmp_arr);
// Get a document
$oDocumentModel = getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl);
// If the document exists
if(!$oDocument->isExists())
{
$content = getXmlRpcFailure(1, 'not exists');
// Check if a permission to delete a document is granted
}
elseif(!$oDocument->isGranted())
{
$content = getXmlRpcFailure(1, 'no permission');
break;
// Delete
}
else
{
$oDocumentController = getController('document');
$output = $oDocumentController->deleteDocument($document_srl);
if(!$output->toBool())
$content = getXmlRpcFailure(1, $output->getMessage());
else
$content = getXmlRpcResponse(true);
}
printContent($content);
break;
// Get recent posts
case 'metaWeblog.getRecentPosts' :
// Options to get a list
$args = new stdClass();
$args->module_srl = $this->module_srl; // /< module_srl of the current module
$args->page = 1;
$args->list_count = 20;
$args->sort_index = 'list_order'; // /< Sorting values
$logged_info = Context::get('logged_info');
$args->search_target = 'member_srl';
$args->search_keyword = $logged_info->member_srl;
$output = $oDocumentModel->getDocumentList($args);
if(!$output->toBool() || !$output->data)
{
$content = getXmlRpcFailure(1, 'post not founded');
}
else
{
$oEditorController = getController('editor');
$posts = array();
foreach($output->data as $key => $oDocument)
{
$post = new stdClass();
$post->categories = array();
$post->dateCreated = date("Ymd", $oDocument->getRegdateTime()) . 'T' . date("H:i:s", $oDocument->getRegdateTime());
$post->description = sprintf('<![CDATA[%s]]>',$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'), ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
$post->publish = 1;
$post->userid = $oDocument->get('user_id');
$post->mt_allow_pings = 0;
$post->mt_allow_comments = $oDocument->allowComment() ? 1 : 0;
$posts[] = $post;
}
$content = getXmlRpcResponse($posts);
printContent($content);
}
break;
// Display RSD if there is no request
default :
$homepagelink = getUrl('', 'mid', $this->mid);
$site_module_info = Context::get('site_module_info');
$api_url = getFullSiteUrl($site_module_info->domain, '', 'mid', $site_module_info->mid, 'act', 'api');
$content = <<<RSDContent
<?xml version="1.0" ?>
<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd" >
<service>
<engineName>Rhymix</engineName>
<engineLink>https://www.rhymix.org/ </engineLink>
<homePageLink>{$homepagelink}</homePageLink>
<apis>
<api name="MetaWeblog" preferred="true" apiLink="{$api_url}" blogID="" />
</apis>
</service>
</rsd>
RSDContent;
printContent($content);
break;
}
}
/* End of file blogapi.addon.php */
/* Location: ./addons/blogapi/blogapi.addon.php */

View file

@ -1,101 +0,0 @@
<?php
/* Copyright (C) NAVER <http://www.navercorp.com> */
if(!defined('__XE__'))
exit();
/**
* @file ./addons/blogapi/blogapi.func.php
* @author NAVER (developers@xpressengine.com)
* @brief Function collections for the implementation of blogapi
* */
// Error messages
function getXmlRpcFailure($error, $message)
{
return
sprintf(
"<methodResponse>\n<fault><value><struct>\n<member>\n<name>faultCode</name>\n<value><int>%d</int></value>\n</member>\n<member>\n<name>faultString</name>\n<value><string>%s</string></value>\n</member>\n</struct></value></fault>\n</methodResponse>\n", $error, htmlspecialchars($message, ENT_COMPAT | ENT_HTML401, 'UTF-8', false)
);
}
// Display results
function getXmlRpcResponse($params)
{
$buff = '<?xml version="1.0" encoding="utf-8"?>' . "\n<methodResponse><params>";
$buff .= _getEncodedVal($params);
$buff .= "</params>\n</methodResponse>\n";
return $buff;
}
// Encoding
function _getEncodedVal($val, $is_sub_set = false)
{
if(preg_match('/^\<\!\[CDATA\[/',$val))
{
$buff = sprintf("<value>%s</value>", $val);
}
elseif(is_int($val))
{
$buff = sprintf("<value><i4>%d</i4></value>", $val);
}
elseif(is_string($val) && preg_match('/^([0-9]+)T([0-9\:]+)$/', $val))
{
$buff = sprintf("<value><dateTime.iso8601>%s</dateTime.iso8601></value>\n", $val);
}
elseif(is_double($val))
{
$buff = sprintf("<value><double>%f</double></value>", $val);
}
elseif(is_bool($val))
{
$buff = sprintf("<value><boolean>%d</boolean></value>", $val ? 1 : 0);
}
elseif(is_object($val))
{
$values = get_object_vars($val);
$val_count = count($values);
$buff = "<value><struct>";
foreach($values as $k => $v)
{
$buff .= sprintf("<member>\n<name>%s</name>\n%s</member>\n", htmlspecialchars($k, ENT_COMPAT | ENT_HTML401, 'UTF-8', false), _getEncodedVal($v, true));
}
$buff .= "</struct></value>\n";
}
elseif(is_array($val))
{
$val_count = count($val);
$buff = "<value><array>\n<data>";
for($i = 0; $i < $val_count; $i++)
{
$buff .= _getEncodedVal($val[$i], true);
}
$buff .= "</data>\n</array></value>";
}
else
{
$buff = sprintf("<value><string>%s</string></value>\n", $val);
}
if(!$is_sub_set)
{
return sprintf("<param>\n%s</param>", $buff);
}
return $buff;
}
// Display the result
function printContent($content)
{
header("Content-Type: text/xml; charset=UTF-8");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
print $content;
Context::close();
exit();
}
/* End of file blogapi.func.php */
/* Location: ./addons/blogapi/blogapi.func.php */

View file

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