forked from joomla/Component-Builder
Update master #1
@ -1,3 +1,9 @@
|
||||
# v3.1.28
|
||||
|
||||
- Updates PHPSecLib.
|
||||
- Fixed connection failure to remote server.
|
||||
- Adds overriding of back-folder and git-folder on component level.
|
||||
|
||||
# v3.1.27
|
||||
|
||||
- Adds better remote repository management for the super power features.
|
||||
|
12
README.md
12
README.md
@ -9,7 +9,7 @@ The Component Builder for [Joomla](https://extensions.joomla.org/extension/compo
|
||||
|
||||
Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/component-builder/) developer, or have just started, Component Builder will save you lots of time and money. A real must have!
|
||||
|
||||
You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.1.27) with **ALL** its features and **ALL** concepts totally open-source and free!
|
||||
You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.1.28) with **ALL** its features and **ALL** concepts totally open-source and free!
|
||||
|
||||
> Watch Quick Build of a Hello World component in [JCB on Youtube](https://www.youtube.com/watch?v=IQfsLYIeblk&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&index=45)
|
||||
|
||||
@ -144,14 +144,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*: 20th October, 2023
|
||||
+ *Version*: 3.1.27
|
||||
+ *Last Build*: 24th October, 2023
|
||||
+ *Version*: 3.1.28
|
||||
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt
|
||||
+ *Line count*: **634936**
|
||||
+ *Line count*: **635155**
|
||||
+ *Field count*: **2047**
|
||||
+ *File count*: **4750**
|
||||
+ *Folder count*: **448**
|
||||
+ *File count*: **4731**
|
||||
+ *Folder count*: **436**
|
||||
|
||||
> This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](https://www.joomlacomponentbuilder.com).
|
||||
> Developed by [Llewellyn van der Merwe](mailto:joomla@vdm.io)
|
||||
|
@ -9,7 +9,7 @@ The Component Builder for [Joomla](https://extensions.joomla.org/extension/compo
|
||||
|
||||
Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/component-builder/) developer, or have just started, Component Builder will save you lots of time and money. A real must have!
|
||||
|
||||
You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.1.27) with **ALL** its features and **ALL** concepts totally open-source and free!
|
||||
You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.1.28) with **ALL** its features and **ALL** concepts totally open-source and free!
|
||||
|
||||
> Watch Quick Build of a Hello World component in [JCB on Youtube](https://www.youtube.com/watch?v=IQfsLYIeblk&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&index=45)
|
||||
|
||||
@ -144,14 +144,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*: 20th October, 2023
|
||||
+ *Version*: 3.1.27
|
||||
+ *Last Build*: 24th October, 2023
|
||||
+ *Version*: 3.1.28
|
||||
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt
|
||||
+ *Line count*: **634936**
|
||||
+ *Line count*: **635155**
|
||||
+ *Field count*: **2047**
|
||||
+ *File count*: **4750**
|
||||
+ *Folder count*: **448**
|
||||
+ *File count*: **4731**
|
||||
+ *Folder count*: **436**
|
||||
|
||||
> This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](https://www.joomlacomponentbuilder.com).
|
||||
> Developed by [Llewellyn van der Merwe](mailto:joomla@vdm.io)
|
||||
|
@ -90,15 +90,26 @@ class Compiler extends Infusion
|
||||
// set some folder paths in relation to distribution
|
||||
if (CFactory::_('Config')->backup)
|
||||
{
|
||||
$this->backupPath = $this->params->get(
|
||||
$this->backupPath = $this->params->get(
|
||||
'backup_folder_path', $this->tempPath
|
||||
);
|
||||
// see if component has overriding options set
|
||||
if (CFactory::_('Component')->get('add_backup_folder_path', 0) == 1)
|
||||
{
|
||||
$this->backupPath = CFactory::_('Component')->get('backup_folder_path', $this->backupPath);
|
||||
}
|
||||
$this->dynamicIntegration = true;
|
||||
}
|
||||
// set local repos switch
|
||||
if (CFactory::_('Config')->repository)
|
||||
{
|
||||
$this->repoPath = $this->params->get('git_folder_path', null);
|
||||
|
||||
// see if component has overriding options set
|
||||
if (CFactory::_('Component')->get('add_git_folder_path', 0) == 1)
|
||||
{
|
||||
$this->repoPath = CFactory::_('Component')->get('git_folder_path', $this->repoPath);
|
||||
}
|
||||
}
|
||||
// remove site folder if not needed (TODO add check if custom script was moved to site folder then we must do a more complex cleanup here)
|
||||
if (CFactory::_('Config')->remove_site_folder && CFactory::_('Config')->remove_site_edit_folder)
|
||||
@ -733,6 +744,7 @@ class Compiler extends Infusion
|
||||
{
|
||||
// move the component update server to host
|
||||
if (CFactory::_('Component')->get('add_update_server', 0) == 1
|
||||
&& CFactory::_('Component')->get('update_server_target', 0) == 1
|
||||
&& isset($this->updateServerFileName)
|
||||
&& $this->dynamicIntegration)
|
||||
{
|
||||
@ -982,7 +994,14 @@ class Compiler extends Infusion
|
||||
// remove old data
|
||||
CFactory::_('Utilities.Folder')->remove($repoFullPath, CFactory::_('Component')->get('toignore'));
|
||||
// set the new data
|
||||
Folder::copy(CFactory::_('Utilities.Paths')->component_path, $repoFullPath, '', true);
|
||||
try {
|
||||
Folder::copy(CFactory::_('Utilities.Paths')->component_path, $repoFullPath, '', true);
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->app->enqueueMessage(
|
||||
JText::_('We where was unable to transfer the component to the git repository:') . ' ' . $e->getMessage()
|
||||
, 'Error'
|
||||
);
|
||||
}
|
||||
// Trigger Event: jcb_ce_onAfterUpdateRepo
|
||||
CFactory::_('Event')->trigger(
|
||||
'jcb_ce_onAfterUpdateRepo',
|
||||
@ -1015,9 +1034,16 @@ class Compiler extends Infusion
|
||||
$repoFullPath, CFactory::_('Component')->get('toignore')
|
||||
);
|
||||
// set the new data
|
||||
Folder::copy(
|
||||
$module->folder_path, $repoFullPath, '', true
|
||||
);
|
||||
try {
|
||||
Folder::copy(
|
||||
$module->folder_path, $repoFullPath, '', true
|
||||
);
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->app->enqueueMessage(
|
||||
JText::sprintf('We where was unable to transfer the (%s) module to the git repository:', $module->name) . ' ' . $e->getMessage()
|
||||
, 'Error'
|
||||
);
|
||||
}
|
||||
// Trigger Event: jcb_ce_onAfterUpdateRepo
|
||||
CFactory::_('Event')->trigger(
|
||||
'jcb_ce_onAfterUpdateRepo',
|
||||
@ -1052,9 +1078,16 @@ class Compiler extends Infusion
|
||||
$repoFullPath, CFactory::_('Component')->get('toignore')
|
||||
);
|
||||
// set the new data
|
||||
Folder::copy(
|
||||
$plugin->folder_path, $repoFullPath, '', true
|
||||
);
|
||||
try {
|
||||
Folder::copy(
|
||||
$plugin->folder_path, $repoFullPath, '', true
|
||||
);
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->app->enqueueMessage(
|
||||
JText::sprintf('We where was unable to transfer the (%s) plugin to the git repository:', $plugin->name) . ' ' . $e->getMessage()
|
||||
, 'Error'
|
||||
);
|
||||
}
|
||||
// Trigger Event: jcb_ce_onAfterUpdateRepo
|
||||
CFactory::_('Event')->trigger(
|
||||
'jcb_ce_onAfterUpdateRepo',
|
||||
@ -1088,7 +1121,8 @@ class Compiler extends Infusion
|
||||
);
|
||||
//create the zip file
|
||||
if (FileHelper::zip(
|
||||
CFactory::_('Utilities.Paths')->component_path, $this->filepath['component']
|
||||
CFactory::_('Utilities.Paths')->component_path,
|
||||
$this->filepath['component']
|
||||
))
|
||||
{
|
||||
// now move to backup if zip was made and backup is required
|
||||
@ -1096,18 +1130,26 @@ class Compiler extends Infusion
|
||||
{
|
||||
// Trigger Event: jcb_ce_onBeforeBackupZip
|
||||
CFactory::_('Event')->trigger(
|
||||
'jcb_ce_onBeforeBackupZip', array(&$component_context,
|
||||
&$this->filepath['component'],
|
||||
&$this->tempPath,
|
||||
&$this->backupPath,
|
||||
&$this->componentData)
|
||||
);
|
||||
'jcb_ce_onBeforeBackupZip',[
|
||||
&$component_context,
|
||||
&$this->filepath['component'],
|
||||
&$this->tempPath,
|
||||
&$this->backupPath,
|
||||
&$this->componentData
|
||||
]);
|
||||
// copy the zip to backup path
|
||||
File::copy(
|
||||
$this->filepath['component'],
|
||||
$this->backupPath . '/' . CFactory::_('Utilities.Paths')->component_backup_name
|
||||
. '.zip'
|
||||
);
|
||||
try {
|
||||
File::copy(
|
||||
$this->filepath['component'],
|
||||
$this->backupPath . '/' . CFactory::_('Utilities.Paths')->component_backup_name
|
||||
. '.zip'
|
||||
);
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->app->enqueueMessage(
|
||||
JText::_('We where was unable to transfer the component ZIP file to the backup folder:') . ' ' . $e->getMessage()
|
||||
, 'Error'
|
||||
);
|
||||
}
|
||||
}
|
||||
// move to sales server host
|
||||
if (CFactory::_('Component')->get('add_sales_server', 0) == 1
|
||||
@ -1205,13 +1247,19 @@ class Compiler extends Infusion
|
||||
&$module)
|
||||
);
|
||||
// copy the zip to backup path
|
||||
File::copy(
|
||||
$this->filepath['modules'][$module->id],
|
||||
$this->backupPath . '/' . $module->zip_name
|
||||
. '.zip'
|
||||
);
|
||||
try {
|
||||
File::copy(
|
||||
$this->filepath['modules'][$module->id],
|
||||
$this->backupPath . '/' . $module->zip_name
|
||||
. '.zip'
|
||||
);
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->app->enqueueMessage(
|
||||
JText::sprintf('We where was unable to transfer the (%s) module zip file to the backup folder:', $module->name) . ' ' . $e->getMessage()
|
||||
, 'Error'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// move to sales server host
|
||||
if ($module->add_sales_server == 1)
|
||||
{
|
||||
@ -1307,11 +1355,18 @@ class Compiler extends Infusion
|
||||
&$plugin)
|
||||
);
|
||||
// copy the zip to backup path
|
||||
File::copy(
|
||||
$this->filepath['plugins'][$plugin->id],
|
||||
$this->backupPath . '/' . $plugin->zip_name
|
||||
. '.zip'
|
||||
);
|
||||
try {
|
||||
File::copy(
|
||||
$this->filepath['plugins'][$plugin->id],
|
||||
$this->backupPath . '/' . $plugin->zip_name
|
||||
. '.zip'
|
||||
);
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->app->enqueueMessage(
|
||||
JText::sprintf('We where was unable to transfer the (%s) plugin zip file to the backup folder:', $plugin->name) . ' ' . $e->getMessage()
|
||||
, 'Error'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// move to sales server host
|
||||
|
@ -1156,7 +1156,7 @@ class Get
|
||||
// Utilities GetHelper
|
||||
CFactory::_('Power')->get('db87c339-5bb6-4291-a7ef-2c48ea1b06bc', 1);
|
||||
// Utilities Json Helper
|
||||
CFactory::_('Power')->get(' 4b225c51-d293-48e4-b3f6-5136cf5c3f18', 1);
|
||||
CFactory::_('Power')->get('4b225c51-d293-48e4-b3f6-5136cf5c3f18', 1);
|
||||
// Utilities FormHelper
|
||||
CFactory::_('Power')->get('1198aecf-84c6-45d2-aea8-d531aa4afdfa', 1);
|
||||
|
||||
|
@ -1181,7 +1181,7 @@ class Interpretation extends Fields
|
||||
$update_['version'] = CFactory::_('Component')->get('old_component_version');
|
||||
// setup SQL
|
||||
$update_['mysql'] = trim(
|
||||
implode(PHP_EOL . PHP_EOL, CFactory::_('Compiler.Builder.Update.Mysql')->active)
|
||||
implode(PHP_EOL . PHP_EOL, CFactory::_('Compiler.Builder.Update.Mysql')->allActive())
|
||||
);
|
||||
// setup URL
|
||||
if (isset($this->lastupdateURL))
|
||||
@ -1248,7 +1248,7 @@ class Interpretation extends Fields
|
||||
{
|
||||
$searchMySQL = preg_replace('/\s+/', '', (string) $update['mysql']);
|
||||
// add the updates to the SQL only if not found
|
||||
foreach (CFactory::_('Compiler.Builder.Update.Mysql')->active as $search => $query)
|
||||
foreach (CFactory::_('Compiler.Builder.Update.Mysql')->allActive() as $search => $query)
|
||||
{
|
||||
if (strpos($searchMySQL, $search) === false)
|
||||
{
|
||||
|
@ -5481,6 +5481,8 @@ COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADDREADME_LABEL="Add README"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADDUIKIT_DESCRIPTION="Select the version of Uikit you would like to use."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADDUIKIT_LABEL="Add Uikit"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_ADMIN_EVENT_LABEL="Add Global Admin Event"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_BACKUP_FOLDER_PATH_DESCRIPTION="Would you like to override the global backup folder path for this component?"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_BACKUP_FOLDER_PATH_LABEL="Backup Folder Path"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_BOTH_V2_AMP_V3="Add Both v2 & v3"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_CSS_ADMIN_LABEL="Add CSS (admin)"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_CSS_SITE_LABEL="Add CSS (site)"
|
||||
@ -5488,6 +5490,8 @@ COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_EMAIL_HELPER_DESCRIPTION="Adding the e
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_EMAIL_HELPER_LABEL="Add Email Helper"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_FOOTABLE_V2="Add FooTable V2"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_FOOTABLE_V3="Add FooTable V3"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_GIT_FOLDER_PATH_DESCRIPTION="Would you like to override the global git folder path for this component?"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_GIT_FOLDER_PATH_LABEL="Git Folder Path"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_JAVASCRIPT_LABEL="Add Javascript"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_LICENSE_DESCRIPTION="Add the option to use the whmcs license add-on in the component."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_LICENSE_LABEL="Add WHMCS<br /><small>(license add-on)</small>"
|
||||
@ -5522,6 +5526,10 @@ COM_COMPONENTBUILDER_JOOMLA_COMPONENT_AUTHOR_MESSAGE="Error! Please add author n
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BACK="Back"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BACKUP_BUTTON_ACCESS="Joomla Component Backup Button Access"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BACKUP_BUTTON_ACCESS_DESC="Allows the users in this group to access the backup button."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BACKUP_FOLDER_PATH_DESCRIPTION="Here you can set the path to the backup folder."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BACKUP_FOLDER_PATH_HINT="/home/user/backup"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BACKUP_FOLDER_PATH_LABEL="Backup Folder Path"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BACKUP_FOLDER_PATH_MESSAGE="Error! Please add folder path here."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BOM_DESCRIPTION="Select the file that should be used for licensing all files (files found in: administrator/components/com_componentbuilder/compiler)"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BOM_LABEL="Licensing Template"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BOTH="Both"
|
||||
@ -5609,6 +5617,11 @@ COM_COMPONENTBUILDER_JOOMLA_COMPONENT_EXPORT_KEY_HINT="Export Key Here"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_EXPORT_KEY_LABEL="Export Key<br /><small>(encrypted field)</small>"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_EXPORT_KEY_MESSAGE="Error! Please add export key here."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_FRONT="Front"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_GIT_FOLDER_PATH_DESCRIPTION="Here you can set the path to the git folder."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_GIT_FOLDER_PATH_HINT="/home/user/git"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_GIT_FOLDER_PATH_LABEL="Git Folder Path"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_GIT_FOLDER_PATH_MESSAGE="Error! Please add folder path here."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_GLOBAL="Global"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_GUID_DESCRIPTION="Globally Unique Identifier"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_GUID_HINT="Auto Generated"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_GUID_LABEL="GUID"
|
||||
@ -5661,6 +5674,8 @@ COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_ADD_CONFIG_DESCRIPTION="You can add c
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_ADD_CONFIG_LABEL="Adding Custom Config Fields"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_ADD_CUSTOM_MENUS_DESCRIPTION="You can add custom menus to the component here. The normal Menus are already being added so only add custom Menus that you would like to use for custom scripts.<span id='jform_button_add_custom_menus'></span>"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_ADD_CUSTOM_MENUS_LABEL="Adding Custom Menus"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_BACKUP_FOLDER_PATH_DESCRIPTION="You component, and all other linked extensions will be placed as zip files inside this folder."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_BACKUP_FOLDER_PATH_LABEL="Adding a backup folder export option"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_BOTTON_COMPONENT_DASHBOARD_DESCRIPTION="<p>The default dashboard has all the icons of the views you have selected as <b>Dashboard (add record)</b> or <b>Dashboard (list of records)</b>, to expand it you can add more tabs.</p><span id='jform_button_component_dashboard'></span>"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_BOTTON_COMPONENT_DASHBOARD_LABEL="Default Dashboard Option"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_BUILDCOMP_DYNAMIC_MYSQL_DESCRIPTION="You can dynamically build the components back-end views and fields by adding a mySql table dump, that has all the tables, or some more tables with its columns and data types. A very basic and generic set of fields and tables will be created, and added to the existing fields and tables of this component."
|
||||
@ -5674,6 +5689,8 @@ COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_DISPLAY_COMPONENT_CUSTOM_ADMIN_VIEWS_
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_DISPLAY_COMPONENT_SITE_VIEWS_DESCRIPTION="<h4>Linked Site Views <span id='header_component_site_views_buttons'></span></h4><div id='display_component_site_views' >Display of the site views will load here!</div>"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_DYNAMIC_DASHBOARD_DESCRIPTION="The dynamic dashboard is basically the option of taking an <b>Admin View</b> or <b>Custom Admin View</b> that is already linked to this component, and making it the dashboard."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_DYNAMIC_DASHBOARD_LABEL="Dynamic Dashboard Option"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_GIT_FOLDER_PATH_DESCRIPTION="You must set the folder where the component and all linked extensions should be deployed for git. You will have to still do your git commit and other git commands yourself. Each extension will create their own folder inside this git folder."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_GIT_FOLDER_PATH_LABEL="Adding a git path to your component"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_MOVED_VIEWS_DESCRIPTION="We have moved the views in to their own tabs for your convenience.<span id='jform_button_create_edit_views'></span>"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_MOVED_VIEWS_LABEL="To add views, please open the corresponding tab."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOTE_MYSQL_TWEAK_OPTIONS_DESCRIPTION="In each admin view you can add data from a MySQL Table (this is done in the admin view MySQL tab). Here you can limit that data in relation to this component. This feature is useful when an admin view with demo data is used in more then one component, and you would like to exclude some demo data without creating a new admin view.<span id='jform_button_mysql_tweak_options'></span>"
|
||||
@ -5703,6 +5720,7 @@ COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NOT_REQUIRED="Not Required"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_NUMBER_LABEL="Number"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ORDERING_LABEL="Ordering"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_OTHER="Other"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_OVERRIDE="Override"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PERMISSION="Permissions"
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_ADMIN_EVENT_DESCRIPTION="PHP script for the global helper admin event method."
|
||||
COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_ADMIN_EVENT_LABEL="Global Helper Admin Event (method)"
|
||||
@ -7302,10 +7320,13 @@ COM_COMPONENTBUILDER_LINK_TO_THE_CONTRIBUTOR="Link to the contributor"
|
||||
COM_COMPONENTBUILDER_LIST_FIELD="List Field"
|
||||
COM_COMPONENTBUILDER_LIST_VIEW="List View"
|
||||
COM_COMPONENTBUILDER_LOADING="loading"
|
||||
COM_COMPONENTBUILDER_LOADING_THE_PRIVATE_KEY_FILE_FAILED="Loading the private key file failed"
|
||||
COM_COMPONENTBUILDER_LOADING_THE_PRIVATE_KEY_TEXT_FAILED="Loading the private key text failed"
|
||||
COM_COMPONENTBUILDER_LOCAL="Local"
|
||||
COM_COMPONENTBUILDER_LOCAL_GET="Local (get)"
|
||||
COM_COMPONENTBUILDER_LOCAL_POWERS_REPOSITORY_PATH="Local Powers Repository Path"
|
||||
COM_COMPONENTBUILDER_LOCAL_SNIPPET="Local snippet"
|
||||
COM_COMPONENTBUILDER_LOGIN_FAILED="Login failed"
|
||||
COM_COMPONENTBUILDER_MAIN_MENU="Main Menu"
|
||||
COM_COMPONENTBUILDER_MAKE_A_DIFFERENCE_WITH_JCB="Make a Difference with JCB"
|
||||
COM_COMPONENTBUILDER_MANUAL="Manual"
|
||||
@ -7324,6 +7345,7 @@ COM_COMPONENTBUILDER_MODEL_BEFORE_MODELLING="Model (before modelling)"
|
||||
COM_COMPONENTBUILDER_MODULE="Module"
|
||||
COM_COMPONENTBUILDER_MODULES="Modules"
|
||||
COM_COMPONENTBUILDER_MOVE="Move"
|
||||
COM_COMPONENTBUILDER_MOVING_OF_THE_S_FAILED="Moving of the %s failed"
|
||||
COM_COMPONENTBUILDER_NAME="Name"
|
||||
COM_COMPONENTBUILDER_NAME_ASC="Name (Asc)"
|
||||
COM_COMPONENTBUILDER_NAME_DESC="Name (Desc)"
|
||||
|
@ -34,7 +34,13 @@ $fields = $displayData->get($fields_tab_layout) ?: array(
|
||||
'note_update_server_note_other',
|
||||
'update_server',
|
||||
'add_sales_server',
|
||||
'sales_server'
|
||||
'sales_server',
|
||||
'add_backup_folder_path',
|
||||
'note_backup_folder_path',
|
||||
'backup_folder_path',
|
||||
'add_git_folder_path',
|
||||
'note_git_folder_path',
|
||||
'git_folder_path'
|
||||
);
|
||||
|
||||
$hiddenFields = $displayData->get('hidden_fields') ?: array();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -107,7 +107,13 @@ class ComponentbuilderModelJoomla_component extends AdminModel
|
||||
'note_update_server_note_other',
|
||||
'update_server',
|
||||
'add_sales_server',
|
||||
'sales_server'
|
||||
'sales_server',
|
||||
'add_backup_folder_path',
|
||||
'note_backup_folder_path',
|
||||
'backup_folder_path',
|
||||
'add_git_folder_path',
|
||||
'note_git_folder_path',
|
||||
'git_folder_path'
|
||||
),
|
||||
'right' => array(
|
||||
'translation_tool',
|
||||
@ -118,15 +124,6 @@ class ComponentbuilderModelJoomla_component extends AdminModel
|
||||
'crowdin_account_api_key'
|
||||
)
|
||||
),
|
||||
'readme' => array(
|
||||
'left' => array(
|
||||
'addreadme',
|
||||
'readme'
|
||||
),
|
||||
'right' => array(
|
||||
'note_readme'
|
||||
)
|
||||
),
|
||||
'dash_install' => array(
|
||||
'left' => array(
|
||||
'dashboard_type'
|
||||
@ -158,6 +155,15 @@ class ComponentbuilderModelJoomla_component extends AdminModel
|
||||
'assets_table_fix'
|
||||
)
|
||||
),
|
||||
'readme' => array(
|
||||
'left' => array(
|
||||
'addreadme',
|
||||
'readme'
|
||||
),
|
||||
'right' => array(
|
||||
'note_readme'
|
||||
)
|
||||
),
|
||||
'dynamic_build_beta' => array(
|
||||
'fullwidth' => array(
|
||||
'note_buildcomp_dynamic_mysql',
|
||||
@ -348,24 +354,6 @@ class ComponentbuilderModelJoomla_component extends AdminModel
|
||||
$item->metadata = $registry->toArray();
|
||||
}
|
||||
|
||||
if (!empty($item->php_helper_both))
|
||||
{
|
||||
// base64 Decode php_helper_both.
|
||||
$item->php_helper_both = base64_decode($item->php_helper_both);
|
||||
}
|
||||
|
||||
if (!empty($item->php_method_uninstall))
|
||||
{
|
||||
// base64 Decode php_method_uninstall.
|
||||
$item->php_method_uninstall = base64_decode($item->php_method_uninstall);
|
||||
}
|
||||
|
||||
if (!empty($item->php_preflight_install))
|
||||
{
|
||||
// base64 Decode php_preflight_install.
|
||||
$item->php_preflight_install = base64_decode($item->php_preflight_install);
|
||||
}
|
||||
|
||||
if (!empty($item->css_admin))
|
||||
{
|
||||
// base64 Decode css_admin.
|
||||
@ -396,6 +384,24 @@ class ComponentbuilderModelJoomla_component extends AdminModel
|
||||
$item->sql_uninstall = base64_decode($item->sql_uninstall);
|
||||
}
|
||||
|
||||
if (!empty($item->php_preflight_install))
|
||||
{
|
||||
// base64 Decode php_preflight_install.
|
||||
$item->php_preflight_install = base64_decode($item->php_preflight_install);
|
||||
}
|
||||
|
||||
if (!empty($item->php_method_uninstall))
|
||||
{
|
||||
// base64 Decode php_method_uninstall.
|
||||
$item->php_method_uninstall = base64_decode($item->php_method_uninstall);
|
||||
}
|
||||
|
||||
if (!empty($item->buildcompsql))
|
||||
{
|
||||
// base64 Decode buildcompsql.
|
||||
$item->buildcompsql = base64_decode($item->buildcompsql);
|
||||
}
|
||||
|
||||
if (!empty($item->php_helper_admin))
|
||||
{
|
||||
// base64 Decode php_helper_admin.
|
||||
@ -438,35 +444,35 @@ class ComponentbuilderModelJoomla_component extends AdminModel
|
||||
$item->sql = base64_decode($item->sql);
|
||||
}
|
||||
|
||||
if (!empty($item->buildcompsql))
|
||||
{
|
||||
// base64 Decode buildcompsql.
|
||||
$item->buildcompsql = base64_decode($item->buildcompsql);
|
||||
}
|
||||
|
||||
if (!empty($item->readme))
|
||||
{
|
||||
// base64 Decode readme.
|
||||
$item->readme = base64_decode($item->readme);
|
||||
}
|
||||
|
||||
if (!empty($item->php_helper_both))
|
||||
{
|
||||
// base64 Decode php_helper_both.
|
||||
$item->php_helper_both = base64_decode($item->php_helper_both);
|
||||
}
|
||||
|
||||
// Get the basic encryption.
|
||||
$basickey = ComponentbuilderHelper::getCryptKey('basic');
|
||||
// Get the encryption object.
|
||||
$basic = new AES($basickey);
|
||||
|
||||
if (!empty($item->whmcs_key) && $basickey && !is_numeric($item->whmcs_key) && $item->whmcs_key === base64_encode(base64_decode($item->whmcs_key, true)))
|
||||
{
|
||||
// basic decrypt data whmcs_key.
|
||||
$item->whmcs_key = rtrim($basic->decryptString($item->whmcs_key), "\0");
|
||||
}
|
||||
|
||||
if (!empty($item->crowdin_username) && $basickey && !is_numeric($item->crowdin_username) && $item->crowdin_username === base64_encode(base64_decode($item->crowdin_username, true)))
|
||||
{
|
||||
// basic decrypt data crowdin_username.
|
||||
$item->crowdin_username = rtrim($basic->decryptString($item->crowdin_username), "\0");
|
||||
}
|
||||
|
||||
if (!empty($item->whmcs_key) && $basickey && !is_numeric($item->whmcs_key) && $item->whmcs_key === base64_encode(base64_decode($item->whmcs_key, true)))
|
||||
{
|
||||
// basic decrypt data whmcs_key.
|
||||
$item->whmcs_key = rtrim($basic->decryptString($item->whmcs_key), "\0");
|
||||
}
|
||||
|
||||
if (!empty($item->export_key) && $basickey && !is_numeric($item->export_key) && $item->export_key === base64_encode(base64_decode($item->export_key, true)))
|
||||
{
|
||||
// basic decrypt data export_key.
|
||||
@ -1415,24 +1421,6 @@ class ComponentbuilderModelJoomla_component extends AdminModel
|
||||
$data['addcontributors'] = '';
|
||||
}
|
||||
|
||||
// Set the php_helper_both string to base64 string.
|
||||
if (isset($data['php_helper_both']))
|
||||
{
|
||||
$data['php_helper_both'] = base64_encode($data['php_helper_both']);
|
||||
}
|
||||
|
||||
// Set the php_method_uninstall string to base64 string.
|
||||
if (isset($data['php_method_uninstall']))
|
||||
{
|
||||
$data['php_method_uninstall'] = base64_encode($data['php_method_uninstall']);
|
||||
}
|
||||
|
||||
// Set the php_preflight_install string to base64 string.
|
||||
if (isset($data['php_preflight_install']))
|
||||
{
|
||||
$data['php_preflight_install'] = base64_encode($data['php_preflight_install']);
|
||||
}
|
||||
|
||||
// Set the css_admin string to base64 string.
|
||||
if (isset($data['css_admin']))
|
||||
{
|
||||
@ -1463,6 +1451,24 @@ class ComponentbuilderModelJoomla_component extends AdminModel
|
||||
$data['sql_uninstall'] = base64_encode($data['sql_uninstall']);
|
||||
}
|
||||
|
||||
// Set the php_preflight_install string to base64 string.
|
||||
if (isset($data['php_preflight_install']))
|
||||
{
|
||||
$data['php_preflight_install'] = base64_encode($data['php_preflight_install']);
|
||||
}
|
||||
|
||||
// Set the php_method_uninstall string to base64 string.
|
||||
if (isset($data['php_method_uninstall']))
|
||||
{
|
||||
$data['php_method_uninstall'] = base64_encode($data['php_method_uninstall']);
|
||||
}
|
||||
|
||||
// Set the buildcompsql string to base64 string.
|
||||
if (isset($data['buildcompsql']))
|
||||
{
|
||||
$data['buildcompsql'] = base64_encode($data['buildcompsql']);
|
||||
}
|
||||
|
||||
// Set the php_helper_admin string to base64 string.
|
||||
if (isset($data['php_helper_admin']))
|
||||
{
|
||||
@ -1505,35 +1511,35 @@ class ComponentbuilderModelJoomla_component extends AdminModel
|
||||
$data['sql'] = base64_encode($data['sql']);
|
||||
}
|
||||
|
||||
// Set the buildcompsql string to base64 string.
|
||||
if (isset($data['buildcompsql']))
|
||||
{
|
||||
$data['buildcompsql'] = base64_encode($data['buildcompsql']);
|
||||
}
|
||||
|
||||
// Set the readme string to base64 string.
|
||||
if (isset($data['readme']))
|
||||
{
|
||||
$data['readme'] = base64_encode($data['readme']);
|
||||
}
|
||||
|
||||
// Set the php_helper_both string to base64 string.
|
||||
if (isset($data['php_helper_both']))
|
||||
{
|
||||
$data['php_helper_both'] = base64_encode($data['php_helper_both']);
|
||||
}
|
||||
|
||||
// Get the basic encryption key.
|
||||
$basickey = ComponentbuilderHelper::getCryptKey('basic');
|
||||
// Get the encryption object
|
||||
$basic = new AES($basickey);
|
||||
|
||||
// Encrypt data whmcs_key.
|
||||
if (isset($data['whmcs_key']) && $basickey)
|
||||
{
|
||||
$data['whmcs_key'] = $basic->encryptString($data['whmcs_key']);
|
||||
}
|
||||
|
||||
// Encrypt data crowdin_username.
|
||||
if (isset($data['crowdin_username']) && $basickey)
|
||||
{
|
||||
$data['crowdin_username'] = $basic->encryptString($data['crowdin_username']);
|
||||
}
|
||||
|
||||
// Encrypt data whmcs_key.
|
||||
if (isset($data['whmcs_key']) && $basickey)
|
||||
{
|
||||
$data['whmcs_key'] = $basic->encryptString($data['whmcs_key']);
|
||||
}
|
||||
|
||||
// Encrypt data export_key.
|
||||
if (isset($data['export_key']) && $basickey)
|
||||
{
|
||||
|
@ -2687,33 +2687,38 @@ class ComponentbuilderModelJoomla_components extends ListModel
|
||||
continue;
|
||||
}
|
||||
|
||||
// decode php_helper_both
|
||||
$item->php_helper_both = base64_decode($item->php_helper_both);
|
||||
// decode php_method_uninstall
|
||||
$item->php_method_uninstall = base64_decode($item->php_method_uninstall);
|
||||
// decode php_preflight_install
|
||||
$item->php_preflight_install = base64_decode($item->php_preflight_install);
|
||||
// decode css_admin
|
||||
$item->css_admin = base64_decode($item->css_admin);
|
||||
// decode php_admin_event
|
||||
$item->php_admin_event = base64_decode($item->php_admin_event);
|
||||
// decode php_site_event
|
||||
$item->php_site_event = base64_decode($item->php_site_event);
|
||||
if ($basickey && !is_numeric($item->crowdin_username) && $item->crowdin_username === base64_encode(base64_decode($item->crowdin_username, true)))
|
||||
{
|
||||
// decrypt crowdin_username
|
||||
$item->crowdin_username = $basic->decryptString($item->crowdin_username);
|
||||
}
|
||||
// decode php_postflight_install
|
||||
$item->php_postflight_install = base64_decode($item->php_postflight_install);
|
||||
// decode sql_uninstall
|
||||
$item->sql_uninstall = base64_decode($item->sql_uninstall);
|
||||
// decode php_preflight_install
|
||||
$item->php_preflight_install = base64_decode($item->php_preflight_install);
|
||||
// decode php_method_uninstall
|
||||
$item->php_method_uninstall = base64_decode($item->php_method_uninstall);
|
||||
// decode buildcompsql
|
||||
$item->buildcompsql = base64_decode($item->buildcompsql);
|
||||
// decode php_helper_admin
|
||||
$item->php_helper_admin = base64_decode($item->php_helper_admin);
|
||||
// decode php_helper_site
|
||||
$item->php_helper_site = base64_decode($item->php_helper_site);
|
||||
// decode javascript
|
||||
$item->javascript = base64_decode($item->javascript);
|
||||
if ($basickey && !is_numeric($item->whmcs_key) && $item->whmcs_key === base64_encode(base64_decode($item->whmcs_key, true)))
|
||||
{
|
||||
// decrypt whmcs_key
|
||||
$item->whmcs_key = $basic->decryptString($item->whmcs_key);
|
||||
}
|
||||
// decode php_helper_site
|
||||
$item->php_helper_site = base64_decode($item->php_helper_site);
|
||||
// decode javascript
|
||||
$item->javascript = base64_decode($item->javascript);
|
||||
// decode css_site
|
||||
$item->css_site = base64_decode($item->css_site);
|
||||
// decode php_preflight_update
|
||||
@ -2722,13 +2727,6 @@ class ComponentbuilderModelJoomla_components extends ListModel
|
||||
$item->php_postflight_update = base64_decode($item->php_postflight_update);
|
||||
// decode sql
|
||||
$item->sql = base64_decode($item->sql);
|
||||
if ($basickey && !is_numeric($item->crowdin_username) && $item->crowdin_username === base64_encode(base64_decode($item->crowdin_username, true)))
|
||||
{
|
||||
// decrypt crowdin_username
|
||||
$item->crowdin_username = $basic->decryptString($item->crowdin_username);
|
||||
}
|
||||
// decode buildcompsql
|
||||
$item->buildcompsql = base64_decode($item->buildcompsql);
|
||||
if ($basickey && !is_numeric($item->export_key) && $item->export_key === base64_encode(base64_decode($item->export_key, true)))
|
||||
{
|
||||
// decrypt export_key
|
||||
@ -2746,6 +2744,8 @@ class ComponentbuilderModelJoomla_components extends ListModel
|
||||
// decrypt crowdin_account_api_key
|
||||
$item->crowdin_account_api_key = $basic->decryptString($item->crowdin_account_api_key);
|
||||
}
|
||||
// decode php_helper_both
|
||||
$item->php_helper_both = base64_decode($item->php_helper_both);
|
||||
// unset the values we don't want exported.
|
||||
unset($item->asset_id);
|
||||
unset($item->checked_out);
|
||||
|
@ -2,9 +2,11 @@ CREATE TABLE IF NOT EXISTS `#__componentbuilder_joomla_component` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.',
|
||||
`add_admin_event` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`add_backup_folder_path` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`add_css_admin` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`add_css_site` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`add_email_helper` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`add_git_folder_path` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`add_javascript` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`add_license` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`add_menu_prefix` CHAR(1) NOT NULL DEFAULT '',
|
||||
@ -29,6 +31,7 @@ CREATE TABLE IF NOT EXISTS `#__componentbuilder_joomla_component` (
|
||||
`adduikit` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`assets_table_fix` TINYINT(1) NOT NULL DEFAULT 3,
|
||||
`author` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`backup_folder_path` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`bom` CHAR(64) NOT NULL DEFAULT '',
|
||||
`buildcomp` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`buildcompsql` MEDIUMTEXT NOT NULL,
|
||||
@ -51,6 +54,7 @@ CREATE TABLE IF NOT EXISTS `#__componentbuilder_joomla_component` (
|
||||
`emptycontributors` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`export_buy_link` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`export_key` TEXT NOT NULL,
|
||||
`git_folder_path` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`guid` VARCHAR(36) NOT NULL DEFAULT '',
|
||||
`image` CHAR(64) NOT NULL DEFAULT '',
|
||||
`javascript` TEXT NOT NULL,
|
||||
@ -105,18 +109,17 @@ CREATE TABLE IF NOT EXISTS `#__componentbuilder_joomla_component` (
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_system_name` (`system_name`),
|
||||
KEY `idx_name_code` (`name_code`),
|
||||
KEY `idx_mvc_versiondate` (`mvc_versiondate`),
|
||||
KEY `idx_remove_line_breaks` (`remove_line_breaks`),
|
||||
KEY `idx_add_placeholders` (`add_placeholders`),
|
||||
KEY `idx_debug_linenr` (`debug_linenr`),
|
||||
KEY `idx_mvc_versiondate` (`mvc_versiondate`),
|
||||
KEY `idx_add_placeholders` (`add_placeholders`),
|
||||
KEY `idx_add_sales_server` (`add_sales_server`),
|
||||
KEY `idx_translation_tool` (`translation_tool`),
|
||||
KEY `idx_add_license` (`add_license`),
|
||||
KEY `idx_license_type` (`license_type`),
|
||||
KEY `idx_add_email_helper` (`add_email_helper`),
|
||||
KEY `idx_addreadme` (`addreadme`),
|
||||
KEY `idx_add_sales_server` (`add_sales_server`),
|
||||
KEY `idx_add_powers` (`add_powers`),
|
||||
KEY `idx_translation_tool` (`translation_tool`),
|
||||
KEY `idx_add_php_helper_both` (`add_php_helper_both`),
|
||||
KEY `idx_add_backup_folder_path` (`add_backup_folder_path`),
|
||||
KEY `idx_add_php_helper_admin` (`add_php_helper_admin`),
|
||||
KEY `idx_add_admin_event` (`add_admin_event`),
|
||||
KEY `idx_add_php_helper_site` (`add_php_helper_site`),
|
||||
@ -137,10 +140,13 @@ CREATE TABLE IF NOT EXISTS `#__componentbuilder_joomla_component` (
|
||||
KEY `idx_emptycontributors` (`emptycontributors`),
|
||||
KEY `idx_add_update_server` (`add_update_server`),
|
||||
KEY `idx_update_server_target` (`update_server_target`),
|
||||
KEY `idx_add_git_folder_path` (`add_git_folder_path`),
|
||||
KEY `idx_creatuserhelper` (`creatuserhelper`),
|
||||
KEY `idx_adduikit` (`adduikit`),
|
||||
KEY `idx_guid` (`guid`),
|
||||
KEY `idx_addfootable` (`addfootable`),
|
||||
KEY `idx_add_email_helper` (`add_email_helper`),
|
||||
KEY `idx_add_php_helper_both` (`add_php_helper_both`),
|
||||
KEY `idx_guid` (`guid`),
|
||||
KEY `idx_access` (`access`),
|
||||
KEY `idx_checkout` (`checked_out`),
|
||||
KEY `idx_createdby` (`created_by`),
|
||||
|
7
admin/sql/updates/mysql/3.1.27.sql
Normal file
7
admin/sql/updates/mysql/3.1.27.sql
Normal file
@ -0,0 +1,7 @@
|
||||
ALTER TABLE `#__componentbuilder_joomla_component` ADD `add_backup_folder_path` TINYINT(1) NOT NULL DEFAULT 0 AFTER `add_admin_event`;
|
||||
|
||||
ALTER TABLE `#__componentbuilder_joomla_component` ADD `add_git_folder_path` TINYINT(1) NOT NULL DEFAULT 0 AFTER `add_email_helper`;
|
||||
|
||||
ALTER TABLE `#__componentbuilder_joomla_component` ADD `backup_folder_path` VARCHAR(255) NOT NULL DEFAULT '' AFTER `author`;
|
||||
|
||||
ALTER TABLE `#__componentbuilder_joomla_component` ADD `git_folder_path` VARCHAR(255) NOT NULL DEFAULT '' AFTER `export_key`;
|
@ -1,15 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension type="component" version="4" method="upgrade">
|
||||
<name>COM_COMPONENTBUILDER</name>
|
||||
<creationDate>20th October, 2023</creationDate>
|
||||
<creationDate>24th October, 2023</creationDate>
|
||||
<author>Llewellyn van der Merwe</author>
|
||||
<authorEmail>joomla@vdm.io</authorEmail>
|
||||
<authorUrl>https://dev.vdm.io</authorUrl>
|
||||
<copyright>Copyright (C) 2015 Vast Development Method. All rights reserved.</copyright>
|
||||
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
|
||||
<version>3.1.27</version>
|
||||
<version>3.1.28</version>
|
||||
<description><![CDATA[
|
||||
<h1>Component Builder (v.3.1.27)</h1>
|
||||
<h1>Component Builder (v.3.1.28)</h1>
|
||||
<div style="clear: both;"></div>
|
||||
<p>The Component Builder for [Joomla](https://extensions.joomla.org/extension/component-builder/) is highly advanced tool that is truly able to build extremely complex components in a fraction of the time.
|
||||
|
||||
|
@ -1217,4 +1217,22 @@
|
||||
<maintainerurl>https://dev.vdm.io</maintainerurl>
|
||||
<targetplatform name="joomla" version="3.*"/>
|
||||
</update>
|
||||
<update>
|
||||
<name>Component Builder</name>
|
||||
<description>Builds Complex Joomla Components</description>
|
||||
<element>pkg_component_builder</element>
|
||||
<type>package</type>
|
||||
<client>site</client>
|
||||
<version>3.1.28</version>
|
||||
<infourl title="Component Builder!">https://dev.vdm.io</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.vdm.dev/api/v1/repos/joomla/pkg-component-builder/archive/v3.1.28.zip</downloadurl>
|
||||
</downloads>
|
||||
<tags>
|
||||
<tag>stable</tag>
|
||||
</tags>
|
||||
<maintainer>Llewellyn van der Merwe</maintainer>
|
||||
<maintainerurl>https://dev.vdm.io</maintainerurl>
|
||||
<targetplatform name="joomla" version="3.*"/>
|
||||
</update>
|
||||
</updates>
|
@ -48,6 +48,22 @@ abstract class Api
|
||||
*/
|
||||
protected Response $response;
|
||||
|
||||
/**
|
||||
* The Url string
|
||||
*
|
||||
* @var string|null
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected ?string $url = null;
|
||||
|
||||
/**
|
||||
* The token string
|
||||
*
|
||||
* @var string|null
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected ?string $token = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@ -67,14 +83,31 @@ abstract class Api
|
||||
/**
|
||||
* Load/Reload API.
|
||||
*
|
||||
* @param string|null $url The url.
|
||||
* @param token|null $token The token.
|
||||
* @param string|null $url The url.
|
||||
* @param token|null $token The token.
|
||||
* @param bool $backup The backup swapping switch.
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function load_(?string $url = null, ?string $token = null)
|
||||
public function load_(?string $url = null, ?string $token = null, bool $backup = true): void
|
||||
{
|
||||
// we keep the old values
|
||||
// so we can reset after our call
|
||||
// for the rest of the container
|
||||
if ($backup)
|
||||
{
|
||||
if ($url !== null)
|
||||
{
|
||||
$this->url = $this->uri->getUrl();
|
||||
}
|
||||
|
||||
if ($token !== null)
|
||||
{
|
||||
$this->token = $this->http->getToken();
|
||||
}
|
||||
}
|
||||
|
||||
if ($url !== null)
|
||||
{
|
||||
$this->uri->setUrl($url);
|
||||
@ -86,6 +119,27 @@ abstract class Api
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset to previous toke, url it set
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function reset_(): void
|
||||
{
|
||||
if ($this->url !== null)
|
||||
{
|
||||
$this->uri->setUrl($this->url);
|
||||
$this->url = null;
|
||||
}
|
||||
|
||||
if ($this->token !== null)
|
||||
{
|
||||
$this->http->setToken($this->token);
|
||||
$this->token = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the API url
|
||||
*
|
||||
|
@ -23,6 +23,14 @@ use Joomla\Registry\Registry;
|
||||
*/
|
||||
final class Http extends JoomlaHttp
|
||||
{
|
||||
/**
|
||||
* The token
|
||||
*
|
||||
* @var string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected string $_token_; // to avoid collusions (but allow swapping)
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@ -45,6 +53,7 @@ final class Http extends JoomlaHttp
|
||||
if (is_string($token))
|
||||
{
|
||||
$config['headers']['Authorization'] = 'token ' . $token;
|
||||
$this->_token_ = $token;
|
||||
}
|
||||
|
||||
$options = new Registry($config);
|
||||
@ -60,7 +69,7 @@ final class Http extends JoomlaHttp
|
||||
*
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function setToken(string $token)
|
||||
public function setToken(string $token): void
|
||||
{
|
||||
// get the current headers
|
||||
$headers = (array) $this->getOption('headers', [
|
||||
@ -70,8 +79,20 @@ final class Http extends JoomlaHttp
|
||||
|
||||
// add the token
|
||||
$headers['Authorization'] = 'token ' . $token;
|
||||
$this->_token_ = $token;
|
||||
|
||||
$this->setOption('headers', $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Token.
|
||||
*
|
||||
* @return string|null
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function getToken(): ?string
|
||||
{
|
||||
return $this->_token_ ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,17 @@ final class Uri
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL of the API
|
||||
*
|
||||
* @return string|null
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function getUrl(): ?string
|
||||
{
|
||||
return $this->url ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the endpoint of the API
|
||||
*
|
||||
|
@ -12,6 +12,9 @@
|
||||
namespace VDM\Joomla\Componentbuilder\Server;
|
||||
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use phpseclib3\Net\SFTP as SftpClient;
|
||||
use VDM\Joomla\Componentbuilder\Crypt\KeyLoader;
|
||||
use VDM\Joomla\Utilities\StringHelper;
|
||||
@ -51,16 +54,26 @@ class Sftp implements Serverinterface
|
||||
**/
|
||||
protected ?object $details = null;
|
||||
|
||||
/**
|
||||
* Application object.
|
||||
*
|
||||
* @var CMSApplication
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected CMSApplication $app;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param KeyLoader $key The key loader object.
|
||||
* @param CMSApplication|null $app The app object.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(KeyLoader $key)
|
||||
public function __construct(KeyLoader $key, ?CMSApplication $app = null)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->app = $app ?: Factory::getApplication();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,10 +119,21 @@ class Sftp implements Serverinterface
|
||||
StringHelper::check($this->details->path) &&
|
||||
$this->details->path !== '/')
|
||||
{
|
||||
$path = '/' . trim((string) $this->details->path, '/');
|
||||
$path = trim((string) $this->details->path);
|
||||
$path = '/' . trim($path, '/') . '/';
|
||||
}
|
||||
|
||||
return $this->client->put($path . '/' . $fileName, $data);
|
||||
try
|
||||
{
|
||||
return $this->client->put($path . trim($fileName), $data);
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
$this->app->enqueueMessage(
|
||||
Text::sprintf('COM_COMPONENTBUILDER_MOVING_OF_THE_S_FAILED', $fileName) . ': ' . $e->getMessage(),
|
||||
'Error'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -147,24 +171,23 @@ class Sftp implements Serverinterface
|
||||
isset($this->details->username) && StringHelper::check($this->details->username))
|
||||
{
|
||||
// insure the port is set
|
||||
$port = (isset($this->details->port) && is_numeric($this->details->port) && $this->details->port > 0)
|
||||
? (int) $this->details->port : 22;
|
||||
$port = (int)($this->details->port ?? 22);
|
||||
|
||||
// open the connection
|
||||
$sftp = new SftpClient($this->details->host, $port);
|
||||
|
||||
// set the passphrase if it exist
|
||||
$passphrase = $this->details->secret ?? null;
|
||||
$passphrase = (isset($this->details->secret) && StringHelper::check(trim($this->details->secret))) ? trim($this->details->secret) : false;
|
||||
|
||||
// set the password if it exist
|
||||
$password = $this->details->password ?? null;
|
||||
$password = (isset($this->details->password) && StringHelper::check(trim($this->details->password))) ? trim($this->details->password) : false;
|
||||
|
||||
// now login based on authentication type
|
||||
$key = null;
|
||||
switch($this->details->authentication)
|
||||
{
|
||||
case 1: // password
|
||||
$key = $this->details->password ?? null;
|
||||
$key = $password ?? null;
|
||||
$password = null;
|
||||
break;
|
||||
case 2: // private key file
|
||||
@ -172,28 +195,77 @@ class Sftp implements Serverinterface
|
||||
if (isset($this->details->private) && StringHelper::check($this->details->private) &&
|
||||
($private_key = FileHelper::getContent($this->details->private, null)) !== null)
|
||||
{
|
||||
$key = $this->key::load($private_key, $passphrase);
|
||||
try
|
||||
{
|
||||
$key = $this->key::load(trim($private_key), $passphrase);
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
$this->app->enqueueMessage(
|
||||
Text::_('COM_COMPONENTBUILDER_LOADING_THE_PRIVATE_KEY_FILE_FAILED') . ': ' . $e->getMessage(),
|
||||
'Error'
|
||||
);
|
||||
$key = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4: // private key field
|
||||
case 5: // both password and private key field
|
||||
if (isset($this->details->private_key) && StringHelper::check($this->details->private_key))
|
||||
{
|
||||
$key = $this->key::load($this->details->private_key, $passphrase);
|
||||
try
|
||||
{
|
||||
$key = $this->key::load(trim($this->details->private_key), $passphrase);
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
$this->app->enqueueMessage(
|
||||
Text::_('COM_COMPONENTBUILDER_LOADING_THE_PRIVATE_KEY_TEXT_FAILED') . ': ' . $e->getMessage(),
|
||||
'Error'
|
||||
);
|
||||
$key = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// remove any null bites from the username
|
||||
$this->details->username = trim($this->details->username);
|
||||
|
||||
// login
|
||||
if ((!empty($key) && !empty($password) && $sftp->login($this->details->username, $key, $password)) ||
|
||||
(!empty($key) && $sftp->login($this->details->username, $key)))
|
||||
if (!empty($key) && !empty($password))
|
||||
{
|
||||
return $sftp;
|
||||
try
|
||||
{
|
||||
$sftp->login($this->details->username, $key, $password);
|
||||
return $sftp;
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
$this->app->enqueueMessage(
|
||||
Text::_('COM_COMPONENTBUILDER_LOGIN_FAILED') . ': ' . $e->getMessage(),
|
||||
'Error'
|
||||
);
|
||||
}
|
||||
}
|
||||
elseif (!empty($key))
|
||||
{
|
||||
try
|
||||
{
|
||||
$sftp->login($this->details->username, $key);
|
||||
return $sftp;
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
$this->app->enqueueMessage(
|
||||
Text::_('COM_COMPONENTBUILDER_LOGIN_FAILED') . ': ' . $e->getMessage(),
|
||||
'Error'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,51 +67,6 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'php_helper_both' => [
|
||||
'name' => 'php_helper_both',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_HELPER_BOTH_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'created' => [
|
||||
'name' => 'created',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CREATED_LABEL',
|
||||
'type' => 'calendar',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'publishing',
|
||||
],
|
||||
'crowdin_project_identifier' => [
|
||||
'name' => 'crowdin_project_identifier',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CROWDIN_PROJECT_IDENTIFIER_LABEL',
|
||||
'type' => 'text',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'php_method_uninstall' => [
|
||||
'name' => 'php_method_uninstall',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_METHOD_UNINSTALL_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Dash & Install',
|
||||
],
|
||||
'php_preflight_install' => [
|
||||
'name' => 'php_preflight_install',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_PREFLIGHT_INSTALL_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Dash & Install',
|
||||
],
|
||||
'css_admin' => [
|
||||
'name' => 'css_admin',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CSS_ADMIN_LABEL',
|
||||
@ -121,33 +76,6 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'mvc_versiondate' => [
|
||||
'name' => 'mvc_versiondate',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_MVC_VERSIONDATE_LABEL',
|
||||
'type' => 'list',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'remove_line_breaks' => [
|
||||
'name' => 'remove_line_breaks',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_REMOVE_LINE_BREAKS_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'add_placeholders' => [
|
||||
'name' => 'add_placeholders',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_PLACEHOLDERS_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'php_admin_event' => [
|
||||
'name' => 'php_admin_event',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_ADMIN_EVENT_LABEL',
|
||||
@ -166,18 +94,18 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'description' => [
|
||||
'name' => 'description',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_DESCRIPTION_LABEL',
|
||||
'type' => 'textarea',
|
||||
'crowdin_username' => [
|
||||
'name' => 'crowdin_username',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CROWDIN_USERNAME_LABEL',
|
||||
'type' => 'text',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
'store' => 'basic_encryption',
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'author' => [
|
||||
'name' => 'author',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_AUTHOR_LABEL',
|
||||
'component_version' => [
|
||||
'name' => 'component_version',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_COMPONENT_VERSION_LABEL',
|
||||
'type' => 'text',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
@ -193,10 +121,19 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Dash & Install',
|
||||
],
|
||||
'email' => [
|
||||
'name' => 'email',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_EMAIL_LABEL',
|
||||
'type' => 'text',
|
||||
'remove_line_breaks' => [
|
||||
'name' => 'remove_line_breaks',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_REMOVE_LINE_BREAKS_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'description' => [
|
||||
'name' => 'description',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_DESCRIPTION_LABEL',
|
||||
'type' => 'textarea',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
@ -211,6 +148,96 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'MySQL',
|
||||
],
|
||||
'debug_linenr' => [
|
||||
'name' => 'debug_linenr',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_DEBUG_LINENR_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'mvc_versiondate' => [
|
||||
'name' => 'mvc_versiondate',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_MVC_VERSIONDATE_LABEL',
|
||||
'type' => 'list',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'php_preflight_install' => [
|
||||
'name' => 'php_preflight_install',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_PREFLIGHT_INSTALL_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Dash & Install',
|
||||
],
|
||||
'backup_folder_path' => [
|
||||
'name' => 'backup_folder_path',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BACKUP_FOLDER_PATH_LABEL',
|
||||
'type' => 'text',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'php_method_uninstall' => [
|
||||
'name' => 'php_method_uninstall',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_METHOD_UNINSTALL_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Dash & Install',
|
||||
],
|
||||
'add_placeholders' => [
|
||||
'name' => 'add_placeholders',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_PLACEHOLDERS_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'author' => [
|
||||
'name' => 'author',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_AUTHOR_LABEL',
|
||||
'type' => 'text',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'add_sales_server' => [
|
||||
'name' => 'add_sales_server',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_SALES_SERVER_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'email' => [
|
||||
'name' => 'email',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_EMAIL_LABEL',
|
||||
'type' => 'text',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'translation_tool' => [
|
||||
'name' => 'translation_tool',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_TRANSLATION_TOOL_LABEL',
|
||||
'type' => 'list',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'website' => [
|
||||
'name' => 'website',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_WEBSITE_LABEL',
|
||||
@ -220,14 +247,14 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'debug_linenr' => [
|
||||
'name' => 'debug_linenr',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_DEBUG_LINENR_LABEL',
|
||||
'type' => 'radio',
|
||||
'buildcompsql' => [
|
||||
'name' => 'buildcompsql',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BUILDCOMPSQL_LABEL',
|
||||
'type' => 'textarea',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Dynamic Build (beta)',
|
||||
],
|
||||
'add_license' => [
|
||||
'name' => 'add_license',
|
||||
@ -238,6 +265,15 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'php_helper_admin' => [
|
||||
'name' => 'php_helper_admin',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_HELPER_ADMIN_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'license_type' => [
|
||||
'name' => 'license_type',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_LICENSE_TYPE_LABEL',
|
||||
@ -247,18 +283,18 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'add_email_helper' => [
|
||||
'name' => 'add_email_helper',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_EMAIL_HELPER_LABEL',
|
||||
'type' => 'radio',
|
||||
'php_helper_site' => [
|
||||
'name' => 'php_helper_site',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_HELPER_SITE_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'php_helper_admin' => [
|
||||
'name' => 'php_helper_admin',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_HELPER_ADMIN_LABEL',
|
||||
'javascript' => [
|
||||
'name' => 'javascript',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_JAVASCRIPT_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
@ -274,9 +310,9 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => 'basic_encryption',
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'php_helper_site' => [
|
||||
'name' => 'php_helper_site',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_HELPER_SITE_LABEL',
|
||||
'css_site' => [
|
||||
'name' => 'css_site',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CSS_SITE_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
@ -292,15 +328,6 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'javascript' => [
|
||||
'name' => 'javascript',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_JAVASCRIPT_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'whmcs_buy_link' => [
|
||||
'name' => 'whmcs_buy_link',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_WHMCS_BUY_LINK_LABEL',
|
||||
@ -310,33 +337,6 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'css_site' => [
|
||||
'name' => 'css_site',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CSS_SITE_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'license' => [
|
||||
'name' => 'license',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_LICENSE_LABEL',
|
||||
'type' => 'textarea',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'bom' => [
|
||||
'name' => 'bom',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BOM_LABEL',
|
||||
'type' => 'filelist',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'php_preflight_update' => [
|
||||
'name' => 'php_preflight_update',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_PREFLIGHT_UPDATE_LABEL',
|
||||
@ -346,10 +346,10 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Dash & Install',
|
||||
],
|
||||
'image' => [
|
||||
'name' => 'image',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_IMAGE_LABEL',
|
||||
'type' => 'media',
|
||||
'license' => [
|
||||
'name' => 'license',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_LICENSE_LABEL',
|
||||
'type' => 'textarea',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
@ -364,10 +364,10 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Dash & Install',
|
||||
],
|
||||
'copyright' => [
|
||||
'name' => 'copyright',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_COPYRIGHT_LABEL',
|
||||
'type' => 'textarea',
|
||||
'bom' => [
|
||||
'name' => 'bom',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BOM_LABEL',
|
||||
'type' => 'filelist',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
@ -382,6 +382,15 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'MySQL',
|
||||
],
|
||||
'image' => [
|
||||
'name' => 'image',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_IMAGE_LABEL',
|
||||
'type' => 'media',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'addreadme' => [
|
||||
'name' => 'addreadme',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADDREADME_LABEL',
|
||||
@ -391,14 +400,14 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Readme',
|
||||
],
|
||||
'add_sales_server' => [
|
||||
'name' => 'add_sales_server',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_SALES_SERVER_LABEL',
|
||||
'type' => 'radio',
|
||||
'copyright' => [
|
||||
'name' => 'copyright',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_COPYRIGHT_LABEL',
|
||||
'type' => 'textarea',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'update_server_url' => [
|
||||
'name' => 'update_server_url',
|
||||
@ -409,15 +418,6 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'component_version' => [
|
||||
'name' => 'component_version',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_COMPONENT_VERSION_LABEL',
|
||||
'type' => 'text',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'add_powers' => [
|
||||
'name' => 'add_powers',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_POWERS_LABEL',
|
||||
@ -427,41 +427,32 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Details',
|
||||
],
|
||||
'translation_tool' => [
|
||||
'name' => 'translation_tool',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_TRANSLATION_TOOL_LABEL',
|
||||
'type' => 'list',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'crowdin_username' => [
|
||||
'name' => 'crowdin_username',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CROWDIN_USERNAME_LABEL',
|
||||
'type' => 'text',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => 'basic_encryption',
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'buildcompsql' => [
|
||||
'name' => 'buildcompsql',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BUILDCOMPSQL_LABEL',
|
||||
'type' => 'textarea',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Dynamic Build (beta)',
|
||||
],
|
||||
'add_php_helper_both' => [
|
||||
'name' => 'add_php_helper_both',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_PHP_HELPER_BOTH_LABEL',
|
||||
'add_backup_folder_path' => [
|
||||
'name' => 'add_backup_folder_path',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_BACKUP_FOLDER_PATH_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'crowdin_project_identifier' => [
|
||||
'name' => 'crowdin_project_identifier',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CROWDIN_PROJECT_IDENTIFIER_LABEL',
|
||||
'type' => 'text',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'created' => [
|
||||
'name' => 'created',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CREATED_LABEL',
|
||||
'type' => 'calendar',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'publishing',
|
||||
],
|
||||
'add_php_helper_admin' => [
|
||||
'name' => 'add_php_helper_admin',
|
||||
@ -742,6 +733,42 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'add_git_folder_path' => [
|
||||
'name' => 'add_git_folder_path',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_GIT_FOLDER_PATH_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'git_folder_path' => [
|
||||
'name' => 'git_folder_path',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_GIT_FOLDER_PATH_LABEL',
|
||||
'type' => 'text',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'creatuserhelper' => [
|
||||
'name' => 'creatuserhelper',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CREATUSERHELPER_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'adduikit' => [
|
||||
'name' => 'adduikit',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADDUIKIT_LABEL',
|
||||
'type' => 'list',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'crowdin_project_api_key' => [
|
||||
'name' => 'crowdin_project_api_key',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CROWDIN_PROJECT_API_KEY_LABEL',
|
||||
@ -751,6 +778,15 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => 'basic_encryption',
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'addfootable' => [
|
||||
'name' => 'addfootable',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADDFOOTABLE_LABEL',
|
||||
'type' => 'list',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'crowdin_account_api_key' => [
|
||||
'name' => 'crowdin_account_api_key',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CROWDIN_ACCOUNT_API_KEY_LABEL',
|
||||
@ -760,9 +796,9 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => 'basic_encryption',
|
||||
'tab_name' => 'Dynamic Integration',
|
||||
],
|
||||
'creatuserhelper' => [
|
||||
'name' => 'creatuserhelper',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CREATUSERHELPER_LABEL',
|
||||
'add_email_helper' => [
|
||||
'name' => 'add_email_helper',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_EMAIL_HELPER_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
@ -778,10 +814,10 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'Dynamic Build (beta)',
|
||||
],
|
||||
'adduikit' => [
|
||||
'name' => 'adduikit',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADDUIKIT_LABEL',
|
||||
'type' => 'list',
|
||||
'add_php_helper_both' => [
|
||||
'name' => 'add_php_helper_both',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADD_PHP_HELPER_BOTH_LABEL',
|
||||
'type' => 'radio',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
@ -796,13 +832,13 @@ class Table extends BaseTable implements Tableinterface
|
||||
'store' => NULL,
|
||||
'tab_name' => 'publishing',
|
||||
],
|
||||
'addfootable' => [
|
||||
'name' => 'addfootable',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_ADDFOOTABLE_LABEL',
|
||||
'type' => 'list',
|
||||
'php_helper_both' => [
|
||||
'name' => 'php_helper_both',
|
||||
'label' => 'COM_COMPONENTBUILDER_JOOMLA_COMPONENT_PHP_HELPER_BOTH_LABEL',
|
||||
'type' => 'editor',
|
||||
'title' => false,
|
||||
'list' => 'joomla_components',
|
||||
'store' => NULL,
|
||||
'store' => 'base64',
|
||||
'tab_name' => 'Libs & Helpers',
|
||||
],
|
||||
'modified' => [
|
||||
|
@ -65,7 +65,7 @@ abstract class TypeHelper
|
||||
$string = StringHelper::transliterate($string);
|
||||
|
||||
// remove all and keep only characters and numbers and point (TODO just one point)
|
||||
$string = trim(preg_replace("/[^A-Za-z0-9\.]/", '', (string) $string));
|
||||
$string = trim(preg_replace("/[^A-Za-z0-9_\.]/", '', (string) $string));
|
||||
|
||||
// best is to return lower (for all string equality in compiler)
|
||||
return strtolower($string);
|
||||
|
@ -125,17 +125,17 @@
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "3.0.18",
|
||||
"version_normalized": "3.0.18.0",
|
||||
"version": "3.0.33",
|
||||
"version_normalized": "3.0.33.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "f28693d38ba21bb0d9f0c411ee5dae2b178201da"
|
||||
"reference": "33fa69b2514a61138dd48e7a49f99445711e0ad0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/f28693d38ba21bb0d9f0c411ee5dae2b178201da",
|
||||
"reference": "f28693d38ba21bb0d9f0c411ee5dae2b178201da",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/33fa69b2514a61138dd48e7a49f99445711e0ad0",
|
||||
"reference": "33fa69b2514a61138dd48e7a49f99445711e0ad0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -153,7 +153,7 @@
|
||||
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
||||
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
|
||||
},
|
||||
"time": "2022-12-17T18:26:50+00:00",
|
||||
"time": "2023-10-21T14:00:39+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@ -218,7 +218,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.18"
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.33"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -38,12 +38,12 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phpseclib/phpseclib' => array(
|
||||
'pretty_version' => '3.0.18',
|
||||
'version' => '3.0.18.0',
|
||||
'pretty_version' => '3.0.33',
|
||||
'version' => '3.0.33.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpseclib/phpseclib',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f28693d38ba21bb0d9f0c411ee5dae2b178201da',
|
||||
'reference' => '33fa69b2514a61138dd48e7a49f99445711e0ad0',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
|
@ -11,4 +11,6 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co
|
||||
- [Setasign](https://www.setasign.com/)
|
||||
- [Charles Severance](https://github.com/csev)
|
||||
- [Rachel Fish](https://github.com/itsrachelfish)
|
||||
- Tharyrok
|
||||
- Tharyrok
|
||||
- [cjhaas](https://github.com/cjhaas)
|
||||
- [istiak-tridip](https://github.com/istiak-tridip)
|
@ -51,8 +51,7 @@ SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 /
|
||||
* PHP4 compatible
|
||||
* Composer compatible (PSR-0 autoloading)
|
||||
* Install using Composer: `composer require phpseclib/phpseclib:~1.0`
|
||||
* Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm)
|
||||
* [Download 1.0.20 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.20.zip/download)
|
||||
* [Download 1.0.21 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.21.zip/download)
|
||||
|
||||
## Security contact information
|
||||
|
||||
|
@ -402,7 +402,7 @@ class Blowfish extends BlockCipher
|
||||
// quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1
|
||||
// "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider"
|
||||
// in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not
|
||||
if (version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) {
|
||||
if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) {
|
||||
return false;
|
||||
}
|
||||
$this->cipher_name_openssl_ecb = 'bf-ecb';
|
||||
|
@ -130,12 +130,17 @@ abstract class AsymmetricKey
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $password optional
|
||||
* @return AsymmetricKey
|
||||
* @return \phpseclib3\Crypt\Common\PublicKey|\phpseclib3\Crypt\Common\PrivateKey
|
||||
*/
|
||||
public static function load($key, $password = false)
|
||||
{
|
||||
self::initialize_static_variables();
|
||||
|
||||
$class = new \ReflectionClass(static::class);
|
||||
if ($class->isFinal()) {
|
||||
throw new \RuntimeException('load() should not be called from final classes (' . static::class . ')');
|
||||
}
|
||||
|
||||
$components = false;
|
||||
foreach (self::$plugins[static::ALGORITHM]['Keys'] as $format) {
|
||||
if (isset(self::$invisiblePlugins[static::ALGORITHM]) && in_array($format, self::$invisiblePlugins[static::ALGORITHM])) {
|
||||
|
@ -315,6 +315,13 @@ abstract class PKCS8 extends PKCS
|
||||
*/
|
||||
protected static function load($key, $password = '')
|
||||
{
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
$isPublic = strpos($key, 'PUBLIC') !== false;
|
||||
$isPrivate = strpos($key, 'PRIVATE') !== false;
|
||||
|
||||
$decoded = self::preParse($key);
|
||||
|
||||
$meta = [];
|
||||
@ -445,6 +452,10 @@ abstract class PKCS8 extends PKCS
|
||||
|
||||
$private = ASN1::asn1map($decoded[0], Maps\OneAsymmetricKey::MAP);
|
||||
if (is_array($private)) {
|
||||
if ($isPublic) {
|
||||
throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
|
||||
}
|
||||
|
||||
if (isset($private['privateKeyAlgorithm']['parameters']) && !$private['privateKeyAlgorithm']['parameters'] instanceof ASN1\Element && isset($decoded[0]['content'][1]['content'][1])) {
|
||||
$temp = $decoded[0]['content'][1]['content'][1];
|
||||
$private['privateKeyAlgorithm']['parameters'] = new ASN1\Element(substr($key, $temp['start'], $temp['length']));
|
||||
@ -474,6 +485,10 @@ abstract class PKCS8 extends PKCS
|
||||
$public = ASN1::asn1map($decoded[0], Maps\PublicKeyInfo::MAP);
|
||||
|
||||
if (is_array($public)) {
|
||||
if ($isPrivate) {
|
||||
throw new \UnexpectedValueException('Human readable string claims private key but DER encoded string claims public key');
|
||||
}
|
||||
|
||||
if ($public['publicKey'][0] != "\0") {
|
||||
throw new \UnexpectedValueException('The first byte of the public key should be null - not ' . bin2hex($public['publicKey'][0]));
|
||||
}
|
||||
@ -650,10 +665,6 @@ abstract class PKCS8 extends PKCS
|
||||
{
|
||||
self::initialize_static_variables();
|
||||
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
if (self::$format != self::MODE_DER) {
|
||||
$decoded = ASN1::extractBER($key);
|
||||
if ($decoded !== false) {
|
||||
@ -679,6 +690,10 @@ abstract class PKCS8 extends PKCS
|
||||
*/
|
||||
public static function extractEncryptionAlgorithm($key)
|
||||
{
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
$decoded = self::preParse($key);
|
||||
|
||||
$r = ASN1::asn1map($decoded[0], ASN1\Maps\EncryptedPrivateKeyInfo::MAP);
|
||||
|
@ -668,11 +668,11 @@ abstract class SymmetricKey
|
||||
switch (true) {
|
||||
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
|
||||
case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
|
||||
case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
|
||||
case !(is_string(php_uname('m')) && (php_uname('m') & "\xDF\xDF\xDF") == 'ARM'):
|
||||
case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
|
||||
self::$use_reg_intval = true;
|
||||
break;
|
||||
case (php_uname('m') & "\xDF\xDF\xDF") == 'ARM':
|
||||
case is_string(php_uname('m')) && (php_uname('m') & "\xDF\xDF\xDF") == 'ARM':
|
||||
switch (true) {
|
||||
/* PHP 7.0.0 introduced a bug that affected 32-bit ARM processors:
|
||||
|
||||
@ -917,7 +917,7 @@ abstract class SymmetricKey
|
||||
* @see Crypt/Hash.php
|
||||
* @param string $password
|
||||
* @param string $method
|
||||
* @param string[] ...$func_args
|
||||
* @param int|string ...$func_args
|
||||
* @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length
|
||||
* @throws \RuntimeException if bcrypt is being used and a salt isn't provided
|
||||
* @return bool
|
||||
@ -2589,12 +2589,8 @@ abstract class SymmetricKey
|
||||
|
||||
$length = ord($text[strlen($text) - 1]);
|
||||
|
||||
if (!$length) {
|
||||
// temp fix for FOFEncryptAes conversions
|
||||
// Added by Llewellyn van der Merwe <joomla@vdm.io>
|
||||
return rtrim($text);
|
||||
} elseif ($length > $this->block_size) {
|
||||
throw new BadDecryptionException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})");
|
||||
if (!$length || $length > $this->block_size) {
|
||||
throw new BadDecryptionException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})");
|
||||
}
|
||||
|
||||
return substr($text, 0, -$length);
|
||||
|
@ -597,7 +597,7 @@ class DES extends BlockCipher
|
||||
// quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1
|
||||
// "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider"
|
||||
// in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not
|
||||
if (version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) {
|
||||
if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) {
|
||||
return false;
|
||||
}
|
||||
$this->cipher_name_openssl_ecb = 'des-ecb';
|
||||
|
@ -81,6 +81,11 @@ abstract class DH extends AsymmetricKey
|
||||
*/
|
||||
public static function createParameters(...$args)
|
||||
{
|
||||
$class = new \ReflectionClass(static::class);
|
||||
if ($class->isFinal()) {
|
||||
throw new \RuntimeException('createParameters() should not be called from final classes (' . static::class . ')');
|
||||
}
|
||||
|
||||
$params = new Parameters();
|
||||
if (count($args) == 2 && $args[0] instanceof BigInteger && $args[1] instanceof BigInteger) {
|
||||
//if (!$args[0]->isPrime()) {
|
||||
@ -242,6 +247,11 @@ abstract class DH extends AsymmetricKey
|
||||
*/
|
||||
public static function createKey(Parameters $params, $length = 0)
|
||||
{
|
||||
$class = new \ReflectionClass(static::class);
|
||||
if ($class->isFinal()) {
|
||||
throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')');
|
||||
}
|
||||
|
||||
$one = new BigInteger(1);
|
||||
if ($length) {
|
||||
$max = $one->bitwise_leftShift($length);
|
||||
@ -387,9 +397,9 @@ abstract class DH extends AsymmetricKey
|
||||
*/
|
||||
public function getParameters()
|
||||
{
|
||||
$type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
|
||||
$type = DH::validatePlugin('Keys', 'PKCS1', 'saveParameters');
|
||||
|
||||
$key = $type::saveParameters($this->prime, $this->base);
|
||||
return self::load($key, 'PKCS1');
|
||||
return DH::load($key, 'PKCS1');
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
namespace phpseclib3\Crypt\DH\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
|
||||
use phpseclib3\File\ASN1;
|
||||
use phpseclib3\File\ASN1\Maps;
|
||||
@ -62,23 +61,10 @@ abstract class PKCS8 extends Progenitor
|
||||
*/
|
||||
public static function load($key, $password = '')
|
||||
{
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
$isPublic = strpos($key, 'PUBLIC') !== false;
|
||||
|
||||
$key = parent::load($key, $password);
|
||||
|
||||
$type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
|
||||
|
||||
switch (true) {
|
||||
case !$isPublic && $type == 'publicKey':
|
||||
throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
|
||||
case $isPublic && $type == 'privateKey':
|
||||
throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
|
||||
}
|
||||
|
||||
$decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
|
||||
if (empty($decoded)) {
|
||||
throw new \RuntimeException('Unable to decode BER of parameters');
|
||||
|
@ -18,7 +18,7 @@ use phpseclib3\Crypt\DH;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class Parameters extends DH
|
||||
final class Parameters extends DH
|
||||
{
|
||||
/**
|
||||
* Returns the parameters
|
||||
|
@ -19,7 +19,7 @@ use phpseclib3\Crypt\DH;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class PrivateKey extends DH
|
||||
final class PrivateKey extends DH
|
||||
{
|
||||
use Common\Traits\PasswordProtected;
|
||||
|
||||
|
@ -19,7 +19,7 @@ use phpseclib3\Crypt\DH;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class PublicKey extends DH
|
||||
final class PublicKey extends DH
|
||||
{
|
||||
use Common\Traits\Fingerprint;
|
||||
|
||||
|
@ -105,6 +105,11 @@ abstract class DSA extends AsymmetricKey
|
||||
{
|
||||
self::initialize_static_variables();
|
||||
|
||||
$class = new \ReflectionClass(static::class);
|
||||
if ($class->isFinal()) {
|
||||
throw new \RuntimeException('createParameters() should not be called from final classes (' . static::class . ')');
|
||||
}
|
||||
|
||||
if (!isset(self::$engines['PHP'])) {
|
||||
self::useBestEngine();
|
||||
}
|
||||
@ -180,6 +185,11 @@ abstract class DSA extends AsymmetricKey
|
||||
{
|
||||
self::initialize_static_variables();
|
||||
|
||||
$class = new \ReflectionClass(static::class);
|
||||
if ($class->isFinal()) {
|
||||
throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')');
|
||||
}
|
||||
|
||||
if (!isset(self::$engines['PHP'])) {
|
||||
self::useBestEngine();
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
namespace phpseclib3\Crypt\DSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
|
||||
use phpseclib3\File\ASN1;
|
||||
use phpseclib3\File\ASN1\Maps;
|
||||
@ -66,23 +65,10 @@ abstract class PKCS8 extends Progenitor
|
||||
*/
|
||||
public static function load($key, $password = '')
|
||||
{
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
$isPublic = strpos($key, 'PUBLIC') !== false;
|
||||
|
||||
$key = parent::load($key, $password);
|
||||
|
||||
$type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
|
||||
|
||||
switch (true) {
|
||||
case !$isPublic && $type == 'publicKey':
|
||||
throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
|
||||
case $isPublic && $type == 'privateKey':
|
||||
throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
|
||||
}
|
||||
|
||||
$decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
|
||||
if (!$decoded) {
|
||||
throw new \RuntimeException('Unable to decode BER of parameters');
|
||||
|
@ -18,7 +18,7 @@ use phpseclib3\Crypt\DSA;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class Parameters extends DSA
|
||||
final class Parameters extends DSA
|
||||
{
|
||||
/**
|
||||
* Returns the parameters
|
||||
|
@ -21,7 +21,7 @@ use phpseclib3\Math\BigInteger;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class PrivateKey extends DSA implements Common\PrivateKey
|
||||
final class PrivateKey extends DSA implements Common\PrivateKey
|
||||
{
|
||||
use Common\Traits\PasswordProtected;
|
||||
|
||||
|
@ -20,7 +20,7 @@ use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class PublicKey extends DSA implements Common\PublicKey
|
||||
final class PublicKey extends DSA implements Common\PublicKey
|
||||
{
|
||||
use Common\Traits\Fingerprint;
|
||||
|
||||
|
@ -140,6 +140,11 @@ abstract class EC extends AsymmetricKey
|
||||
{
|
||||
self::initialize_static_variables();
|
||||
|
||||
$class = new \ReflectionClass(static::class);
|
||||
if ($class->isFinal()) {
|
||||
throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')');
|
||||
}
|
||||
|
||||
if (!isset(self::$engines['PHP'])) {
|
||||
self::useBestEngine();
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
namespace phpseclib3\Crypt\EC\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
|
||||
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
|
||||
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
|
||||
@ -74,23 +73,10 @@ abstract class PKCS8 extends Progenitor
|
||||
// one that's called
|
||||
self::initialize_static_variables();
|
||||
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
$isPublic = strpos($key, 'PUBLIC') !== false;
|
||||
|
||||
$key = parent::load($key, $password);
|
||||
|
||||
$type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
|
||||
|
||||
switch (true) {
|
||||
case !$isPublic && $type == 'publicKey':
|
||||
throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
|
||||
case $isPublic && $type == 'privateKey':
|
||||
throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
|
||||
}
|
||||
|
||||
switch ($key[$type . 'Algorithm']['algorithm']) {
|
||||
case 'id-Ed25519':
|
||||
case 'id-Ed448':
|
||||
@ -109,7 +95,7 @@ abstract class PKCS8 extends Progenitor
|
||||
$components = [];
|
||||
$components['curve'] = self::loadCurveByParam($params);
|
||||
|
||||
if ($isPublic) {
|
||||
if ($type == 'publicKey') {
|
||||
$components['QA'] = self::extractPoint("\0" . $key['publicKey'], $components['curve']);
|
||||
|
||||
return $components;
|
||||
|
@ -18,7 +18,7 @@ use phpseclib3\Crypt\EC;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class Parameters extends EC
|
||||
final class Parameters extends EC
|
||||
{
|
||||
/**
|
||||
* Returns the parameters
|
||||
|
@ -29,7 +29,7 @@ use phpseclib3\Math\BigInteger;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class PrivateKey extends EC implements Common\PrivateKey
|
||||
final class PrivateKey extends EC implements Common\PrivateKey
|
||||
{
|
||||
use Common\Traits\PasswordProtected;
|
||||
|
||||
|
@ -28,7 +28,7 @@ use phpseclib3\Math\BigInteger;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class PublicKey extends EC implements Common\PublicKey
|
||||
final class PublicKey extends EC implements Common\PublicKey
|
||||
{
|
||||
use Common\Traits\Fingerprint;
|
||||
|
||||
|
@ -275,7 +275,7 @@ class RC2 extends BlockCipher
|
||||
// quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1
|
||||
// "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider"
|
||||
// in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not
|
||||
if (version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) {
|
||||
if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) {
|
||||
return false;
|
||||
}
|
||||
$this->cipher_name_openssl_ecb = 'rc2-ecb';
|
||||
|
@ -111,7 +111,7 @@ class RC4 extends StreamCipher
|
||||
// quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1
|
||||
// "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider"
|
||||
// in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not
|
||||
if (version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) {
|
||||
if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) {
|
||||
return false;
|
||||
}
|
||||
$this->cipher_name_openssl = 'rc4-40';
|
||||
|
@ -304,6 +304,11 @@ abstract class RSA extends AsymmetricKey
|
||||
{
|
||||
self::initialize_static_variables();
|
||||
|
||||
$class = new \ReflectionClass(static::class);
|
||||
if ($class->isFinal()) {
|
||||
throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')');
|
||||
}
|
||||
|
||||
$regSize = $bits >> 1; // divide by two to see how many bits P and Q would be
|
||||
if ($regSize > self::$smallestPrime) {
|
||||
$num_primes = floor($bits / self::$smallestPrime);
|
||||
@ -836,15 +841,15 @@ abstract class RSA extends AsymmetricKey
|
||||
self::ENCRYPTION_PKCS1,
|
||||
self::ENCRYPTION_NONE
|
||||
];
|
||||
$numSelected = 0;
|
||||
$encryptedCount = 0;
|
||||
$selected = 0;
|
||||
foreach ($masks as $mask) {
|
||||
if ($padding & $mask) {
|
||||
$selected = $mask;
|
||||
$numSelected++;
|
||||
$encryptedCount++;
|
||||
}
|
||||
}
|
||||
if ($numSelected > 1) {
|
||||
if ($encryptedCount > 1) {
|
||||
throw new InconsistentSetupException('Multiple encryption padding modes have been selected; at most only one should be selected');
|
||||
}
|
||||
$encryptionPadding = $selected;
|
||||
@ -854,22 +859,26 @@ abstract class RSA extends AsymmetricKey
|
||||
self::SIGNATURE_RELAXED_PKCS1,
|
||||
self::SIGNATURE_PKCS1
|
||||
];
|
||||
$numSelected = 0;
|
||||
$signatureCount = 0;
|
||||
$selected = 0;
|
||||
foreach ($masks as $mask) {
|
||||
if ($padding & $mask) {
|
||||
$selected = $mask;
|
||||
$numSelected++;
|
||||
$signatureCount++;
|
||||
}
|
||||
}
|
||||
if ($numSelected > 1) {
|
||||
if ($signatureCount > 1) {
|
||||
throw new InconsistentSetupException('Multiple signature padding modes have been selected; at most only one should be selected');
|
||||
}
|
||||
$signaturePadding = $selected;
|
||||
|
||||
$new = clone $this;
|
||||
$new->encryptionPadding = $encryptionPadding;
|
||||
$new->signaturePadding = $signaturePadding;
|
||||
if ($encryptedCount) {
|
||||
$new->encryptionPadding = $encryptionPadding;
|
||||
}
|
||||
if ($signatureCount) {
|
||||
$new->signaturePadding = $signaturePadding;
|
||||
}
|
||||
return $new;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
|
||||
use phpseclib3\File\ASN1;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
@ -67,29 +66,13 @@ abstract class PKCS8 extends Progenitor
|
||||
*/
|
||||
public static function load($key, $password = '')
|
||||
{
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
if (strpos($key, 'PUBLIC') !== false) {
|
||||
$components = ['isPublicKey' => true];
|
||||
} elseif (strpos($key, 'PRIVATE') !== false) {
|
||||
$components = ['isPublicKey' => false];
|
||||
} else {
|
||||
$components = [];
|
||||
}
|
||||
|
||||
$key = parent::load($key, $password);
|
||||
|
||||
if (isset($key['privateKey'])) {
|
||||
if (!isset($components['isPublicKey'])) {
|
||||
$components['isPublicKey'] = false;
|
||||
}
|
||||
$components['isPublicKey'] = false;
|
||||
$type = 'private';
|
||||
} else {
|
||||
if (!isset($components['isPublicKey'])) {
|
||||
$components['isPublicKey'] = true;
|
||||
}
|
||||
$components['isPublicKey'] = true;
|
||||
$type = 'public';
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ use phpseclib3\Math\BigInteger;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class PrivateKey extends RSA implements Common\PrivateKey
|
||||
final class PrivateKey extends RSA implements Common\PrivateKey
|
||||
{
|
||||
use Common\Traits\PasswordProtected;
|
||||
|
||||
|
@ -28,7 +28,7 @@ use phpseclib3\Math\BigInteger;
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class PublicKey extends RSA implements Common\PublicKey
|
||||
final class PublicKey extends RSA implements Common\PublicKey
|
||||
{
|
||||
use Common\Traits\Fingerprint;
|
||||
|
||||
|
@ -833,7 +833,6 @@ class Rijndael extends BlockCipher
|
||||
|
||||
// Generating encrypt code:
|
||||
$init_encrypt .= '
|
||||
static $tables;
|
||||
if (empty($tables)) {
|
||||
$tables = &$this->getTables();
|
||||
}
|
||||
@ -890,7 +889,6 @@ class Rijndael extends BlockCipher
|
||||
|
||||
// Generating decrypt code:
|
||||
$init_decrypt .= '
|
||||
static $invtables;
|
||||
if (empty($invtables)) {
|
||||
$invtables = &$this->getInvTables();
|
||||
}
|
||||
@ -947,7 +945,7 @@ class Rijndael extends BlockCipher
|
||||
|
||||
$this->inline_crypt = $this->createInlineCryptFunction(
|
||||
[
|
||||
'init_crypt' => '',
|
||||
'init_crypt' => 'static $tables; static $invtables;',
|
||||
'init_encrypt' => $init_encrypt,
|
||||
'init_decrypt' => $init_decrypt,
|
||||
'encrypt_block' => $encrypt_block,
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
namespace phpseclib3\File;
|
||||
|
||||
use DateTime;
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\File\ASN1\Element;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
@ -205,7 +204,7 @@ abstract class ASN1
|
||||
return null;
|
||||
}
|
||||
|
||||
return [self::decode_ber($encoded)];
|
||||
return [$decoded];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1403,7 +1402,7 @@ abstract class ASN1
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ($c & 0x80000000) != 0:
|
||||
case ($c & (PHP_INT_SIZE == 8 ? 0x80000000 : (1 << 31))) != 0:
|
||||
return false;
|
||||
case $c >= 0x04000000:
|
||||
$v .= chr(0x80 | ($c & 0x3F));
|
||||
|
@ -164,7 +164,7 @@ class X509
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $CAs;
|
||||
private $CAs = [];
|
||||
|
||||
/**
|
||||
* The currently loaded certificate
|
||||
@ -315,6 +315,10 @@ class X509
|
||||
'id-at-uniqueIdentifier' => '2.5.4.45',
|
||||
'id-at-role' => '2.5.4.72',
|
||||
'id-at-postalAddress' => '2.5.4.16',
|
||||
'jurisdictionOfIncorporationCountryName' => '1.3.6.1.4.1.311.60.2.1.3',
|
||||
'jurisdictionOfIncorporationStateOrProvinceName' => '1.3.6.1.4.1.311.60.2.1.2',
|
||||
'jurisdictionLocalityName' => '1.3.6.1.4.1.311.60.2.1.1',
|
||||
'id-at-businessCategory' => '2.5.4.15',
|
||||
|
||||
//'id-domainComponent' => '0.9.2342.19200300.100.1.25',
|
||||
//'pkcs-9' => '1.2.840.113549.1.9',
|
||||
@ -1038,7 +1042,8 @@ class X509
|
||||
if ($names = $this->getExtension('id-ce-subjectAltName')) {
|
||||
foreach ($names as $name) {
|
||||
foreach ($name as $key => $value) {
|
||||
$value = str_replace(['.', '*'], ['\.', '[^.]*'], $value);
|
||||
$value = preg_quote($value);
|
||||
$value = str_replace('\*', '[^.]*', $value);
|
||||
switch ($key) {
|
||||
case 'dNSName':
|
||||
/* From RFC2818 "HTTP over TLS":
|
||||
@ -1538,6 +1543,20 @@ class X509
|
||||
private function translateDNProp($propName)
|
||||
{
|
||||
switch (strtolower($propName)) {
|
||||
case 'jurisdictionofincorporationcountryname':
|
||||
case 'jurisdictioncountryname':
|
||||
case 'jurisdictionc':
|
||||
return 'jurisdictionOfIncorporationCountryName';
|
||||
case 'jurisdictionofincorporationstateorprovincename':
|
||||
case 'jurisdictionstateorprovincename':
|
||||
case 'jurisdictionst':
|
||||
return 'jurisdictionOfIncorporationStateOrProvinceName';
|
||||
case 'jurisdictionlocalityname':
|
||||
case 'jurisdictionl':
|
||||
return 'jurisdictionLocalityName';
|
||||
case 'id-at-businesscategory':
|
||||
case 'businesscategory':
|
||||
return 'id-at-businessCategory';
|
||||
case 'id-at-countryname':
|
||||
case 'countryname':
|
||||
case 'c':
|
||||
@ -2030,9 +2049,6 @@ class X509
|
||||
if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
|
||||
return false;
|
||||
}
|
||||
if (empty($this->CAs)) {
|
||||
return $chain;
|
||||
}
|
||||
while (true) {
|
||||
$currentCert = $chain[count($chain) - 1];
|
||||
for ($i = 0; $i < count($this->CAs); $i++) {
|
||||
|
@ -29,6 +29,7 @@ namespace phpseclib3\Math;
|
||||
|
||||
use phpseclib3\Exception\BadConfigurationException;
|
||||
use phpseclib3\Math\BigInteger\Engines\Engine;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
|
||||
@ -100,10 +101,6 @@ class BigInteger implements \JsonSerializable
|
||||
/** @var class-string<Engine> $fqmain */
|
||||
self::$mainEngine = $fqmain;
|
||||
|
||||
if (!in_array('Default', $modexps)) {
|
||||
$modexps[] = 'DefaultEngine';
|
||||
}
|
||||
|
||||
$found = false;
|
||||
foreach ($modexps as $modexp) {
|
||||
try {
|
||||
@ -140,18 +137,23 @@ class BigInteger implements \JsonSerializable
|
||||
{
|
||||
if (!isset(self::$mainEngine)) {
|
||||
$engines = [
|
||||
['GMP'],
|
||||
['GMP', ['DefaultEngine']],
|
||||
['PHP64', ['OpenSSL']],
|
||||
['BCMath', ['OpenSSL']],
|
||||
['PHP32', ['OpenSSL']]
|
||||
['PHP32', ['OpenSSL']],
|
||||
['PHP64', ['DefaultEngine']],
|
||||
['PHP32', ['DefaultEngine']]
|
||||
];
|
||||
|
||||
foreach ($engines as $engine) {
|
||||
try {
|
||||
self::setEngine($engine[0], isset($engine[1]) ? $engine[1] : []);
|
||||
break;
|
||||
self::setEngine($engine[0], $engine[1]);
|
||||
return;
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
throw new UnexpectedValueException('No valid BigInteger found. This is only possible when JIT is enabled on Windows and neither the GMP or BCMath extensions are available so either disable JIT or install GMP / BCMath');
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,6 +439,8 @@ class BigInteger implements \JsonSerializable
|
||||
* JSON Serialize
|
||||
*
|
||||
* Will be called, automatically, when json_encode() is called on a BigInteger object.
|
||||
*
|
||||
* @return array{hex: string, precision?: int]
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
|
@ -166,7 +166,7 @@ abstract class Engine implements \JsonSerializable
|
||||
$x = substr($x, 1);
|
||||
}
|
||||
|
||||
$x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
|
||||
$x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#s', '$1', $x);
|
||||
|
||||
$is_negative = false;
|
||||
if ($base < 0 && hexdec($x[0]) >= 8) {
|
||||
@ -187,7 +187,7 @@ abstract class Engine implements \JsonSerializable
|
||||
// (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
|
||||
// (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
|
||||
// [^-0-9].*: find any non-numeric characters and then any characters that follow that
|
||||
$this->value = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
|
||||
$this->value = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#s', '', $x);
|
||||
if (!strlen($this->value) || $this->value == '-') {
|
||||
$this->value = '0';
|
||||
}
|
||||
@ -200,7 +200,7 @@ abstract class Engine implements \JsonSerializable
|
||||
$x = substr($x, 1);
|
||||
}
|
||||
|
||||
$x = preg_replace('#^([01]*).*#', '$1', $x);
|
||||
$x = preg_replace('#^([01]*).*#s', '$1', $x);
|
||||
|
||||
$temp = new static(Strings::bits2bin($x), 128 * $base); // ie. either -16 or +16
|
||||
$this->value = $temp->value;
|
||||
@ -370,6 +370,8 @@ abstract class Engine implements \JsonSerializable
|
||||
* JSON Serialize
|
||||
*
|
||||
* Will be called, automatically, when json_encode() is called on a BigInteger object.
|
||||
*
|
||||
* @return array{hex: string, precision?: int]
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
@ -642,6 +644,11 @@ abstract class Engine implements \JsonSerializable
|
||||
return $this->normalize($temp->powModInner($e, $n));
|
||||
}
|
||||
|
||||
if ($this->compare($n) > 0) {
|
||||
list(, $temp) = $this->divide($n);
|
||||
return $temp->powModInner($e, $n);
|
||||
}
|
||||
|
||||
return $this->powModInner($e, $n);
|
||||
}
|
||||
|
||||
|
@ -1326,4 +1326,18 @@ abstract class PHP extends Engine
|
||||
|
||||
return array_reverse($vals);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected static function testJITOnWindows()
|
||||
{
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && function_exists('opcache_get_status') && !defined('PHPSECLIB_ALLOW_JIT')) {
|
||||
$status = opcache_get_status();
|
||||
if ($status && isset($status['jit']) && $status['jit']['enabled'] && $status['jit']['on']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -80,10 +80,10 @@ class PHP32 extends PHP
|
||||
}
|
||||
$step = count($vals) & 3;
|
||||
if ($step) {
|
||||
$digit = floor($digit / pow(2, 2 * $step));
|
||||
$digit = (int) floor($digit / pow(2, 2 * $step));
|
||||
}
|
||||
if ($step != 3) {
|
||||
$digit &= static::MAX_DIGIT;
|
||||
$digit = (int) fmod($digit, static::BASE_FULL);
|
||||
$i++;
|
||||
}
|
||||
$vals[] = $digit;
|
||||
@ -102,7 +102,7 @@ class PHP32 extends PHP
|
||||
*/
|
||||
public static function isValidEngine()
|
||||
{
|
||||
return PHP_INT_SIZE >= 4;
|
||||
return PHP_INT_SIZE >= 4 && !self::testJITOnWindows();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,7 +103,7 @@ class PHP64 extends PHP
|
||||
*/
|
||||
public static function isValidEngine()
|
||||
{
|
||||
return PHP_INT_SIZE >= 8;
|
||||
return PHP_INT_SIZE >= 8 && !self::testJITOnWindows();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,6 +26,8 @@ abstract class Integer implements \JsonSerializable
|
||||
*
|
||||
* PHP Serialize isn't supported because unserializing would require the factory be
|
||||
* serialized as well and that just sounds like too much
|
||||
*
|
||||
* @return array{hex: string}
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
|
@ -44,9 +44,9 @@ class PrimeField extends FiniteField
|
||||
*/
|
||||
public function __construct(BigInteger $modulo)
|
||||
{
|
||||
//if (!$modulo->isPrime()) {
|
||||
// throw new \UnexpectedValueException('PrimeField requires a prime number be passed to the constructor');
|
||||
//}
|
||||
if (!$modulo->isPrime()) {
|
||||
throw new \UnexpectedValueException('PrimeField requires a prime number be passed to the constructor');
|
||||
}
|
||||
|
||||
$this->instanceID = self::$instanceCounter++;
|
||||
Integer::setModulo($this->instanceID, $modulo);
|
||||
|
@ -263,13 +263,13 @@ class Integer extends Base
|
||||
$r = $this->value->powMod($temp, static::$modulo[$this->instanceID]);
|
||||
|
||||
while (!$t->equals($one)) {
|
||||
$i = clone $one;
|
||||
|
||||
while (!$t->powMod($two->pow($i), static::$modulo[$this->instanceID])->equals($one)) {
|
||||
$i = $i->add($one);
|
||||
for ($i == clone $one; $i->compare($m) < 0; $i = $i->add($one)) {
|
||||
if ($t->powMod($two->pow($i), static::$modulo[$this->instanceID])->equals($one)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($i->compare($m) >= 0) {
|
||||
if ($i->compare($m) == 0) {
|
||||
return false;
|
||||
}
|
||||
$b = $c->powMod($two->pow($m->subtract($i)->subtract($one)), static::$modulo[$this->instanceID]);
|
||||
@ -312,8 +312,11 @@ class Integer extends Base
|
||||
*/
|
||||
public function toBytes()
|
||||
{
|
||||
$length = static::$modulo[$this->instanceID]->getLengthInBytes();
|
||||
return str_pad($this->value->toBytes(), $length, "\0", STR_PAD_LEFT);
|
||||
if (isset(static::$modulo[$this->instanceID])) {
|
||||
$length = static::$modulo[$this->instanceID]->getLengthInBytes();
|
||||
return str_pad($this->value->toBytes(), $length, "\0", STR_PAD_LEFT);
|
||||
}
|
||||
return $this->value->toBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,7 +93,7 @@ class SFTP extends SSH2
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private $packet_types = [];
|
||||
private static $packet_types = [];
|
||||
|
||||
/**
|
||||
* Status Codes
|
||||
@ -102,19 +102,19 @@ class SFTP extends SSH2
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private $status_codes = [];
|
||||
private static $status_codes = [];
|
||||
|
||||
/** @var array<int, string> */
|
||||
private $attributes;
|
||||
private static $attributes;
|
||||
|
||||
/** @var array<int, string> */
|
||||
private $open_flags;
|
||||
private static $open_flags;
|
||||
|
||||
/** @var array<int, string> */
|
||||
private $open_flags5;
|
||||
private static $open_flags5;
|
||||
|
||||
/** @var array<int, string> */
|
||||
private $file_types;
|
||||
private static $file_types;
|
||||
|
||||
/**
|
||||
* The Request ID
|
||||
@ -350,7 +350,9 @@ class SFTP extends SSH2
|
||||
*
|
||||
* Connects to an SFTP server
|
||||
*
|
||||
* @param string $host
|
||||
* $host can either be a string, representing the host, or a stream resource.
|
||||
*
|
||||
* @param mixed $host
|
||||
* @param int $port
|
||||
* @param int $timeout
|
||||
*/
|
||||
@ -360,154 +362,156 @@ class SFTP extends SSH2
|
||||
|
||||
$this->max_sftp_packet = 1 << 15;
|
||||
|
||||
$this->packet_types = [
|
||||
1 => 'NET_SFTP_INIT',
|
||||
2 => 'NET_SFTP_VERSION',
|
||||
3 => 'NET_SFTP_OPEN',
|
||||
4 => 'NET_SFTP_CLOSE',
|
||||
5 => 'NET_SFTP_READ',
|
||||
6 => 'NET_SFTP_WRITE',
|
||||
7 => 'NET_SFTP_LSTAT',
|
||||
9 => 'NET_SFTP_SETSTAT',
|
||||
10 => 'NET_SFTP_FSETSTAT',
|
||||
11 => 'NET_SFTP_OPENDIR',
|
||||
12 => 'NET_SFTP_READDIR',
|
||||
13 => 'NET_SFTP_REMOVE',
|
||||
14 => 'NET_SFTP_MKDIR',
|
||||
15 => 'NET_SFTP_RMDIR',
|
||||
16 => 'NET_SFTP_REALPATH',
|
||||
17 => 'NET_SFTP_STAT',
|
||||
18 => 'NET_SFTP_RENAME',
|
||||
19 => 'NET_SFTP_READLINK',
|
||||
20 => 'NET_SFTP_SYMLINK',
|
||||
21 => 'NET_SFTP_LINK',
|
||||
if (empty(self::$packet_types)) {
|
||||
self::$packet_types = [
|
||||
1 => 'NET_SFTP_INIT',
|
||||
2 => 'NET_SFTP_VERSION',
|
||||
3 => 'NET_SFTP_OPEN',
|
||||
4 => 'NET_SFTP_CLOSE',
|
||||
5 => 'NET_SFTP_READ',
|
||||
6 => 'NET_SFTP_WRITE',
|
||||
7 => 'NET_SFTP_LSTAT',
|
||||
9 => 'NET_SFTP_SETSTAT',
|
||||
10 => 'NET_SFTP_FSETSTAT',
|
||||
11 => 'NET_SFTP_OPENDIR',
|
||||
12 => 'NET_SFTP_READDIR',
|
||||
13 => 'NET_SFTP_REMOVE',
|
||||
14 => 'NET_SFTP_MKDIR',
|
||||
15 => 'NET_SFTP_RMDIR',
|
||||
16 => 'NET_SFTP_REALPATH',
|
||||
17 => 'NET_SFTP_STAT',
|
||||
18 => 'NET_SFTP_RENAME',
|
||||
19 => 'NET_SFTP_READLINK',
|
||||
20 => 'NET_SFTP_SYMLINK',
|
||||
21 => 'NET_SFTP_LINK',
|
||||
|
||||
101 => 'NET_SFTP_STATUS',
|
||||
102 => 'NET_SFTP_HANDLE',
|
||||
103 => 'NET_SFTP_DATA',
|
||||
104 => 'NET_SFTP_NAME',
|
||||
105 => 'NET_SFTP_ATTRS',
|
||||
101 => 'NET_SFTP_STATUS',
|
||||
102 => 'NET_SFTP_HANDLE',
|
||||
103 => 'NET_SFTP_DATA',
|
||||
104 => 'NET_SFTP_NAME',
|
||||
105 => 'NET_SFTP_ATTRS',
|
||||
|
||||
200 => 'NET_SFTP_EXTENDED'
|
||||
];
|
||||
$this->status_codes = [
|
||||
0 => 'NET_SFTP_STATUS_OK',
|
||||
1 => 'NET_SFTP_STATUS_EOF',
|
||||
2 => 'NET_SFTP_STATUS_NO_SUCH_FILE',
|
||||
3 => 'NET_SFTP_STATUS_PERMISSION_DENIED',
|
||||
4 => 'NET_SFTP_STATUS_FAILURE',
|
||||
5 => 'NET_SFTP_STATUS_BAD_MESSAGE',
|
||||
6 => 'NET_SFTP_STATUS_NO_CONNECTION',
|
||||
7 => 'NET_SFTP_STATUS_CONNECTION_LOST',
|
||||
8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED',
|
||||
9 => 'NET_SFTP_STATUS_INVALID_HANDLE',
|
||||
10 => 'NET_SFTP_STATUS_NO_SUCH_PATH',
|
||||
11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS',
|
||||
12 => 'NET_SFTP_STATUS_WRITE_PROTECT',
|
||||
13 => 'NET_SFTP_STATUS_NO_MEDIA',
|
||||
14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM',
|
||||
15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED',
|
||||
16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL',
|
||||
17 => 'NET_SFTP_STATUS_LOCK_CONFLICT',
|
||||
18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY',
|
||||
19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY',
|
||||
20 => 'NET_SFTP_STATUS_INVALID_FILENAME',
|
||||
21 => 'NET_SFTP_STATUS_LINK_LOOP',
|
||||
22 => 'NET_SFTP_STATUS_CANNOT_DELETE',
|
||||
23 => 'NET_SFTP_STATUS_INVALID_PARAMETER',
|
||||
24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY',
|
||||
25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT',
|
||||
26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED',
|
||||
27 => 'NET_SFTP_STATUS_DELETE_PENDING',
|
||||
28 => 'NET_SFTP_STATUS_FILE_CORRUPT',
|
||||
29 => 'NET_SFTP_STATUS_OWNER_INVALID',
|
||||
30 => 'NET_SFTP_STATUS_GROUP_INVALID',
|
||||
31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'
|
||||
];
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
|
||||
// the order, in this case, matters quite a lot - see \phpseclib3\Net\SFTP::_parseAttributes() to understand why
|
||||
$this->attributes = [
|
||||
0x00000001 => 'NET_SFTP_ATTR_SIZE',
|
||||
0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
|
||||
0x00000080 => 'NET_SFTP_ATTR_OWNERGROUP', // defined in SFTPv4+
|
||||
0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
|
||||
0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
|
||||
0x00000010 => 'NET_SFTP_ATTR_CREATETIME', // SFTPv4+
|
||||
0x00000020 => 'NET_SFTP_ATTR_MODIFYTIME',
|
||||
0x00000040 => 'NET_SFTP_ATTR_ACL',
|
||||
0x00000100 => 'NET_SFTP_ATTR_SUBSECOND_TIMES',
|
||||
0x00000200 => 'NET_SFTP_ATTR_BITS', // SFTPv5+
|
||||
0x00000400 => 'NET_SFTP_ATTR_ALLOCATION_SIZE', // SFTPv6+
|
||||
0x00000800 => 'NET_SFTP_ATTR_TEXT_HINT',
|
||||
0x00001000 => 'NET_SFTP_ATTR_MIME_TYPE',
|
||||
0x00002000 => 'NET_SFTP_ATTR_LINK_COUNT',
|
||||
0x00004000 => 'NET_SFTP_ATTR_UNTRANSLATED_NAME',
|
||||
0x00008000 => 'NET_SFTP_ATTR_CTIME',
|
||||
// 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers
|
||||
// yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in
|
||||
// two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000.
|
||||
// that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
|
||||
(PHP_INT_SIZE == 4 ? -1 : 0xFFFFFFFF) => 'NET_SFTP_ATTR_EXTENDED'
|
||||
];
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
|
||||
// the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
|
||||
// the array for that $this->open5_flags and similarly alter the constant names.
|
||||
$this->open_flags = [
|
||||
0x00000001 => 'NET_SFTP_OPEN_READ',
|
||||
0x00000002 => 'NET_SFTP_OPEN_WRITE',
|
||||
0x00000004 => 'NET_SFTP_OPEN_APPEND',
|
||||
0x00000008 => 'NET_SFTP_OPEN_CREATE',
|
||||
0x00000010 => 'NET_SFTP_OPEN_TRUNCATE',
|
||||
0x00000020 => 'NET_SFTP_OPEN_EXCL',
|
||||
0x00000040 => 'NET_SFTP_OPEN_TEXT' // defined in SFTPv4
|
||||
];
|
||||
// SFTPv5+ changed the flags up:
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-8.1.1.3
|
||||
$this->open_flags5 = [
|
||||
// when SSH_FXF_ACCESS_DISPOSITION is a 3 bit field that controls how the file is opened
|
||||
0x00000000 => 'NET_SFTP_OPEN_CREATE_NEW',
|
||||
0x00000001 => 'NET_SFTP_OPEN_CREATE_TRUNCATE',
|
||||
0x00000002 => 'NET_SFTP_OPEN_OPEN_EXISTING',
|
||||
0x00000003 => 'NET_SFTP_OPEN_OPEN_OR_CREATE',
|
||||
0x00000004 => 'NET_SFTP_OPEN_TRUNCATE_EXISTING',
|
||||
// the rest of the flags are not supported
|
||||
0x00000008 => 'NET_SFTP_OPEN_APPEND_DATA', // "the offset field of SS_FXP_WRITE requests is ignored"
|
||||
0x00000010 => 'NET_SFTP_OPEN_APPEND_DATA_ATOMIC',
|
||||
0x00000020 => 'NET_SFTP_OPEN_TEXT_MODE',
|
||||
0x00000040 => 'NET_SFTP_OPEN_BLOCK_READ',
|
||||
0x00000080 => 'NET_SFTP_OPEN_BLOCK_WRITE',
|
||||
0x00000100 => 'NET_SFTP_OPEN_BLOCK_DELETE',
|
||||
0x00000200 => 'NET_SFTP_OPEN_BLOCK_ADVISORY',
|
||||
0x00000400 => 'NET_SFTP_OPEN_NOFOLLOW',
|
||||
0x00000800 => 'NET_SFTP_OPEN_DELETE_ON_CLOSE',
|
||||
0x00001000 => 'NET_SFTP_OPEN_ACCESS_AUDIT_ALARM_INFO',
|
||||
0x00002000 => 'NET_SFTP_OPEN_ACCESS_BACKUP',
|
||||
0x00004000 => 'NET_SFTP_OPEN_BACKUP_STREAM',
|
||||
0x00008000 => 'NET_SFTP_OPEN_OVERRIDE_OWNER',
|
||||
];
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
|
||||
// see \phpseclib3\Net\SFTP::_parseLongname() for an explanation
|
||||
$this->file_types = [
|
||||
1 => 'NET_SFTP_TYPE_REGULAR',
|
||||
2 => 'NET_SFTP_TYPE_DIRECTORY',
|
||||
3 => 'NET_SFTP_TYPE_SYMLINK',
|
||||
4 => 'NET_SFTP_TYPE_SPECIAL',
|
||||
5 => 'NET_SFTP_TYPE_UNKNOWN',
|
||||
// the following types were first defined for use in SFTPv5+
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
|
||||
6 => 'NET_SFTP_TYPE_SOCKET',
|
||||
7 => 'NET_SFTP_TYPE_CHAR_DEVICE',
|
||||
8 => 'NET_SFTP_TYPE_BLOCK_DEVICE',
|
||||
9 => 'NET_SFTP_TYPE_FIFO'
|
||||
];
|
||||
$this->define_array(
|
||||
$this->packet_types,
|
||||
$this->status_codes,
|
||||
$this->attributes,
|
||||
$this->open_flags,
|
||||
$this->open_flags5,
|
||||
$this->file_types
|
||||
);
|
||||
200 => 'NET_SFTP_EXTENDED'
|
||||
];
|
||||
self::$status_codes = [
|
||||
0 => 'NET_SFTP_STATUS_OK',
|
||||
1 => 'NET_SFTP_STATUS_EOF',
|
||||
2 => 'NET_SFTP_STATUS_NO_SUCH_FILE',
|
||||
3 => 'NET_SFTP_STATUS_PERMISSION_DENIED',
|
||||
4 => 'NET_SFTP_STATUS_FAILURE',
|
||||
5 => 'NET_SFTP_STATUS_BAD_MESSAGE',
|
||||
6 => 'NET_SFTP_STATUS_NO_CONNECTION',
|
||||
7 => 'NET_SFTP_STATUS_CONNECTION_LOST',
|
||||
8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED',
|
||||
9 => 'NET_SFTP_STATUS_INVALID_HANDLE',
|
||||
10 => 'NET_SFTP_STATUS_NO_SUCH_PATH',
|
||||
11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS',
|
||||
12 => 'NET_SFTP_STATUS_WRITE_PROTECT',
|
||||
13 => 'NET_SFTP_STATUS_NO_MEDIA',
|
||||
14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM',
|
||||
15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED',
|
||||
16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL',
|
||||
17 => 'NET_SFTP_STATUS_LOCK_CONFLICT',
|
||||
18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY',
|
||||
19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY',
|
||||
20 => 'NET_SFTP_STATUS_INVALID_FILENAME',
|
||||
21 => 'NET_SFTP_STATUS_LINK_LOOP',
|
||||
22 => 'NET_SFTP_STATUS_CANNOT_DELETE',
|
||||
23 => 'NET_SFTP_STATUS_INVALID_PARAMETER',
|
||||
24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY',
|
||||
25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT',
|
||||
26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED',
|
||||
27 => 'NET_SFTP_STATUS_DELETE_PENDING',
|
||||
28 => 'NET_SFTP_STATUS_FILE_CORRUPT',
|
||||
29 => 'NET_SFTP_STATUS_OWNER_INVALID',
|
||||
30 => 'NET_SFTP_STATUS_GROUP_INVALID',
|
||||
31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'
|
||||
];
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
|
||||
// the order, in this case, matters quite a lot - see \phpseclib3\Net\SFTP::_parseAttributes() to understand why
|
||||
self::$attributes = [
|
||||
0x00000001 => 'NET_SFTP_ATTR_SIZE',
|
||||
0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
|
||||
0x00000080 => 'NET_SFTP_ATTR_OWNERGROUP', // defined in SFTPv4+
|
||||
0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
|
||||
0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
|
||||
0x00000010 => 'NET_SFTP_ATTR_CREATETIME', // SFTPv4+
|
||||
0x00000020 => 'NET_SFTP_ATTR_MODIFYTIME',
|
||||
0x00000040 => 'NET_SFTP_ATTR_ACL',
|
||||
0x00000100 => 'NET_SFTP_ATTR_SUBSECOND_TIMES',
|
||||
0x00000200 => 'NET_SFTP_ATTR_BITS', // SFTPv5+
|
||||
0x00000400 => 'NET_SFTP_ATTR_ALLOCATION_SIZE', // SFTPv6+
|
||||
0x00000800 => 'NET_SFTP_ATTR_TEXT_HINT',
|
||||
0x00001000 => 'NET_SFTP_ATTR_MIME_TYPE',
|
||||
0x00002000 => 'NET_SFTP_ATTR_LINK_COUNT',
|
||||
0x00004000 => 'NET_SFTP_ATTR_UNTRANSLATED_NAME',
|
||||
0x00008000 => 'NET_SFTP_ATTR_CTIME',
|
||||
// 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers
|
||||
// yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in
|
||||
// two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000.
|
||||
// that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
|
||||
(PHP_INT_SIZE == 4 ? (-1 << 31) : 0x80000000) => 'NET_SFTP_ATTR_EXTENDED'
|
||||
];
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
|
||||
// the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
|
||||
// the array for that $this->open5_flags and similarly alter the constant names.
|
||||
self::$open_flags = [
|
||||
0x00000001 => 'NET_SFTP_OPEN_READ',
|
||||
0x00000002 => 'NET_SFTP_OPEN_WRITE',
|
||||
0x00000004 => 'NET_SFTP_OPEN_APPEND',
|
||||
0x00000008 => 'NET_SFTP_OPEN_CREATE',
|
||||
0x00000010 => 'NET_SFTP_OPEN_TRUNCATE',
|
||||
0x00000020 => 'NET_SFTP_OPEN_EXCL',
|
||||
0x00000040 => 'NET_SFTP_OPEN_TEXT' // defined in SFTPv4
|
||||
];
|
||||
// SFTPv5+ changed the flags up:
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-8.1.1.3
|
||||
self::$open_flags5 = [
|
||||
// when SSH_FXF_ACCESS_DISPOSITION is a 3 bit field that controls how the file is opened
|
||||
0x00000000 => 'NET_SFTP_OPEN_CREATE_NEW',
|
||||
0x00000001 => 'NET_SFTP_OPEN_CREATE_TRUNCATE',
|
||||
0x00000002 => 'NET_SFTP_OPEN_OPEN_EXISTING',
|
||||
0x00000003 => 'NET_SFTP_OPEN_OPEN_OR_CREATE',
|
||||
0x00000004 => 'NET_SFTP_OPEN_TRUNCATE_EXISTING',
|
||||
// the rest of the flags are not supported
|
||||
0x00000008 => 'NET_SFTP_OPEN_APPEND_DATA', // "the offset field of SS_FXP_WRITE requests is ignored"
|
||||
0x00000010 => 'NET_SFTP_OPEN_APPEND_DATA_ATOMIC',
|
||||
0x00000020 => 'NET_SFTP_OPEN_TEXT_MODE',
|
||||
0x00000040 => 'NET_SFTP_OPEN_BLOCK_READ',
|
||||
0x00000080 => 'NET_SFTP_OPEN_BLOCK_WRITE',
|
||||
0x00000100 => 'NET_SFTP_OPEN_BLOCK_DELETE',
|
||||
0x00000200 => 'NET_SFTP_OPEN_BLOCK_ADVISORY',
|
||||
0x00000400 => 'NET_SFTP_OPEN_NOFOLLOW',
|
||||
0x00000800 => 'NET_SFTP_OPEN_DELETE_ON_CLOSE',
|
||||
0x00001000 => 'NET_SFTP_OPEN_ACCESS_AUDIT_ALARM_INFO',
|
||||
0x00002000 => 'NET_SFTP_OPEN_ACCESS_BACKUP',
|
||||
0x00004000 => 'NET_SFTP_OPEN_BACKUP_STREAM',
|
||||
0x00008000 => 'NET_SFTP_OPEN_OVERRIDE_OWNER',
|
||||
];
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
|
||||
// see \phpseclib3\Net\SFTP::_parseLongname() for an explanation
|
||||
self::$file_types = [
|
||||
1 => 'NET_SFTP_TYPE_REGULAR',
|
||||
2 => 'NET_SFTP_TYPE_DIRECTORY',
|
||||
3 => 'NET_SFTP_TYPE_SYMLINK',
|
||||
4 => 'NET_SFTP_TYPE_SPECIAL',
|
||||
5 => 'NET_SFTP_TYPE_UNKNOWN',
|
||||
// the following types were first defined for use in SFTPv5+
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
|
||||
6 => 'NET_SFTP_TYPE_SOCKET',
|
||||
7 => 'NET_SFTP_TYPE_CHAR_DEVICE',
|
||||
8 => 'NET_SFTP_TYPE_BLOCK_DEVICE',
|
||||
9 => 'NET_SFTP_TYPE_FIFO'
|
||||
];
|
||||
self::define_array(
|
||||
self::$packet_types,
|
||||
self::$status_codes,
|
||||
self::$attributes,
|
||||
self::$open_flags,
|
||||
self::$open_flags5,
|
||||
self::$file_types
|
||||
);
|
||||
}
|
||||
|
||||
if (!defined('NET_SFTP_QUEUE_SIZE')) {
|
||||
define('NET_SFTP_QUEUE_SIZE', 32);
|
||||
@ -543,22 +547,7 @@ class SFTP extends SSH2
|
||||
*/
|
||||
private function partial_init_sftp_connection()
|
||||
{
|
||||
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
|
||||
|
||||
$packet = Strings::packSSH2(
|
||||
'CsN3',
|
||||
NET_SSH2_MSG_CHANNEL_OPEN,
|
||||
'session',
|
||||
self::CHANNEL,
|
||||
$this->window_size,
|
||||
0x4000
|
||||
);
|
||||
|
||||
$this->send_binary_packet($packet);
|
||||
|
||||
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||
|
||||
$response = $this->get_channel_packet(self::CHANNEL, true);
|
||||
$response = $this->openChannel(self::CHANNEL, true);
|
||||
if ($response === true && $this->isTimeout()) {
|
||||
return false;
|
||||
}
|
||||
@ -715,7 +704,7 @@ class SFTP extends SSH2
|
||||
if (!$this->canonicalize_paths) {
|
||||
throw $e;
|
||||
}
|
||||
$this->$this->canonicalize_paths = false;
|
||||
$this->canonicalize_paths = false;
|
||||
$this->reset_connection(NET_SSH2_DISCONNECT_CONNECTION_LOST);
|
||||
}
|
||||
|
||||
@ -815,7 +804,7 @@ class SFTP extends SSH2
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
}
|
||||
|
||||
$error = $this->status_codes[$status];
|
||||
$error = self::$status_codes[$status];
|
||||
|
||||
if ($this->version > 2) {
|
||||
list($message) = Strings::unpackSSH2('s', $response);
|
||||
@ -2138,7 +2127,7 @@ class SFTP extends SSH2
|
||||
|
||||
if ($start >= 0) {
|
||||
$offset = $start;
|
||||
} elseif ($mode & self::RESUME) {
|
||||
} elseif ($mode & (self::RESUME | self::RESUME_START)) {
|
||||
// if NET_SFTP_OPEN_APPEND worked as it should _size() wouldn't need to be called
|
||||
$size = $this->stat($remote_file)['size'];
|
||||
$offset = $size !== false ? $size : 0;
|
||||
@ -2210,6 +2199,9 @@ class SFTP extends SSH2
|
||||
if ($local_start >= 0) {
|
||||
fseek($fp, $local_start);
|
||||
$size -= $local_start;
|
||||
} elseif ($mode & self::RESUME) {
|
||||
fseek($fp, $offset);
|
||||
$size -= $offset;
|
||||
}
|
||||
} elseif ($dataCallback) {
|
||||
$size = 0;
|
||||
@ -2497,14 +2489,6 @@ class SFTP extends SSH2
|
||||
}
|
||||
}
|
||||
|
||||
if ($length > 0 && $length <= $offset - $start) {
|
||||
if ($local_file === false) {
|
||||
$content = substr($content, 0, $length);
|
||||
} else {
|
||||
ftruncate($fp, $length + $res_offset);
|
||||
}
|
||||
}
|
||||
|
||||
if ($fclose_check) {
|
||||
fclose($fp);
|
||||
|
||||
@ -2840,15 +2824,37 @@ class SFTP extends SSH2
|
||||
return $this->get_stat_cache_prop($path, 'gid');
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively go through rawlist() output to get the total filesize
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function recursiveFilesize(array $files)
|
||||
{
|
||||
$size = 0;
|
||||
foreach ($files as $name => $file) {
|
||||
if ($name == '.' || $name == '..') {
|
||||
continue;
|
||||
}
|
||||
$size += is_array($file) ?
|
||||
self::recursiveFilesize($file) :
|
||||
$file->size;
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets file size
|
||||
*
|
||||
* @param string $path
|
||||
* @param bool $recursive
|
||||
* @return mixed
|
||||
*/
|
||||
public function filesize($path)
|
||||
public function filesize($path, $recursive = false)
|
||||
{
|
||||
return $this->get_stat_cache_prop($path, 'size');
|
||||
return !$recursive || $this->filetype($path) != 'dir' ?
|
||||
$this->get_stat_cache_prop($path, 'size') :
|
||||
self::recursiveFilesize($this->rawlist($path, true));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3041,7 +3047,7 @@ class SFTP extends SSH2
|
||||
list($flags) = Strings::unpackSSH2('N', $response);
|
||||
}
|
||||
|
||||
foreach ($this->attributes as $key => $value) {
|
||||
foreach (self::$attributes as $key => $value) {
|
||||
switch ($flags & $key) {
|
||||
case NET_SFTP_ATTR_UIDGID:
|
||||
if ($this->version > 3) {
|
||||
@ -3272,7 +3278,7 @@ class SFTP extends SSH2
|
||||
$stop = microtime(true);
|
||||
|
||||
if (defined('NET_SFTP_LOGGING')) {
|
||||
$packet_type = '-> ' . $this->packet_types[$type] .
|
||||
$packet_type = '-> ' . self::$packet_types[$type] .
|
||||
' (' . round($stop - $start, 4) . 's)';
|
||||
$this->append_log($packet_type, $data);
|
||||
}
|
||||
@ -3376,7 +3382,7 @@ class SFTP extends SSH2
|
||||
$packet = Strings::shift($this->packet_buffer, $length);
|
||||
|
||||
if (defined('NET_SFTP_LOGGING')) {
|
||||
$packet_type = '<- ' . $this->packet_types[$this->packet_type] .
|
||||
$packet_type = '<- ' . self::$packet_types[$this->packet_type] .
|
||||
' (' . round($stop - $start, 4) . 's)';
|
||||
$this->append_log($packet_type, $packet);
|
||||
}
|
||||
@ -3420,7 +3426,7 @@ class SFTP extends SSH2
|
||||
*
|
||||
* Returns a string if NET_SFTP_LOGGING == self::LOG_COMPLEX, an array if NET_SFTP_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
|
||||
*
|
||||
* @return array|string
|
||||
* @return array|string|false
|
||||
*/
|
||||
public function getSFTPLog()
|
||||
{
|
||||
|
@ -553,7 +553,7 @@ class SSH2
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private $message_numbers = [];
|
||||
private static $message_numbers = [];
|
||||
|
||||
/**
|
||||
* Disconnection Message 'reason codes' defined in RFC4253
|
||||
@ -562,7 +562,7 @@ class SSH2
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private $disconnect_reasons = [];
|
||||
private static $disconnect_reasons = [];
|
||||
|
||||
/**
|
||||
* SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254
|
||||
@ -571,7 +571,7 @@ class SSH2
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private $channel_open_failure_reasons = [];
|
||||
private static $channel_open_failure_reasons = [];
|
||||
|
||||
/**
|
||||
* Terminal Modes
|
||||
@ -581,7 +581,7 @@ class SSH2
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private $terminal_modes = [];
|
||||
private static $terminal_modes = [];
|
||||
|
||||
/**
|
||||
* SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes
|
||||
@ -591,7 +591,7 @@ class SSH2
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private $channel_extended_data_type_codes = [];
|
||||
private static $channel_extended_data_type_codes = [];
|
||||
|
||||
/**
|
||||
* Send Sequence Number
|
||||
@ -646,6 +646,14 @@ class SSH2
|
||||
*/
|
||||
protected $channel_status = [];
|
||||
|
||||
/**
|
||||
* The identifier of the interactive channel which was opened most recently
|
||||
*
|
||||
* @see self::getInteractiveChannelId()
|
||||
* @var int
|
||||
*/
|
||||
private $channel_id_last_interactive = 0;
|
||||
|
||||
/**
|
||||
* Packet Size
|
||||
*
|
||||
@ -837,20 +845,6 @@ class SSH2
|
||||
*/
|
||||
private $request_pty = false;
|
||||
|
||||
/**
|
||||
* Flag set while exec() is running when using enablePTY()
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $in_request_pty_exec = false;
|
||||
|
||||
/**
|
||||
* Flag set after startSubsystem() is called
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $in_subsystem;
|
||||
|
||||
/**
|
||||
* Contents of stdError
|
||||
*
|
||||
@ -1093,6 +1087,21 @@ class SSH2
|
||||
*/
|
||||
private $smartMFA = true;
|
||||
|
||||
/**
|
||||
* How many channels are currently opened
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $channelCount = 0;
|
||||
|
||||
/**
|
||||
* Does the server support multiple channels? If not then error out
|
||||
* when multiple channels are attempted to be opened
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $errorOnMultipleChannels;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
@ -1105,84 +1114,86 @@ class SSH2
|
||||
*/
|
||||
public function __construct($host, $port = 22, $timeout = 10)
|
||||
{
|
||||
$this->message_numbers = [
|
||||
1 => 'NET_SSH2_MSG_DISCONNECT',
|
||||
2 => 'NET_SSH2_MSG_IGNORE',
|
||||
3 => 'NET_SSH2_MSG_UNIMPLEMENTED',
|
||||
4 => 'NET_SSH2_MSG_DEBUG',
|
||||
5 => 'NET_SSH2_MSG_SERVICE_REQUEST',
|
||||
6 => 'NET_SSH2_MSG_SERVICE_ACCEPT',
|
||||
20 => 'NET_SSH2_MSG_KEXINIT',
|
||||
21 => 'NET_SSH2_MSG_NEWKEYS',
|
||||
30 => 'NET_SSH2_MSG_KEXDH_INIT',
|
||||
31 => 'NET_SSH2_MSG_KEXDH_REPLY',
|
||||
50 => 'NET_SSH2_MSG_USERAUTH_REQUEST',
|
||||
51 => 'NET_SSH2_MSG_USERAUTH_FAILURE',
|
||||
52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS',
|
||||
53 => 'NET_SSH2_MSG_USERAUTH_BANNER',
|
||||
if (empty(self::$message_numbers)) {
|
||||
self::$message_numbers = [
|
||||
1 => 'NET_SSH2_MSG_DISCONNECT',
|
||||
2 => 'NET_SSH2_MSG_IGNORE',
|
||||
3 => 'NET_SSH2_MSG_UNIMPLEMENTED',
|
||||
4 => 'NET_SSH2_MSG_DEBUG',
|
||||
5 => 'NET_SSH2_MSG_SERVICE_REQUEST',
|
||||
6 => 'NET_SSH2_MSG_SERVICE_ACCEPT',
|
||||
20 => 'NET_SSH2_MSG_KEXINIT',
|
||||
21 => 'NET_SSH2_MSG_NEWKEYS',
|
||||
30 => 'NET_SSH2_MSG_KEXDH_INIT',
|
||||
31 => 'NET_SSH2_MSG_KEXDH_REPLY',
|
||||
50 => 'NET_SSH2_MSG_USERAUTH_REQUEST',
|
||||
51 => 'NET_SSH2_MSG_USERAUTH_FAILURE',
|
||||
52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS',
|
||||
53 => 'NET_SSH2_MSG_USERAUTH_BANNER',
|
||||
|
||||
80 => 'NET_SSH2_MSG_GLOBAL_REQUEST',
|
||||
81 => 'NET_SSH2_MSG_REQUEST_SUCCESS',
|
||||
82 => 'NET_SSH2_MSG_REQUEST_FAILURE',
|
||||
90 => 'NET_SSH2_MSG_CHANNEL_OPEN',
|
||||
91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION',
|
||||
92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE',
|
||||
93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST',
|
||||
94 => 'NET_SSH2_MSG_CHANNEL_DATA',
|
||||
95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA',
|
||||
96 => 'NET_SSH2_MSG_CHANNEL_EOF',
|
||||
97 => 'NET_SSH2_MSG_CHANNEL_CLOSE',
|
||||
98 => 'NET_SSH2_MSG_CHANNEL_REQUEST',
|
||||
99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS',
|
||||
100 => 'NET_SSH2_MSG_CHANNEL_FAILURE'
|
||||
];
|
||||
$this->disconnect_reasons = [
|
||||
1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT',
|
||||
2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR',
|
||||
3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED',
|
||||
4 => 'NET_SSH2_DISCONNECT_RESERVED',
|
||||
5 => 'NET_SSH2_DISCONNECT_MAC_ERROR',
|
||||
6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR',
|
||||
7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE',
|
||||
8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED',
|
||||
9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE',
|
||||
10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST',
|
||||
11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION',
|
||||
12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS',
|
||||
13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER',
|
||||
14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE',
|
||||
15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'
|
||||
];
|
||||
$this->channel_open_failure_reasons = [
|
||||
1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED'
|
||||
];
|
||||
$this->terminal_modes = [
|
||||
0 => 'NET_SSH2_TTY_OP_END'
|
||||
];
|
||||
$this->channel_extended_data_type_codes = [
|
||||
1 => 'NET_SSH2_EXTENDED_DATA_STDERR'
|
||||
];
|
||||
80 => 'NET_SSH2_MSG_GLOBAL_REQUEST',
|
||||
81 => 'NET_SSH2_MSG_REQUEST_SUCCESS',
|
||||
82 => 'NET_SSH2_MSG_REQUEST_FAILURE',
|
||||
90 => 'NET_SSH2_MSG_CHANNEL_OPEN',
|
||||
91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION',
|
||||
92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE',
|
||||
93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST',
|
||||
94 => 'NET_SSH2_MSG_CHANNEL_DATA',
|
||||
95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA',
|
||||
96 => 'NET_SSH2_MSG_CHANNEL_EOF',
|
||||
97 => 'NET_SSH2_MSG_CHANNEL_CLOSE',
|
||||
98 => 'NET_SSH2_MSG_CHANNEL_REQUEST',
|
||||
99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS',
|
||||
100 => 'NET_SSH2_MSG_CHANNEL_FAILURE'
|
||||
];
|
||||
self::$disconnect_reasons = [
|
||||
1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT',
|
||||
2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR',
|
||||
3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED',
|
||||
4 => 'NET_SSH2_DISCONNECT_RESERVED',
|
||||
5 => 'NET_SSH2_DISCONNECT_MAC_ERROR',
|
||||
6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR',
|
||||
7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE',
|
||||
8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED',
|
||||
9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE',
|
||||
10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST',
|
||||
11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION',
|
||||
12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS',
|
||||
13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER',
|
||||
14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE',
|
||||
15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'
|
||||
];
|
||||
self::$channel_open_failure_reasons = [
|
||||
1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED'
|
||||
];
|
||||
self::$terminal_modes = [
|
||||
0 => 'NET_SSH2_TTY_OP_END'
|
||||
];
|
||||
self::$channel_extended_data_type_codes = [
|
||||
1 => 'NET_SSH2_EXTENDED_DATA_STDERR'
|
||||
];
|
||||
|
||||
$this->define_array(
|
||||
$this->message_numbers,
|
||||
$this->disconnect_reasons,
|
||||
$this->channel_open_failure_reasons,
|
||||
$this->terminal_modes,
|
||||
$this->channel_extended_data_type_codes,
|
||||
[60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'],
|
||||
[60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'],
|
||||
[60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
|
||||
61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'],
|
||||
// RFC 4419 - diffie-hellman-group-exchange-sha{1,256}
|
||||
[30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD',
|
||||
31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP',
|
||||
32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT',
|
||||
33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY',
|
||||
34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'],
|
||||
// RFC 5656 - Elliptic Curves (for curve25519-sha256@libssh.org)
|
||||
[30 => 'NET_SSH2_MSG_KEX_ECDH_INIT',
|
||||
31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY']
|
||||
);
|
||||
self::define_array(
|
||||
self::$message_numbers,
|
||||
self::$disconnect_reasons,
|
||||
self::$channel_open_failure_reasons,
|
||||
self::$terminal_modes,
|
||||
self::$channel_extended_data_type_codes,
|
||||
[60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'],
|
||||
[60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'],
|
||||
[60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
|
||||
61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'],
|
||||
// RFC 4419 - diffie-hellman-group-exchange-sha{1,256}
|
||||
[30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD',
|
||||
31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP',
|
||||
32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT',
|
||||
33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY',
|
||||
34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'],
|
||||
// RFC 5656 - Elliptic Curves (for curve25519-sha256@libssh.org)
|
||||
[30 => 'NET_SSH2_MSG_KEX_ECDH_INIT',
|
||||
31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Typehint is required due to a bug in Psalm: https://github.com/vimeo/psalm/issues/7508
|
||||
@ -1269,6 +1280,32 @@ class SSH2
|
||||
$this->send_kex_first = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* stream_select wrapper
|
||||
*
|
||||
* Quoting https://stackoverflow.com/a/14262151/569976,
|
||||
* "The general approach to `EINTR` is to simply handle the error and retry the operation again"
|
||||
*
|
||||
* This wrapper does that loop
|
||||
*/
|
||||
private static function stream_select(&$read, &$write, &$except, $seconds, $microseconds = null)
|
||||
{
|
||||
$remaining = $seconds + $microseconds / 1000000;
|
||||
$start = microtime(true);
|
||||
while (true) {
|
||||
$result = @stream_select($read, $write, $except, $seconds, $microseconds);
|
||||
if ($result !== false) {
|
||||
return $result;
|
||||
}
|
||||
$elapsed = microtime(true) - $start;
|
||||
$seconds = (int) ($remaining - floor($elapsed));
|
||||
$microseconds = (int) (1000000 * ($remaining - $seconds));
|
||||
if ($elapsed >= $remaining) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to an SSHv2 server
|
||||
*
|
||||
@ -1333,7 +1370,7 @@ class SSH2
|
||||
$start = microtime(true);
|
||||
$sec = (int) floor($this->curTimeout);
|
||||
$usec = (int) (1000000 * ($this->curTimeout - $sec));
|
||||
if (@stream_select($read, $write, $except, $sec, $usec) === false) {
|
||||
if (static::stream_select($read, $write, $except, $sec, $usec) === false) {
|
||||
throw new \RuntimeException('Connection timed out whilst receiving server identification string');
|
||||
}
|
||||
$elapsed = microtime(true) - $start;
|
||||
@ -1388,6 +1425,18 @@ class SSH2
|
||||
throw new UnableToConnectException("Cannot connect to SSH $matches[3] servers");
|
||||
}
|
||||
|
||||
// Ubuntu's OpenSSH from 5.8 to 6.9 didn't work with multiple channels. see
|
||||
// https://bugs.launchpad.net/ubuntu/+source/openssh/+bug/1334916 for more info.
|
||||
// https://lists.ubuntu.com/archives/oneiric-changes/2011-July/005772.html discusses
|
||||
// when consolekit was incorporated.
|
||||
// https://marc.info/?l=openssh-unix-dev&m=163409903417589&w=2 discusses some of the
|
||||
// issues with how Ubuntu incorporated consolekit
|
||||
$pattern = '#^SSH-2\.0-OpenSSH_([\d.]+)[^ ]* Ubuntu-.*$#';
|
||||
$match = preg_match($pattern, $this->server_identifier, $matches);
|
||||
$match = $match && version_compare('5.8', $matches[1], '<=');
|
||||
$match = $match && version_compare('6.9', $matches[1], '>=');
|
||||
$this->errorOnMultipleChannels = $match;
|
||||
|
||||
if (!$this->send_id_string_first) {
|
||||
fputs($this->fsock, $this->identifier . "\r\n");
|
||||
}
|
||||
@ -2121,7 +2170,7 @@ class SSH2
|
||||
* The $password parameter can be a plaintext password, a \phpseclib3\Crypt\RSA|EC|DSA object, a \phpseclib3\System\SSH\Agent object or an array
|
||||
*
|
||||
* @param string $username
|
||||
* @param string|AsymmetricKey|array[]|Agent|null ...$args
|
||||
* @param string|PrivateKey|array[]|Agent|null ...$args
|
||||
* @return bool
|
||||
* @see self::_login()
|
||||
*/
|
||||
@ -2146,7 +2195,7 @@ class SSH2
|
||||
* Login Helper
|
||||
*
|
||||
* @param string $username
|
||||
* @param string ...$args
|
||||
* @param string|PrivateKey|array[]|Agent|null ...$args
|
||||
* @return bool
|
||||
* @see self::_login_helper()
|
||||
*/
|
||||
@ -2664,6 +2713,16 @@ class SSH2
|
||||
throw new ConnectionClosedException('Unexpected response to publickey authentication pt 2');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the currently configured timeout
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTimeout()
|
||||
{
|
||||
return $this->timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Timeout
|
||||
*
|
||||
@ -2719,32 +2778,11 @@ class SSH2
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->in_request_pty_exec) {
|
||||
throw new \RuntimeException('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.');
|
||||
}
|
||||
//if ($this->isPTYOpen()) {
|
||||
// throw new \RuntimeException('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.');
|
||||
//}
|
||||
|
||||
// RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to
|
||||
// be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but,
|
||||
// honestly, if you're transferring more than 2GB, you probably shouldn't be using phpseclib, anyway.
|
||||
// see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
|
||||
$this->window_size_server_to_client[self::CHANNEL_EXEC] = $this->window_size;
|
||||
// 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
|
||||
// uses 0x4000, that's what will be used here, as well.
|
||||
$packet_size = 0x4000;
|
||||
|
||||
$packet = Strings::packSSH2(
|
||||
'CsN3',
|
||||
NET_SSH2_MSG_CHANNEL_OPEN,
|
||||
'session',
|
||||
self::CHANNEL_EXEC,
|
||||
$this->window_size_server_to_client[self::CHANNEL_EXEC],
|
||||
$packet_size
|
||||
);
|
||||
$this->send_binary_packet($packet);
|
||||
|
||||
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||
|
||||
$this->get_channel_packet(self::CHANNEL_EXEC);
|
||||
$this->openChannel(self::CHANNEL_EXEC);
|
||||
|
||||
if ($this->request_pty === true) {
|
||||
$terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
|
||||
@ -2769,8 +2807,6 @@ class SSH2
|
||||
$this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
throw new \RuntimeException('Unable to request pseudo-terminal');
|
||||
}
|
||||
|
||||
$this->in_request_pty_exec = true;
|
||||
}
|
||||
|
||||
// sending a pty-req SSH_MSG_CHANNEL_REQUEST message is unnecessary and, in fact, in most cases, slows things
|
||||
@ -2800,7 +2836,8 @@ class SSH2
|
||||
|
||||
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA;
|
||||
|
||||
if ($this->in_request_pty_exec) {
|
||||
if ($this->request_pty === true) {
|
||||
$this->channel_id_last_interactive = self::CHANNEL_EXEC;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2826,37 +2863,80 @@ class SSH2
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an interactive shell
|
||||
* How many channels are currently open?
|
||||
*
|
||||
* @see self::read()
|
||||
* @see self::write()
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @return int
|
||||
*/
|
||||
private function initShell()
|
||||
public function getOpenChannelCount()
|
||||
{
|
||||
if ($this->in_request_pty_exec === true) {
|
||||
return true;
|
||||
return $this->channelCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a channel
|
||||
*
|
||||
* @param string $channel
|
||||
* @param bool $skip_extended
|
||||
* @return bool
|
||||
*/
|
||||
protected function openChannel($channel, $skip_extended = false)
|
||||
{
|
||||
if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_CLOSE) {
|
||||
throw new \RuntimeException('Please close the channel (' . $channel . ') before trying to open it again');
|
||||
}
|
||||
|
||||
$this->window_size_server_to_client[self::CHANNEL_SHELL] = $this->window_size;
|
||||
$this->channelCount++;
|
||||
|
||||
if ($this->channelCount > 1 && $this->errorOnMultipleChannels) {
|
||||
throw new \RuntimeException("Ubuntu's OpenSSH from 5.8 to 6.9 doesn't work with multiple channels");
|
||||
}
|
||||
|
||||
// RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to
|
||||
// be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but,
|
||||
// honestly, if you're transferring more than 2GB, you probably shouldn't be using phpseclib, anyway.
|
||||
// see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
|
||||
$this->window_size_server_to_client[$channel] = $this->window_size;
|
||||
// 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
|
||||
// uses 0x4000, that's what will be used here, as well.
|
||||
$packet_size = 0x4000;
|
||||
|
||||
$packet = Strings::packSSH2(
|
||||
'CsN3',
|
||||
NET_SSH2_MSG_CHANNEL_OPEN,
|
||||
'session',
|
||||
self::CHANNEL_SHELL,
|
||||
$this->window_size_server_to_client[self::CHANNEL_SHELL],
|
||||
$channel,
|
||||
$this->window_size_server_to_client[$channel],
|
||||
$packet_size
|
||||
);
|
||||
|
||||
$this->send_binary_packet($packet);
|
||||
|
||||
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||
$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||
|
||||
$this->get_channel_packet(self::CHANNEL_SHELL);
|
||||
return $this->get_channel_packet($channel, $skip_extended);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an interactive shell
|
||||
*
|
||||
* Returns bool(true) if the shell was opened.
|
||||
* Returns bool(false) if the shell was already open.
|
||||
*
|
||||
* @see self::isShellOpen()
|
||||
* @see self::read()
|
||||
* @see self::write()
|
||||
* @return bool
|
||||
* @throws InsufficientSetupException if not authenticated
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
*/
|
||||
public function openShell()
|
||||
{
|
||||
if (!$this->isAuthenticated()) {
|
||||
throw new InsufficientSetupException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
$this->openChannel(self::CHANNEL_SHELL);
|
||||
|
||||
$terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
|
||||
$packet = Strings::packSSH2(
|
||||
@ -2897,14 +2977,18 @@ class SSH2
|
||||
|
||||
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
|
||||
|
||||
$this->channel_id_last_interactive = self::CHANNEL_SHELL;
|
||||
|
||||
$this->bitmap |= self::MASK_SHELL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the channel to be used with read() / write()
|
||||
*
|
||||
* Return the channel to be used with read(), write(), and reset(), if none were specified
|
||||
* @deprecated for lack of transparency in intended channel target, to be potentially replaced
|
||||
* with method which guarantees open-ness of all yielded channels and throws
|
||||
* error for multiple open channels
|
||||
* @see self::read()
|
||||
* @see self::write()
|
||||
* @return int
|
||||
@ -2912,15 +2996,26 @@ class SSH2
|
||||
private function get_interactive_channel()
|
||||
{
|
||||
switch (true) {
|
||||
case $this->in_subsystem:
|
||||
case $this->is_channel_status_data(self::CHANNEL_SUBSYSTEM):
|
||||
return self::CHANNEL_SUBSYSTEM;
|
||||
case $this->in_request_pty_exec:
|
||||
case $this->is_channel_status_data(self::CHANNEL_EXEC):
|
||||
return self::CHANNEL_EXEC;
|
||||
default:
|
||||
return self::CHANNEL_SHELL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the DATA status on the given channel
|
||||
*
|
||||
* @param int $channel The channel number to evaluate
|
||||
* @return bool
|
||||
*/
|
||||
private function is_channel_status_data($channel)
|
||||
{
|
||||
return isset($this->channel_status[$channel]) && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an available open channel
|
||||
*
|
||||
@ -2977,26 +3072,41 @@ class SSH2
|
||||
* Returns when there's a match for $expect, which can take the form of a string literal or,
|
||||
* if $mode == self::READ_REGEX, a regular expression.
|
||||
*
|
||||
* If not specifying a channel, an open interactive channel will be selected, or, if there are
|
||||
* no open channels, an interactive shell will be created. If there are multiple open
|
||||
* interactive channels, a legacy behavior will apply in which channel selection prioritizes
|
||||
* an active subsystem, the exec pty, and, lastly, the shell. If using multiple interactive
|
||||
* channels, callers are discouraged from relying on this legacy behavior and should specify
|
||||
* the intended channel.
|
||||
*
|
||||
* @see self::write()
|
||||
* @param string $expect
|
||||
* @param int $mode
|
||||
* @param int $mode One of the self::READ_* constants
|
||||
* @param int|null $channel Channel id returned by self::getInteractiveChannelId()
|
||||
* @return string|bool|null
|
||||
* @throws \RuntimeException on connection error
|
||||
* @throws InsufficientSetupException on unexpected channel status, possibly due to closure
|
||||
*/
|
||||
public function read($expect = '', $mode = self::READ_SIMPLE)
|
||||
public function read($expect = '', $mode = self::READ_SIMPLE, $channel = null)
|
||||
{
|
||||
$this->curTimeout = $this->timeout;
|
||||
$this->is_timeout = false;
|
||||
|
||||
if (!$this->isAuthenticated()) {
|
||||
throw new InsufficientSetupException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) {
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
$this->curTimeout = $this->timeout;
|
||||
$this->is_timeout = false;
|
||||
|
||||
if ($channel === null) {
|
||||
$channel = $this->get_interactive_channel();
|
||||
}
|
||||
|
||||
$channel = $this->get_interactive_channel();
|
||||
if (!$this->is_channel_status_data($channel) && empty($this->channel_buffers[$channel])) {
|
||||
if ($channel != self::CHANNEL_SHELL) {
|
||||
throw new InsufficientSetupException('Data is not available on channel');
|
||||
} elseif (!$this->openShell()) {
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
}
|
||||
}
|
||||
|
||||
if ($mode == self::READ_NEXT) {
|
||||
return $this->get_channel_packet($channel);
|
||||
@ -3014,7 +3124,6 @@ class SSH2
|
||||
}
|
||||
$response = $this->get_channel_packet($channel);
|
||||
if ($response === true) {
|
||||
$this->in_request_pty_exec = false;
|
||||
return Strings::shift($this->interactiveBuffer, strlen($this->interactiveBuffer));
|
||||
}
|
||||
|
||||
@ -3025,22 +3134,39 @@ class SSH2
|
||||
/**
|
||||
* Inputs a command into an interactive shell.
|
||||
*
|
||||
* If not specifying a channel, an open interactive channel will be selected, or, if there are
|
||||
* no open channels, an interactive shell will be created. If there are multiple open
|
||||
* interactive channels, a legacy behavior will apply in which channel selection prioritizes
|
||||
* an active subsystem, the exec pty, and, lastly, the shell. If using multiple interactive
|
||||
* channels, callers are discouraged from relying on this legacy behavior and should specify
|
||||
* the intended channel.
|
||||
*
|
||||
* @see SSH2::read()
|
||||
* @param string $cmd
|
||||
* @param int|null $channel Channel id returned by self::getInteractiveChannelId()
|
||||
* @return void
|
||||
* @throws \RuntimeException on connection error
|
||||
* @throws InsufficientSetupException on unexpected channel status, possibly due to closure
|
||||
*/
|
||||
public function write($cmd)
|
||||
public function write($cmd, $channel = null)
|
||||
{
|
||||
if (!$this->isAuthenticated()) {
|
||||
throw new InsufficientSetupException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) {
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
if ($channel === null) {
|
||||
$channel = $this->get_interactive_channel();
|
||||
}
|
||||
|
||||
$this->send_channel_packet($this->get_interactive_channel(), $cmd);
|
||||
if (!$this->is_channel_status_data($channel)) {
|
||||
if ($channel != self::CHANNEL_SHELL) {
|
||||
throw new InsufficientSetupException('Data is not available on channel');
|
||||
} elseif (!$this->openShell()) {
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
}
|
||||
}
|
||||
|
||||
$this->send_channel_packet($channel, $cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3058,22 +3184,7 @@ class SSH2
|
||||
*/
|
||||
public function startSubsystem($subsystem)
|
||||
{
|
||||
$this->window_size_server_to_client[self::CHANNEL_SUBSYSTEM] = $this->window_size;
|
||||
|
||||
$packet = Strings::packSSH2(
|
||||
'CsN3',
|
||||
NET_SSH2_MSG_CHANNEL_OPEN,
|
||||
'session',
|
||||
self::CHANNEL_SUBSYSTEM,
|
||||
$this->window_size,
|
||||
0x4000
|
||||
);
|
||||
|
||||
$this->send_binary_packet($packet);
|
||||
|
||||
$this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||
|
||||
$this->get_channel_packet(self::CHANNEL_SUBSYSTEM);
|
||||
$this->openChannel(self::CHANNEL_SUBSYSTEM);
|
||||
|
||||
$packet = Strings::packSSH2(
|
||||
'CNsCs',
|
||||
@ -3093,8 +3204,7 @@ class SSH2
|
||||
|
||||
$this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA;
|
||||
|
||||
$this->bitmap |= self::MASK_SHELL;
|
||||
$this->in_subsystem = true;
|
||||
$this->channel_id_last_interactive = self::CHANNEL_SUBSYSTEM;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -3107,8 +3217,9 @@ class SSH2
|
||||
*/
|
||||
public function stopSubsystem()
|
||||
{
|
||||
$this->in_subsystem = false;
|
||||
$this->close_channel(self::CHANNEL_SUBSYSTEM);
|
||||
if ($this->isInteractiveChannelOpen(self::CHANNEL_SUBSYSTEM)) {
|
||||
$this->close_channel(self::CHANNEL_SUBSYSTEM);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3117,10 +3228,23 @@ class SSH2
|
||||
*
|
||||
* If read() timed out you might want to just close the channel and have it auto-restart on the next read() call
|
||||
*
|
||||
* If not specifying a channel, an open interactive channel will be selected. If there are
|
||||
* multiple open interactive channels, a legacy behavior will apply in which channel selection
|
||||
* prioritizes an active subsystem, the exec pty, and, lastly, the shell. If using multiple
|
||||
* interactive channels, callers are discouraged from relying on this legacy behavior and
|
||||
* should specify the intended channel.
|
||||
*
|
||||
* @param int|null $channel Channel id returned by self::getInteractiveChannelId()
|
||||
* @return void
|
||||
*/
|
||||
public function reset()
|
||||
public function reset($channel = null)
|
||||
{
|
||||
$this->close_channel($this->get_interactive_channel());
|
||||
if ($channel === null) {
|
||||
$channel = $this->get_interactive_channel();
|
||||
}
|
||||
if ($this->isInteractiveChannelOpen($channel)) {
|
||||
$this->close_channel($channel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3166,7 +3290,7 @@ class SSH2
|
||||
*/
|
||||
public function isConnected()
|
||||
{
|
||||
return (bool) ($this->bitmap & self::MASK_CONNECTED);
|
||||
return ($this->bitmap & self::MASK_CONNECTED) && is_resource($this->fsock) && !feof($this->fsock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3179,6 +3303,49 @@ class SSH2
|
||||
return (bool) ($this->bitmap & self::MASK_LOGIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the interactive shell active?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isShellOpen()
|
||||
{
|
||||
return $this->isInteractiveChannelOpen(self::CHANNEL_SHELL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the exec pty active?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPTYOpen()
|
||||
{
|
||||
return $this->isInteractiveChannelOpen(self::CHANNEL_EXEC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the given interactive channel active?
|
||||
*
|
||||
* @param int $channel Channel id returned by self::getInteractiveChannelId()
|
||||
* @return bool
|
||||
*/
|
||||
public function isInteractiveChannelOpen($channel)
|
||||
{
|
||||
return $this->isAuthenticated() && $this->is_channel_status_data($channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a channel identifier, presently of the last interactive channel opened, regardless of current status.
|
||||
* Returns 0 if no interactive channel has been opened.
|
||||
*
|
||||
* @see self::isInteractiveChannelOpen()
|
||||
* @return int
|
||||
*/
|
||||
public function getInteractiveChannelId()
|
||||
{
|
||||
return $this->channel_id_last_interactive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pings a server connection, or tries to reconnect if the connection has gone down
|
||||
*
|
||||
@ -3195,23 +3362,8 @@ class SSH2
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->window_size_server_to_client[self::CHANNEL_KEEP_ALIVE] = $this->window_size;
|
||||
$packet_size = 0x4000;
|
||||
$packet = Strings::packSSH2(
|
||||
'CsN3',
|
||||
NET_SSH2_MSG_CHANNEL_OPEN,
|
||||
'session',
|
||||
self::CHANNEL_KEEP_ALIVE,
|
||||
$this->window_size_server_to_client[self::CHANNEL_KEEP_ALIVE],
|
||||
$packet_size
|
||||
);
|
||||
|
||||
try {
|
||||
$this->send_binary_packet($packet);
|
||||
|
||||
$this->channel_status[self::CHANNEL_KEEP_ALIVE] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||
|
||||
$response = $this->get_channel_packet(self::CHANNEL_KEEP_ALIVE);
|
||||
$this->openChannel(self::CHANNEL_KEEP_ALIVE);
|
||||
} catch (\RuntimeException $e) {
|
||||
return $this->reconnect();
|
||||
}
|
||||
@ -3273,9 +3425,9 @@ class SSH2
|
||||
|
||||
if (!$this->curTimeout) {
|
||||
if ($this->keepAlive <= 0) {
|
||||
@stream_select($read, $write, $except, null);
|
||||
static::stream_select($read, $write, $except, null);
|
||||
} else {
|
||||
if (!@stream_select($read, $write, $except, $this->keepAlive)) {
|
||||
if (!static::stream_select($read, $write, $except, $this->keepAlive)) {
|
||||
$this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
|
||||
return $this->get_binary_packet(true);
|
||||
}
|
||||
@ -3289,7 +3441,7 @@ class SSH2
|
||||
$start = microtime(true);
|
||||
|
||||
if ($this->keepAlive > 0 && $this->keepAlive < $this->curTimeout) {
|
||||
if (!@stream_select($read, $write, $except, $this->keepAlive)) {
|
||||
if (!static::stream_select($read, $write, $except, $this->keepAlive)) {
|
||||
$this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
|
||||
$elapsed = microtime(true) - $start;
|
||||
$this->curTimeout -= $elapsed;
|
||||
@ -3303,7 +3455,7 @@ class SSH2
|
||||
$usec = (int) (1000000 * ($this->curTimeout - $sec));
|
||||
|
||||
// this can return a "stream_select(): unable to select [4]: Interrupted system call" error
|
||||
if (!@stream_select($read, $write, $except, $sec, $usec)) {
|
||||
if (!static::stream_select($read, $write, $except, $sec, $usec)) {
|
||||
$this->is_timeout = true;
|
||||
return true;
|
||||
}
|
||||
@ -3494,7 +3646,7 @@ class SSH2
|
||||
|
||||
if (defined('NET_SSH2_LOGGING')) {
|
||||
$current = microtime(true);
|
||||
$message_number = isset($this->message_numbers[ord($payload[0])]) ? $this->message_numbers[ord($payload[0])] : 'UNKNOWN (' . ord($payload[0]) . ')';
|
||||
$message_number = isset(self::$message_numbers[ord($payload[0])]) ? self::$message_numbers[ord($payload[0])] : 'UNKNOWN (' . ord($payload[0]) . ')';
|
||||
$message_number = '<- ' . $message_number .
|
||||
' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
|
||||
$this->append_log($message_number, $payload);
|
||||
@ -3576,7 +3728,7 @@ class SSH2
|
||||
case NET_SSH2_MSG_DISCONNECT:
|
||||
Strings::shift($payload, 1);
|
||||
list($reason_code, $message) = Strings::unpackSSH2('Ns', $payload);
|
||||
$this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n$message";
|
||||
$this->errors[] = 'SSH_MSG_DISCONNECT: ' . self::$disconnect_reasons[$reason_code] . "\r\n$message";
|
||||
$this->bitmap = 0;
|
||||
return false;
|
||||
case NET_SSH2_MSG_IGNORE:
|
||||
@ -3763,9 +3915,8 @@ class SSH2
|
||||
*/
|
||||
public function disablePTY()
|
||||
{
|
||||
if ($this->in_request_pty_exec) {
|
||||
if ($this->isPTYOpen()) {
|
||||
$this->close_channel(self::CHANNEL_EXEC);
|
||||
$this->in_request_pty_exec = false;
|
||||
}
|
||||
$this->request_pty = false;
|
||||
}
|
||||
@ -3791,6 +3942,7 @@ class SSH2
|
||||
* - if the connection times out
|
||||
* - if the channel status is CHANNEL_OPEN and the response was CHANNEL_OPEN_CONFIRMATION
|
||||
* - if the channel status is CHANNEL_REQUEST and the response was CHANNEL_SUCCESS
|
||||
* - if the channel status is CHANNEL_CLOSE and the response was CHANNEL_CLOSE
|
||||
*
|
||||
* bool(false) is returned if:
|
||||
*
|
||||
@ -3958,7 +4110,10 @@ class SSH2
|
||||
throw new \RuntimeException('Unable to fulfill channel request');
|
||||
}
|
||||
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
||||
return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->get_channel_packet($client_channel, $skip_extended);
|
||||
if ($client_channel == $channel && $type == NET_SSH2_MSG_CHANNEL_CLOSE) {
|
||||
return true;
|
||||
}
|
||||
return $this->get_channel_packet($client_channel, $skip_extended);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3993,14 +4148,15 @@ class SSH2
|
||||
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
||||
$this->curTimeout = 5;
|
||||
|
||||
if ($this->bitmap & self::MASK_SHELL) {
|
||||
$this->bitmap &= ~self::MASK_SHELL;
|
||||
}
|
||||
$this->close_channel_bitmap($channel);
|
||||
|
||||
if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) {
|
||||
$this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
|
||||
}
|
||||
|
||||
$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
|
||||
$this->channelCount--;
|
||||
|
||||
if ($client_channel == $channel) {
|
||||
return true;
|
||||
}
|
||||
@ -4147,7 +4303,7 @@ class SSH2
|
||||
|
||||
if (defined('NET_SSH2_LOGGING')) {
|
||||
$current = microtime(true);
|
||||
$message_number = isset($this->message_numbers[ord($logged[0])]) ? $this->message_numbers[ord($logged[0])] : 'UNKNOWN (' . ord($logged[0]) . ')';
|
||||
$message_number = isset(self::$message_numbers[ord($logged[0])]) ? self::$message_numbers[ord($logged[0])] : 'UNKNOWN (' . ord($logged[0]) . ')';
|
||||
$message_number = '-> ' . $message_number .
|
||||
' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
|
||||
$this->append_log($message_number, $logged);
|
||||
@ -4156,7 +4312,10 @@ class SSH2
|
||||
|
||||
if (strlen($packet) != $sent) {
|
||||
$this->bitmap = 0;
|
||||
throw new \RuntimeException("Only $sent of " . strlen($packet) . " bytes were sent");
|
||||
$message = $sent === false ?
|
||||
'Unable to write ' . strlen($packet) . ' bytes' :
|
||||
"Only $sent of " . strlen($packet) . " bytes were sent";
|
||||
throw new \RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4332,22 +4491,36 @@ class SSH2
|
||||
}
|
||||
|
||||
$this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
|
||||
$this->channelCount--;
|
||||
|
||||
$this->curTimeout = 5;
|
||||
|
||||
while (!is_bool($this->get_channel_packet($client_channel))) {
|
||||
}
|
||||
|
||||
if ($this->is_timeout) {
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
if ($want_reply) {
|
||||
$this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
|
||||
}
|
||||
|
||||
if ($this->bitmap & self::MASK_SHELL) {
|
||||
$this->bitmap &= ~self::MASK_SHELL;
|
||||
$this->close_channel_bitmap($client_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maintains execution state bitmap in response to channel closure
|
||||
*
|
||||
* @param int $client_channel The channel number to maintain closure status of
|
||||
* @return void
|
||||
*/
|
||||
private function close_channel_bitmap($client_channel)
|
||||
{
|
||||
switch ($client_channel) {
|
||||
case self::CHANNEL_SHELL:
|
||||
// Shell status has been maintained in the bitmap for backwards
|
||||
// compatibility sake, but can be removed going forward
|
||||
if ($this->bitmap & self::MASK_SHELL) {
|
||||
$this->bitmap &= ~self::MASK_SHELL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4385,7 +4558,7 @@ class SSH2
|
||||
* @param mixed[] ...$args
|
||||
* @access protected
|
||||
*/
|
||||
protected function define_array(...$args)
|
||||
protected static function define_array(...$args)
|
||||
{
|
||||
foreach ($args as $arg) {
|
||||
foreach ($arg as $key => $value) {
|
||||
@ -4790,6 +4963,14 @@ class SSH2
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Force multiple channels (even if phpseclib has decided to disable them)
|
||||
*/
|
||||
public function forceMultipleChannels()
|
||||
{
|
||||
$this->errorOnMultipleChannels = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows you to set the terminal
|
||||
*
|
||||
|
10
script.php
10
script.php
@ -6146,9 +6146,9 @@ class com_componentbuilderInstallerScript
|
||||
$joomla_component->type_title = 'Componentbuilder Joomla_component';
|
||||
$joomla_component->type_alias = 'com_componentbuilder.joomla_component';
|
||||
$joomla_component->table = '{"special": {"dbtable": "#__componentbuilder_joomla_component","key": "id","type": "Joomla_component","prefix": "componentbuilderTable","config": "array()"},"common": {"dbtable": "#__ucm_content","key": "ucm_id","type": "Corecontent","prefix": "JTable","config": "array()"}}';
|
||||
$joomla_component->field_mappings = '{"common": {"core_content_item_id": "id","core_title": "system_name","core_state": "published","core_alias": "null","core_created_time": "created","core_modified_time": "modified","core_body": "php_helper_both","core_hits": "hits","core_publish_up": "null","core_publish_down": "null","core_access": "access","core_params": "params","core_featured": "null","core_metadata": "metadata","core_language": "null","core_images": "null","core_urls": "null","core_version": "version","core_ordering": "ordering","core_metakey": "metakey","core_metadesc": "metadesc","core_catid": "null","core_xreference": "null","asset_id": "asset_id"},"special": {"system_name":"system_name","name_code":"name_code","short_description":"short_description","companyname":"companyname","php_helper_both":"php_helper_both","crowdin_project_identifier":"crowdin_project_identifier","php_method_uninstall":"php_method_uninstall","php_preflight_install":"php_preflight_install","css_admin":"css_admin","mvc_versiondate":"mvc_versiondate","remove_line_breaks":"remove_line_breaks","add_placeholders":"add_placeholders","php_admin_event":"php_admin_event","php_site_event":"php_site_event","description":"description","author":"author","php_postflight_install":"php_postflight_install","email":"email","sql_uninstall":"sql_uninstall","website":"website","debug_linenr":"debug_linenr","add_license":"add_license","license_type":"license_type","add_email_helper":"add_email_helper","php_helper_admin":"php_helper_admin","whmcs_key":"whmcs_key","php_helper_site":"php_helper_site","whmcs_url":"whmcs_url","javascript":"javascript","whmcs_buy_link":"whmcs_buy_link","css_site":"css_site","license":"license","bom":"bom","php_preflight_update":"php_preflight_update","image":"image","php_postflight_update":"php_postflight_update","copyright":"copyright","sql":"sql","addreadme":"addreadme","add_sales_server":"add_sales_server","update_server_url":"update_server_url","component_version":"component_version","add_powers":"add_powers","translation_tool":"translation_tool","crowdin_username":"crowdin_username","buildcompsql":"buildcompsql","add_php_helper_both":"add_php_helper_both","add_php_helper_admin":"add_php_helper_admin","add_admin_event":"add_admin_event","add_php_helper_site":"add_php_helper_site","add_site_event":"add_site_event","add_javascript":"add_javascript","add_menu_prefix":"add_menu_prefix","add_css_admin":"add_css_admin","menu_prefix":"menu_prefix","add_css_site":"add_css_site","dashboard_type":"dashboard_type","dashboard":"dashboard","toignore":"toignore","add_php_preflight_install":"add_php_preflight_install","add_php_preflight_update":"add_php_preflight_update","add_php_postflight_install":"add_php_postflight_install","export_key":"export_key","add_php_postflight_update":"add_php_postflight_update","joomla_source_link":"joomla_source_link","add_php_method_uninstall":"add_php_method_uninstall","export_buy_link":"export_buy_link","add_sql":"add_sql","add_sql_uninstall":"add_sql_uninstall","assets_table_fix":"assets_table_fix","readme":"readme","emptycontributors":"emptycontributors","add_update_server":"add_update_server","number":"number","update_server_target":"update_server_target","update_server":"update_server","sales_server":"sales_server","crowdin_project_api_key":"crowdin_project_api_key","crowdin_account_api_key":"crowdin_account_api_key","creatuserhelper":"creatuserhelper","buildcomp":"buildcomp","adduikit":"adduikit","guid":"guid","addfootable":"addfootable","name":"name"}}';
|
||||
$joomla_component->field_mappings = '{"common": {"core_content_item_id": "id","core_title": "system_name","core_state": "published","core_alias": "null","core_created_time": "created","core_modified_time": "modified","core_body": "css_admin","core_hits": "hits","core_publish_up": "null","core_publish_down": "null","core_access": "access","core_params": "params","core_featured": "null","core_metadata": "metadata","core_language": "null","core_images": "null","core_urls": "null","core_version": "version","core_ordering": "ordering","core_metakey": "metakey","core_metadesc": "metadesc","core_catid": "null","core_xreference": "null","asset_id": "asset_id"},"special": {"system_name":"system_name","name_code":"name_code","short_description":"short_description","companyname":"companyname","css_admin":"css_admin","php_admin_event":"php_admin_event","php_site_event":"php_site_event","crowdin_username":"crowdin_username","component_version":"component_version","php_postflight_install":"php_postflight_install","remove_line_breaks":"remove_line_breaks","description":"description","sql_uninstall":"sql_uninstall","debug_linenr":"debug_linenr","mvc_versiondate":"mvc_versiondate","php_preflight_install":"php_preflight_install","backup_folder_path":"backup_folder_path","php_method_uninstall":"php_method_uninstall","add_placeholders":"add_placeholders","author":"author","add_sales_server":"add_sales_server","email":"email","translation_tool":"translation_tool","website":"website","buildcompsql":"buildcompsql","add_license":"add_license","php_helper_admin":"php_helper_admin","license_type":"license_type","php_helper_site":"php_helper_site","javascript":"javascript","whmcs_key":"whmcs_key","css_site":"css_site","whmcs_url":"whmcs_url","whmcs_buy_link":"whmcs_buy_link","php_preflight_update":"php_preflight_update","license":"license","php_postflight_update":"php_postflight_update","bom":"bom","sql":"sql","image":"image","addreadme":"addreadme","copyright":"copyright","update_server_url":"update_server_url","add_powers":"add_powers","add_backup_folder_path":"add_backup_folder_path","crowdin_project_identifier":"crowdin_project_identifier","add_php_helper_admin":"add_php_helper_admin","add_admin_event":"add_admin_event","add_php_helper_site":"add_php_helper_site","add_site_event":"add_site_event","add_javascript":"add_javascript","add_menu_prefix":"add_menu_prefix","add_css_admin":"add_css_admin","menu_prefix":"menu_prefix","add_css_site":"add_css_site","dashboard_type":"dashboard_type","dashboard":"dashboard","toignore":"toignore","add_php_preflight_install":"add_php_preflight_install","add_php_preflight_update":"add_php_preflight_update","add_php_postflight_install":"add_php_postflight_install","export_key":"export_key","add_php_postflight_update":"add_php_postflight_update","joomla_source_link":"joomla_source_link","add_php_method_uninstall":"add_php_method_uninstall","export_buy_link":"export_buy_link","add_sql":"add_sql","add_sql_uninstall":"add_sql_uninstall","assets_table_fix":"assets_table_fix","readme":"readme","emptycontributors":"emptycontributors","add_update_server":"add_update_server","number":"number","update_server_target":"update_server_target","update_server":"update_server","sales_server":"sales_server","add_git_folder_path":"add_git_folder_path","git_folder_path":"git_folder_path","creatuserhelper":"creatuserhelper","adduikit":"adduikit","crowdin_project_api_key":"crowdin_project_api_key","addfootable":"addfootable","crowdin_account_api_key":"crowdin_account_api_key","add_email_helper":"add_email_helper","buildcomp":"buildcomp","add_php_helper_both":"add_php_helper_both","guid":"guid","php_helper_both":"php_helper_both","name":"name"}}';
|
||||
$joomla_component->router = 'ComponentbuilderHelperRoute::getJoomla_componentRoute';
|
||||
$joomla_component->content_history_options = '{"formFile": "administrator/components/com_componentbuilder/models/forms/joomla_component.xml","hideFields": ["asset_id","checked_out","checked_out_time","version"],"ignoreChanges": ["modified_by","modified","checked_out","checked_out_time","version","hits"],"convertToInt": ["published","ordering","mvc_versiondate","remove_line_breaks","add_placeholders","debug_linenr","add_license","license_type","add_email_helper","addreadme","add_sales_server","add_powers","translation_tool","add_php_helper_both","add_php_helper_admin","add_admin_event","add_php_helper_site","add_site_event","add_javascript","add_css_admin","add_css_site","dashboard_type","add_php_preflight_install","add_php_preflight_update","add_php_postflight_install","add_php_postflight_update","add_php_method_uninstall","add_sql","add_sql_uninstall","assets_table_fix","emptycontributors","add_update_server","number","update_server_target","update_server","sales_server","creatuserhelper","buildcomp","adduikit","addfootable"],"displayLookup": [{"sourceColumn": "created_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "access","targetTable": "#__viewlevels","targetColumn": "id","displayColumn": "title"},{"sourceColumn": "modified_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "dashboard","targetTable": "#__componentbuilder_custom_admin_view","targetColumn": "","displayColumn": "system_name"},{"sourceColumn": "update_server","targetTable": "#__componentbuilder_server","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "sales_server","targetTable": "#__componentbuilder_server","targetColumn": "id","displayColumn": "name"}]}';
|
||||
$joomla_component->content_history_options = '{"formFile": "administrator/components/com_componentbuilder/models/forms/joomla_component.xml","hideFields": ["asset_id","checked_out","checked_out_time","version"],"ignoreChanges": ["modified_by","modified","checked_out","checked_out_time","version","hits"],"convertToInt": ["published","ordering","remove_line_breaks","debug_linenr","mvc_versiondate","add_placeholders","add_sales_server","translation_tool","add_license","license_type","addreadme","add_powers","add_backup_folder_path","add_php_helper_admin","add_admin_event","add_php_helper_site","add_site_event","add_javascript","add_css_admin","add_css_site","dashboard_type","add_php_preflight_install","add_php_preflight_update","add_php_postflight_install","add_php_postflight_update","add_php_method_uninstall","add_sql","add_sql_uninstall","assets_table_fix","emptycontributors","add_update_server","number","update_server_target","update_server","sales_server","add_git_folder_path","creatuserhelper","adduikit","addfootable","add_email_helper","buildcomp","add_php_helper_both"],"displayLookup": [{"sourceColumn": "created_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "access","targetTable": "#__viewlevels","targetColumn": "id","displayColumn": "title"},{"sourceColumn": "modified_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "dashboard","targetTable": "#__componentbuilder_custom_admin_view","targetColumn": "","displayColumn": "system_name"},{"sourceColumn": "update_server","targetTable": "#__componentbuilder_server","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "sales_server","targetTable": "#__componentbuilder_server","targetColumn": "id","displayColumn": "name"}]}';
|
||||
|
||||
// Set the object into the content types table.
|
||||
$joomla_component_Inserted = $db->insertObject('#__content_types', $joomla_component);
|
||||
@ -7616,9 +7616,9 @@ class com_componentbuilderInstallerScript
|
||||
$joomla_component->type_title = 'Componentbuilder Joomla_component';
|
||||
$joomla_component->type_alias = 'com_componentbuilder.joomla_component';
|
||||
$joomla_component->table = '{"special": {"dbtable": "#__componentbuilder_joomla_component","key": "id","type": "Joomla_component","prefix": "componentbuilderTable","config": "array()"},"common": {"dbtable": "#__ucm_content","key": "ucm_id","type": "Corecontent","prefix": "JTable","config": "array()"}}';
|
||||
$joomla_component->field_mappings = '{"common": {"core_content_item_id": "id","core_title": "system_name","core_state": "published","core_alias": "null","core_created_time": "created","core_modified_time": "modified","core_body": "php_helper_both","core_hits": "hits","core_publish_up": "null","core_publish_down": "null","core_access": "access","core_params": "params","core_featured": "null","core_metadata": "metadata","core_language": "null","core_images": "null","core_urls": "null","core_version": "version","core_ordering": "ordering","core_metakey": "metakey","core_metadesc": "metadesc","core_catid": "null","core_xreference": "null","asset_id": "asset_id"},"special": {"system_name":"system_name","name_code":"name_code","short_description":"short_description","companyname":"companyname","php_helper_both":"php_helper_both","crowdin_project_identifier":"crowdin_project_identifier","php_method_uninstall":"php_method_uninstall","php_preflight_install":"php_preflight_install","css_admin":"css_admin","mvc_versiondate":"mvc_versiondate","remove_line_breaks":"remove_line_breaks","add_placeholders":"add_placeholders","php_admin_event":"php_admin_event","php_site_event":"php_site_event","description":"description","author":"author","php_postflight_install":"php_postflight_install","email":"email","sql_uninstall":"sql_uninstall","website":"website","debug_linenr":"debug_linenr","add_license":"add_license","license_type":"license_type","add_email_helper":"add_email_helper","php_helper_admin":"php_helper_admin","whmcs_key":"whmcs_key","php_helper_site":"php_helper_site","whmcs_url":"whmcs_url","javascript":"javascript","whmcs_buy_link":"whmcs_buy_link","css_site":"css_site","license":"license","bom":"bom","php_preflight_update":"php_preflight_update","image":"image","php_postflight_update":"php_postflight_update","copyright":"copyright","sql":"sql","addreadme":"addreadme","add_sales_server":"add_sales_server","update_server_url":"update_server_url","component_version":"component_version","add_powers":"add_powers","translation_tool":"translation_tool","crowdin_username":"crowdin_username","buildcompsql":"buildcompsql","add_php_helper_both":"add_php_helper_both","add_php_helper_admin":"add_php_helper_admin","add_admin_event":"add_admin_event","add_php_helper_site":"add_php_helper_site","add_site_event":"add_site_event","add_javascript":"add_javascript","add_menu_prefix":"add_menu_prefix","add_css_admin":"add_css_admin","menu_prefix":"menu_prefix","add_css_site":"add_css_site","dashboard_type":"dashboard_type","dashboard":"dashboard","toignore":"toignore","add_php_preflight_install":"add_php_preflight_install","add_php_preflight_update":"add_php_preflight_update","add_php_postflight_install":"add_php_postflight_install","export_key":"export_key","add_php_postflight_update":"add_php_postflight_update","joomla_source_link":"joomla_source_link","add_php_method_uninstall":"add_php_method_uninstall","export_buy_link":"export_buy_link","add_sql":"add_sql","add_sql_uninstall":"add_sql_uninstall","assets_table_fix":"assets_table_fix","readme":"readme","emptycontributors":"emptycontributors","add_update_server":"add_update_server","number":"number","update_server_target":"update_server_target","update_server":"update_server","sales_server":"sales_server","crowdin_project_api_key":"crowdin_project_api_key","crowdin_account_api_key":"crowdin_account_api_key","creatuserhelper":"creatuserhelper","buildcomp":"buildcomp","adduikit":"adduikit","guid":"guid","addfootable":"addfootable","name":"name"}}';
|
||||
$joomla_component->field_mappings = '{"common": {"core_content_item_id": "id","core_title": "system_name","core_state": "published","core_alias": "null","core_created_time": "created","core_modified_time": "modified","core_body": "css_admin","core_hits": "hits","core_publish_up": "null","core_publish_down": "null","core_access": "access","core_params": "params","core_featured": "null","core_metadata": "metadata","core_language": "null","core_images": "null","core_urls": "null","core_version": "version","core_ordering": "ordering","core_metakey": "metakey","core_metadesc": "metadesc","core_catid": "null","core_xreference": "null","asset_id": "asset_id"},"special": {"system_name":"system_name","name_code":"name_code","short_description":"short_description","companyname":"companyname","css_admin":"css_admin","php_admin_event":"php_admin_event","php_site_event":"php_site_event","crowdin_username":"crowdin_username","component_version":"component_version","php_postflight_install":"php_postflight_install","remove_line_breaks":"remove_line_breaks","description":"description","sql_uninstall":"sql_uninstall","debug_linenr":"debug_linenr","mvc_versiondate":"mvc_versiondate","php_preflight_install":"php_preflight_install","backup_folder_path":"backup_folder_path","php_method_uninstall":"php_method_uninstall","add_placeholders":"add_placeholders","author":"author","add_sales_server":"add_sales_server","email":"email","translation_tool":"translation_tool","website":"website","buildcompsql":"buildcompsql","add_license":"add_license","php_helper_admin":"php_helper_admin","license_type":"license_type","php_helper_site":"php_helper_site","javascript":"javascript","whmcs_key":"whmcs_key","css_site":"css_site","whmcs_url":"whmcs_url","whmcs_buy_link":"whmcs_buy_link","php_preflight_update":"php_preflight_update","license":"license","php_postflight_update":"php_postflight_update","bom":"bom","sql":"sql","image":"image","addreadme":"addreadme","copyright":"copyright","update_server_url":"update_server_url","add_powers":"add_powers","add_backup_folder_path":"add_backup_folder_path","crowdin_project_identifier":"crowdin_project_identifier","add_php_helper_admin":"add_php_helper_admin","add_admin_event":"add_admin_event","add_php_helper_site":"add_php_helper_site","add_site_event":"add_site_event","add_javascript":"add_javascript","add_menu_prefix":"add_menu_prefix","add_css_admin":"add_css_admin","menu_prefix":"menu_prefix","add_css_site":"add_css_site","dashboard_type":"dashboard_type","dashboard":"dashboard","toignore":"toignore","add_php_preflight_install":"add_php_preflight_install","add_php_preflight_update":"add_php_preflight_update","add_php_postflight_install":"add_php_postflight_install","export_key":"export_key","add_php_postflight_update":"add_php_postflight_update","joomla_source_link":"joomla_source_link","add_php_method_uninstall":"add_php_method_uninstall","export_buy_link":"export_buy_link","add_sql":"add_sql","add_sql_uninstall":"add_sql_uninstall","assets_table_fix":"assets_table_fix","readme":"readme","emptycontributors":"emptycontributors","add_update_server":"add_update_server","number":"number","update_server_target":"update_server_target","update_server":"update_server","sales_server":"sales_server","add_git_folder_path":"add_git_folder_path","git_folder_path":"git_folder_path","creatuserhelper":"creatuserhelper","adduikit":"adduikit","crowdin_project_api_key":"crowdin_project_api_key","addfootable":"addfootable","crowdin_account_api_key":"crowdin_account_api_key","add_email_helper":"add_email_helper","buildcomp":"buildcomp","add_php_helper_both":"add_php_helper_both","guid":"guid","php_helper_both":"php_helper_both","name":"name"}}';
|
||||
$joomla_component->router = 'ComponentbuilderHelperRoute::getJoomla_componentRoute';
|
||||
$joomla_component->content_history_options = '{"formFile": "administrator/components/com_componentbuilder/models/forms/joomla_component.xml","hideFields": ["asset_id","checked_out","checked_out_time","version"],"ignoreChanges": ["modified_by","modified","checked_out","checked_out_time","version","hits"],"convertToInt": ["published","ordering","mvc_versiondate","remove_line_breaks","add_placeholders","debug_linenr","add_license","license_type","add_email_helper","addreadme","add_sales_server","add_powers","translation_tool","add_php_helper_both","add_php_helper_admin","add_admin_event","add_php_helper_site","add_site_event","add_javascript","add_css_admin","add_css_site","dashboard_type","add_php_preflight_install","add_php_preflight_update","add_php_postflight_install","add_php_postflight_update","add_php_method_uninstall","add_sql","add_sql_uninstall","assets_table_fix","emptycontributors","add_update_server","number","update_server_target","update_server","sales_server","creatuserhelper","buildcomp","adduikit","addfootable"],"displayLookup": [{"sourceColumn": "created_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "access","targetTable": "#__viewlevels","targetColumn": "id","displayColumn": "title"},{"sourceColumn": "modified_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "dashboard","targetTable": "#__componentbuilder_custom_admin_view","targetColumn": "","displayColumn": "system_name"},{"sourceColumn": "update_server","targetTable": "#__componentbuilder_server","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "sales_server","targetTable": "#__componentbuilder_server","targetColumn": "id","displayColumn": "name"}]}';
|
||||
$joomla_component->content_history_options = '{"formFile": "administrator/components/com_componentbuilder/models/forms/joomla_component.xml","hideFields": ["asset_id","checked_out","checked_out_time","version"],"ignoreChanges": ["modified_by","modified","checked_out","checked_out_time","version","hits"],"convertToInt": ["published","ordering","remove_line_breaks","debug_linenr","mvc_versiondate","add_placeholders","add_sales_server","translation_tool","add_license","license_type","addreadme","add_powers","add_backup_folder_path","add_php_helper_admin","add_admin_event","add_php_helper_site","add_site_event","add_javascript","add_css_admin","add_css_site","dashboard_type","add_php_preflight_install","add_php_preflight_update","add_php_postflight_install","add_php_postflight_update","add_php_method_uninstall","add_sql","add_sql_uninstall","assets_table_fix","emptycontributors","add_update_server","number","update_server_target","update_server","sales_server","add_git_folder_path","creatuserhelper","adduikit","addfootable","add_email_helper","buildcomp","add_php_helper_both"],"displayLookup": [{"sourceColumn": "created_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "access","targetTable": "#__viewlevels","targetColumn": "id","displayColumn": "title"},{"sourceColumn": "modified_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "dashboard","targetTable": "#__componentbuilder_custom_admin_view","targetColumn": "","displayColumn": "system_name"},{"sourceColumn": "update_server","targetTable": "#__componentbuilder_server","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "sales_server","targetTable": "#__componentbuilder_server","targetColumn": "id","displayColumn": "name"}]}';
|
||||
|
||||
// Check if joomla_component type is already in content_type DB.
|
||||
$joomla_component_id = null;
|
||||
@ -9437,7 +9437,7 @@ class com_componentbuilderInstallerScript
|
||||
echo '<a target="_blank" href="https://dev.vdm.io" title="Component Builder">
|
||||
<img src="components/com_componentbuilder/assets/images/vdm-component.jpg"/>
|
||||
</a>
|
||||
<h3>Upgrade to Version 3.1.27 Was Successful! Let us know if anything is not working as expected.</h3>';
|
||||
<h3>Upgrade to Version 3.1.28 Was Successful! Let us know if anything is not working as expected.</h3>';
|
||||
|
||||
// Set db if not set already.
|
||||
if (!isset($db))
|
||||
|
@ -67,8 +67,12 @@ COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BUILDER_BACKUP_KEY="Joomla Component Build
|
||||
COM_COMPONENTBUILDER_KEY_HAS_NOT_CHANGED="Key has not changed"
|
||||
COM_COMPONENTBUILDER_LICENSE_S="License: %s"
|
||||
COM_COMPONENTBUILDER_LINK="Link"
|
||||
COM_COMPONENTBUILDER_LOADING_THE_PRIVATE_KEY_FILE_FAILED="Loading the private key file failed"
|
||||
COM_COMPONENTBUILDER_LOADING_THE_PRIVATE_KEY_TEXT_FAILED="Loading the private key text failed"
|
||||
COM_COMPONENTBUILDER_LOCAL="Local"
|
||||
COM_COMPONENTBUILDER_LOGIN_FAILED="Login failed"
|
||||
COM_COMPONENTBUILDER_MODULE="Module"
|
||||
COM_COMPONENTBUILDER_MOVING_OF_THE_S_FAILED="Moving of the %s failed"
|
||||
COM_COMPONENTBUILDER_NEW="New"
|
||||
COM_COMPONENTBUILDER_NONE="None"
|
||||
COM_COMPONENTBUILDER_NOT_FOUND_OR_ACCESS_DENIED="Not found or access denied!"
|
||||
|
Loading…
Reference in New Issue
Block a user