bug fix: fix opendkim on config rest

This commit is contained in:
usmannasir
2024-01-06 15:11:55 +05:00
parent 0e5995566b
commit f895bd5e1e
7 changed files with 275 additions and 174 deletions

View File

@@ -5,6 +5,7 @@ import json
import re import re
from loginSystem.models import Administrator from loginSystem.models import Administrator
class secMiddleware: class secMiddleware:
HIGH = 0 HIGH = 0
LOW = 1 LOW = 1
@@ -52,7 +53,7 @@ class secMiddleware:
if request.method == 'POST': if request.method == 'POST':
try: try:
#logging.writeToFile(request.body) # logging.writeToFile(request.body)
data = json.loads(request.body) data = json.loads(request.body)
for key, value in data.items(): for key, value in data.items():
if request.path.find('gitNotify') > -1: if request.path.find('gitNotify') > -1:
@@ -78,7 +79,8 @@ class secMiddleware:
continue continue
if key == 'backupDestinations': if key == 'backupDestinations':
if re.match('^[a-z|0-9]+:[a-z|0-9|\.]+\/?[A-Z|a-z|0-9|\.]*$', value) == None and value != 'local': if re.match('^[a-z|0-9]+:[a-z|0-9|\.]+\/?[A-Z|a-z|0-9|\.]*$',
value) == None and value != 'local':
logging.writeToFile(request.body) logging.writeToFile(request.body)
final_dic = {'error_message': "Data supplied is not accepted.", final_dic = {'error_message': "Data supplied is not accepted.",
"errorMessage": "Data supplied is not accepted."} "errorMessage": "Data supplied is not accepted."}
@@ -87,14 +89,14 @@ class secMiddleware:
if request.build_absolute_uri().find( if request.build_absolute_uri().find(
'api/remoteTransfer') > -1 or request.build_absolute_uri().find( 'api/remoteTransfer') > -1 or request.build_absolute_uri().find(
'api/verifyConn') > -1 or request.build_absolute_uri().find( 'api/verifyConn') > -1 or request.build_absolute_uri().find(
'webhook') > -1 or request.build_absolute_uri().find( 'webhook') > -1 or request.build_absolute_uri().find(
'saveSpamAssassinConfigurations') > -1 or request.build_absolute_uri().find( 'saveSpamAssassinConfigurations') > -1 or request.build_absolute_uri().find(
'docker') > -1 or request.build_absolute_uri().find( 'docker') > -1 or request.build_absolute_uri().find(
'cloudAPI') > -1 or request.build_absolute_uri().find( 'cloudAPI') > -1 or request.build_absolute_uri().find(
'verifyLogin') > -1 or request.build_absolute_uri().find('submitUserCreation') > -1: 'verifyLogin') > -1 or request.build_absolute_uri().find('submitUserCreation') > -1:
continue continue
if key == 'CLAMAV_VIRUS' or key == "Rspamdserver" or key == 'smtpd_milters' or key == 'non_smtpd_milters' or key == 'key' or key == 'cert' or key == 'recordContentAAAA' or key == 'backupDestinations' or key == 'ports' \ if key == 'scriptUrl' or key == 'CLAMAV_VIRUS' or key == "Rspamdserver" or key == 'smtpd_milters' or key == 'non_smtpd_milters' or key == 'key' or key == 'cert' or key == 'recordContentAAAA' or key == 'backupDestinations' or key == 'ports' \
or key == 'imageByPass' or key == 'passwordByPass' or key == 'cronCommand' \ or key == 'imageByPass' or key == 'passwordByPass' or key == 'cronCommand' \
or key == 'emailMessage' or key == 'configData' or key == 'rewriteRules' \ or key == 'emailMessage' or key == 'configData' or key == 'rewriteRules' \
or key == 'modSecRules' or key == 'recordContentTXT' or key == 'SecAuditLogRelevantStatus' \ or key == 'modSecRules' or key == 'recordContentTXT' or key == 'SecAuditLogRelevantStatus' \
@@ -106,7 +108,7 @@ class secMiddleware:
")") > -1 \ ")") > -1 \
or value.find("'") > -1 or value.find("[") > -1 or value.find("]") > -1 or value.find( or value.find("'") > -1 or value.find("[") > -1 or value.find("]") > -1 or value.find(
"{") > -1 or value.find("}") > -1 \ "{") > -1 or value.find("}") > -1 \
or value.find(":") > -1 or value.find("<") >-1 or value.find(">") > -1: or value.find(":") > -1 or value.find("<") > -1 or value.find(">") > -1:
logging.writeToFile(request.body) logging.writeToFile(request.body)
final_dic = { final_dic = {
'error_message': "Data supplied is not accepted, following characters are not allowed in the input ` $ & ( ) [ ] { } ; : < >.", 'error_message': "Data supplied is not accepted, following characters are not allowed in the input ` $ & ( ) [ ] { } ; : < >.",
@@ -143,9 +145,11 @@ class secMiddleware:
response['X-Frame-Options'] = "sameorigin" response['X-Frame-Options'] = "sameorigin"
response['Content-Security-Policy'] = "script-src 'self' https://www.jsdelivr.com" response['Content-Security-Policy'] = "script-src 'self' https://www.jsdelivr.com"
response['Content-Security-Policy'] = "connect-src *;" response['Content-Security-Policy'] = "connect-src *;"
response['Content-Security-Policy'] = "font-src 'self' 'unsafe-inline' https://www.jsdelivr.com https://fonts.googleapis.com" response[
response['Content-Security-Policy'] = "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://www.jsdelivr.com https://cdnjs.cloudflare.com https://maxcdn.bootstrapcdn.com https://cdn.jsdelivr.net" 'Content-Security-Policy'] = "font-src 'self' 'unsafe-inline' https://www.jsdelivr.com https://fonts.googleapis.com"
#response['Content-Security-Policy'] = "default-src 'self' cyberpanel.cloud *.cyberpanel.cloud" response[
'Content-Security-Policy'] = "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://www.jsdelivr.com https://cdnjs.cloudflare.com https://maxcdn.bootstrapcdn.com https://cdn.jsdelivr.net"
# response['Content-Security-Policy'] = "default-src 'self' cyberpanel.cloud *.cyberpanel.cloud"
response['X-Content-Type-Options'] = "nosniff" response['X-Content-Type-Options'] = "nosniff"
response['Referrer-Policy'] = "same-origin" response['Referrer-Policy'] = "same-origin"

View File

@@ -595,9 +595,6 @@
title="{% trans 'DKIM Manager' %}"><span>{% trans "DKIM Manager" %}</span></a> title="{% trans 'DKIM Manager' %}"><span>{% trans "DKIM Manager" %}</span></a>
</li> </li>
{% endif %} {% endif %}
<li><a href="{% url 'EmailDebugger' %}"
title="{% trans 'Email Debugger' %}"><span>{% trans "Email Debugger" %}</span></a>
</li>
{% if admin or createEmail %} {% if admin or createEmail %}
<li><a href="/snappymail/index.php" title="{% trans 'Access Webmail' %}" <li><a href="/snappymail/index.php" title="{% trans 'Access Webmail' %}"
@@ -1039,6 +1036,9 @@
<div class="sidebar-submenu"> <div class="sidebar-submenu">
<ul> <ul>
<li><a href="{% url 'EmailDebugger' %}"
title="{% trans 'Email Debugger' %}"><span>{% trans "Email Debugger" %}</span></a>
</li>
<li><a href="{% url 'mailQueue' %}" <li><a href="{% url 'mailQueue' %}"
title="{% trans 'Mail Queue' %}"><span>{% trans "Mail Queue" %}</span></a> title="{% trans 'Mail Queue' %}"><span>{% trans "Mail Queue" %}</span></a>
</li> </li>

View File

@@ -10,7 +10,7 @@ urlpatterns = [
url(r'^design', views.design, name='design'), url(r'^design', views.design, name='design'),
url(r'^getthemedata', views.getthemedata, name='getthemedata'), url(r'^getthemedata', views.getthemedata, name='getthemedata'),
#url(r'^upgrade',views.upgrade, name='upgrade'), url(r'^upgrade',views.upgrade, name='upgrade'),
url(r'^UpgradeStatus',views.upgradeStatus, name='UpgradeStatus'), url(r'^UpgradeStatus',views.upgradeStatus, name='UpgradeStatus'),
url(r'^upgradeVersion',views.upgradeVersion, name='upgradeVersion'), url(r'^upgradeVersion',views.upgradeVersion, name='upgradeVersion'),

View File

@@ -206,7 +206,7 @@ def upgrade(request):
vers = version.objects.get(pk=1) vers = version.objects.get(pk=1)
from upgrade import Upgrade from plogical.upgrade import Upgrade
Upgrade.initiateUpgrade(vers.currentVersion, vers.build) Upgrade.initiateUpgrade(vers.currentVersion, vers.build)

View File

@@ -1380,6 +1380,39 @@ class MailServerManager(multi.Thread):
return 1 return 1
def installOpenDKIMNew(self):
try:
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
'Installing opendkim..,40')
if ProcessUtilities.decideDistro() == ProcessUtilities.centos:
command = 'yum -y install opendkim'
elif ProcessUtilities.decideDistro() == ProcessUtilities.cent8:
command = 'dnf install opendkim -y'
else:
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install opendkim'
os.system(command)
if ProcessUtilities.decideDistro() == ProcessUtilities.cent8:
command = 'dnf install opendkim-tools -y'
ProcessUtilities.executioner(command)
if ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu or ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu20:
command = 'apt install opendkim-tools -y'
ProcessUtilities.executioner(command)
command = 'mkdir -p /etc/opendkim/keys/'
ProcessUtilities.executioner(command)
except BaseException as msg:
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
'%s [installOpenDKIM][404]' % (str(msg)), 10)
return 0
return 1
def configureOpenDKIM(self): def configureOpenDKIM(self):
try: try:
@@ -1440,6 +1473,7 @@ milter_default_action = accept
return 1 return 1
except BaseException as msg: except BaseException as msg:
logging.CyberCPLogFileWriter.writeToFile(f'Error in configureOpenDKIM {str(msg)}')
return 0 return 0
def fixCyberPanelPermissions(self): def fixCyberPanelPermissions(self):
@@ -1652,6 +1686,11 @@ milter_default_action = accept
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Restoreing OpenDKIM configurations..,70') logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Restoreing OpenDKIM configurations..,70')
if self.installOpenDKIMNew() == 0:
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
'Install OpenDKIM failed. [404].')
return 0
if self.configureOpenDKIM() == 0: if self.configureOpenDKIM() == 0:
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'configureOpenDKIM failed. [404].') logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'configureOpenDKIM failed. [404].')
return 0 return 0

View File

@@ -2059,6 +2059,51 @@ class MailServerManagerUtils(multi.Thread):
### ###
def installOpenDKIMNew(self):
try:
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
'Installing opendkim..,40')
if ProcessUtilities.decideDistro() == ProcessUtilities.centos:
command = 'yum -y erase opendkim*'
os.system(command)
command = 'yum -y install opendkim'
elif ProcessUtilities.decideDistro() == ProcessUtilities.cent8:
command = 'yum -y erase opendkim*'
os.system(command)
command = 'dnf install opendkim -y'
else:
command = 'apt-get -y purge opendkim'
os.system(command)
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install opendkim'
os.system(command)
if ProcessUtilities.decideDistro() == ProcessUtilities.cent8:
command = 'dnf install opendkim-tools -y'
ProcessUtilities.executioner(command)
if ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu or ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu20:
command = 'apt install opendkim-tools -y'
ProcessUtilities.executioner(command)
command = 'mkdir -p /etc/opendkim/keys/'
ProcessUtilities.executioner(command)
except BaseException as msg:
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
'%s [installOpenDKIM][404]' % (str(msg)), 10)
return 0
return 1
def ResetEmailConfigurations(self): def ResetEmailConfigurations(self):
try: try:
### Check if remote or local mysql ### Check if remote or local mysql
@@ -2121,6 +2166,11 @@ class MailServerManagerUtils(multi.Thread):
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
'Restoring OpenDKIM configurations..,70') 'Restoring OpenDKIM configurations..,70')
if self.installOpenDKIMNew() == 0:
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
'Install OpenDKIM failed. [404].')
return 0
if self.configureOpenDKIM() == 0: if self.configureOpenDKIM() == 0:
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
'configureOpenDKIM failed. [404].') 'configureOpenDKIM failed. [404].')
@@ -2159,6 +2209,9 @@ class MailServerManagerUtils(multi.Thread):
self.fixCyberPanelPermissions() self.fixCyberPanelPermissions()
command = 'touch /home/cyberpanel/postfix'
ProcessUtilities.executioner(command)
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Completed [200].') logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Completed [200].')
except BaseException as msg: except BaseException as msg:
@@ -2203,11 +2256,11 @@ milter_default_action = accept
writeToFile.write(configData) writeToFile.write(configData)
writeToFile.close() writeToFile.close()
if ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu: if ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu or ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu20:
data = open(openDKIMConfigurePath, 'r').readlines() data = open(openDKIMConfigurePath, 'r').readlines()
writeToFile = open(openDKIMConfigurePath, 'w') writeToFile = open(openDKIMConfigurePath, 'w')
for items in data: for items in data:
if items.find('Socket') > -1 and items.find('local:') and items[0] != '#': if items.find('Socket') > -1 and items.find('local:') > -1:
writeToFile.writelines('Socket inet:8891@localhost\n') writeToFile.writelines('Socket inet:8891@localhost\n')
else: else:
writeToFile.writelines(items) writeToFile.writelines(items)

View File

@@ -2907,163 +2907,168 @@ vmail
# Upgrade.stdOut("Upgrades are currently disabled") # Upgrade.stdOut("Upgrades are currently disabled")
# return 0 # return 0
if os.path.exists(Upgrade.CentOSPath) or os.path.exists(Upgrade.openEulerPath): if branch.find('SoftUpgrade') == -1:
command = 'yum list installed'
Upgrade.installedOutput = subprocess.check_output(shlex.split(command)).decode() if os.path.exists(Upgrade.CentOSPath) or os.path.exists(Upgrade.openEulerPath):
command = 'yum list installed'
Upgrade.installedOutput = subprocess.check_output(shlex.split(command)).decode()
else:
command = 'apt list'
Upgrade.installedOutput = subprocess.check_output(shlex.split(command)).decode()
command = 'systemctl stop cpssh'
Upgrade.executioner(command, 'fix csf if there', 0)
## Add LSPHP7.4 TO LSWS Ent configs
if not os.path.exists('/usr/local/lsws/bin/openlitespeed'):
if os.path.exists('httpd_config.xml'):
os.remove('httpd_config.xml')
command = 'wget https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/install/litespeed/httpd_config.xml'
Upgrade.executioner(command, command, 0)
# os.remove('/usr/local/lsws/conf/httpd_config.xml')
# shutil.copy('httpd_config.xml', '/usr/local/lsws/conf/httpd_config.xml')
postfixPath = '/home/cyberpanel/postfix'
pdns = '/home/cyberpanel/pdns'
pureftpd = '/home/cyberpanel/ftp'
Upgrade.updateRepoURL()
os.chdir("/usr/local")
command = 'yum remove yum-plugin-priorities -y'
Upgrade.executioner(command, 'remove yum-plugin-priorities', 0)
## Current Version
command = "systemctl stop lscpd"
Upgrade.executioner(command, 'stop lscpd', 0)
Upgrade.fixSudoers()
Upgrade.mountTemp()
Upgrade.dockerUsers()
Upgrade.setupComposer()
##
versionNumbring = Upgrade.downloadLink()
if os.path.exists('/usr/local/CyberPanel.' + versionNumbring):
os.remove('/usr/local/CyberPanel.' + versionNumbring)
##
Upgrade.downloadAndUpgrade(versionNumbring, branch)
Upgrade.download_install_phpmyadmin()
Upgrade.downoad_and_install_raindloop()
##
##
Upgrade.mailServerMigrations()
Upgrade.emailMarketingMigrationsa()
Upgrade.dockerMigrations()
Upgrade.CLMigrations()
Upgrade.IncBackupMigrations()
Upgrade.installRestic()
##
# Upgrade.setupVirtualEnv()
##
Upgrade.applyLoginSystemMigrations()
## Put function here to update custom ACLs
Upgrade.UpdateConfigOfCustomACL()
Upgrade.s3BackupMigrations()
Upgrade.containerMigrations()
Upgrade.manageServiceMigrations()
Upgrade.enableServices()
Upgrade.installPHP73()
Upgrade.setupCLI()
Upgrade.someDirectories()
Upgrade.installLSCPD(branch)
### General migrations are not needed any more
# Upgrade.GeneralMigrations()
# Upgrade.p3()
## Also disable email service upgrade
# if os.path.exists(postfixPath):
# Upgrade.upgradeDovecot()
## Upgrade version
Upgrade.fixPermissions()
##
### Disable version upgrade too
# Upgrade.upgradeVersion()
Upgrade.UpdateMaxSSLCons()
## Update LSCPD PHP
phpPath = '/usr/local/lscp/fcgi-bin/lsphp'
try:
os.remove(phpPath)
except:
pass
command = 'cp /usr/local/lsws/lsphp80/bin/lsphp %s' % (phpPath)
Upgrade.executioner(command, 0)
try:
command = "systemctl start lscpd"
Upgrade.executioner(command, 'Start LSCPD', 0)
except:
pass
command = 'csf -uf'
Upgrade.executioner(command, 'fix csf if there', 0)
command = 'systemctl stop cpssh'
Upgrade.executioner(command, 'fix csf if there', 0)
Upgrade.AutoUpgradeAcme()
Upgrade.installCLScripts()
Upgrade.runSomeImportantBash()
# ## Move static files
#
# imunifyPath = '/usr/local/CyberCP/public/imunify'
#
# if os.path.exists(imunifyPath):
# command = "yum reinstall imunify360-firewall-generic -y"
# Upgrade.executioner(command, command, 1)
#
imunifyAVPath = '/etc/sysconfig/imunify360/integration.conf'
if os.path.exists(imunifyAVPath):
execPath = "/usr/local/CyberCP/bin/python /usr/local/CyberCP/CLManager/CageFS.py"
command = execPath + " --function submitinstallImunifyAV"
Upgrade.executioner(command, command, 1)
command = 'chmod +x /usr/local/CyberCP/public/imunifyav/bin/execute.py'
Upgrade.executioner(command, command, 1)
Upgrade.stdOut("Upgrade Completed.")
else: else:
command = 'apt list'
Upgrade.installedOutput = subprocess.check_output(shlex.split(command)).decode()
command = 'systemctl stop cpssh'
Upgrade.executioner(command, 'fix csf if there', 0)
## Add LSPHP7.4 TO LSWS Ent configs
if not os.path.exists('/usr/local/lsws/bin/openlitespeed'):
if os.path.exists('httpd_config.xml'):
os.remove('httpd_config.xml')
command = 'wget https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/install/litespeed/httpd_config.xml'
Upgrade.executioner(command, command, 0)
# os.remove('/usr/local/lsws/conf/httpd_config.xml')
# shutil.copy('httpd_config.xml', '/usr/local/lsws/conf/httpd_config.xml')
postfixPath = '/home/cyberpanel/postfix'
pdns = '/home/cyberpanel/pdns'
pureftpd = '/home/cyberpanel/ftp'
Upgrade.updateRepoURL()
os.chdir("/usr/local")
command = 'yum remove yum-plugin-priorities -y'
Upgrade.executioner(command, 'remove yum-plugin-priorities', 0)
## Current Version
command = "systemctl stop lscpd"
Upgrade.executioner(command, 'stop lscpd', 0)
Upgrade.fixSudoers()
Upgrade.mountTemp()
Upgrade.dockerUsers()
Upgrade.setupComposer()
##
versionNumbring = Upgrade.downloadLink()
if os.path.exists('/usr/local/CyberPanel.' + versionNumbring):
os.remove('/usr/local/CyberPanel.' + versionNumbring)
##
Upgrade.downloadAndUpgrade(versionNumbring, branch)
Upgrade.download_install_phpmyadmin()
Upgrade.downoad_and_install_raindloop()
##
##
Upgrade.mailServerMigrations()
Upgrade.emailMarketingMigrationsa()
Upgrade.dockerMigrations()
Upgrade.CLMigrations()
Upgrade.IncBackupMigrations()
Upgrade.installRestic()
##
# Upgrade.setupVirtualEnv()
##
Upgrade.applyLoginSystemMigrations()
## Put function here to update custom ACLs
Upgrade.UpdateConfigOfCustomACL()
Upgrade.s3BackupMigrations()
Upgrade.containerMigrations()
Upgrade.manageServiceMigrations()
Upgrade.enableServices()
Upgrade.installPHP73()
Upgrade.setupCLI()
Upgrade.someDirectories()
Upgrade.installLSCPD(branch)
### General migrations are not needed any more
# Upgrade.GeneralMigrations()
# Upgrade.p3()
## Also disable email service upgrade
# if os.path.exists(postfixPath):
# Upgrade.upgradeDovecot()
## Upgrade version
Upgrade.fixPermissions()
##
### Disable version upgrade too
# Upgrade.upgradeVersion()
Upgrade.UpdateMaxSSLCons()
## Update LSCPD PHP
phpPath = '/usr/local/lscp/fcgi-bin/lsphp'
try:
os.remove(phpPath)
except:
pass pass
command = 'cp /usr/local/lsws/lsphp80/bin/lsphp %s' % (phpPath)
Upgrade.executioner(command, 0)
try:
command = "systemctl start lscpd"
Upgrade.executioner(command, 'Start LSCPD', 0)
except:
pass
command = 'csf -uf'
Upgrade.executioner(command, 'fix csf if there', 0)
command = 'systemctl stop cpssh'
Upgrade.executioner(command, 'fix csf if there', 0)
Upgrade.AutoUpgradeAcme()
Upgrade.installCLScripts()
Upgrade.runSomeImportantBash()
# ## Move static files
#
# imunifyPath = '/usr/local/CyberCP/public/imunify'
#
# if os.path.exists(imunifyPath):
# command = "yum reinstall imunify360-firewall-generic -y"
# Upgrade.executioner(command, command, 1)
#
imunifyAVPath = '/etc/sysconfig/imunify360/integration.conf'
if os.path.exists(imunifyAVPath):
execPath = "/usr/local/CyberCP/bin/python /usr/local/CyberCP/CLManager/CageFS.py"
command = execPath + " --function submitinstallImunifyAV"
Upgrade.executioner(command, command, 1)
command = 'chmod +x /usr/local/CyberCP/public/imunifyav/bin/execute.py'
Upgrade.executioner(command, command, 1)
Upgrade.stdOut("Upgrade Completed.")
def main(): def main():