453 lines
13 KiB
PHP
453 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* @package Joomla.Site
|
|
* @subpackage com_j2xml
|
|
*
|
|
* @version 3.9.229-rc1
|
|
*
|
|
* @author Helios Ciancio <info (at) eshiol (dot) it>
|
|
* @link https://www.eshiol.it
|
|
* @copyright Copyright (C) 2010 - 2023 Helios Ciancio. All Rights Reserved
|
|
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU/GPL v3
|
|
* J2XML is free software. This version may have been modified pursuant
|
|
* to the GNU General Public License, and as distributed it includes or
|
|
* is derivative of works licensed under the GNU General Public License
|
|
* or other free or open source software licenses.
|
|
*/
|
|
|
|
// no direct access
|
|
defined('_JEXEC') or die();
|
|
|
|
use eshiol\J2xml\Messages;
|
|
|
|
jimport('eshiol.J2xml.Importer');
|
|
jimport('eshiol.J2xmlpro.Importer');
|
|
jimport('eshiol.J2xml.Messages');
|
|
jimport('eshiol.J2xml.Version');
|
|
jimport('eshiol.J2xmlpro.Version');
|
|
|
|
// Import JTableCategory
|
|
//JLoader::register('JTableCategory', JPATH_PLATFORM . '/joomla/database/table/category.php');
|
|
// Import JTableContent
|
|
//JLoader::register('JTableContent', JPATH_PLATFORM . '/joomla/database/table/content.php');
|
|
|
|
//require_once JPATH_ADMINISTRATOR . '/components/com_j2xml/helpers/j2xml.php';
|
|
|
|
/**
|
|
* Joomla! J2XML XML-RPC Plugin
|
|
*
|
|
* @since 1.5.3
|
|
*/
|
|
class XMLRPCJ2XMLServices
|
|
{
|
|
|
|
/**
|
|
* The service message queue.
|
|
*
|
|
* @var array
|
|
* @since 3.1.107
|
|
*/
|
|
protected static $_messageQueue = array();
|
|
|
|
/**
|
|
* Import articles from xml file
|
|
*
|
|
* @param base64 $xml
|
|
* @param string $username
|
|
* Username
|
|
* @param string $password
|
|
* Password
|
|
* @return string
|
|
* @since 1.5
|
|
*/
|
|
public static function import($xml, $username = '', $password = '')
|
|
{
|
|
// global $xmlrpcerruser, $xmlrpcI4, $xmlrpcInt, $xmlrpcBoolean, $xmlrpcDouble, $xmlrpcString, $xmlrpcDateTime, $xmlrpcBase64, $xmlrpcArray, $xmlrpcStruct, $xmlrpcValue;
|
|
|
|
$lang = JFactory::getApplication()->getLanguage();
|
|
$lang->load('lib_j2xml', JPATH_SITE, null, false, false) ||
|
|
// Fallback to the library file in the default language
|
|
$lang->load('lib_j2xml', JPATH_SITE, null, true);
|
|
|
|
$params = JComponentHelper::getParams('com_j2xml');
|
|
if ((int) $params->get('xmlrpc', 0) == 0)
|
|
{
|
|
JLog::add(new JLogEntry(JText::_('LIB_J2XML_MSG_XMLRPC_DISABLED'), JLog::ERROR, 'com_j2xml'));
|
|
return new xmlrpcresp(new xmlrpcval(self::$_messageQueue, 'array'));
|
|
}
|
|
|
|
$app = JFactory::getApplication();
|
|
$options = array();
|
|
$response = $app->login(array(
|
|
'username' => $username,
|
|
'password' => $password
|
|
), $options);
|
|
if (true !== $response)
|
|
{
|
|
JLog::add(new JLogEntry(JText::_('JGLOBAL_AUTH_NO_USER'), JLog::ERROR, 'com_j2xml'));
|
|
return new xmlrpcresp(new xmlrpcval(self::$_messageQueue, 'array'));
|
|
}
|
|
|
|
$cparams = JComponentHelper::getParams('com_j2xml');
|
|
$params = new JRegistry();
|
|
$params->set('categories', $cparams->get('categories', 1));
|
|
$params->set('contacts', $cparams->get('contacts', 1));
|
|
$params->set('content', $cparams->get('content'));
|
|
$params->set('fields', $cparams->get('fields', 1));
|
|
$params->set('images', $cparams->get('images', 1));
|
|
if ($cparams->get('keep_category', 1) == 2)
|
|
{
|
|
$params->set('content_category_forceto', $cparams->get('category'));
|
|
}
|
|
$params->set('keep_id', $cparams->get('keep_id', 0));
|
|
$params->set('keep_user_id', $cparams->get('keep_user_id', 0));
|
|
$params->set('tags', $cparams->get('tags', 1));
|
|
$params->set('superusers', $cparams->get('superusers', 0));
|
|
$params->set('usernotes', $cparams->get('usernotes', 0));
|
|
$params->set('users', $cparams->get('users', 1));
|
|
$params->set('viewlevels', $cparams->get('viewlevels', 1));
|
|
$params->set('weblinks', $cparams->get('weblinks'));
|
|
$params->set('keep_data', $cparams->get('keep_data'));
|
|
|
|
$options = $params->toString();
|
|
return self::importAjax($xml, $params->toString());
|
|
}
|
|
|
|
/**
|
|
* Import content from xml file
|
|
*
|
|
* @param string $xml
|
|
* @param string $options
|
|
* json string
|
|
*
|
|
* @return string
|
|
* @since 3.9
|
|
*/
|
|
public static function importAjax($xml, $options)
|
|
{
|
|
// global $xmlrpcerruser, $xmlrpcI4, $xmlrpcInt, $xmlrpcBoolean, $xmlrpcDouble, $xmlrpcString, $xmlrpcDateTime, $xmlrpcBase64, $xmlrpcArray, $xmlrpcStruct, $xmlrpcValue;
|
|
|
|
$lang = JFactory::getApplication()->getLanguage();
|
|
$lang->load('lib_j2xml', JPATH_SITE, null, false, false) ||
|
|
// Fallback to the library file in the default language
|
|
$lang->load('lib_j2xml', JPATH_SITE, null, true);
|
|
|
|
$user = JFactory::getUser();
|
|
if (!$user->authorise('core.admin', 'com_j2xml'))
|
|
{
|
|
if ($user->guest)
|
|
{
|
|
JFactory::getApplication()->setHeader('status', 401, true);
|
|
}
|
|
JLog::add(new JLogEntry(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'), JLog::ERROR, 'com_j2xml'));
|
|
// return new xmlrpcresp(new xmlrpcval(self::$_messageQueue, 'array'));
|
|
return new xmlrpcresp(new xmlrpcval(self::$_messageQueue, 'array'), 28, JText::_('JGLOBAL_AUTH_ACCESS_DENIED'));
|
|
}
|
|
|
|
$data = self::gzdecode($xml);
|
|
if (!$data)
|
|
{
|
|
$data = $xml;
|
|
}
|
|
|
|
libxml_use_internal_errors(true);
|
|
$xml = simplexml_load_string($data);
|
|
if (!$xml)
|
|
{
|
|
$data = base64_decode($data);
|
|
libxml_clear_errors();
|
|
}
|
|
|
|
if (!mb_detect_encoding($data, 'UTF-8'))
|
|
{
|
|
$data = mb_convert_encoding($data, 'UTF-8');
|
|
}
|
|
|
|
$data = utf8_encode(trim($data));
|
|
|
|
$data = strstr($data, '<?xml version="1.0" ');
|
|
|
|
//$data = J2XMLHelper::stripInvalidXml($data);
|
|
if (!defined('LIBXML_PARSEHUGE'))
|
|
{
|
|
define(LIBXML_PARSEHUGE, 524288);
|
|
}
|
|
|
|
$xml = simplexml_load_string($data, 'SimpleXMLElement', LIBXML_PARSEHUGE);
|
|
|
|
if (!$xml)
|
|
{
|
|
$errors = libxml_get_errors();
|
|
foreach ($errors as $error)
|
|
{
|
|
$msg = $error->code . ' - ' . JText::_($error->message);
|
|
switch ($error->level)
|
|
{
|
|
default:
|
|
case LIBXML_ERR_WARNING:
|
|
JLog::add(new JLogEntry(JText::_($msg), JLog::WARNING, 'com_j2xml'));
|
|
return new xmlrpcresp(new xmlrpcval(self::$_messageQueue, 'array'));
|
|
break;
|
|
case LIBXML_ERR_ERROR:
|
|
JLog::add(new JLogEntry(JText::_($msg), JLog::ERROR, 'com_j2xml'));
|
|
return new xmlrpcresp(new xmlrpcval(self::$_messageQueue, 'array'));
|
|
break;
|
|
case LIBXML_ERR_FATAL:
|
|
JLog::add(new JLogEntry(JText::_($msg), JLog::CRITICAL, 'com_j2xml'));
|
|
return new xmlrpcresp(new xmlrpcval(self::$_messageQueue, 'array'));
|
|
break;
|
|
}
|
|
}
|
|
libxml_clear_errors();
|
|
}
|
|
|
|
$params = new JRegistry($options);
|
|
|
|
JPluginHelper::importPlugin('j2xml');
|
|
$results = JFactory::getApplication()->triggerEvent('onContentBeforeImport', array('com_j2xml.xmlrpc', &$xml, $params));
|
|
|
|
if (!isset($xml['version']))
|
|
{
|
|
JLog::add(new JLogEntry(JText::_('LIB_J2XML_MSG_FILE_FORMAT_UNKNOWN'), JLog::ERROR, 'com_j2xml'));
|
|
return new xmlrpcresp(new xmlrpcval(self::$_messageQueue, 'array'));
|
|
}
|
|
|
|
$xmlVersion = $xml['version'];
|
|
$version = explode(".", $xmlVersion);
|
|
$xmlVersionNumber = $version[0] . substr('0' . $version[1], strlen($version[1]) - 1) . substr('0' . $version[2], strlen($version[2]) - 1);
|
|
|
|
$j2xmlVersion = class_exists('eshiol\J2xmlpro\Version') ? eshiol\J2xmlpro\Version::$DOCVERSION : eshiol\J2xml\Version::$DOCVERSION;
|
|
$version = explode(".", $j2xmlVersion);
|
|
$j2xmlVersionNumber = $version[0] . substr('0' . $version[1], strlen($version[1]) - 1) . substr('0' . $version[2], strlen($version[2]) - 1);
|
|
|
|
if (($xmlVersionNumber == $j2xmlVersionNumber) || ($xmlVersionNumber == "150900") || ($xmlVersionNumber == "120500"))
|
|
{
|
|
// set_time_limit(120);
|
|
$params->set('version', (string) $xml['version']);
|
|
$params->set('logger', 'xmlrpc');
|
|
|
|
$importer = class_exists('eshiol\J2xmlpro\Importer') ? new eshiol\J2xmlpro\Importer() : new eshiol\J2xml\Importer();
|
|
$importer->import($xml, $params);
|
|
}
|
|
else
|
|
{
|
|
JLog::add(new JLogEntry(JText::sprintf('LIB_J2XML_MSG_FILE_FORMAT_NOT_SUPPORTED', $xmlVersion), JLog::ERROR, 'com_j2xml'));
|
|
}
|
|
|
|
//$app->logout();
|
|
return new xmlrpcresp(new xmlrpcval(self::$_messageQueue, 'array'));
|
|
}
|
|
|
|
static function gzdecode($data, &$filename = '', &$error = '', $maxlength = null)
|
|
{
|
|
$len = strlen($data);
|
|
if ($len < 18 || strcmp(substr($data, 0, 2), "\x1f\x8b"))
|
|
{
|
|
$error = "Not in GZIP format.";
|
|
return null; // Not GZIP format (See RFC 1952)
|
|
}
|
|
$method = ord(substr($data, 2, 1)); // Compression method
|
|
$flags = ord(substr($data, 3, 1)); // Flags
|
|
if ($flags & 31 != $flags)
|
|
{
|
|
$error = "Reserved bits not allowed.";
|
|
return null;
|
|
}
|
|
// NOTE: $mtime may be negative (PHP integer limitations)
|
|
$mtime = unpack("V", substr($data, 4, 4));
|
|
$mtime = $mtime[1];
|
|
$xfl = substr($data, 8, 1);
|
|
$os = substr($data, 8, 1);
|
|
$headerlen = 10;
|
|
$extralen = 0;
|
|
$extra = "";
|
|
if ($flags & 4)
|
|
{
|
|
// 2-byte length prefixed EXTRA data in header
|
|
if ($len - $headerlen - 2 < 8)
|
|
{
|
|
return false; // invalid
|
|
}
|
|
$extralen = unpack("v", substr($data, 8, 2));
|
|
$extralen = $extralen[1];
|
|
if ($len - $headerlen - 2 - $extralen < 8)
|
|
{
|
|
return false; // invalid
|
|
}
|
|
$extra = substr($data, 10, $extralen);
|
|
$headerlen += 2 + $extralen;
|
|
}
|
|
$filenamelen = 0;
|
|
$filename = "";
|
|
if ($flags & 8)
|
|
{
|
|
// C-style string
|
|
if ($len - $headerlen - 1 < 8)
|
|
{
|
|
return false; // invalid
|
|
}
|
|
$filenamelen = strpos(substr($data, $headerlen), chr(0));
|
|
if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8)
|
|
{
|
|
return false; // invalid
|
|
}
|
|
$filename = substr($data, $headerlen, $filenamelen);
|
|
$headerlen += $filenamelen + 1;
|
|
}
|
|
$commentlen = 0;
|
|
$comment = "";
|
|
if ($flags & 16)
|
|
{
|
|
// C-style string COMMENT data in header
|
|
if ($len - $headerlen - 1 < 8)
|
|
{
|
|
return false; // invalid
|
|
}
|
|
$commentlen = strpos(substr($data, $headerlen), chr(0));
|
|
if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8)
|
|
{
|
|
return false; // Invalid header format
|
|
}
|
|
$comment = substr($data, $headerlen, $commentlen);
|
|
$headerlen += $commentlen + 1;
|
|
}
|
|
$headercrc = "";
|
|
if ($flags & 2)
|
|
{
|
|
// 2-bytes (lowest order) of CRC32 on header present
|
|
if ($len - $headerlen - 2 < 8)
|
|
{
|
|
return false; // invalid
|
|
}
|
|
$calccrc = crc32(substr($data, 0, $headerlen)) & 0xffff;
|
|
$headercrc = unpack("v", substr($data, $headerlen, 2));
|
|
$headercrc = $headercrc[1];
|
|
if ($headercrc != $calccrc)
|
|
{
|
|
$error = "Header checksum failed.";
|
|
return false; // Bad header CRC
|
|
}
|
|
$headerlen += 2;
|
|
}
|
|
// GZIP FOOTER
|
|
$datacrc = unpack("V", substr($data, - 8, 4));
|
|
$datacrc = sprintf('%u', $datacrc[1] & 0xFFFFFFFF);
|
|
$isize = unpack("V", substr($data, - 4));
|
|
$isize = $isize[1];
|
|
// decompression:
|
|
$bodylen = $len - $headerlen - 8;
|
|
if ($bodylen < 1)
|
|
{
|
|
// IMPLEMENTATION BUG!
|
|
return null;
|
|
}
|
|
$body = substr($data, $headerlen, $bodylen);
|
|
$data = "";
|
|
if ($bodylen > 0)
|
|
{
|
|
switch ($method)
|
|
{
|
|
case 8:
|
|
// Currently the only supported compression method:
|
|
$data = gzinflate($body, $maxlength);
|
|
break;
|
|
default:
|
|
$error = "Unknown compression method.";
|
|
return false;
|
|
}
|
|
} // zero-byte body content is allowed
|
|
// Verifiy CRC32
|
|
$crc = sprintf("%u", crc32($data));
|
|
$crcOK = $crc == $datacrc;
|
|
$lenOK = $isize == strlen($data);
|
|
if (!$lenOK || !$crcOK)
|
|
{
|
|
$error = ($lenOK ? '' : 'Length check FAILED. ') . ($crcOK ? '' : 'Checksum FAILED.');
|
|
return false;
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Enqueue a system message.
|
|
*
|
|
* @param string $message
|
|
* The message to log.
|
|
* @param string $priority
|
|
* Message priority based on {$this->priorities}.
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 3.1.107
|
|
*/
|
|
public static function enqueueMessage($message, $priority)
|
|
{
|
|
$codes = array(
|
|
'error' => 28,
|
|
'warning' => 29,
|
|
'notice' => 30,
|
|
'message' => 31
|
|
);
|
|
|
|
$message = htmlentities($message);
|
|
$found = false;
|
|
$msgs = array();
|
|
|
|
foreach (Messages::$messages as $i => $m)
|
|
{
|
|
if ($message == JText::_($m))
|
|
{
|
|
self::$_messageQueue[] = new xmlrpcval(array(
|
|
"code" => new xmlrpcval($i, 'int'),
|
|
"string" => new xmlrpcval($message, 'string'),
|
|
"message" => new xmlrpcval($message, 'string')
|
|
), "struct");
|
|
$found = true;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
$pattern = '/' . str_replace(array('(', ')', '[', ']', '.'), array('\(', '\)', '\[', '\]', '\.'), JText::_($m)) . '/i';
|
|
$pattern = preg_replace('/%(?:\d+\$)?[+-]?(?:[ 0]|\'.{1})?-?\d*(?:\.\d+)?[bcdeEufFgGosxX]/', '(.+)', $pattern);
|
|
|
|
if (preg_match($pattern, $message, $matches))
|
|
{
|
|
array_shift($matches);
|
|
|
|
preg_match_all($pattern, JText::_($m), $expected);
|
|
array_shift($expected);
|
|
|
|
$j = 1;
|
|
foreach($expected as $index => $value)
|
|
{
|
|
$expected[$index] = trim(strstr(strstr($value[0], '%'), '$', true), '%$') ?: $j++;
|
|
}
|
|
$expected = array_flip($expected);
|
|
ksort($expected);
|
|
|
|
$strings = array();
|
|
foreach ($expected as $index => $value)
|
|
{
|
|
$strings[] = new xmlrpcval($matches[$value], 'string');
|
|
}
|
|
self::$_messageQueue[] = new xmlrpcval(array(
|
|
"code" => new xmlrpcval($i, 'int'),
|
|
// "string" => new xmlrpcval($matches[1], 'string'),
|
|
"strings" => new xmlrpcval($strings, 'array'),
|
|
"message" => new xmlrpcval($message, 'string')
|
|
), "struct");
|
|
$found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!$found)
|
|
{
|
|
self::$_messageQueue[] = new xmlrpcval(array(
|
|
"code" => new xmlrpcval(isset($codes[$priority]) ? $codes[$priority] : 28, 'int'),
|
|
"string" => new xmlrpcval($message, 'string'),
|
|
"message" => new xmlrpcval($message, 'string')
|
|
), "struct");
|
|
}
|
|
}
|
|
} |