From 17195cd05921a10b1a90c4f2447dc718228047fc Mon Sep 17 00:00:00 2001 From: Llewellyn van der Merwe Date: Mon, 19 Feb 2018 14:52:08 +0200 Subject: [PATCH] Adapted the server implementation to more reusable object, added more permission control. Resolved gh-230 by adding the full shtp integration --- README.md | 4 +- admin/README.txt | 4 +- admin/helpers/compiler.php | 117 ++------- admin/helpers/compiler/a_Get.php | 5 - admin/helpers/componentbuilder.php | 232 +++++++++++++++--- .../en-GB/en-GB.com_componentbuilder.ini | 6 +- componentbuilder.xml | 2 +- site/helpers/componentbuilder.php | 232 +++++++++++++++--- .../en-GB/en-GB.com_componentbuilder.ini | 6 +- 9 files changed, 444 insertions(+), 164 deletions(-) diff --git a/README.md b/README.md index 036397fb9..1d0e701a5 100644 --- a/README.md +++ b/README.md @@ -126,11 +126,11 @@ Component Builder is mapped as a component in itself on my local development env + *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) + *Name*: [Component Builder](http://joomlacomponentbuilder.com) + *First Build*: 30th April, 2015 -+ *Last Build*: 17th February, 2018 ++ *Last Build*: 19th February, 2018 + *Version*: 2.6.15 + *Copyright*: Copyright (C) 2015. All Rights Reserved + *License*: GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html -+ *Line count*: **181747** ++ *Line count*: **182099** + *Field count*: **1639** + *File count*: **1167** + *Folder count*: **188** diff --git a/admin/README.txt b/admin/README.txt index 036397fb9..1d0e701a5 100644 --- a/admin/README.txt +++ b/admin/README.txt @@ -126,11 +126,11 @@ Component Builder is mapped as a component in itself on my local development env + *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) + *Name*: [Component Builder](http://joomlacomponentbuilder.com) + *First Build*: 30th April, 2015 -+ *Last Build*: 17th February, 2018 ++ *Last Build*: 19th February, 2018 + *Version*: 2.6.15 + *Copyright*: Copyright (C) 2015. All Rights Reserved + *License*: GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html -+ *Line count*: **181747** ++ *Line count*: **182099** + *Field count*: **1639** + *File count*: **1167** + *Folder count*: **188** diff --git a/admin/helpers/compiler.php b/admin/helpers/compiler.php index 370746aca..c911a2d38 100644 --- a/admin/helpers/compiler.php +++ b/admin/helpers/compiler.php @@ -321,27 +321,29 @@ class Compiler extends Infusion // use FTP if ($this->componentData->update_server_protocol == 1) { - // Get the basic encription. - $basickey = ComponentbuilderHelper::getCryptKey('basic'); - // Get the encription object. - $basic = new FOFEncryptAes($basickey, 128); - if (!empty($this->componentData->update_server) && $basickey && !is_numeric($this->componentData->update_server) && $this->componentData->update_server === base64_encode(base64_decode($this->componentData->update_server, true))) + // get server details + if ($ftp = ComponentbuilderHelper::getServer((int) $this->componentData->update_server, 1)) { - // basic decript data update_server. - $this->componentData->update_server = rtrim($basic->decryptString($this->componentData->update_server), "\0"); + // now move the file + if (!$ftp->store($xml_update_server_path, null)) + { + $this->app->enqueueMessage(JText::sprintf('The %s file could not be moved to %s server.', $this->updateServerFileName . '.xml', $$ftp->remote_server_name[(int) $this->componentData->update_server]), 'Error'); + } + // remove the local file + JFile::delete($xml_update_server_path); + // close the connection + $ftp->quit(); } - // now move the file - $this->moveFileToFtpServer($xml_update_server_path, $this->componentData->update_server); } // use SFTP elseif ($this->componentData->update_server_protocol == 2) { - if ($sftp = ComponentbuilderHelper::getSftp((int) $this->componentData->update_server)) + if ($sftp = ComponentbuilderHelper::getServer((int) $this->componentData->update_server, 2)) { // now move the file - if (!$sftp->put($sftp->remote_server_path . $this->updateServerFileName . '.xml', ComponentbuilderHelper::getFileContents($xml_update_server_path, null))) + if (!$sftp->put($sftp->remote_server_path[(int) $this->componentData->update_server] . $this->updateServerFileName . '.xml', ComponentbuilderHelper::getFileContents($xml_update_server_path, null))) { - $this->app->enqueueMessage(JText::sprintf('The %s file could not be moved to %s path on %s server.', $this->updateServerFileName . '.xml', $sftp->remote_server_path, $sftp->remote_server_name), 'Error'); + $this->app->enqueueMessage(JText::sprintf('The %s file could not be moved to %s path on %s server.', $this->updateServerFileName . '.xml', $sftp->remote_server_path[(int) $this->componentData->update_server], $sftp->remote_server_name[(int) $this->componentData->update_server]), 'Error'); } // remove the local file JFile::delete($xml_update_server_path); @@ -520,27 +522,26 @@ class Compiler extends Infusion // use FTP if ($this->componentData->sales_server_protocol == 1) { - // Get the basic encription. - $basickey = ComponentbuilderHelper::getCryptKey('basic'); - // Get the encription object. - $basic = new FOFEncryptAes($basickey, 128); - if (!empty($this->componentData->sales_server) && $basickey && !is_numeric($this->componentData->sales_server) && $this->componentData->sales_server === base64_encode(base64_decode($this->componentData->sales_server, true))) + if ($ftp = ComponentbuilderHelper::getServer((int) $this->componentData->sales_server, 1)) { - // basic decript data sales_server. - $this->componentData->sales_server = rtrim($basic->decryptString($this->componentData->sales_server), "\0"); + // now move the file + if (!$ftp->store($xml_update_server_path, $this->componentSalesName . '.zip')) + { + $this->app->enqueueMessage(JText::sprintf('The %s file could not be moved to %s server.', $this->componentSalesName . '.zip', $ftp->remote_server_name[(int) $this->componentData->sales_server]), 'Error'); + } + // close the connection + $ftp->quit(); } - // now move the file - $this->moveFileToFtpServer($this->filepath, $this->componentData->sales_server, $this->componentSalesName . '.zip', false); } // use SFTP elseif ($this->componentData->sales_server_protocol == 2) { - if ($sftp = ComponentbuilderHelper::getSftp((int) $this->componentData->sales_server)) + if ($sftp = ComponentbuilderHelper::getServer((int) $this->componentData->sales_server, 2)) { // now move the file - if (!$sftp->put($sftp->remote_server_path . $this->componentSalesName . '.zip', ComponentbuilderHelper::getFileContents($this->filepath, null))) + if (!$sftp->put($sftp->remote_server_path[(int) $this->componentData->sales_server] . $this->componentSalesName . '.zip', ComponentbuilderHelper::getFileContents($this->filepath, null))) { - $this->app->enqueueMessage(JText::sprintf('The %s file could not be moved to %s path on %s server.', $this->componentSalesName . '.zip', $sftp->remote_server_path, $sftp->remote_server_name), 'Error'); + $this->app->enqueueMessage(JText::sprintf('The %s file could not be moved to %s path on %s server.', $this->componentSalesName . '.zip', $sftp->remote_server_path[(int) $this->componentData->sales_server], $sftp->remote_server_name[(int) $this->componentData->sales_server]), 'Error'); } } } @@ -555,74 +556,6 @@ class Compiler extends Infusion return false; } - private function moveFileToFtpServer($localPath, $clientInput, $remote = null, $removeLocal = true) - { - // get the ftp opbject - $ftp = $this->getFTP($clientInput); - // chack if we are conected - if ($ftp instanceof JClientFtp && $ftp->isConnected()) - { - // move the file - if ($ftp->store($localPath, $remote)) - { - // if moved then remove the file from repository - if ($removeLocal) - { - JFile::delete($localPath); - } - } - // at the end close the conection - $ftp->quit(); - } - } - - private function getFTP($clientInput) - { - $s1GnAtnr3 = md5($clientInput); - if (isset($this->FTP[$s1GnAtnr3]) && $this->FTP[$s1GnAtnr3] instanceof JClientFtp) - { - // return the FTP instance - return $this->FTP[$s1GnAtnr3]; - } - else - { - // make sure we have a string and it is not default or empty - if (ComponentbuilderHelper::checkString($clientInput)) - { - // turn into variables - parse_str($clientInput); // because of this I am using strand variable naming to avoid any collisions. - // set options - if (isset($options) && ComponentbuilderHelper::checkArray($options)) - { - foreach ($options as $o__p0t1on => $vAln3) - { - if ('timeout' === $o__p0t1on) - { - $options[$o__p0t1on] = (int) $vAln3; - } - if ('type' === $o__p0t1on) - { - $options[$o__p0t1on] = (string) $vAln3; - } - } - } - else - { - $options = array(); - } - // get ftp object - if (isset($host) && $host != 'HOSTNAME' && isset($port) && $port != 'PORT_INT' && isset($username) && $username != 'user@name.com' && isset($password) && $password != 'password') - { - // load for reuse - $this->FTP[$s1GnAtnr3] = JClientFtp::getInstance($host, $port, $options, $username, $password); - // return the FTP instance - return $this->FTP[$s1GnAtnr3]; - } - } - } - return false; - } - protected function addCustomCode() { // reset all these diff --git a/admin/helpers/compiler/a_Get.php b/admin/helpers/compiler/a_Get.php index 93825d073..49676de49 100644 --- a/admin/helpers/compiler/a_Get.php +++ b/admin/helpers/compiler/a_Get.php @@ -1160,11 +1160,6 @@ class Get { // get the server protocol $component->{$server.'_protocol'} = ComponentbuilderHelper::getVar('server', (int) $component->{$server}, 'id', 'protocol'); - // load the FTP - if (1 == $component->{$server.'_protocol'}) - { - $component->{$server} = ComponentbuilderHelper::getVar('server', (int) $component->{$server}, 'id', 'signature'); - } } else { diff --git a/admin/helpers/componentbuilder.php b/admin/helpers/componentbuilder.php index 6450530cd..fb7f41bcd 100644 --- a/admin/helpers/componentbuilder.php +++ b/admin/helpers/componentbuilder.php @@ -1954,39 +1954,76 @@ abstract class ComponentbuilderHelper } /** - * the SFTP object + * the SFTP objects **/ protected static $sftp = array(); + /** + * the FTP objects + **/ + protected static $ftp = array(); + + /** + * get the server object + * + * @param int $serverID The server local id to use + * @param int $protocol The server protocol to use + * @param string $permission The permission validation area + * + * @return object on success server object + **/ + public static function getServer($serverID, $protocol, $permission = 'core.export') + { + // return the server object + switch ($protocol) + { + case 1: // FTP + return self::getFtp($serverID, $permission); + break; + case 2: // SFTP + return self::getSftp($serverID, $permission); + break; + } + return false; + } + /** * get the sftp object * - * @param int $serverID The server local id to use + * @param int $serverID The server local id to use + * @param string $permission The permission validation area * * @return object on success with sftp power **/ - public static function getSftp($serverID) + public static function getSftp($serverID, $permission = 'core.export') { - // check if it was already set - if (!self::checkObject(self::$sftp[$serverID])) + // check if we have a server with that id + if ($server = self::getServerDetails($serverID, 2, $permission)) { - // check if we have a server with that id - if ($server = self::getServerDetails($serverID, 2)) + // check if it was already set + if (!isset(self::$sftp[$server->cache]) || !self::checkObject(self::$sftp[$server->cache])) { // make sure we have the composer classes loaded self::composerAutoload(); + // make sure we have the phpseclib classes + if (!class_exists('\phpseclib\Net\SFTP')) + { + // class not in place so send out error + JFactory::getApplication()->enqueueMessage(JText::_('COM_COMPONENTBUILDER_THE_BPHPSECLIBNETSFTPB_LIBRARYCLASS_IS_NOT_AVAILABLE_THIS_LIBRARYCLASS_SHOULD_HAVE_BEEN_ADDED_TO_YOUR_ADMINHELPERSVENDOR_FOLDER_OF_JCB_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_INFO'), 'Error'); + return false; + } // insure the port is set $server->port = (isset($server->port) && is_int($server->port) && $server->port > 0) ? $server->port : 22; // open the connection - self::$sftp[$serverID] = new phpseclib\Net\SFTP($server->host, $server->port); + self::$sftp[$server->cache] = new phpseclib\Net\SFTP($server->host, $server->port); // now login based on authentication type switch($server->authentication) { case 1: // password - // now login - if (!self::$sftp[$serverID]->login($server->username, $server->password)) + if (!self::$sftp[$server->cache]->login($server->username, $server->password)) { JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_LOGIN_TO_BSB_HAS_FAILED_PLEASE_CHECK_THAT_YOUR_USERNAME_AND_PASSWORD_ARE_CORRECT', $server->name), 'Error'); + unset(self::$sftp[$server->cache]); return false; } break; @@ -2001,12 +2038,14 @@ abstract class ComponentbuilderHelper if (!$rsa->loadKey(self::getFileContents($server->private, null))) { JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_PRIVATE_KEY_FILE_COULD_NOT_BE_LOADEDFOUND_FOR_BSB_SERVER', $server->name), 'Error'); + unset(self::$sftp[$server->cache]); return false; } // now login - if (!self::$sftp[$serverID]->login($server->username, $rsa)) + if (!self::$sftp[$server->cache]->login($server->username, $rsa)) { JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_LOGIN_TO_BSB_HAS_FAILED_PLEASE_CHECK_THAT_YOUR_USERNAME_AND_PRIVATE_KEY_FILE_ARE_CORRECT', $server->name), 'Error'); + unset(self::$sftp[$server->cache]); return false; } break; @@ -2021,54 +2060,166 @@ abstract class ComponentbuilderHelper if (!$rsa->loadKey(self::getFileContents($server->private, null))) { JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_PRIVATE_KEY_FILE_COULD_NOT_BE_LOADEDFOUND_FOR_BSB_SERVER', $server->name), 'Error'); + unset(self::$sftp[$server->cache]); return false; } // now login - if (!self::$sftp[$serverID]->login($server->username, $server->password, $rsa)) + if (!self::$sftp[$server->cache]->login($server->username, $server->password, $rsa)) { JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_LOGIN_TO_BSB_HAS_FAILED_PLEASE_CHECK_THAT_YOUR_USERNAME_PASSWORD_AND_PRIVATE_KEY_FILE_ARE_CORRECT', $server->name), 'Error'); + unset(self::$sftp[$server->cache]); return false; } break; } - // set some defaults - self::$sftp[$serverID]->remote_server_name = $server->name; - self::$sftp[$serverID]->remote_server_path = (self::checkString($server->path) && $server->path !== '/') ? $server->path : ''; } - else + // only continue if object is set + if (isset(self::$sftp[$server->cache]) && self::checkObject(self::$sftp[$server->cache])) { - JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_SERVER_DETAILS_FOR_BSB_COULD_NOT_BE_RETRIEVED', $serverID), 'Error'); - return false; + // set the unique buckets + if (!isset(self::$sftp[$server->cache]->remote_server_name)) + { + self::$sftp[$server->cache]->remote_server_name = array(); + self::$sftp[$server->cache]->remote_server_path = array(); + } + // always set the name and remote server path + self::$sftp[$server->cache]->remote_server_name[$serverID] = $server->name; + self::$sftp[$server->cache]->remote_server_path[$serverID] = (self::checkString($server->path) && $server->path !== '/') ? $server->path : ''; + // return the sftp object + return self::$sftp[$server->cache]; } } - // return the sftp object - return self::$sftp[$serverID]; + return false; + } + + /** + * get the JClientFtp object + * + * @param int $serverID The server local id to use + * @param string $permission The permission validation area + * + * @return object on success with ftp power + **/ + public static function getFtp($serverID, $permission) + { + // check if we have a server with that id + if ($server = self::getServerDetails($serverID, 1, $permission)) + { + // check if we already have the server instance + if (isset(self::$ftp[$server->cache]) && self::$ftp[$server->cache] instanceof JClientFtp) + { + // always set the name and remote server path + self::$ftp[$server->cache]->remote_server_name[$serverID] = $server->name; + // if still connected we are ready to go + if (self::$ftp[$server->cache]->isConnected()) + { + // return the FTP instance + return self::$ftp[$server->cache]; + } + // check if we can reinitialise the server + if (self::$ftp[$server->cache]->reinit()) + { + // return the FTP instance + return self::$ftp[$server->cache]; + } + } + // make sure we have a string and it is not default or empty + if (self::checkString($server->signature)) + { + // turn into variables + parse_str($server->signature); // because of this I am using strange variable naming to avoid any collisions. + // set options + if (isset($options) && self::checkArray($options)) + { + foreach ($options as $o__p0t1on => $vAln3) + { + if ('timeout' === $o__p0t1on) + { + $options[$o__p0t1on] = (int) $vAln3; + } + if ('type' === $o__p0t1on) + { + $options[$o__p0t1on] = (string) $vAln3; + } + } + } + else + { + $options = array(); + } + // get ftp object + if (isset($host) && $host != 'HOSTNAME' && isset($port) && $port != 'PORT_INT' && isset($username) && $username != 'user@name.com' && isset($password) && $password != 'password') + { + // load for reuse + self::$ftp[$server->cache] = JClientFtp::getInstance($host, $port, $options, $username, $password); + } + else + { + // load error to indicate signature was in error + JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_FTP_SIGNATURE_FOR_BSB_WAS_NOT_WELL_FORMED_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS', $server->name), 'Error'); + return false; + } + // check if we are connected + if (self::$ftp[$server->cache] instanceof JClientFtp && self::$ftp[$server->cache]->isConnected()) + { + // set the unique buckets + if (!isset(self::$ftp[$server->cache]->remote_server_name)) + { + self::$ftp[$server->cache]->remote_server_name = array(); + } + // always set the name and remote server path + self::$ftp[$server->cache]->remote_server_name[$serverID] = $server->name; + // return the FTP instance + return self::$ftp[$server->cache]; + } + // reset since we have no connection + unset(self::$ftp[$server->cache]); + } + // load error to indicate signature was in error + JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_FTP_CONNECTION_FOR_BSB_COULD_NOT_BE_MADE_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS', $server->name), 'Error'); + } + return false; } /** * get the server details * - * @param int $serverID The server local id to use - * @param int $protocol The server protocol to use + * @param int $serverID The server local id to use + * @param int $protocol The server protocol to use + * @param string $permission The permission validation area * - * @return array on success with sftp server details + * @return object on success with server details **/ - protected static function getServerDetails($serverID, $protocol = 2) + public static function getServerDetails($serverID, $protocol = 2, $permission = 'core.export') { - if (is_int($serverID) && is_int($serverID)) + // check if this user has permission to access items + if (!JFactory::getUser()->authorise($permission, 'com_componentbuilder')) + { + // set message to inform the user that permission was denied + JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_ACCESS_THE_SERVER_DETAILS_BS_DENIEDB_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_INFO', self::safeString($permission, 'w')), 'Error'); + return false; + } + // now insure we have correct values + if (is_int($serverID) && is_int($protocol)) { // Get a db connection $db = JFactory::getDbo(); // start the query $query = $db->getQuery(true); - // select based to protocal + // select based to protocol if (2 == $protocol) { + // SFTP $query->select($db->quoteName(array('name','authentication','username','host','password','path','port','private','secret'))); + // cache builder + $cache = array('authentication','username','host','password','port','private','secret'); } else { + // FTP $query->select($db->quoteName(array('name','signature'))); + // cache builder + $cache = array('signature'); } $query->from($db->quoteName('#__componentbuilder_server')); $query->where($db->quoteName('id') . ' = ' . (int) $serverID); @@ -2082,21 +2233,42 @@ abstract class ComponentbuilderHelper $basickey = self::getCryptKey('basic'); // Get the encryption object. $basic = new FOFEncryptAes($basickey, 128); + // start cache keys + $keys = array(); // unlock the needed fields - foreach($server as $name => $value) + foreach($server as $name => &$value) { - if ($name !== 'name' && !empty($server->{$name}) && $basickey && !is_numeric($server->{$name}) && $server->{$name} === base64_encode(base64_decode($server->{$name}, true))) + // unlock the needed fields + if ($name !== 'name' && !empty($value) && $basickey && !is_numeric($value) && $value === base64_encode(base64_decode($value, true))) { // basic decrypt of data - $server->{$name} = rtrim($basic->decryptString($server->{$name}), "\0"); + $value = rtrim($basic->decryptString($value), "\0"); } + // build cache (keys) for lower connection latency + if (in_array($name, $cache)) + { + $keys[] = $value; + } + } + // check if cache keys were found + if (self::checkArray($keys)) + { + // now set cache + $server->cache = md5(implode('', $keys)); + } + else + { + // default is ID + $server->cache = $serverID; } // return the server details return $server; } } + JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_SERVER_DETAILS_FOR_BID_SB_COULD_NOT_BE_RETRIEVED', $serverID), 'Error'); return false; - } + } + /** * Load the Component xml manifest. **/ diff --git a/admin/language/en-GB/en-GB.com_componentbuilder.ini b/admin/language/en-GB/en-GB.com_componentbuilder.ini index be50dae6e..a7adb9ae1 100644 --- a/admin/language/en-GB/en-GB.com_componentbuilder.ini +++ b/admin/language/en-GB/en-GB.com_componentbuilder.ini @@ -6133,6 +6133,7 @@ COM_COMPONENTBUILDER_THERE_ARE_NO_OUT_OF_DATE_SNIPPETS_AT_THIS_TIME="There are n COM_COMPONENTBUILDER_THERE_ARE_NO_SNIPPETS_TO_UPDATE_AT_THIS_TIME="There are no snippets to update at this time" COM_COMPONENTBUILDER_THERE_HAS_BEEN_AN_ERROR_IF_THIS_CONTINUES_PLEASE_INFORM_YOUR_SYSTEM_ADMINISTRATOR_OF_A_TYPE_ERROR_IN_THE_FIELDS_DISPLAY_REQUEST="There has been an error, if this continues please inform your system administrator of a type error in the fields display request!" COM_COMPONENTBUILDER_THERE_WAS_A_PROBLEM_BNO_VIEW_OR_ID_FOUND_IN_SESSION_OR_VIEW_NOT_ALLOWED_TO_ACCESS_AREAB_WE_COULD_NOT_LOAD_ANY_LINKED_TO_VALUES_PLEASE_INFORM_YOUR_SYSTEM_ADMINISTRATOR="There was a problem, no view or id found in session or view not allowed to access area, we could not load any linked to values. Please inform your system administrator!" +COM_COMPONENTBUILDER_THE_BPHPSECLIBNETSFTPB_LIBRARYCLASS_IS_NOT_AVAILABLE_THIS_LIBRARYCLASS_SHOULD_HAVE_BEEN_ADDED_TO_YOUR_ADMINHELPERSVENDOR_FOLDER_OF_JCB_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_INFO="The phpseclib\NET\SFTP library\class is not available! This library\class should have been added to your admin/helpers/vendor folder of JCB. Please contact your system administrator for more info" COM_COMPONENTBUILDER_THE_BSB_LIBRARY_CAN_NOT_BE_DELETED_OR_THINGS_WILL_BREAK="The %s library can not be deleted, or things will break." COM_COMPONENTBUILDER_THE_COMPONENT_ADMIN_VIEWS="The component admin views" COM_COMPONENTBUILDER_THE_COMPONENT_CONFIG="The component config" @@ -6143,6 +6144,8 @@ COM_COMPONENTBUILDER_THE_COMPONENT_FILES_FOLDERS="The component files & folders" COM_COMPONENTBUILDER_THE_COMPONENT_MYSQL_TWEAKS="The component mysql tweaks" COM_COMPONENTBUILDER_THE_COMPONENT_SITE_VIEWS="The component site views" COM_COMPONENTBUILDER_THE_COMPONENT_UPDATES="The component updates" +COM_COMPONENTBUILDER_THE_FTP_CONNECTION_FOR_BSB_COULD_NOT_BE_MADE_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS="The FTP connection for %s could not be made. Please check your signature details!" +COM_COMPONENTBUILDER_THE_FTP_SIGNATURE_FOR_BSB_WAS_NOT_WELL_FORMED_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS="The FTP signature for %s was not well formed, please check your signature details!" COM_COMPONENTBUILDER_THE_KEY_OF_THIS_PACKAGE="The key of this package." COM_COMPONENTBUILDER_THE_LIBRARY_CONFIG_FIELDS="The library config fields" COM_COMPONENTBUILDER_THE_LIBRARY_FILES_FOLDERS_URLS="The library files, folders & URLs" @@ -6156,7 +6159,7 @@ COM_COMPONENTBUILDER_THE_PACKAGE_KEY_IS_S="The package key is: %s" COM_COMPONENTBUILDER_THE_PRIVATE_KEY_FILE_COULD_NOT_BE_LOADEDFOUND_FOR_BSB_SERVER="The private key file could not be loaded/found for %s server!" COM_COMPONENTBUILDER_THE_README_IS_LOADING="The readme is loading" COM_COMPONENTBUILDER_THE_SEARCH_FOR_THE_SNIPPETS_ARE_CASE_SENSITIVE_SO_IF_YOU_CHANGED_THE_LOCAL_BNAMESB_OF_EITHER_OR_THE_BSNIPPET_LIBRARY_OR_SNIPPET_TYPESB_IN_ANY_SMALL_WAY_THE_SYSTEM_WILL_NOT_BE_ABLE_TO_CONNECT_YOUR_LOCAL_SNIPPETS_WITH_THOSE_IN_THE_COMMUNITY_REPOSITORY_SO_WE_STRONGLY_ADVICE_TO_BKEEP_TO_THE_COMMUNITY_NAMINGB_TO_AVOID_MISMATCHING_THAT_WILL_IN_TURN_CAUSE_DUPLICATION_SO_IF_YOU_CHANGED_ANY_NAMES_JUST_CHANGE_THEM_BACK_AND_ALL_WILL_AGAIN_WORK_AS_EXPECTED="The search for the snippets are case sensitive so if you changed the local names of either or the snippet, library or snippet types in any small way, the system will not be able to connect your local snippets with those in the community repository. So we strongly advice to keep to the community naming to avoid mismatching, that will in turn cause duplication. So if you changed any names, just change them back and all will again work as expected." -COM_COMPONENTBUILDER_THE_SERVER_DETAILS_FOR_BSB_COULD_NOT_BE_RETRIEVED="The server details for (%s) could not be retrieved!" +COM_COMPONENTBUILDER_THE_SERVER_DETAILS_FOR_BID_SB_COULD_NOT_BE_RETRIEVED="The server details for (ID: %s) could not be retrieved!" COM_COMPONENTBUILDER_THE_SNIPPETS_WERE_SUCCESSFULLY_EXPORTED="The Snippets Were Successfully Exported!" COM_COMPONENTBUILDER_THE_SNIPPET_WAS_SUCCESSFULLY_EXPORTED="The Snippet Was Successfully Exported!" COM_COMPONENTBUILDER_THE_WIKI_IS_LOADING="The wiki is loading" @@ -6207,6 +6210,7 @@ COM_COMPONENTBUILDER_YES="Yes" COM_COMPONENTBUILDER_YOUR_DATA_IS_ENCRYPTED_WITH_A_AES_ONE_HUNDRED_AND_TWENTY_EIGHT_BIT_ENCRYPTION_USING_THE_ABOVE_THIRTY_TWO_CHARACTER_KEYBR_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="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 700 000 000 000 000 000 000 000 000 000 000 years to crack theoretically." 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 700 000 000 000 000 000 000 000 000 000 000 years to crack theoretically. Unless they have this key above, so do keep it safe." COM_COMPONENTBUILDER_YOU_CAN_NOW_SELECT_THE_COMPONENT_BZIPB_PACKAGE_YOU_WOULD_LIKE_TO_IMPORTBR_SMALLPLEASE_NOTE_THAT_SMART_COMPONENT_IMPORT_ONLY_WORKS_WITH_THE_FOLLOWING_FORMAT_BZIPBSMALL="You can now select the component zip package you would like to import.
Please note that smart component import only works with the following format: (.zip)" +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 (%s - denied), please contact your system administrator for more info." COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_IMPORT_A_COMPONENT_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_HELP="You do not have permission to import a component, please contact your system administrator for more help." COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_SHARE_THE_SNIPPETS_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_HELP="You do not have permission to share the snippets, please contact your system administrator for more help." COM_COMPONENTBUILDER_YOU_HAVE_S_S_ADDING_MORE_THEN_FIFTY_S_IS_CONSIDERED_BAD_PRACTICE="You have %s %s. Adding more then 50 %s is considered bad practice." diff --git a/componentbuilder.xml b/componentbuilder.xml index 20d4d515c..147a0c35b 100644 --- a/componentbuilder.xml +++ b/componentbuilder.xml @@ -1,7 +1,7 @@ COM_COMPONENTBUILDER - 17th February, 2018 + 19th February, 2018 Llewellyn van der Merwe llewellyn@joomlacomponentbuilder.com http://joomlacomponentbuilder.com diff --git a/site/helpers/componentbuilder.php b/site/helpers/componentbuilder.php index e0aea1303..b26bb21bf 100644 --- a/site/helpers/componentbuilder.php +++ b/site/helpers/componentbuilder.php @@ -1020,39 +1020,76 @@ abstract class ComponentbuilderHelper } /** - * the SFTP object + * the SFTP objects **/ protected static $sftp = array(); + /** + * the FTP objects + **/ + protected static $ftp = array(); + + /** + * get the server object + * + * @param int $serverID The server local id to use + * @param int $protocol The server protocol to use + * @param string $permission The permission validation area + * + * @return object on success server object + **/ + public static function getServer($serverID, $protocol, $permission = 'core.export') + { + // return the server object + switch ($protocol) + { + case 1: // FTP + return self::getFtp($serverID, $permission); + break; + case 2: // SFTP + return self::getSftp($serverID, $permission); + break; + } + return false; + } + /** * get the sftp object * - * @param int $serverID The server local id to use + * @param int $serverID The server local id to use + * @param string $permission The permission validation area * * @return object on success with sftp power **/ - public static function getSftp($serverID) + public static function getSftp($serverID, $permission = 'core.export') { - // check if it was already set - if (!self::checkObject(self::$sftp[$serverID])) + // check if we have a server with that id + if ($server = self::getServerDetails($serverID, 2, $permission)) { - // check if we have a server with that id - if ($server = self::getServerDetails($serverID, 2)) + // check if it was already set + if (!isset(self::$sftp[$server->cache]) || !self::checkObject(self::$sftp[$server->cache])) { // make sure we have the composer classes loaded self::composerAutoload(); + // make sure we have the phpseclib classes + if (!class_exists('\phpseclib\Net\SFTP')) + { + // class not in place so send out error + JFactory::getApplication()->enqueueMessage(JText::_('COM_COMPONENTBUILDER_THE_BPHPSECLIBNETSFTPB_LIBRARYCLASS_IS_NOT_AVAILABLE_THIS_LIBRARYCLASS_SHOULD_HAVE_BEEN_ADDED_TO_YOUR_ADMINHELPERSVENDOR_FOLDER_OF_JCB_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_INFO'), 'Error'); + return false; + } // insure the port is set $server->port = (isset($server->port) && is_int($server->port) && $server->port > 0) ? $server->port : 22; // open the connection - self::$sftp[$serverID] = new phpseclib\Net\SFTP($server->host, $server->port); + self::$sftp[$server->cache] = new phpseclib\Net\SFTP($server->host, $server->port); // now login based on authentication type switch($server->authentication) { case 1: // password - // now login - if (!self::$sftp[$serverID]->login($server->username, $server->password)) + if (!self::$sftp[$server->cache]->login($server->username, $server->password)) { JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_LOGIN_TO_BSB_HAS_FAILED_PLEASE_CHECK_THAT_YOUR_USERNAME_AND_PASSWORD_ARE_CORRECT', $server->name), 'Error'); + unset(self::$sftp[$server->cache]); return false; } break; @@ -1067,12 +1104,14 @@ abstract class ComponentbuilderHelper if (!$rsa->loadKey(self::getFileContents($server->private, null))) { JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_PRIVATE_KEY_FILE_COULD_NOT_BE_LOADEDFOUND_FOR_BSB_SERVER', $server->name), 'Error'); + unset(self::$sftp[$server->cache]); return false; } // now login - if (!self::$sftp[$serverID]->login($server->username, $rsa)) + if (!self::$sftp[$server->cache]->login($server->username, $rsa)) { JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_LOGIN_TO_BSB_HAS_FAILED_PLEASE_CHECK_THAT_YOUR_USERNAME_AND_PRIVATE_KEY_FILE_ARE_CORRECT', $server->name), 'Error'); + unset(self::$sftp[$server->cache]); return false; } break; @@ -1087,54 +1126,166 @@ abstract class ComponentbuilderHelper if (!$rsa->loadKey(self::getFileContents($server->private, null))) { JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_PRIVATE_KEY_FILE_COULD_NOT_BE_LOADEDFOUND_FOR_BSB_SERVER', $server->name), 'Error'); + unset(self::$sftp[$server->cache]); return false; } // now login - if (!self::$sftp[$serverID]->login($server->username, $server->password, $rsa)) + if (!self::$sftp[$server->cache]->login($server->username, $server->password, $rsa)) { JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_LOGIN_TO_BSB_HAS_FAILED_PLEASE_CHECK_THAT_YOUR_USERNAME_PASSWORD_AND_PRIVATE_KEY_FILE_ARE_CORRECT', $server->name), 'Error'); + unset(self::$sftp[$server->cache]); return false; } break; } - // set some defaults - self::$sftp[$serverID]->remote_server_name = $server->name; - self::$sftp[$serverID]->remote_server_path = (self::checkString($server->path) && $server->path !== '/') ? $server->path : ''; } - else + // only continue if object is set + if (isset(self::$sftp[$server->cache]) && self::checkObject(self::$sftp[$server->cache])) { - JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_SERVER_DETAILS_FOR_BSB_COULD_NOT_BE_RETRIEVED', $serverID), 'Error'); - return false; + // set the unique buckets + if (!isset(self::$sftp[$server->cache]->remote_server_name)) + { + self::$sftp[$server->cache]->remote_server_name = array(); + self::$sftp[$server->cache]->remote_server_path = array(); + } + // always set the name and remote server path + self::$sftp[$server->cache]->remote_server_name[$serverID] = $server->name; + self::$sftp[$server->cache]->remote_server_path[$serverID] = (self::checkString($server->path) && $server->path !== '/') ? $server->path : ''; + // return the sftp object + return self::$sftp[$server->cache]; } } - // return the sftp object - return self::$sftp[$serverID]; + return false; + } + + /** + * get the JClientFtp object + * + * @param int $serverID The server local id to use + * @param string $permission The permission validation area + * + * @return object on success with ftp power + **/ + public static function getFtp($serverID, $permission) + { + // check if we have a server with that id + if ($server = self::getServerDetails($serverID, 1, $permission)) + { + // check if we already have the server instance + if (isset(self::$ftp[$server->cache]) && self::$ftp[$server->cache] instanceof JClientFtp) + { + // always set the name and remote server path + self::$ftp[$server->cache]->remote_server_name[$serverID] = $server->name; + // if still connected we are ready to go + if (self::$ftp[$server->cache]->isConnected()) + { + // return the FTP instance + return self::$ftp[$server->cache]; + } + // check if we can reinitialise the server + if (self::$ftp[$server->cache]->reinit()) + { + // return the FTP instance + return self::$ftp[$server->cache]; + } + } + // make sure we have a string and it is not default or empty + if (self::checkString($server->signature)) + { + // turn into variables + parse_str($server->signature); // because of this I am using strange variable naming to avoid any collisions. + // set options + if (isset($options) && self::checkArray($options)) + { + foreach ($options as $o__p0t1on => $vAln3) + { + if ('timeout' === $o__p0t1on) + { + $options[$o__p0t1on] = (int) $vAln3; + } + if ('type' === $o__p0t1on) + { + $options[$o__p0t1on] = (string) $vAln3; + } + } + } + else + { + $options = array(); + } + // get ftp object + if (isset($host) && $host != 'HOSTNAME' && isset($port) && $port != 'PORT_INT' && isset($username) && $username != 'user@name.com' && isset($password) && $password != 'password') + { + // load for reuse + self::$ftp[$server->cache] = JClientFtp::getInstance($host, $port, $options, $username, $password); + } + else + { + // load error to indicate signature was in error + JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_FTP_SIGNATURE_FOR_BSB_WAS_NOT_WELL_FORMED_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS', $server->name), 'Error'); + return false; + } + // check if we are connected + if (self::$ftp[$server->cache] instanceof JClientFtp && self::$ftp[$server->cache]->isConnected()) + { + // set the unique buckets + if (!isset(self::$ftp[$server->cache]->remote_server_name)) + { + self::$ftp[$server->cache]->remote_server_name = array(); + } + // always set the name and remote server path + self::$ftp[$server->cache]->remote_server_name[$serverID] = $server->name; + // return the FTP instance + return self::$ftp[$server->cache]; + } + // reset since we have no connection + unset(self::$ftp[$server->cache]); + } + // load error to indicate signature was in error + JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_FTP_CONNECTION_FOR_BSB_COULD_NOT_BE_MADE_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS', $server->name), 'Error'); + } + return false; } /** * get the server details * - * @param int $serverID The server local id to use - * @param int $protocol The server protocol to use + * @param int $serverID The server local id to use + * @param int $protocol The server protocol to use + * @param string $permission The permission validation area * - * @return array on success with sftp server details + * @return object on success with server details **/ - protected static function getServerDetails($serverID, $protocol = 2) + public static function getServerDetails($serverID, $protocol = 2, $permission = 'core.export') { - if (is_int($serverID) && is_int($serverID)) + // check if this user has permission to access items + if (!JFactory::getUser()->authorise($permission, 'com_componentbuilder')) + { + // set message to inform the user that permission was denied + JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_ACCESS_THE_SERVER_DETAILS_BS_DENIEDB_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_INFO', self::safeString($permission, 'w')), 'Error'); + return false; + } + // now insure we have correct values + if (is_int($serverID) && is_int($protocol)) { // Get a db connection $db = JFactory::getDbo(); // start the query $query = $db->getQuery(true); - // select based to protocal + // select based to protocol if (2 == $protocol) { + // SFTP $query->select($db->quoteName(array('name','authentication','username','host','password','path','port','private','secret'))); + // cache builder + $cache = array('authentication','username','host','password','port','private','secret'); } else { + // FTP $query->select($db->quoteName(array('name','signature'))); + // cache builder + $cache = array('signature'); } $query->from($db->quoteName('#__componentbuilder_server')); $query->where($db->quoteName('id') . ' = ' . (int) $serverID); @@ -1148,21 +1299,42 @@ abstract class ComponentbuilderHelper $basickey = self::getCryptKey('basic'); // Get the encryption object. $basic = new FOFEncryptAes($basickey, 128); + // start cache keys + $keys = array(); // unlock the needed fields - foreach($server as $name => $value) + foreach($server as $name => &$value) { - if ($name !== 'name' && !empty($server->{$name}) && $basickey && !is_numeric($server->{$name}) && $server->{$name} === base64_encode(base64_decode($server->{$name}, true))) + // unlock the needed fields + if ($name !== 'name' && !empty($value) && $basickey && !is_numeric($value) && $value === base64_encode(base64_decode($value, true))) { // basic decrypt of data - $server->{$name} = rtrim($basic->decryptString($server->{$name}), "\0"); + $value = rtrim($basic->decryptString($value), "\0"); } + // build cache (keys) for lower connection latency + if (in_array($name, $cache)) + { + $keys[] = $value; + } + } + // check if cache keys were found + if (self::checkArray($keys)) + { + // now set cache + $server->cache = md5(implode('', $keys)); + } + else + { + // default is ID + $server->cache = $serverID; } // return the server details return $server; } } + JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_THE_SERVER_DETAILS_FOR_BID_SB_COULD_NOT_BE_RETRIEVED', $serverID), 'Error'); return false; - } + } + public static function jsonToString($value, $sperator = ", ", $table = null) { diff --git a/site/language/en-GB/en-GB.com_componentbuilder.ini b/site/language/en-GB/en-GB.com_componentbuilder.ini index 6372ffbc3..b2370c224 100644 --- a/site/language/en-GB/en-GB.com_componentbuilder.ini +++ b/site/language/en-GB/en-GB.com_componentbuilder.ini @@ -37,18 +37,22 @@ COM_COMPONENTBUILDER_SINCE_THE_OWNER_DETAILS_ARE_DISPLAYED_DURING_BIMPORT_PROCES COM_COMPONENTBUILDER_SINCE_THE_OWNER_DETAILS_ARE_DISPLAYED_DURING_IMPORT_PROCESS_BEFORE_ADDING_THE_KEY_THIS_WAY_IF_THE_USERDEV_DOES_NOT_HAVE_THE_KEY_THEY_CAN_SEE_WHERE_TO_GET_IT="Since the owner details are displayed during import process before adding the key, this way if the user/dev does not have the key they can see where to get it." COM_COMPONENTBUILDER_THAT_MEANS_ANYONE_WHO_HAS_THIS_PACKAGE_CAN_INSTALL_IT_INTO_JCB_TO_ADD_AN_EXPORT_KEY_SIMPLY_OPEN_THE_COMPONENT_GO_TO_THE_TAB_CALLED_BSETTINGSB_BOTTOM_RIGHT_THERE_IS_A_FIELD_CALLED_BEXPORT_KEYB="That means anyone who has this package can install it into JCB. To add an export key simply open the component, go to the tab called settings, bottom right there is a field called Export Key." COM_COMPONENTBUILDER_THAT_MEANS_ANYONE_WHO_HAS_THIS_PACKAGE_CAN_INSTALL_IT_INTO_JCB_TO_ADD_AN_EXPORT_KEY_SIMPLY_OPEN_THE_COMPONENT_GO_TO_THE_TAB_CALLED_SETTINGS_BOTTOM_RIGHT_THERE_IS_A_FIELD_CALLED_EXPORT_KEY="That means anyone who has this package can install it into JCB. To add an export key simply open the component, go to the tab called settings, bottom right there is a field called Export Key." +COM_COMPONENTBUILDER_THE_BPHPSECLIBNETSFTPB_LIBRARYCLASS_IS_NOT_AVAILABLE_THIS_LIBRARYCLASS_SHOULD_HAVE_BEEN_ADDED_TO_YOUR_ADMINHELPERSVENDOR_FOLDER_OF_JCB_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_INFO="The phpseclib\NET\SFTP library\class is not available! This library\class should have been added to your admin/helpers/vendor folder of JCB. Please contact your system administrator for more info" +COM_COMPONENTBUILDER_THE_FTP_CONNECTION_FOR_BSB_COULD_NOT_BE_MADE_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS="The FTP connection for %s could not be made. Please check your signature details!" +COM_COMPONENTBUILDER_THE_FTP_SIGNATURE_FOR_BSB_WAS_NOT_WELL_FORMED_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS="The FTP signature for %s was not well formed, please check your signature details!" COM_COMPONENTBUILDER_THE_LOGIN_TO_BSB_HAS_FAILED_PLEASE_CHECK_THAT_YOUR_USERNAME_AND_PASSWORD_ARE_CORRECT="The login to %s has failed, please check that your username and password are correct!" COM_COMPONENTBUILDER_THE_LOGIN_TO_BSB_HAS_FAILED_PLEASE_CHECK_THAT_YOUR_USERNAME_AND_PRIVATE_KEY_FILE_ARE_CORRECT="The login to %s has failed, please check that your username and private key file are correct!" COM_COMPONENTBUILDER_THE_LOGIN_TO_BSB_HAS_FAILED_PLEASE_CHECK_THAT_YOUR_USERNAME_PASSWORD_AND_PRIVATE_KEY_FILE_ARE_CORRECT="The login to %s has failed, please check that your username, password and private key file are correct!" COM_COMPONENTBUILDER_THE_PACKAGE_KEY_IS_CODESCODE="The package key is: %s" COM_COMPONENTBUILDER_THE_PACKAGE_KEY_IS_S="The package key is: %s" COM_COMPONENTBUILDER_THE_PRIVATE_KEY_FILE_COULD_NOT_BE_LOADEDFOUND_FOR_BSB_SERVER="The private key file could not be loaded/found for %s server!" -COM_COMPONENTBUILDER_THE_SERVER_DETAILS_FOR_BSB_COULD_NOT_BE_RETRIEVED="The server details for (%s) could not be retrieved!" +COM_COMPONENTBUILDER_THE_SERVER_DETAILS_FOR_BID_SB_COULD_NOT_BE_RETRIEVED="The server details for (ID: %s) could not be retrieved!" COM_COMPONENTBUILDER_THIS_PACKAGE_HAS_NO_KEY="This package has no key." COM_COMPONENTBUILDER_TO_CHANGE_THE_PACKAGE_OWNER_DEFAULTS_OPEN_THE_BJCB_GLOBAL_OPTIONSB_GO_TO_THE_BCOMPANYB_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_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_WEBSITE_S="Website: %s" 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 700 000 000 000 000 000 000 000 000 000 000 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 (%s - denied), please contact your system administrator for more info." COM_COMPONENTBUILDER_YOU_SHOULD_ADD_THE_CORRECT_OWNER_DETAILS="You should add the correct owner details." COM_CONTENT_FIELD_MODIFIED_DESC="The last date this item was modified." JGLOBAL_FIELD_ID_DESC="Record number in the database."