HEX
Server: LiteSpeed
System: Linux php-prod-1.spaceapp.ru 5.15.0-157-generic #167-Ubuntu SMP Wed Sep 17 21:35:53 UTC 2025 x86_64
User: xnsbb3110 (1041)
PHP: 8.1.33
Disabled: NONE
Upload Files
File: //usr/local/CyberCP/dns/dnsManager.py.backup_dns_fix
#!/usr/local/CyberCP/bin/python
import argparse
import errno
import os.path
import sys
import django

sys.path.append('/usr/local/CyberCP')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
django.setup()
from django.http import HttpResponse
import json
try:
    from plogical.dnsUtilities import DNS
    from loginSystem.models import Administrator
    from .models import Domains,Records
    from plogical.mailUtilities import mailUtilities
except:
    pass
import os
from re import match,I,M
from plogical.acl import ACLManager
import CloudFlare
import re
import plogical.CyberCPLogFileWriter as logging
from plogical.processUtilities import ProcessUtilities
from plogical.httpProc import httpProc

class DNSManager:
    defaultNameServersPath = '/home/cyberpanel/defaultNameservers'

    def __init__(self, extraArgs=None):
        self.extraArgs = extraArgs

    def loadCFKeys(self):
        cfFile = '%s%s' % (DNS.CFPath, self.admin.userName)
        data = open(cfFile, 'r').readlines()
        self.email = data[0].rstrip('\n')
        self.key = data[1].rstrip('\n')

    def loadDNSHome(self, request = None, userID = None):
        admin = Administrator.objects.get(pk=userID)
        template = 'dns/index.html'
        proc = httpProc(request, template, {"type": admin.type}, 'createDNSZone')
        return proc.render()

    def createNameserver(self, request = None, userID = None):
        mailUtilities.checkHome()

        if os.path.exists('/home/cyberpanel/powerdns'):
            finalData = {"status": 1}
        else:
            finalData = {"status": 0}

        template = 'dns/createNameServer.html'
        proc = httpProc(request, template, finalData, 'createNameServer')
        return proc.render()

    def NSCreation(self, userID = None, data = None):
        try:
            admin = Administrator.objects.get(pk=userID)
            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'createNameServer') == 0:
                return ACLManager.loadErrorJson('NSCreation', 0)


            domainForNS = data['domainForNS']
            ns1 = data['ns1']
            ns2 = data['ns2']
            firstNSIP = data['firstNSIP']
            secondNSIP = data['secondNSIP']

            DNS.dnsTemplate(domainForNS, admin)

            newZone = Domains.objects.get(name=domainForNS)

            ## NS1


            record = Records(domainOwner=newZone,
                             domain_id=newZone.id,
                             name=ns1,
                             type="A",
                             content=firstNSIP,
                             ttl=3600,
                             prio=0,
                             disabled=0,
                             auth=1)
            record.save()

            ## NS2

            record = Records(domainOwner=newZone,
                             domain_id=newZone.id,
                             name=ns2,
                             type="A",
                             content=secondNSIP,
                             ttl=3600,
                             prio=0,
                             disabled=0,
                             auth=1)
            record.save()

            final_dic = {'NSCreation': 1, 'error_message': "None"}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)


        except BaseException as msg:
            final_dic = {'NSCreation': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def createDNSZone(self, request = None, userID = None):

        if os.path.exists('/home/cyberpanel/powerdns'):
            finalData = {'status': 1}
        else:
            finalData = {'status': 0}

        template = 'dns/createDNSZone.html'
        proc = httpProc(request, template, finalData, 'createDNSZone')
        return proc.render()

    def zoneCreation(self, userID = None, data = None):
        try:
            admin = Administrator.objects.get(pk=userID)

            currentACL = ACLManager.loadedACL(userID)
            if ACLManager.currentContextPermission(currentACL, 'createDNSZone') == 0:
                return ACLManager.loadErrorJson('zoneCreation', 0)

            zoneDomain = data['zoneDomain']

            newZone = Domains(admin=admin, name=zoneDomain, type="MASTER")
            newZone.save()

            content = "ns1." + zoneDomain + " hostmaster." + zoneDomain + " 1 10800 3600 1209600 3600"

            soaRecord = Records(domainOwner=newZone,
                                domain_id=newZone.id,
                                name=zoneDomain,
                                type="SOA",
                                content=content,
                                ttl=3600,
                                prio=0,
                                disabled=0,
                                auth=1)
            soaRecord.save()

            final_dic = {'zoneCreation': 1}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'zoneCreation': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def addDeleteDNSRecords(self, request = None, userID = None):
        currentACL = ACLManager.loadedACL(userID)

        if not os.path.exists('/home/cyberpanel/powerdns'):
            finalData = {"status": 0}
        else:
            finalData = {"status": 1}

        tempList = ACLManager.findAllDomains(currentACL, userID)

        finalData['domainsList'] = []
        import tldextract

        no_cache_extract = tldextract.TLDExtract(cache_dir=None)
        for items in tempList:
            extractDomain = no_cache_extract(items)
            subDomain = extractDomain.subdomain
            if len(subDomain) == 0:
                finalData['domainsList'].append(items)


        template = 'dns/addDeleteDNSRecords.html'
        proc = httpProc(request, template, finalData, 'addDeleteRecords')
        return proc.render()

    def getCurrentRecordsForDomain(self, userID = None, data = None):
        try:

            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'addDeleteRecords') == 0:
                return ACLManager.loadErrorJson('fetchStatus', 0)


            zoneDomain = data['selectedZone']
            currentSelection = data['currentSelection']

            admin = Administrator.objects.get(pk=userID)
            if ACLManager.checkOwnershipZone(zoneDomain, admin, currentACL) == 1:
                pass
            else:
                return ACLManager.loadErrorJson()

            domain = Domains.objects.get(name=zoneDomain)
            records = Records.objects.filter(domain_id=domain.id)

            fetchType = ""

            if currentSelection == 'aRecord':
                fetchType = 'A'
            elif currentSelection == 'aaaaRecord':
                fetchType = 'AAAA'
            elif currentSelection == 'cNameRecord':
                fetchType = 'CNAME'
            elif currentSelection == 'mxRecord':
                fetchType = 'MX'
            elif currentSelection == 'txtRecord':
                fetchType = 'TXT'
            elif currentSelection == 'spfRecord':
                fetchType = 'SPF'
            elif currentSelection == 'nsRecord':
                fetchType = 'NS'
            elif currentSelection == 'soaRecord':
                fetchType = 'SOA'
            elif currentSelection == 'srvRecord':
                fetchType = 'SRV'
            elif currentSelection == 'caaRecord':
                fetchType = 'CAA'

            json_data = "["
            checker = 0

            for items in records:
                if items.type == fetchType:
                    dic = {'id': items.id,
                           'type': items.type,
                           'name': items.name,
                           'content': items.content,
                           'priority': items.prio,
                           'ttl': items.ttl
                           }

                    if checker == 0:
                        json_data = json_data + json.dumps(dic)
                        checker = 1
                    else:
                        json_data = json_data + ',' + json.dumps(dic)
                else:
                    continue

            json_data = json_data + ']'
            final_json = json.dumps({'status': 1, 'fetchStatus': 1, 'error_message': "None", "data": json_data})
            return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'fetchStatus': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def addDNSRecord(self, userID = None, data = None):
        try:

            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'addDeleteRecords') == 0:
                return ACLManager.loadErrorJson('add_status', 0)

            zoneDomain = data['selectedZone']
            recordType = data['recordType']
            recordName = data['recordName']

            ttl = int(data['ttl'])
            if ttl < 0:
                raise ValueError("TTL: The item must be greater than 0")
            elif ttl > 86400:
                raise ValueError("TTL: The item must be lesser than 86401")

            admin = Administrator.objects.get(pk=userID)
            if ACLManager.checkOwnershipZone(zoneDomain, admin, currentACL) == 1:
                pass
            else:
                return ACLManager.loadErrorJson()

            zone = Domains.objects.get(name=zoneDomain)
            value = ""

            if recordType == "A":

                recordContentA = data['recordContentA']  ## IP or pointing value

                if recordName == "@":
                    value = zoneDomain
                ## re.match
                elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                           M | I):
                    value = recordName
                else:
                    value = recordName + "." + zoneDomain

                DNS.createDNSRecord(zone, value, recordType, recordContentA, 0, ttl)

            elif recordType == "MX":

                if recordName == "@":
                    value = zoneDomain
                ## re.match
                elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                           M | I):
                    value = recordName
                else:
                    value = recordName + "." + zoneDomain

                recordContentMX = data['recordContentMX']
                priority = data['priority']

                DNS.createDNSRecord(zone, value, recordType, recordContentMX, priority, ttl)

            elif recordType == "AAAA":

                if recordName == "@":
                    value = zoneDomain
                ## re.match
                elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                           M | I):
                    value = recordName
                else:
                    value = recordName + "." + zoneDomain

                recordContentAAAA = data['recordContentAAAA']  ## IP or pointing value

                DNS.createDNSRecord(zone, value, recordType, recordContentAAAA, 0, ttl)

            elif recordType == "CNAME":

                if recordName == "@":
                    value = zoneDomain
                ## re.match
                elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                           M | I):
                    value = recordName
                else:
                    value = recordName + "." + zoneDomain

                recordContentCNAME = data['recordContentCNAME']  ## IP or pointing value

                DNS.createDNSRecord(zone, value, recordType, recordContentCNAME, 0, ttl)

            elif recordType == "SPF":

                if recordName == "@":
                    value = zoneDomain
                ## re.match
                elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                           M | I):
                    value = recordName
                else:
                    value = recordName + "." + zoneDomain

                recordContentSPF = data['recordContentSPF']  ## IP or pointing value

                DNS.createDNSRecord(zone, value, recordType, recordContentSPF, 0, ttl)

            elif recordType == "TXT":

                if recordName == "@":
                    value = zoneDomain
                ## re.match
                elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                           M | I):
                    value = recordName
                else:
                    value = recordName + "." + zoneDomain

                recordContentTXT = data['recordContentTXT']  ## IP or pointing value

                DNS.createDNSRecord(zone, value, recordType, recordContentTXT, 0, ttl)

            elif recordType == "SOA":

                recordContentSOA = data['recordContentSOA']

                DNS.createDNSRecord(zone, recordName, recordType, recordContentSOA, 0, ttl)

            elif recordType == "NS":

                recordContentNS = data['recordContentNS']

                if recordContentNS == "@":
                    recordContentNS = "ns1." + zoneDomain
                ## re.match
                elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?',
                           recordContentNS, M | I):
                    recordContentNS = recordContentNS
                else:
                    recordContentNS = recordContentNS + "." + zoneDomain

                DNS.createDNSRecord(zone, recordName, recordType, recordContentNS, 0, ttl)

            elif recordType == "SRV":

                if recordName == "@":
                    value = zoneDomain
                ## re.match
                elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                           M | I):
                    value = recordName
                else:
                    value = recordName + "." + zoneDomain

                recordContentSRV = data['recordContentSRV']
                priority = data['priority']

                DNS.createDNSRecord(zone, value, recordType, recordContentSRV, priority, ttl)

            elif recordType == "CAA":
                if recordName == "@":
                    value = zoneDomain
                ## re.match
                elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                           M | I):
                    value = recordName
                else:
                    value = recordName + "." + zoneDomain
                recordContentCAA = data['recordContentCAA']  ## IP or pointing value
                DNS.createDNSRecord(zone, value, recordType, recordContentCAA, 0, ttl)

            final_dic = {'status': 1, 'add_status': 1, 'error_message': "None"}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'add_status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def updateRecord(self, userID = None, data = None):
        try:

            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'addDeleteRecords') == 0:
                return ACLManager.loadErrorJson('add_status', 0)

            zoneDomain = data['selectedZone']

            admin = Administrator.objects.get(pk=userID)
            if ACLManager.checkOwnershipZone(zoneDomain, admin, currentACL) == 1:
                pass
            else:
                return ACLManager.loadErrorJson()

            record = Records.objects.get(pk=data['id'])

            if ACLManager.VerifyRecordOwner(currentACL, record, zoneDomain) == 1:
                pass
            else:
                return ACLManager.loadErrorJson()

            if data['nameNow'] != None:
                record.name = data['nameNow']

            if data['ttlNow'] != None:
                record.ttl = int(data['ttlNow'])
                if record.ttl < 0:
                    raise ValueError("TTL: The item must be greater than 0")
                elif record.ttl > 86400:
                    raise ValueError("TTL: The item must be lesser than 86401")

            if data['priorityNow'] != None:
                record.prio = int(data['priorityNow'])

            if data['contentNow'] != None:
                record.content = data['contentNow']

            record.save()

            final_dic = {'status': 1, 'error_message': "None"}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def deleteDNSRecord(self, userID = None, data = None):
        try:
            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'addDeleteRecords') == 0:
                return ACLManager.loadErrorJson('delete_status', 0)

            id = data['id']

            delRecord = Records.objects.get(id=id)

            admin = Administrator.objects.get(pk=userID)

            if ACLManager.checkOwnershipZone(delRecord.domainOwner.name, admin, currentACL) == 1:
                pass
            else:
                return ACLManager.loadError()


            delRecord.delete()

            final_dic = {'status': 1, 'delete_status': 1, 'error_message': "None"}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'delete_status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def deleteDNSZone(self, request = None, userID = None):
        currentACL = ACLManager.loadedACL(userID)
        if not os.path.exists('/home/cyberpanel/powerdns'):
            finalData = {"status": 0}
        else:
            finalData = {"status": 1}

        finalData['domainsList'] = ACLManager.findAllDomains(currentACL, userID)
        template = 'dns/deleteDNSZone.html'
        proc = httpProc(request, template, finalData, 'deleteZone')
        return proc.render()

    def submitZoneDeletion(self, userID = None, data = None):
        try:
            zoneDomain = data['zoneDomain']

            currentACL = ACLManager.loadedACL(userID)
            admin = Administrator.objects.get(pk=userID)
            if ACLManager.currentContextPermission(currentACL, 'deleteZone') == 0:
                return ACLManager.loadErrorJson('delete_status', 0)


            if ACLManager.checkOwnershipZone(zoneDomain, admin, currentACL) == 1:
                pass
            else:
                return ACLManager.loadError()

            delZone = Domains.objects.get(name=zoneDomain)
            admin = Administrator.objects.get(pk=userID)
            if currentACL['admin'] == 1:
                if delZone.admin != admin:
                    return ACLManager.loadErrorJson()

            delZone.delete()

            final_dic = {'delete_status': 1, 'error_message': "None"}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'delete_status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def configureDefaultNameServers(self, request=None, userID=None):
        currentACL = ACLManager.loadedACL(userID)

        if not os.path.exists('/home/cyberpanel/powerdns'):
            data = {"status": 0}
        else:
            data = {"status": 1}

        data['domainsList'] = ACLManager.findAllDomains(currentACL, userID)
        if os.path.exists(DNSManager.defaultNameServersPath):
            nsData = open(DNSManager.defaultNameServersPath, 'r').readlines()
            try:
                data['firstNS'] = nsData[0].rstrip('\n')
            except:
                pass
            try:
                data['secondNS'] = nsData[1].rstrip('\n')
            except:
                pass
            try:
                data['thirdNS'] = nsData[2].rstrip('\n')
            except:
                pass
            try:
                data['forthNS'] = nsData[3].rstrip('\n')
            except:
                pass

        template = 'dns/configureDefaultNameServers.html'
        proc = httpProc(request, template, data, 'admin')
        return proc.render()

    def saveNSConfigurations(self, userID = None, data = None):
        try:
            currentACL = ACLManager.loadedACL(userID)

            if currentACL['admin'] == 1:
                pass
            else:
                return ACLManager.loadErrorJson()

            nsContent = ''

            try:
                nsContent = '%s\n%s\n%s\n%s\n' % (data['firstNS'].rstrip('\n'), data['secondNS'].rstrip('\n'), data['thirdNS'].rstrip('\n'), data['forthNS'].rstrip('\n'))
            except:
                try:
                    nsContent = '%s\n%s\n%s\n' % (data['firstNS'].rstrip('\n'), data['secondNS'].rstrip('\n'), data['thirdNS'].rstrip('\n'))
                except:
                    try:
                        nsContent = '%s\n%s\n' % (data['firstNS'].rstrip('\n'), data['secondNS'].rstrip('\n'))
                    except:
                        try:
                            nsContent = '%s\n' % (data['firstNS'].rstrip('\n'))
                        except:
                            pass

            writeToFile = open(DNSManager.defaultNameServersPath, 'w')
            writeToFile.write(nsContent.rstrip('\n'))
            writeToFile.close()

            ###

            import tldextract

            no_cache_extract = tldextract.TLDExtract(cache_dir=None)

            nsData = open(DNSManager.defaultNameServersPath, 'r').readlines()

            for ns in nsData:
                extractDomain = no_cache_extract(ns.rstrip('\n'))
                topLevelDomain = extractDomain.domain + '.' + extractDomain.suffix

                zone = Domains.objects.get(name=topLevelDomain)

                DNS.createDNSRecord(zone, ns, 'A', ACLManager.fetchIP(), 0, 1400)

            final_dic = {'status': 1, 'error_message': "None"}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def addDeleteDNSRecordsCloudFlare(self, request = None, userID = None):
        currentACL = ACLManager.loadedACL(userID)
        if not os.path.exists('/home/cyberpanel/powerdns'):
            status = 0
        else:
            status = 1
        admin = Administrator.objects.get(pk=userID)

        CloudFlare = 0

        cfPath = '%s%s' % (DNS.CFPath, admin.userName)

        if os.path.exists(cfPath):
            CloudFlare = 1
            domainsList = ACLManager.findAllDomains(currentACL, userID)
            self.admin = admin
            self.loadCFKeys()
            data = {"domainsList": domainsList, "status": status, 'CloudFlare': CloudFlare, 'cfEmail': self.email,
                    'cfToken': self.key}
        else:
            data = {"status": status, 'CloudFlare': CloudFlare}

        template = 'dns/addDeleteDNSRecordsCloudFlare.html'
        proc = httpProc(request, template, data, 'addDeleteRecords')
        return proc.render()

    def saveCFConfigs(self, userID = None, data = None):
        try:
            cfEmail = data['cfEmail']
            cfToken = data['cfToken']
            cfSync = data['cfSync']

            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'addDeleteRecords') == 0:
                return ACLManager.loadErrorJson('status', 0)

            admin = Administrator.objects.get(pk=userID)
            cfPath = '%s%s' % (DNS.CFPath, admin.userName)

            writeToFile = open(cfPath, 'w')
            writeToFile.write('%s\n%s\n%s' % (cfEmail, cfToken, cfSync))
            writeToFile.close()

            os.chmod(cfPath, 0o600)

            final_dic = {'status': 1, 'error_message': "None"}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def getCurrentRecordsForDomainCloudFlare(self, userID = None, data = None):
        try:

            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'addDeleteRecords') == 0:
                return ACLManager.loadErrorJson('fetchStatus', 0)


            zoneDomain = data['selectedZone']
            currentSelection = data['currentSelection']

            admin = Administrator.objects.get(pk=userID)
            self.admin = admin

            if ACLManager.checkOwnershipZone(zoneDomain, admin, currentACL) == 1:
                pass
            else:
                return ACLManager.loadErrorJson()

            self.loadCFKeys()

            params = {'name': zoneDomain, 'per_page':50}
            cf = CloudFlare.CloudFlare(email=self.email,token=self.key)

            try:
                zones = cf.zones.get(params=params)
            except BaseException as e:
                final_json = json.dumps({'status': 0, 'fetchStatus': 0, 'error_message': str(e), "data": '[]'})
                return HttpResponse(final_json)

            # there should only be one zone

            if len(zones) == 0:
                final_json = json.dumps({'status': 1, 'fetchStatus': 1, 'error_message': '', "data": '[]'})
                return HttpResponse(final_json)

            for zone in sorted(zones, key=lambda v: v['name']):
                zone_name = zone['name']
                zone_id = zone['id']

                fetchType = ""

                if currentSelection == 'aRecord':
                    fetchType = 'A'
                elif currentSelection == 'aaaaRecord':
                    fetchType = 'AAAA'
                elif currentSelection == 'cNameRecord':
                    fetchType = 'CNAME'
                elif currentSelection == 'mxRecord':
                    fetchType = 'MX'
                elif currentSelection == 'txtRecord':
                    fetchType = 'TXT'
                elif currentSelection == 'spfRecord':
                    fetchType = 'SPF'
                elif currentSelection == 'nsRecord':
                    fetchType = 'NS'
                elif currentSelection == 'soaRecord':
                    fetchType = 'SOA'
                elif currentSelection == 'srvRecord':
                    fetchType = 'SRV'
                elif currentSelection == 'caaRecord':
                    fetchType = 'CAA'

                try:
                    dns_records = cf.zones.dns_records.get(zone_id, params={'per_page':50, 'type':fetchType})
                except BaseException as e:
                    final_json = json.dumps({'status': 0, 'fetchStatus': 0, 'error_message': str(e), "data": '[]'})
                    return HttpResponse(final_json)

                prog = re.compile('\.*' + zone_name + '$')
                dns_records = sorted(dns_records, key=lambda v: prog.sub('', v['name']) + '_' + v['type'])

                json_data = "["
                checker = 0

                for dns_record in dns_records:
                    if dns_record['ttl'] == 1:
                        ttl = 'AUTO'
                    else:
                        ttl = dns_record['ttl']

                    dic = {'id': dns_record['id'],
                           'type': dns_record['type'],
                           'name': dns_record['name'],
                           'content': dns_record['content'],
                           'priority': '1400',
                           'ttl': ttl,
                           'proxy': dns_record['proxied'],
                           'proxiable': dns_record['proxiable']
                           }

                    if checker == 0:
                        json_data = json_data + json.dumps(dic)
                        checker = 1
                    else:
                        json_data = json_data + ',' + json.dumps(dic)


                json_data = json_data + ']'
                final_json = json.dumps({'status': 1, 'fetchStatus': 1, 'error_message': "None", "data": json_data})
                return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'fetchStatus': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def deleteDNSRecordCloudFlare(self, userID = None, data = None):
        try:
            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'addDeleteRecords') == 0:
                return ACLManager.loadErrorJson('fetchStatus', 0)

            zoneDomain = data['selectedZone']
            id = data['id']

            admin = Administrator.objects.get(pk=userID)
            self.admin = admin

            if ACLManager.checkOwnershipZone(zoneDomain, admin, currentACL) == 1:
                pass
            else:
                return ACLManager.loadErrorJson()

            self.loadCFKeys()

            params = {'name': zoneDomain, 'per_page': 50}
            cf = CloudFlare.CloudFlare(email=self.email, token=self.key)

            try:
                zones = cf.zones.get(params=params)
            except BaseException as e:
                final_json = json.dumps({'status': 0, 'delete_status': 0, 'error_message': str(e), "data": '[]'})
                return HttpResponse(final_json)

            for zone in sorted(zones, key=lambda v: v['name']):
                zone_id = zone['id']

                cf.zones.dns_records.delete(zone_id, id)

                final_dic = {'status': 1, 'delete_status': 1, 'error_message': "None"}
                final_json = json.dumps(final_dic)
                return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'delete_status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)


    def addDNSRecordCloudFlare(self, userID = None, data = None):
        try:

            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'addDeleteRecords') == 0:
                return ACLManager.loadErrorJson('add_status', 0)

            zoneDomain = data['selectedZone']
            recordType = data['recordType']
            recordName = data['recordName']
            ttl = int(data['ttl'])
            if ttl < 0:
                raise ValueError("TTL: The item must be greater than 0")
            elif ttl > 86400:
                raise ValueError("TTL: The item must be lesser than 86401")

            admin = Administrator.objects.get(pk=userID)
            self.admin = admin
            if ACLManager.checkOwnershipZone(zoneDomain, admin, currentACL) == 1:
                pass
            else:
                return ACLManager.loadErrorJson()

            ## Get zone

            self.loadCFKeys()

            params = {'name': zoneDomain, 'per_page': 50}
            cf = CloudFlare.CloudFlare(email=self.email, token=self.key)

            try:
                zones = cf.zones.get(params=params)
            except BaseException as e:
                final_json = json.dumps({'status': 0, 'delete_status': 0, 'error_message': str(e), "data": '[]'})
                return HttpResponse(final_json)

            for zone in sorted(zones, key=lambda v: v['name']):
                zone = zone['id']

                value = ""

                if recordType == "A":

                    recordContentA = data['recordContentA']  ## IP or pointing value

                    if recordName == "@":
                        value = zoneDomain
                    ## re.match
                    elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                               M | I):
                        value = recordName
                    else:
                        value = recordName + "." + zoneDomain

                    DNS.createDNSRecordCloudFlare(cf, zone, value, recordType, recordContentA, 0, ttl)

                elif recordType == "MX":

                    if recordName == "@":
                        value = zoneDomain
                    ## re.match
                    elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                               M | I):
                        value = recordName
                    else:
                        value = recordName + "." + zoneDomain

                    recordContentMX = data['recordContentMX']
                    priority = data['priority']

                    DNS.createDNSRecordCloudFlare(cf, zone, value, recordType, recordContentMX, priority, ttl)

                elif recordType == "AAAA":

                    if recordName == "@":
                        value = zoneDomain
                    ## re.match
                    elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                               M | I):
                        value = recordName
                    else:
                        value = recordName + "." + zoneDomain

                    recordContentAAAA = data['recordContentAAAA']  ## IP or pointing value

                    DNS.createDNSRecordCloudFlare(cf, zone, value, recordType, recordContentAAAA, 0, ttl)

                elif recordType == "CNAME":

                    if recordName == "@":
                        value = zoneDomain
                    ## re.match
                    elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                               M | I):
                        value = recordName
                    else:
                        value = recordName + "." + zoneDomain

                    recordContentCNAME = data['recordContentCNAME']  ## IP or pointing value

                    DNS.createDNSRecordCloudFlare(cf, zone, value, recordType, recordContentCNAME, 0, ttl)

                elif recordType == "SPF":

                    if recordName == "@":
                        value = zoneDomain
                    ## re.match
                    elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                               M | I):
                        value = recordName
                    else:
                        value = recordName + "." + zoneDomain

                    recordContentSPF = data['recordContentSPF']  ## IP or pointing value

                    DNS.createDNSRecordCloudFlare(cf, zone, value, recordType, recordContentSPF, 0, ttl)

                elif recordType == "TXT":

                    if recordName == "@":
                        value = zoneDomain
                    ## re.match
                    elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                               M | I):
                        value = recordName
                    else:
                        value = recordName + "." + zoneDomain

                    recordContentTXT = data['recordContentTXT']  ## IP or pointing value

                    DNS.createDNSRecordCloudFlare(cf, zone, value, recordType, recordContentTXT, 0, ttl)

                elif recordType == "SOA":

                    recordContentSOA = data['recordContentSOA']

                    DNS.createDNSRecordCloudFlare(cf, zone, recordName, recordType, recordContentSOA, 0, ttl)

                elif recordType == "NS":

                    recordContentNS = data['recordContentNS']

                    if recordContentNS == "@":
                        recordContentNS = "ns1." + zoneDomain
                    ## re.match
                    elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?',
                               recordContentNS, M | I):
                        recordContentNS = recordContentNS
                    else:
                        recordContentNS = recordContentNS + "." + zoneDomain

                    DNS.createDNSRecordCloudFlare(cf, zone, recordName, recordType, recordContentNS, 0, ttl)

                elif recordType == "SRV":

                    if recordName == "@":
                        value = zoneDomain
                    ## re.match
                    elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                               M | I):
                        value = recordName
                    else:
                        value = recordName + "." + zoneDomain

                    recordContentSRV = data['recordContentSRV']
                    priority = data['priority']

                    DNS.createDNSRecordCloudFlare(cf, zone, value, recordType, recordContentSRV, priority, ttl)

                elif recordType == "CAA":
                    if recordName == "@":
                        value = zoneDomain
                    ## re.match
                    elif match(r'([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?', recordName,
                               M | I):
                        value = recordName
                    else:
                        value = recordName + "." + zoneDomain
                    recordContentCAA = data['recordContentCAA']  ## IP or pointing value
                    DNS.createDNSRecordCloudFlare(cf, zone, value, recordType, recordContentCAA, 0, ttl)

                final_dic = {'status': 1, 'add_status': 1, 'error_message': "None"}
                final_json = json.dumps(final_dic)
                return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'add_status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def syncCF(self, userID = None, data = None):
        try:

            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'addDeleteRecords') == 0:
                return ACLManager.loadErrorJson('add_status', 0)

            zoneDomain = data['selectedZone']

            admin = Administrator.objects.get(pk=userID)
            self.admin = admin

            if ACLManager.checkOwnershipZone(zoneDomain, admin, currentACL) == 1:
                pass
            else:
                return ACLManager.loadErrorJson()

            ## Get zone

            dns = DNS()

            status, error = dns.cfTemplate(zoneDomain, admin)

            if status == 1:
                final_dic = {'status': 1, 'error_message': 'None'}
                final_json = json.dumps(final_dic)
                return HttpResponse(final_json)
            else:
                final_dic = {'status': 0, 'error_message': error}
                final_json = json.dumps(final_dic)
                return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)


    def enableProxy(self, userID = None, data = None):
        try:
            currentACL = ACLManager.loadedACL(userID)

            if ACLManager.currentContextPermission(currentACL, 'addDeleteRecords') == 0:
                return ACLManager.loadErrorJson('fetchStatus', 0)

            zoneDomain = data['selectedZone']
            name = data['name']
            value = data['value']

            admin = Administrator.objects.get(pk=userID)
            self.admin = admin

            if ACLManager.checkOwnershipZone(zoneDomain, admin, currentACL) == 1:
                pass
            else:
                return ACLManager.loadErrorJson()

            self.loadCFKeys()

            params = {'name': zoneDomain, 'per_page': 50}
            cf = CloudFlare.CloudFlare(email=self.email, token=self.key)

            ## Get zone

            zones = cf.zones.get(params=params)

            zone = zones[0]

            ##

            zone_id = zone['id']

            params = {'name': name}
            dns_records = cf.zones.dns_records.get(zone_id, params=params)

            ##


            if value == True:
                new_r_proxied_flag = False
            else:
                new_r_proxied_flag = True

            for dns_record in dns_records:
                r_zone_id = dns_record['zone_id']
                r_id = dns_record['id']
                r_name = dns_record['name']
                r_type = dns_record['type']
                r_content = dns_record['content']
                r_ttl = dns_record['ttl']
                r_proxied = dns_record['proxied']
                r_proxiable = dns_record['proxiable']

                if r_proxied == new_r_proxied_flag:
                    # Nothing to do
                    continue

                dns_record_id = dns_record['id']

                new_dns_record = {
                    'zone_id': r_zone_id,
                    'id': r_id,
                    'type': r_type,
                    'name': r_name,
                    'content': r_content,
                    'ttl': r_ttl,
                    'proxied': new_r_proxied_flag
                }

                cf.zones.dns_records.put(zone_id, dns_record_id, data=new_dns_record)

                final_dic = {'status': 1, 'delete_status': 1, 'error_message': "None"}
                final_json = json.dumps(final_dic)
                return HttpResponse(final_json)

        except BaseException as msg:
            final_dic = {'status': 0, 'delete_status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

    def installPowerDNS(self):
        try:

            if ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu or ProcessUtilities.decideDistro() == ProcessUtilities.cent8:

                command = 'systemctl stop systemd-resolved'
                ProcessUtilities.executioner(command, 'root', True)
                command = 'systemctl disable systemd-resolved.service'
                ProcessUtilities.executioner(command, 'root', True)

            if ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu or ProcessUtilities.ubuntu20:

                command = 'DEBIAN_FRONTEND=noninteractive apt-get -y purge pdns-server pdns-backend-mysql -y'
                ProcessUtilities.executioner(command, 'root', True)
            else:
                command = 'yum -y erase pdns pdns-backend-mysql'
                ProcessUtilities.executioner(command, 'root', True)


            #### new install

            if ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu or ProcessUtilities.decideDistro() == ProcessUtilities.cent8:
                try:
                    os.rename('/etc/resolv.conf', 'etc/resolved.conf')
                except OSError as e:
                    if e.errno != errno.EEXIST and e.errno != errno.ENOENT:
                        logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], "[ERROR] Unable to rename /etc/resolv.conf to install PowerDNS: " +
                                                 str(e) + "[404]")
                        return 0
                    try:
                        os.remove('/etc/resolv.conf')
                    except OSError as e1:
                        logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
                                                                  "[ERROR] Unable to remove existing /etc/resolv.conf to install PowerDNS: " +
                            str(e1) + "[404]")
                        return 0


            if ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu or ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu20:
                # Update package list first
                command = "DEBIAN_FRONTEND=noninteractive apt-get update"
                ProcessUtilities.executioner(command, 'root', True)
                
                command = "DEBIAN_FRONTEND=noninteractive apt-get -y install pdns-server pdns-backend-mysql"
                result = ProcessUtilities.executioner(command, 'root', True)
                
                # Ensure service is stopped after installation for configuration
                command = 'systemctl stop pdns || true'
                ProcessUtilities.executioner(command, 'root', True)
                
                return 1
            else:
                command = 'yum -y install pdns pdns-backend-mysql'

            ProcessUtilities.executioner(command, 'root', True)

            return 1

        except BaseException as msg:
            logging.CyberCPLogFileWriter.writeToFile('[ERROR] ' + str(msg) + " [installPowerDNS]")
            logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
                                                      '[ERROR] ' + str(msg) + " [installPowerDNS][404]")
            return 0

    def installPowerDNSConfigurations(self, mysqlPassword):
        try:

            ### let see if this is needed the chdir
            cwd = os.getcwd()
            os.chdir('/usr/local/CyberCP/install')
            if ProcessUtilities.decideDistro() == ProcessUtilities.centos or ProcessUtilities.decideDistro() == ProcessUtilities.cent8:
                dnsPath = "/etc/pdns/pdns.conf"
            else:
                dnsPath = "/etc/powerdns/pdns.conf"
                # Ensure directory exists for Ubuntu
                dnsDir = os.path.dirname(dnsPath)
                if not os.path.exists(dnsDir):
                    try:
                        os.makedirs(dnsDir, mode=0o755)
                    except OSError as e:
                        if e.errno != errno.EEXIST:
                            raise

            import shutil
            # Backup existing config if it exists
            if os.path.exists(dnsPath):
                try:
                    shutil.move(dnsPath, dnsPath + '.bak')
                except:
                    os.remove(dnsPath)
            
            shutil.copy("dns-one/pdns.conf", dnsPath)
            
            # Verify the file was copied and has MySQL backend configuration
            try:
                with open(dnsPath, "r") as f:
                    content = f.read()
                    if not content or "launch=gmysql" not in content:
                        writeToFile.writeToFile("PowerDNS config incomplete, attempting to fix...")
                        logging.InstallLog.writeToFile("PowerDNS config incomplete, fixing...")
                        
                        # Directly write the essential MySQL configuration
                        mysql_config = """# PowerDNS MySQL Backend Configuration
launch=gmysql
gmysql-host=localhost
gmysql-port=3306
gmysql-user=cyberpanel
gmysql-password=""" + mysqlPassword + """
gmysql-dbname=cyberpanel

# Basic PowerDNS settings
daemon=no
guardian=no
setgid=pdns
setuid=pdns
"""
                        # Write complete config
                        with open(dnsPath, "w") as f:
                            f.write(mysql_config)
                        
                        writeToFile.writeToFile("MySQL backend configuration written directly")
            except Exception as e:
                writeToFile.writeToFile("Warning: Could not verify config content: " + str(e))
                # Continue anyway as the file copy might have worked

            data = open(dnsPath, "r").readlines()

            writeDataToFile = open(dnsPath, "w")

            dataWritten = "gmysql-password=" + mysqlPassword + "\n"

            for items in data:
                if items.find("gmysql-password") > -1:
                    writeDataToFile.writelines(dataWritten)
                else:
                    writeDataToFile.writelines(items)

            # if self.distro == ubuntu:
            #    os.fchmod(writeDataToFile.fileno(), stat.S_IRUSR | stat.S_IWUSR)

            writeDataToFile.close()

            if self.remotemysql == 'ON':
                command = "sed -i 's|gmysql-host=localhost|gmysql-host=%s|g' %s" % (self.mysqlhost, dnsPath)
                ProcessUtilities.executioner(command, 'root', True)

                command = "sed -i 's|gmysql-port=3306|gmysql-port=%s|g' %s" % (self.mysqlport, dnsPath)
                ProcessUtilities.executioner(command, 'root', True)

            # Set proper permissions for PowerDNS config
            if ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu or ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu20:
                # Ensure pdns user/group exists
                command = 'id -u pdns &>/dev/null || useradd -r -s /usr/sbin/nologin pdns'
                ProcessUtilities.executioner(command, 'root', True)
                
                command = 'chown root:pdns %s' % dnsPath
                ProcessUtilities.executioner(command, 'root', True)
                
                command = 'chmod 640 %s' % dnsPath
                ProcessUtilities.executioner(command, 'root', True)

            return 1
        except IOError as msg:
            logging.CyberCPLogFileWriter.writeToFile('[ERROR] ' + str(msg) + " [installPowerDNSConfigurations]")
            logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
                                                      '[ERROR] ' + str(msg) + " [installPowerDNSConfigurations][404]")
            return 0

    def startPowerDNS(self):

        ############## Start PowerDNS ######################

        command = 'systemctl enable pdns'
        ProcessUtilities.executioner(command)

        # Give PowerDNS time to read configuration
        import time
        time.sleep(2)

        command = 'systemctl start pdns'
        result = ProcessUtilities.executioner(command)
        
        # Check if service started successfully
        command = 'systemctl is-active pdns'
        output = ProcessUtilities.outputExecutioner(command)
        
        if output.strip() != 'active':
            logging.CyberCPLogFileWriter.writeToFile('[ERROR] PowerDNS failed to start. Service status: ' + output)
            logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
                                                      '[ERROR] PowerDNS service failed to start properly [404]')
            return 0

        return 1

    def ResetDNSConfigurations(self):
        try:

            ### Check if remote or local mysql

            passFile = "/etc/cyberpanel/mysqlPassword"

            try:
                jsonData = json.loads(ProcessUtilities.outputExecutioner('cat %s' % (passFile)))

                self.mysqluser = jsonData['mysqluser']
                self.mysqlpassword = jsonData['mysqlpassword']
                self.mysqlport = jsonData['mysqlport']
                self.mysqlhost = jsonData['mysqlhost']
                self.remotemysql = 'ON'

                if self.mysqlhost.find('rds.amazon') > -1:
                    self.RDS = 1

                ## Also set localhost to this server

                ipFile = "/etc/cyberpanel/machineIP"
                f = open(ipFile)
                ipData = f.read()
                ipAddressLocal = ipData.split('\n', 1)[0]

                self.LOCALHOST = ipAddressLocal
            except BaseException as msg:
                self.remotemysql = 'OFF'

                if os.path.exists(ProcessUtilities.debugPath):
                    logging.CyberCPLogFileWriter.writeToFile('%s. [setupConnection:75]' % (str(msg)))

            logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Removing and re-installing DNS..,5')

            if self.installPowerDNS() == 0:
                logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
                                                          'installPowerDNS failed. [404].')
                return 0

            logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Resetting configurations..,40')

            import sys
            sys.path.append('/usr/local/CyberCP')
            os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
            from CyberCP import settings

            logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Configurations reset..,70')

            if self.installPowerDNSConfigurations(settings.DATABASES['default']['PASSWORD']) == 0:
                logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'installPowerDNSConfigurations failed. [404].')
                return 0

            if self.startPowerDNS() == 0:
                logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
                                                          'startPowerDNS failed. [404].')
                return 0

            logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Fixing permissions..,90')

            ACLManager.fixPermissions()
            logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Completed [200].')

        except BaseException as msg:
            final_dic = {'status': 0, 'error_message': str(msg)}
            final_json = json.dumps(final_dic)
            return HttpResponse(final_json)

def main():

    parser = argparse.ArgumentParser(description='CyberPanel')
    parser.add_argument('function', help='Specify a function to call!')
    parser.add_argument('--tempStatusPath', help='Path of temporary status file.')

    args = parser.parse_args()

    if args.function == "ResetDNSConfigurations":
        extraArgs = {'tempStatusPath': args.tempStatusPath}
        ftp = DNSManager(extraArgs)
        ftp.ResetDNSConfigurations()

if __name__ == "__main__":
    main()