Update master #1

Merged
root merged 49 commits from joomla/Component-Builder:master into master 2024-02-06 12:33:45 +00:00
15 changed files with 1735 additions and 1133 deletions
Showing only changes of commit 0512af0f33 - Show all commits

View File

@ -140,14 +140,14 @@ TODO
+ *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io)
+ *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder)
+ *First Build*: 30th April, 2015
+ *Last Build*: 31st August, 2022
+ *Last Build*: 2nd September, 2022
+ *Version*: 3.1.5
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt
+ *Line count*: **319873**
+ *Line count*: **321348**
+ *Field count*: **2002**
+ *File count*: **2090**
+ *Folder count*: **359**
+ *File count*: **2094**
+ *Folder count*: **360**
> This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](http://joomlacomponentbuilder.com).
> Developed by [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com)

View File

@ -140,14 +140,14 @@ TODO
+ *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io)
+ *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder)
+ *First Build*: 30th April, 2015
+ *Last Build*: 31st August, 2022
+ *Last Build*: 2nd September, 2022
+ *Version*: 3.1.5
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt
+ *Line count*: **319873**
+ *Line count*: **321348**
+ *Field count*: **2002**
+ *File count*: **2090**
+ *Folder count*: **359**
+ *File count*: **2094**
+ *Folder count*: **360**
> This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](http://joomlacomponentbuilder.com).
> Developed by [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com)

File diff suppressed because it is too large Load Diff

View File

@ -3679,8 +3679,10 @@ abstract class ComponentbuilderHelper
/**
* prepare base64 string for url
**/
* prepare base64 string for url
*
* @deprecate Use urlencode();
*/
public static function base64_urlencode($string, $encode = false)
{
if ($encode)
@ -3691,8 +3693,10 @@ abstract class ComponentbuilderHelper
}
/**
* prepare base64 string form url
**/
* prepare base64 string form url
*
* @deprecate
*/
public static function base64_urldecode($string, $decode = false)
{
$string = str_replace(array('-', '_'), array('+', '/'), $string);

View File

@ -5597,6 +5597,7 @@ COM_COMPONENTBUILDER_HI="Hi"
COM_COMPONENTBUILDER_HIDE_ONLY="Hide Only"
COM_COMPONENTBUILDER_HIDE_TOGGLE="Hide Toggle"
COM_COMPONENTBUILDER_HOW_TO_GET_A_S_FREE_KEYSA_FROM_VDM="How to get <a %s >free keys</a> from VDM."
COM_COMPONENTBUILDER_HR_HTHREECUSTOM_CODES_WARNINGHTHREE="<hr /><h3>Custom Codes Warning</h3>"
COM_COMPONENTBUILDER_HR_HTHREEEXTERNAL_CODE_ERRORHTHREE="<hr /><h3>External Code Error</h3>"
COM_COMPONENTBUILDER_HR_HTHREEEXTERNAL_CODE_NOTICEHTHREE="<hr /><h3>External Code Notice</h3>"
COM_COMPONENTBUILDER_HR_HTHREEEXTERNAL_CODE_WARNINGHTHREE="<hr /><h3>External Code Warning</h3>"
@ -9361,6 +9362,7 @@ COM_COMPONENTBUILDER_WEBSITE_OF_S="Website of %s"
COM_COMPONENTBUILDER_WEBSITE_S="Website: %s"
COM_COMPONENTBUILDER_WE_DID_NOT_CHECK_THE_SNIPPET_IT_SELF_TO_SEE_IF_IT_CHANGED_WE_ONLY_WORK_ON_DATES="We did not check the snippet it self, to see if it changed. We only work on dates."
COM_COMPONENTBUILDER_WE_FAILED_TO_MOVE_BSB="We failed to move <b>%s</b>!"
COM_COMPONENTBUILDER_WE_FOUND_DYNAMIC_CODE_BALL_IN_ONE_LINEB_AND_IGNORED_IT_PLEASE_REVIEW_S_FOR_MORE_DETAILS="We found dynamic code <b>all in one line</b>, and ignored it! Please review (%s) for more details!"
COM_COMPONENTBUILDER_WE_SUCCESSFULLY_MOVED_BSB="We successfully moved <b>%s</b>!"
COM_COMPONENTBUILDER_WHILE_WE_DOWNLOAD_ALL_TWENTY_SIX_COMPILER_GIF_ANIMATIONS_RANDOMLY_USED_IN_THE_COMPILER_GUI_DURING_COMPILATION="While we download all 26 compiler GIF animations randomly used in the compiler GUI during compilation"
COM_COMPONENTBUILDER_WIKI="Wiki"

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="4" method="upgrade">
<name>COM_COMPONENTBUILDER</name>
<creationDate>31st August, 2022</creationDate>
<creationDate>2nd September, 2022</creationDate>
<author>Llewellyn van der Merwe</author>
<authorEmail>joomla@vdm.io</authorEmail>
<authorUrl>https://dev.vdm.io</authorUrl>

View File

@ -36,14 +36,6 @@ class Dispenser
**/
public array $hub;
/**
* Compiler Customcode
*
* @var Customcode
* @since 3.2.0
**/
protected Customcode $customcode;
/**
* Compiler Placeholder
*
@ -52,6 +44,14 @@ class Dispenser
**/
protected Placeholder $placeholder;
/**
* Compiler Customcode
*
* @var Customcode
* @since 3.2.0
**/
protected Customcode $customcode;
/**
* Compiler Customcode in Gui
*
@ -79,8 +79,8 @@ class Dispenser
/**
* Constructor.
*
* @param Customcode|null $customcode The compiler customcode object.
* @param Placeholder|null $placeholder The compiler placeholder object.
* @param Customcode|null $customcode The compiler customcode object.
* @param Gui|null $gui The compiler customcode gui object.
* @param Hash|null $hash The compiler customcode hash object.
* @param LockBase|null $base64 The compiler customcode lock base64 object.

View File

@ -0,0 +1,927 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 30th April, 2015
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace VDM\Joomla\Componentbuilder\Compiler\Customcode;
use Joomla\CMS\Factory;
use Joomla\CMS\User\User;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Config;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\Gui;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\Extractor\Paths;
use VDM\Joomla\Componentbuilder\Compiler\Placeholder\Reverse;
use VDM\Joomla\Componentbuilder\Compiler\Component\Placeholder;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Placefix;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Path;
/**
* Compiler Custom Code Extractor
*
* The custom script placeholders - we use the (xxx) to avoid detection it should be (***)
* ##################################---> PHP/JS ---####################################
*
* New Insert Code = /xxx[INSERT>$$$$]xxx/ /xxx[/INSERT>$$$$]xxx/
* New Replace Code = /xxx[REPLACE>$$$$]xxx/ /xxx[/REPLACE>$$$$]xxx/
*
* //////////////////////////////// when JCB adds it back //////////////////////////////////
* JCB Add Inserted Code = /xxx[INSERTED$$$$]xxx//xx23xx/ /xxx[/INSERTED$$$$]xxx/
* JCB Add Replaced Code = /xxx[REPLACED$$$$]xxx//xx25xx/ /xxx[/REPLACED$$$$]xxx/
*
* /////////////////////////////// changeing existing custom code /////////////////////////
* Update Inserted Code = /xxx[INSERTED>$$$$]xxx//xx23xx/ /xxx[/INSERTED>$$$$]xxx/
* Update Replaced Code = /xxx[REPLACED>$$$$]xxx//xx25xx/ /xxx[/REPLACED>$$$$]xxx/
*
* The custom script placeholders - we use the (==) to avoid detection it should be (--)
* ###################################---> HTML ---#####################################
*
* New Insert Code = !==[INSERT>$$$$]==> !==[/INSERT>$$$$]==>
* New Replace Code = !==[REPLACE>$$$$]==> !==[/REPLACE>$$$$]==>
*
* ///////////////////////////////// when JCB adds it back ///////////////////////////////
* JCB Add Inserted Code =
* JCB Add Replaced Code =
*
* //////////////////////////// changeing existing custom code ///////////////////////////
* Update Inserted Code = !==[INSERTED>$$$$]==> !==[/INSERTED>$$$$]==>
* Update Replaced Code = !==[REPLACED>$$$$]==> !==[/REPLACED>$$$$]==>
*
* ////////23 is the ID of the code in the system don't change it!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* More info read: https://git.vdm.dev/joomla/Component-Builder/wiki/TIPS:-Custom-Code
*
* @since 3.2.0
*/
class Extractor
{
/**
* The placeholder keys
*
* @var array
* @since 3.2.0
*/
protected array $PKeys
= [
1 => 'REPLACE<>$$$$]',
2 => 'INSERT<>$$$$]',
3 => 'REPLACED<>$$$$]',
4 => 'INSERTED<>$$$$]'
];
/**
* The custom code in local files that already exist in system
*
* @var array
* @since 3.2.0
*/
protected array $existing = [];
/**
* The custom code in local files that are new
*
* @var array
* @since 3.2.0
*/
protected array $new = [];
/**
* The index of code already loaded
*
* @var array
* @since 3.2.0
*/
protected array $done = [];
/**
* The search counter
*
* @var array
* @since 3.2.0
*/
protected array $counter = [1 => 0, 2 => 0];
/**
* The file types to search
*
* @var array
* @since 3.2.0
*/
protected array $fileTypes = ['\.php', '\.js', '\.xml'];
/**
* The local placeholders
*
* @var array
* @since 3.2.0
*/
protected array $placeholders;
/**
* Today's date in SQL format
*
* @var string
* @since 3.2.0
*/
protected string $today;
/**
* Compiler Config
*
* @var Config
* @since 3.2.0
**/
protected Config $config;
/**
* Compiler Customcode Gui
*
* @var Gui
* @since 3.2.0
**/
protected Gui $gui;
/**
* Compiler Customcode Extractor Paths
*
* @var Paths
* @since 3.2.0
**/
protected Paths $paths;
/**
* Compiler Placeholder Reverse
*
* @var Reverse
* @since 3.2.0
**/
protected Reverse $reverse;
/**
* Compiler Component Placeholder
*
* @var Placeholder
* @since 3.2.0
**/
protected Placeholder $componentPlaceholder;
/**
* Current User Object
*
* @var User
* @since 3.2.0
**/
protected User $user;
/**
* Database object to query local DB
*
* @var \JDatabaseDriver
* @since 3.2.0
**/
protected \JDatabaseDriver $db;
/**
* Database object to query local DB
*
* @var CMSApplication
* @since 3.2.0
**/
protected CMSApplication $app;
/**
* Constructor.
*
* @param Config|null $config The compiler config object.
* @param Gui|null $gui The compiler customcode gui object.
* @param Paths|null $paths The compiler customcode extractor paths object.
* @param Reverse|null $reverse The compiler placeholder reverse object.
* @param Placeholder|null $placeholder The compiler component placeholder object.
* @param User|null $user The current User object.
* @param \JDatabaseDriver|null $db The Database Driver object.
* @param CMSApplication|null $app The CMS Application object.
*
* @throws \Exception
* @since 3.2.0
*/
public function __construct(?Config $config = null, ?Gui $gui = null, ?Paths $paths = null,
?Reverse $reverse = null, ?Placeholder $placeholder = null,
?User $user = null, ?\JDatabaseDriver $db = null, ?CMSApplication $app = null)
{
$this->config = $config ?: Compiler::_('Config');
$this->gui = $gui ?: Compiler::_('Customcode.Gui');
$this->paths = $paths ?: Compiler::_('Customcode.Extractor.Paths');
$this->reverse = $reverse ?: Compiler::_('Placeholder.Reverse');
$this->componentPlaceholder = $placeholder ?: Compiler::_('Component.Placeholder');
$this->user = $user ?: Factory::getUser();
$this->db = $db ?: Factory::getDbo();
$this->app = $app ?: Factory::getApplication();
// set today's date
$this->today = Factory::getDate()->toSql();
// set some local placeholders
$placeholders = array_flip(
$this->componentPlaceholder->get()
);
$placeholders[StringHelper::safe(
$this->config->component_code_name, 'F'
) . 'Helper::'] = Placefix::_('Component') . 'Helper::';
$placeholders['COM_' . StringHelper::safe(
$this->config->component_code_name, 'U'
)] = 'COM_' . Placefix::_('COMPONENT');
$placeholders['com_' . $this->config->component_code_name] = 'com_' . Placefix::_('component');
// set the local placeholders
$this->placeholders = array_reverse($placeholders, true);
}
/**
* get the custom code from the local files
*
* @return void
* @since 3.2.0
*/
public function run()
{
// we must first store the current working directory
$joomla = getcwd();
foreach ($this->paths->active as $target => $path)
{
// we are changing the working directory to the component path
chdir($path);
foreach ($this->fileTypes as $type)
{
// get a list of files in the current directory tree (only PHP, JS and XML for now)
$files = Folder::files('.', $type, true, true);
// check if files found
if (ArrayHelper::check($files))
{
foreach ($files as $file)
{
// search the file
$this->searchFileContent($file, $target);
// insert new code
$this->insert(100);
// update existing custom code
$this->update(30);
}
}
}
}
// change back to Joomla working directory
chdir($joomla);
// make sure all code is stored
$this->insert();
// update existing custom code
$this->update();
}
/**
* search a file for placeholders and store result
*
* @param string $file The file path to search
*
* @return array on success
* @since 3.2.0
*/
protected function searchFileContent(&$file, &$target)
{
// we add a new search for the GUI CODE Blocks
$this->gui->search($file, $this->placeholders, $this->today, $target);
// reset each time per file
$loadEndFingerPrint = false;
$endFingerPrint = [];
$fingerPrint = [];
$codeBucket = [];
$pointer = [];
$reading = [];
$reader = 0;
// reset found Start type
$commentType = 0;
// make sure we have the path correct (the script file is not in admin path for example)
// there may be more... will nead to keep our eye on this... since files could be moved during install
$file = str_replace('./', '', $file); # TODO (windows path issues)
if ($file !== 'script.php')
{
$path = $target . '/' . $file;
}
else
{
$path = $file;
}
// now we go line by line
foreach (new \SplFileObject($file) as $lineNumber => $lineContent)
{
// we must keep last few lines to dynamic find target entry later
$fingerPrint[$lineNumber] = trim($lineContent);
// load the end fingerprint
if ($loadEndFingerPrint)
{
$endFingerPrint[$lineNumber] = trim($lineContent);
}
foreach ($this->PKeys as $type => $search)
{
$i = (int) ($type == 3 || $type == 4) ? 2 : 1;
$_type = (int) ($type == 1 || $type == 3) ? 1 : 2;
if ($reader === 0 || $reader === $i)
{
$targetKey = $type;
$start = '/***[' . $search . '***/';
$end = '/***[/' . $search . '***/';
$startHTML = '<!--[' . $search . '-->';
$endHTML = '<!--[/' . $search . '-->';
// check if the ending placeholder was found
if (isset($reading[$targetKey]) && $reading[$targetKey]
&& ((trim($lineContent) === $end
|| strpos($lineContent, $end) !== false)
|| (trim($lineContent) === $endHTML
|| strpos($lineContent, $endHTML) !== false)))
{
// trim the placeholder and if there is still data then load it
if (isset($endReplace)
&& ($_line = $this->addLineChecker($endReplace, 2, $lineContent)) !== false)
{
$codeBucket[$pointer[$targetKey]][] = $_line;
}
// deactivate the reader
$reading[$targetKey] = false;
if ($_type == 2)
{
// deactivate search
$reader = 0;
}
else
{
// activate fingerPrint for replacement end target
$loadEndFingerPrint = true;
$backupTargetKey = $targetKey;
$backupI = $i;
}
// all new records we can do a bulk insert
if ($i === 1)
{
// end the bucket info for this code block
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
(int) $lineNumber
); // 'toline'
// first reverse engineer this code block
$c0de = $this->reverse->engine(
implode('', $codeBucket[$pointer[$targetKey]]),
$this->placeholders, $target
);
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
base64_encode($c0de)
); // 'code'
if ($_type == 2)
{
// load the last value
$this->new[$pointer[$targetKey]][]
= $this->db->quote(0); // 'hashendtarget'
}
}
// the record already exist so we must update instead
elseif ($i === 2)
{
// end the bucket info for this code block
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('to_line') . ' = '
. $this->db->quote($lineNumber);
// first reverse engineer this code block
$c0de = $this->reverse->engine(
implode('', $codeBucket[$pointer[$targetKey]]),
$this->placeholders, $target,
$this->existing[$pointer[$targetKey]]['id']
);
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('code') . ' = '
. $this->db->quote(base64_encode($c0de));
if ($_type == 2)
{
// load the last value
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('hashendtarget')
. ' = ' . $this->db->quote(0);
}
}
}
// check if the endfingerprint is ready to save
if (count((array) $endFingerPrint) === 3)
{
$hashendtarget = '3__' . md5(
implode('', $endFingerPrint)
);
// all new records we can do a bulk insert
if ($i === 1)
{
// load the last value
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
$hashendtarget
); // 'hashendtarget'
}
// the record already exist so we must update
elseif ($i === 2)
{
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('hashendtarget') . ' = '
. $this->db->quote($hashendtarget);
}
// reset the needed values
$endFingerPrint = [];
$loadEndFingerPrint = false;
// deactivate reader (to allow other search)
$reader = 0;
}
// then read in the code
if (isset($reading[$targetKey]) && $reading[$targetKey])
{
$codeBucket[$pointer[$targetKey]][] = $lineContent;
}
// see if the custom code line starts now with PHP/JS comment type
if ((!isset($reading[$targetKey]) || !$reading[$targetKey])
&& (($i === 1 && trim($lineContent) === $start)
|| strpos($lineContent, $start) !== false))
{
$commentType = 1; // PHP/JS type
$startReplace = $start;
$endReplace = $end;
}
// see if the custom code line starts now with HTML comment type
elseif ((!isset($reading[$targetKey])
|| !$reading[$targetKey])
&& (($i === 1 && trim($lineContent) === $startHTML)
|| strpos($lineContent, $startHTML) !== false))
{
$commentType = 2; // HTML type
$startReplace = $startHTML;
$endReplace = $endHTML;
}
// check if the starting place holder was found
if ($commentType > 0)
{
// if we have all on one line we have a problem (don't load it TODO)
if (strpos($lineContent, $endReplace) !== false)
{
// reset found comment type
$commentType = 0;
$this->app->enqueueMessage(
Text::_('COM_COMPONENTBUILDER_HR_HTHREECUSTOM_CODES_WARNINGHTHREE'),
'Warning'
);
$this->app->enqueueMessage(
Text::sprintf('COM_COMPONENTBUILDER_WE_FOUND_DYNAMIC_CODE_BALL_IN_ONE_LINEB_AND_IGNORED_IT_PLEASE_REVIEW_S_FOR_MORE_DETAILS',
$path
), 'Warning'
);
continue;
}
// do a quick check to insure we have an id
$id = false;
if ($i === 2)
{
$id = $this->getSystemID(
$lineContent,
array(1 => $start, 2 => $startHTML),
$commentType
);
}
if ($i === 2 && $id > 0)
{
// make sure we update it only once even if found again.
if (isset($this->done[$id]))
{
// reset found comment type
$commentType = 0;
continue;
}
// store the id to avoid duplication
$this->done[$id] = (int) $id;
}
// start replace
$startReplace = $this->setStartReplace(
$id, $commentType, $startReplace
);
// set active reader (to lock out other search)
$reader = $i;
// set pointer
$pointer[$targetKey] = $this->counter[$i];
// activate the reader
$reading[$targetKey] = true;
// start code bucket
$codeBucket[$pointer[$targetKey]] = [];
// trim the placeholder and if there is still data then load it
if ($_line = $this->addLineChecker(
$startReplace, 1, $lineContent
))
{
$codeBucket[$pointer[$targetKey]][] = $_line;
}
// get the finger print around the custom code
$inFinger = count($fingerPrint);
$getFinger = $inFinger - 1;
$hasharray = array_slice(
$fingerPrint, -$inFinger, $getFinger, true
);
$hasleng = count($hasharray);
$hashtarget = $hasleng . '__' . md5(
implode('', $hasharray)
);
// for good practice
Path::fix($path);
// all new records we can do a bulk insert
if ($i === 1 || !$id)
{
// start the bucket for this code
$this->new[$pointer[$targetKey]] = [];
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
$path
); // 'path'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
(int) $_type
); // 'type'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
1
); // 'target'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
$commentType
); // 'comment_type'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
(int) $this->config->component_id
); // 'component'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
1
); // 'published'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
$this->today
); // 'created'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
(int) $this->user->id
); // 'created_by'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
1
); // 'version'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
1
); // 'access'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
$hashtarget
); // 'hashtarget'
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
(int) $lineNumber
); // 'fromline'
}
// the record already exist so we must update instead
elseif ($i === 2 && $id > 0)
{
// start the bucket for this code
$this->existing[$pointer[$targetKey]] = [];
$this->existing[$pointer[$targetKey]]['id']
= (int) $id;
$this->existing[$pointer[$targetKey]]['conditions'] = [];
$this->existing[$pointer[$targetKey]]['conditions'][]
= $this->db->quoteName('id') . ' = '
. $this->db->quote($id);
$this->existing[$pointer[$targetKey]]['fields'] = [];
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('path') . ' = '
. $this->db->quote($path);
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('type') . ' = '
. $this->db->quote($_type);
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('comment_type') . ' = '
. $this->db->quote($commentType);
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('component') . ' = '
. $this->db->quote($this->config->component_id);
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('from_line') . ' = '
. $this->db->quote($lineNumber);
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('modified') . ' = '
. $this->db->quote($this->today);
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('modified_by') . ' = '
. $this->db->quote($this->user->id);
$this->existing[$pointer[$targetKey]]['fields'][]
= $this->db->quoteName('hashtarget') . ' = '
. $this->db->quote($hashtarget);
}
else // this should actualy never happen
{
// de activate the reader
$reading[$targetKey] = false;
$reader = 0;
}
// reset found comment type
$commentType = 0;
// update the counter
$this->counter[$i]++;
}
}
}
// make sure only a few lines is kept at a time
if (count((array) $fingerPrint) > 10)
{
$fingerPrint = array_slice($fingerPrint, -6, 6, true);
}
}
// if the code is at the end of the page and there were not three more lines
if (count((array) $endFingerPrint) > 0 || $loadEndFingerPrint)
{
if (count((array) $endFingerPrint) > 0)
{
$leng = count($endFingerPrint);
$hashendtarget = $leng . '__' . md5(
implode('', $endFingerPrint)
);
}
else
{
$hashendtarget = 0;
}
// all new records we can do a buldk insert
if ($backupI === 1)
{
// load the last value
$this->new[$pointer[$backupTargetKey]][]
= $this->db->quote($hashendtarget); // 'hashendtarget'
}
// the record already exist so we must use module to update
elseif ($backupI === 2)
{
$this->existing[$pointer[$backupTargetKey]]['fields'][]
= $this->db->quoteName('hashendtarget') . ' = '
. $this->db->quote($hashendtarget);
}
}
}
/**
* Insert the code
*
* @param int $when To set when to update
*
* @return void
* @since 3.2.0
*/
protected function insert(int $when = 1)
{
if (ArrayHelper::check($this->new) >= $when)
{
// Create a new query object.
$query = $this->db->getQuery(true);
$continue = false;
// Insert columns.
$columns = array('path', 'type', 'target', 'comment_type',
'component', 'published', 'created', 'created_by',
'version', 'access', 'hashtarget', 'from_line',
'to_line', 'code', 'hashendtarget');
// Prepare the insert query.
$query->insert(
$this->db->quoteName('#__componentbuilder_custom_code')
);
$query->columns($this->db->quoteName($columns));
foreach ($this->new as $values)
{
if (count((array) $values) == 15)
{
$query->values(implode(',', $values));
$continue = true;
}
else
{
// TODO line mismatch... should not happen
}
}
// clear the values array
$this->new = [];
if (!$continue)
{
return; // insure we don't continue if no values were loaded
}
// Set the query using our newly populated query object and execute it.
$this->db->setQuery($query);
$this->db->execute();
}
}
/**
* Update the code
*
* @param int $when To set when to update
*
* @return void
* @since 3.2.0
*/
protected function update(int $when = 1)
{
if (ArrayHelper::check($this->existing) >= $when)
{
foreach ($this->existing as $code)
{
// Create a new query object.
$query = $this->db->getQuery(true);
// Prepare the update query.
$query->update(
$this->db->quoteName('#__componentbuilder_custom_code')
)->set($code['fields'])->where($code['conditions']);
// Set the query using our newly populated query object and execute it.
$this->db->setQuery($query);
$this->db->execute();
}
// clear the values array
$this->existing = [];
}
}
/**
* set the start replace placeholder
*
* @param int $id The comment id
* @param int $commentType The comment type
* @param string $startReplace The main replace string
*
* @return string on success
* @since 3.2.0
*/
protected function setStartReplace(int $id, int $commentType, string $startReplace): string
{
if ($id > 0)
{
switch ($commentType)
{
case 1: // the PHP & JS type
$startReplace .= '/*' . $id . '*/';
break;
case 2: // the HTML type
$startReplace .= '<!--' . $id . '-->';
break;
}
}
return $startReplace;
}
/**
* Check if this line should be added
*
* @param string $replaceKey The key to remove from line
* @param int $type The line type
* @param string $lineContent The line to check
*
* @return bool|int true on success
* @since 3.2.0
*/
protected function addLineChecker(string $replaceKey, int $type, string $lineContent)
{
$check = explode($replaceKey, $lineContent);
switch ($type)
{
case 1:
// beginning of code
if (isset($check[1]) && StringHelper::check($check[1]))
{
return trim($check[1]);
}
break;
case 2:
// end of code
if (isset($check[0]) && StringHelper::check($check[0]))
{
return trim($check[0]);
}
break;
}
return false;
}
/**
* search for the system id in the line given
*
* @param string $lineContent The file path to search
* @param array $placeholders The values to search for
* @param int $commentType The comment type
*
* @return mixed on success
* @since 3.2.0
*/
protected function getSystemID(string &$lineContent, array $placeholders, int $commentType)
{
$trim = '/';
if ($commentType == 2)
{
$trim = '<!--';
}
// remove place holder from content
$string = trim(
str_replace($placeholders[$commentType] . $trim, '', $lineContent)
);
// now get all numbers
$numbers = [];
preg_match_all('!\d+!', $string, $numbers);
// return the first number
if (isset($numbers[0])
&& ArrayHelper::check(
$numbers[0]
))
{
return reset($numbers[0]);
}
return false;
}
}

View File

@ -0,0 +1,429 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 30th April, 2015
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace VDM\Joomla\Componentbuilder\Compiler\Customcode\Extractor;
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\Folder;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Utilities\GetHelper;
use VDM\Joomla\Utilities\String\ClassfunctionHelper;
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Config;
use VDM\Joomla\Componentbuilder\Compiler\Placeholder;
use VDM\Joomla\Componentbuilder\Compiler\Component\Placeholder as ComponentPlaceholder;
use VDM\Joomla\Componentbuilder\Compiler\Customcode;
use VDM\Joomla\Componentbuilder\Compiler\Language\Extractor;
/**
* Compiler Custom Code Paths
*
* @since 3.2.0
*/
class Paths
{
/**
* The local paths
*
* @var array
* @since 3.2.0
**/
public array $active = [];
/**
* Compiler Component Placeholder
*
* @var array
* @since 3.2.0
**/
protected array $componentPlaceholder;
/**
* Compiler Config
*
* @var Config
* @since 3.2.0
**/
protected Config $config;
/**
* Compiler Placeholder
*
* @var Placeholder
* @since 3.2.0
**/
protected Placeholder $placeholder;
/**
* Compiler Customcode
*
* @var Customcode
* @since 3.2.0
**/
protected Customcode $customcode;
/**
* Compiler Language Extractor
*
* @var Extractor
* @since 3.2.0
**/
protected Extractor $extractor;
/**
* Database object to query local DB
*
* @var \JDatabaseDriver
* @since 3.2.0
**/
protected \JDatabaseDriver $db;
/**
* Constructor.
*
* @param Config|null $config The compiler config object.
* @param Placeholder|null $placeholder The compiler placeholder object.
* @param ComponentPlaceholder|null $componentPlaceholder The compiler component placeholder object.
* @param Customcode|null $customcode The compiler customcode object.
* @param Extractor|null $extractor The compiler language extractor object.
* @param \JDatabaseDriver|null $db The Database Driver object.
*
* @throws \Exception
* @since 3.2.0
*/
public function __construct(?Config $config = null, ?Placeholder $placeholder = null,
?ComponentPlaceholder $componentPlaceholder = null, ?Customcode $customcode = null,
?Extractor $extractor = null, ?\JDatabaseDriver $db = null)
{
$this->config = $config ?: Compiler::_('Config');
$this->placeholder = $placeholder ?: Compiler::_('Placeholder');
/** @var ComponentPlaceholder $componentPlaceholder */
$componentPlaceholder = $componentPlaceholder ?: Compiler::_('Component.Placeholder');
$this->customcode = $customcode ?: Compiler::_('Customcode');
$this->extractor = $extractor ?: Compiler::_('Language.Extractor');
$this->db = $db ?: Factory::getDbo();
// load the placeholders to local array
$this->componentPlaceholder = $componentPlaceholder->get();
// load the paths on initialization
$this->load();
}
/**
* get the local installed path of this component
*
* @return void
* @since 3.2.0
*/
protected function load()
{
// set the local paths to search
$local_paths = array();
// admin path
$local_paths['admin'] = JPATH_ADMINISTRATOR . '/components/com_'
. $this->config->component_code_name;
// site path
$local_paths['site'] = JPATH_ROOT . '/components/com_'
. $this->config->component_code_name;
// media path
$local_paths['media'] = JPATH_ROOT . '/media/com_'
. $this->config->component_code_name;
// power path
$local_paths['power'] = JPATH_ROOT . '/' . $this->config->get('jcb_powers_path', 'libraries/jcb_powers');
// lets also go over the REPOS - TODO
// Painful but we need to folder paths for the linked modules
if (($module_ids = $this->getModuleIDs()) !== false)
{
foreach ($module_ids as $module_id)
{
// get the module folder path
if (($path = $this->getModulePath($module_id)) !== false)
{
// set the path
$local_paths['module_' . str_replace('/', '_', $path)] = $path;
}
}
}
// Painful but we need to folder paths for the linked plugins
if (($plugin_ids = $this->getPluginIDs()) !== false)
{
foreach ($plugin_ids as $plugin_id)
{
// get the plugin group and folder name
if (($path = $this->getPluginPath($plugin_id)) !== false)
{
// set the path
$local_paths['plugin_' . str_replace('/', '_', $path)] = JPATH_ROOT . '/plugins/' . $path;
}
}
}
// check if the local install is found
foreach ($local_paths as $key => $localPath)
{
if (!Folder::exists($localPath))
{
unset($local_paths[$key]);
}
}
if (ArrayHelper::check($local_paths))
{
$this->active = $local_paths;
}
}
/**
* get the Joomla Modules IDs
*
* @return mixed of IDs on success
* @since 3.2.0
*/
protected function getModuleIDs()
{
if (($addjoomla_modules = GetHelper::var(
'component_modules', $this->config->component_id, 'joomla_component',
'addjoomla_modules'
)) !== false)
{
$addjoomla_modules = (JsonHelper::check(
$addjoomla_modules
)) ? json_decode($addjoomla_modules, true) : null;
if (ArrayHelper::check($addjoomla_modules))
{
$joomla_modules = array_filter(
array_values($addjoomla_modules),
function ($array) {
// only load the modules whose target association call for it
if (!isset($array['target']) || $array['target'] != 2)
{
return true;
}
return false;
}
);
// if we have values we return IDs
if (ArrayHelper::check($joomla_modules))
{
return array_map(
function ($array) {
return (int) $array['module'];
}, $joomla_modules
);
}
}
}
return false;
}
/**
* get the Joomla module path
*
* @return mixed of module path and target site area on success
* @since 3.2.0
*/
protected function getModulePath($id)
{
if (is_numeric($id) && $id > 0)
{
// Create a new query object.
$query = $this->db->getQuery(true);
$query->select('a.*');
$query->select(
$this->db->quoteName(
array(
'a.name',
'a.target'
), array(
'name',
'target'
)
)
);
// from these tables
$query->from('#__componentbuilder_joomla_module AS a');
$query->where($this->db->quoteName('a.id') . ' = ' . (int) $id);
$this->db->setQuery($query);
$this->db->execute();
if ($this->db->getNumRows())
{
// get the module data
$module = $this->db->loadObject();
// update the name if it has dynamic values
$module->name = $this->placeholder->update(
$this->customcode->add($module->name),
$this->componentPlaceholder
);
// set safe class function name
$module->code_name
= ClassfunctionHelper::safe(
$module->name
);
// set module folder name
$module->folder_name = 'mod_' . strtolower($module->code_name);
// set the lang key
$this->extractor->langKeys[strtoupper($module->folder_name)] =
$module->id . '_M0dU|3';
// return the path
if ($module->target == 2)
{
// administrator client area
return JPATH_ADMINISTRATOR . '/modules/'
. $module->folder_name;
}
else
{
// default is the site client area
return JPATH_ROOT . '/modules/' . $module->folder_name;
}
}
}
return false;
}
/**
* get the Joomla plugins IDs
*
* @return mixed of IDs on success
* @since 3.2.0
*/
protected function getPluginIDs()
{
if (($addjoomla_plugins = GetHelper::var(
'component_plugins', $this->config->component_id, 'joomla_component',
'addjoomla_plugins'
)) !== false)
{
$addjoomla_plugins = (JsonHelper::check(
$addjoomla_plugins
)) ? json_decode($addjoomla_plugins, true) : null;
if (ArrayHelper::check($addjoomla_plugins))
{
$joomla_plugins = array_filter(
array_values($addjoomla_plugins),
function ($array) {
// only load the plugins whose target association call for it
if (!isset($array['target']) || $array['target'] != 2)
{
return true;
}
return false;
}
);
// if we have values we return IDs
if (ArrayHelper::check($joomla_plugins))
{
return array_map(
function ($array) {
return (int) $array['plugin'];
}, $joomla_plugins
);
}
}
}
return false;
}
/**
* get the Joomla plugin path
*
* @return mixed of plugin path on success
* @deprecated 3.3
*/
protected function getPluginPath($id)
{
if (is_numeric($id) && $id > 0)
{
// Create a new query object.
$query = $this->db->getQuery(true);
$query->select('a.*');
$query->select(
$this->db->quoteName(
array(
'a.name',
'g.name'
), array(
'name',
'group'
)
)
);
// from these tables
$query->from('#__componentbuilder_joomla_plugin AS a');
$query->join(
'LEFT', $this->db->quoteName(
'#__componentbuilder_joomla_plugin_group', 'g'
) . ' ON (' . $this->db->quoteName('a.joomla_plugin_group')
. ' = ' . $this->db->quoteName('g.id') . ')'
);
$query->where($this->db->quoteName('a.id') . ' = ' . (int) $id);
$this->db->setQuery($query);
$this->db->execute();
if ($this->db->getNumRows())
{
// get the plugin data
$plugin = $this->db->loadObject();
// update the name if it has dynamic values
$plugin->name = $this->placeholder->update(
$this->customcode->add($plugin->name),
$this->componentPlaceholder
);
// update the name if it has dynamic values
$plugin->code_name
= ClassfunctionHelper::safe(
$plugin->name
);
// set plugin folder name
$plugin->group = strtolower($plugin->group);
// set plugin file name
$plugin->file_name = strtolower($plugin->code_name);
// set the lang key
$this->extractor->langKeys['PLG_' . strtoupper(
$plugin->group . '_' . $plugin->file_name
)] = $plugin->id . '_P|uG!n';
// return the path
return $plugin->group . '/' . $plugin->file_name;
}
}
return false;
}
}

View File

@ -0,0 +1 @@
<html><body bgcolor="#FFFFFF"></body></html>

View File

@ -84,18 +84,18 @@ class Reverse
/**
* Reverse Engineer the dynamic placeholders (TODO hmmmm this is not ideal)
*
* @param string $string The string to revers
* @param array $placeholders The values to search for
* @param string $target The target path type
* @param int|null $id The custom code id
* @param string $field The field name
* @param string $table The table name
* @param string $string The string to revers
* @param array $placeholders The values to search for
* @param string $target The target path type
* @param int|null $id The custom code id
* @param string $field The field name
* @param string $table The table name
*
* @return string
* @since 3.2.0
*/
public function engine(string $string, array &$placeholders,
string $target, ?int $id = null, $field = 'code', $table = 'custom_code'): string
string $target, ?int $id = null, string $field = 'code', string $table = 'custom_code'): string
{
// get local code if set
if ($id > 0 && $code = base64_decode(
@ -222,7 +222,7 @@ class Reverse
}
}
// return the found placeholders
$updateString = $this->placeholder->replace(
$updateString = $this->placeholder->update(
$updateString, $lang_holders
);
}

View File

@ -20,6 +20,8 @@ use VDM\Joomla\Componentbuilder\Compiler\Customcode\Gui;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\Hash;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\LockBase;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\Dispenser;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\Extractor;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\Extractor\Paths;
/**
@ -56,6 +58,12 @@ class Customcode implements ServiceProviderInterface
$container->alias(Dispenser::class, 'Customcode.Dispenser')
->share('Customcode.Dispenser', [$this, 'getDispenser'], true);
$container->alias(Paths::class, 'Customcode.Extractor.Paths')
->share('Customcode.Extractor.Paths', [$this, 'getPaths'], true);
$container->alias(Extractor::class, 'Customcode.Extractor')
->share('Customcode.Extractor', [$this, 'getExtractor'], true);
}
/**
@ -156,5 +164,43 @@ class Customcode implements ServiceProviderInterface
);
}
/**
* Get the Customcode Extractor Paths
*
* @param Container $container The DI container.
*
* @return Paths
* @since 3.2.0
*/
public function getPaths(Container $container): Paths
{
return new Paths(
$container->get('Config'),
$container->get('Placeholder'),
$container->get('Component.Placeholder'),
$container->get('Customcode'),
$container->get('Language.Extractor')
);
}
/**
* Get the Customcode Extractor
*
* @param Container $container The DI container.
*
* @return Extractor
* @since 3.2.0
*/
public function getExtractor(Container $container): Extractor
{
return new Extractor(
$container->get('Config'),
$container->get('Customcode.Gui'),
$container->get('Customcode.Extractor.Paths'),
$container->get('Placeholder.Reverse'),
$container->get('Component.Placeholder')
);
}
}

View File

@ -0,0 +1,61 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 30th April, 2015
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace VDM\Joomla\Componentbuilder\Compiler\Utilities;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\StringHelper;
/**
* Compiler Path Fix
*
* @since 3.2.0
*/
abstract class Path
{
/**
* Fix the path to work in the JCB script <-- (main issue here)
* Since we need / slash in all paths, for the JCB script even if it is Windows
* and since MS works with both forward and back slashes
* we just convert all slashes to forward slashes
*
* THIS is just my hack (fix) if you know a better way! speak-up!
*
* @param mixed $values the array of paths or the path as a string
* @param array $targets paths to target
*
* @return void
* @since 3.2.0
*/
public static function fix(&$values, $targets = array())
{
// if multiple to gets searched and fixed
if (ArrayHelper::check($values) && ArrayHelper::check($targets))
{
foreach ($targets as $target)
{
if (isset($values[$target]) && strpos($values[$target], '\\') !== false)
{
$values[$target] = str_replace('\\', '/', $values[$target]);
}
}
}
// if just a string
elseif (StringHelper::check($values) && strpos($values, '\\') !== false)
{
$values = str_replace('\\', '/', $values);
}
}
}

View File

@ -3676,8 +3676,10 @@ abstract class ComponentbuilderHelper
/**
* prepare base64 string for url
**/
* prepare base64 string for url
*
* @deprecate Use urlencode();
*/
public static function base64_urlencode($string, $encode = false)
{
if ($encode)
@ -3688,8 +3690,10 @@ abstract class ComponentbuilderHelper
}
/**
* prepare base64 string form url
**/
* prepare base64 string form url
*
* @deprecate
*/
public static function base64_urldecode($string, $decode = false)
{
$string = str_replace(array('-', '_'), array('+', '/'), $string);

View File

@ -41,6 +41,7 @@ COM_COMPONENTBUILDER_FREEOPEN="Free/Open"
COM_COMPONENTBUILDER_GREAT_THIS_PLACEHOLDER_WILL_WORK="Great, this placeholder will work!"
COM_COMPONENTBUILDER_HFOUR_CLASSNAVHEADERCOPYRIGHTHFOURPSP="<h4 class="nav-header">Copyright</h4><p>%s</p>"
COM_COMPONENTBUILDER_HFOUR_CLASSNAVHEADERLICENSEHFOURPSP="<h4 class="nav-header">License</h4><p>%s</p>"
COM_COMPONENTBUILDER_HR_HTHREECUSTOM_CODES_WARNINGHTHREE="<hr /><h3>Custom Codes Warning</h3>"
COM_COMPONENTBUILDER_HR_HTHREEEXTERNAL_CODE_ERRORHTHREE="<hr /><h3>External Code Error</h3>"
COM_COMPONENTBUILDER_HR_HTHREEEXTERNAL_CODE_NOTICEHTHREE="<hr /><h3>External Code Notice</h3>"
COM_COMPONENTBUILDER_HR_HTHREEEXTERNAL_CODE_WARNINGHTHREE="<hr /><h3>External Code Warning</h3>"
@ -116,6 +117,7 @@ COM_COMPONENTBUILDER_TO_CHANGE_THE_PACKAGE_OWNER_DEFAULTS_OPEN_THE_BJCB_GLOBAL_O
COM_COMPONENTBUILDER_TO_CHANGE_THE_PACKAGE_OWNER_DEFAULTS_OPEN_THE_JCB_GLOBAL_OPTIONS_GO_TO_THE_COMPANY_TAB_AND_ADD_THE_CORRECT_COMPANY_DETAILS_THERE="To change the package owner defaults. Open the JCB Global Options, go to the Company tab and add the correct company details there."
COM_COMPONENTBUILDER_TRANSLATOR_MODULE_NOT_READYBR_THIS_AREA_IS_STILL_UNDER_PRODUCTION_HOPEFULLY_WITH_NEXT_UPDATE="Translator Module not ready!<br />This area is still under production, hopefully with next update."
COM_COMPONENTBUILDER_WEBSITE_S="Website: %s"
COM_COMPONENTBUILDER_WE_FOUND_DYNAMIC_CODE_BALL_IN_ONE_LINEB_AND_IGNORED_IT_PLEASE_REVIEW_S_FOR_MORE_DETAILS="We found dynamic code <b>all in one line</b>, and ignored it! Please review (%s) for more details!"
COM_COMPONENTBUILDER_YOUR_DATA_IS_ENCRYPTED_WITH_A_AES_ONE_HUNDRED_AND_TWENTY_EIGHT_BIT_ENCRYPTION_USING_THE_ABOVE_THIRTY_TWO_CHARACTER_KEY_WITHOUT_THIS_KEY_IT_WILL_TAKE_THE_CURRENT_TECHNOLOGY_WITH_A_BRUTE_FORCE_ATTACK_METHOD_MORE_THEN_A_HREFHTTPRANDOMIZECOMHOWLONGTOHACKPASS_TARGET_BLANK_TITLEHOW_LONG_TO_HACK_PASSSEVEN_HUNDRED_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZEROA_YEARS_TO_CRACK_THEORETICALLY_UNLESS_THEY_HAVE_THIS_KEY_ABOVE_SO_DO_KEEP_IT_SAFE="Your data is encrypted with a AES 128 bit encryption using the above 32 character key. Without this key it will take the current technology with a brute force attack method more then <a href="http://random-ize.com/how-long-to-hack-pass/" target="_blank" title="How long to hack pass">700 000 000 000 000 000 000 000 000 000 000</a> years to crack theoretically. Unless they have this key above, so do keep it safe."
COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_ACCESS_THE_SERVER_DETAILS_BS_DENIEDB_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_INFO="You do not have permission to access the server details (<b>%s - denied</b>), please contact your system administrator for more info."
COM_COMPONENTBUILDER_YOU_SHOULD_ADD_THE_CORRECT_OWNER_DETAILS="You should add the correct owner details."