Welcome To Our Shell

Mister Spy & Souheyl Bypass Shell

Current Path : /home/ift/

Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64
Upload File :
Current File : //home/ift/kto11.py

#  coding:  utf
import os,sys,re,glob,time,base64,hashlib,random

#******************************************************************************

class Kto9 ():

    def mark (self,remark=""):
    
        t = time.perf_counter()
        if 't0' in vars(self):
            print ( ("%9.2f" % ((t-self.t0)*1000)) + " ms for:  " + remark )
        self.t0 = t

#******************************************************************************

    def parse_pattern (self,pattern=""):    #   parse the pattern

        self.interval = None
        self.pattern  = pattern
        m = re.search(r"^(.*)([\.\:])(.*)$",pattern)
        
        if m:

            self.pattern  = m.group(1)
            mode          = m.group(2)
            interval      = "20" + m.group(3)[0:2]
            months        = m.group(3)[2:]
            
            if   months == "A":
                months = "10"
            elif months == "B":
                months = "11"
            elif months == "C":
                months = "12"
            elif months == "I":
                months = "0[123]"
            elif months == "J":
                months = "0[456]"
            elif months == "K":
                months = "0[789]"
            elif months == "L":
                months = "1[012]"
            elif months == "M":
                months = "0[123456]"
            elif months == "N":
                months = "[01][789012]"
            elif months == "P":
                months = ""
            elif not months == "":
                months = "0" + months
        
            if mode == ":":
                intervals = []
                jahr      = "2000"
                while (0 == 0):
                    intervals.append(jahr)
                    jahr = str(int(jahr)+1)
                    if jahr == interval:
                        break
                month = "01"
                while (0 == 0):
                    intervals.append(jahr+month)
                    if month in (months,"12"):
                        break
                    month = "%02u" % (int(month) + 1)
                self.interval = "\\(" + "\\|".join(intervals) + "\\)"
#                print(self.interval)
                self.egrep    = "e"
            else:
                self.interval = interval + months
                self.egrep    = ""
            
#******************************************************************************

    def kto_match (self,file):   #  deliver the matching part of database

        pattern1 = re.sub(r"\^"," ",self.pattern,9999)
#        print(pattern1,file)
        if self.interval:
            if self.pattern == "":
                self.text_match = os.popen(self.egrep+"grep -i ^"+self.interval + " " + file).read()
            else:
                self.text_match = os.popen(self.egrep+"grep -i ^"+self.interval + " " + file + " | grep -i '" + pattern1 + "'").read()
        else:
            if self.pattern == "":
                self.text_match = open(file).read()
            else:
                self.text_match = os.popen("grep -i '" + pattern1 + "' " + file).read()

#******************************************************************************

    def kto_rest (self,file):   #   deliver the rest of the database, not matched by the pattern

        pattern1 = re.sub(r"\^"," ",self.pattern,9999)

        if self.interval:
            if self.pattern == "":
                self.text_rest  = os.popen(self.egrep+"grep -i -v ^"+self.interval + " " + file).read()
            else:
                self.text_rest  = ( os.popen(self.egrep+"grep -i -v ^"+self.interval + " " + file).read() + 
                                    os.popen(self.egrep+"grep -i ^"   +self.interval + " " + file + 
                                        " | grep -i -v '" + pattern1 + "'").read() )
        else:
            if self.pattern == "":
                self.text_rest  = ""
            else:
                self.text_rest  = os.popen("grep -i -v '" + pattern1 + "' " + file).read()
        
#******************************************************************************

    def sync (self,file="",file0="",pattern_new="",add_string=""):

        if file == "m":
            paths = ['*/*/*/*/*/*/*/*/*/*/',
                     '*/*/*/*/*/*/*/*/*/',
                     '*/*/*/*/*/*/*/*/',
                     '*/*/*/*/*/*/*/',
                     '*/*/*/*/*/*/',
                     '*/*/*/*/*/',
                     '*/*/*/*/',
                     '*/*/*/',
                     '*/*/',
                     '*/'
#                     ,'.'
                     ]
            ktodir = []
                     
            for path in paths:
                for dir in glob.glob(path):
                    if not os.path.isdir(dir):
                        continue
                    if len(glob.glob(dir+"/*.kto")) == 0:
                        continue
                    ktodir.append(dir)
#                    print(dir)
            self.multisync(ktodir)
            return()
                        

        self.mark("O. Start sync")
        self.ukto = None
        id        = None

        zaehler = 0
        file1   = file0
        while (0 == 0):
            db_ktobase = glob.glob(file0+"/*.db.kto")
            if len(db_ktobase) == 1:
                file0 = db_ktobase[0]
            if os.path.isfile(file0):
                break
            file0 = file0 + "/.." 
            zaehler = zaehler + 1
            if zaehler == 20:
                file0 = file
            if zaehler > 40:
                if pattern_new == "":
                    id = self.sync(file,".",file1)
                else:
                    print("no parent file found: " + file0)
                return(id)

        if os.path.isdir(file):
            file1 = glob.glob(file+"/*.kto")
            if len(file1) > 1:
                print("More than one ktofile.")
                return()
            if len(file1) == 0:
                file = file + "/kto.kto"
            else:
                file = file1[0]

        if not re.search(r"\.kto$",file):
            id = self.sync(".",file0,file)
            return(id)


        if not os.path.isfile(file):
            self.parse_pattern(pattern_new)
            self.kto_match(file0)
            open(file,"w").write("     " + pattern_new + "\n" + self.text_match)
            return(None)

        text    = open(file)
        keyline = text.readline()
        text    = text.read()
        text2   = keyline + text
        pattern = ""

        m = re.search(r"\((\S\S\S\S\S\S)\) +(\S+)",keyline)
        if not m:
            m = re.search(r"\((\S\S\S\S\S\S)\)",keyline)
        elif pattern == "":
            pattern = m.group(2)
        if not m:
            if re.search(r"^ +(\S+) *$",keyline):
                pattern = keyline.strip()
            else: 
                text = keyline + text

        if pattern_new == "":
            pattern_new = pattern

        if pattern_new == "":
            print("No pattern in file: "+file)
            os.system("mv "+file+" "+file+".DELETE")
            return()
       
        self.parse_pattern(pattern_new)
        self.mark("A. Parse pattern")

        self.kto_match(file0)
        if not pattern_new == pattern:   # neues Pattern, daher Datei neu anlegen
#            self.kto_match(file0)
            open(file,"w").write("     " + pattern_new + "\n" + self.text_match)
            return()

        if not m:
#            self.kto_match(file0)
            if not text == self.text_match:
                self.kto_rest(file0)
                open(file0,"w").write(self.text_rest + text)
                open(file,"w").write("    (xxxxxx)\n\n"+text)
                return()
            key = "xxxxxx"
            id  = "yyyyyy"
        else:
            key  = m.group(1)
            id   = self.make_id(0,text.strip()+add_string)
        
#        print("KKK",key,id)
        rule_file_exists = False
        abs_file         = os.path.abspath(file)
        m = re.search(r"^(.*)[\\\/](.*)$",abs_file)
        if m:
            rule_dir         = m.group(1)
            file1            = m.group(2)
            try:
                self.rules_done
            except:
                self.rules_done = []
            rule_file_exists = os.path.isfile(rule_dir+"/rule.xxxx") and not rule_dir in (self.rules_done)

        self.rule_executed = 0
        if not id  == key:
            if not key == "_rule_" and m:
                if rule_file_exists:
                    orig_dir = os.path.relpath(".",rule_dir)
                    os.chdir(rule_dir)
                    print( os.popen("python3 rule.py " + file1).read() )
                    self.mark("  ... apply rule.")
                    os.chdir(orig_dir)
                    text = open(file)
                    text.readline()
                    text = text.read()
                    if len(text) == 0:
                        text = " "
                    self.rule_executed = 1
                    self.rules_done.append(rule_dir)
            if self.rule_executed == 0:
                os.unlink(file)
                text = self.format_kto(text)

        else:
            self.kto_match(file0)
            os.unlink(file)
            text = self.format_kto(self.text_match,text.split("\n"))


        if not text == None: #  and len(text) > 0:

            self.kto_rest(file0)

            if self.rule_executed == 0:
                text0 = self.text_rest + text
                open(file0,"w").write(text0)

            id0 = id
            if self.rule_executed == 1:
                id = "_rule_"
            else:
                id = self.make_id(0,text.strip()+add_string)
#                print("XXX",key,id0,id)
                if not id0 == id and not key == "_rule_" and not id == key and rule_file_exists:
                    id = "_chng_"
                    self.mark("  ... prepare for rule.")

            if self.ukto:
                open(file,"w").write(("%-25s" % self.ukto) + "  " + "(" + id + ")   " +
                                      pattern + " " + self.last_sum + "\n\n"+text)
            else:
                open(file,"w").write("    (" + id + ")   " + pattern + "\n\n"+text)
            return(id)

        else:
            open(file,"w").write(text2)
            
        

        if self.ukto:
            return(id)
        else:
            return(None)
        
#****************************************************************************************

    def make_id (self,mode,text):
    
        profile = False
        if profile:
            self.mark("--1")
            
        if mode == 9:
            text = text.replace("  ","")  #  for performance reasons, this line doubles the speed!
            text = text.replace(" ","").split("\n")
            if profile:
                self.mark("--2")
            text.sort()
            text1 = []
            for line in text:
                line1 = list(line)
                line1.sort()
                text1.append("".join(line))
            if profile:
                self.mark("--3")
            text = "\n".join(text1)
            if profile:
                self.mark("--4")

        if mode == 1:
#            text = text.replace("  ","")  #  for performance reasons, this line doubles the speed!
#            text = text.replace(" ","").split("\n")
            text1 = []
            for line in text.split("\n"):
                m = re.search("^(\d\d\d\d\d\d\d\d) +\-?(\d+\.\d\d) +(\S+) +(\S+) +\S+ +(.*?) *$",line)
                if m:
                    line1 = [m.group(3),m.group(4)]
                    line1.sort()
                    line1 = [m.group(1) + m.group(2)] + line1 + [m.group(5)]
#                    line1.sort()
                    text1.append("".join(line1))
            text1.sort()
            text = "\n".join(text1)
                
        if mode == 2:
            text1 = []
            elements = []
            
            for line in text.split("\n")+["99999999"]:
                if len(line) == 8:
                    if re.search(r"^\d\d\d\d\d\d\d\d$",line):
                        if len(elements) > 0:
                            elements_a = elements[1:2]
                            elements_a.sort()
                            elements   = [ elements[0] ] + elements_a + elements[3:]
                            text1.append("".join(line))
                            elements = [line]
                else:
                    elements.append(line)
            text1.sort()
            text = "\n".join(text1)
                

        text = text.replace("  ","")  #  for performance reasons, this line doubles the speed!
        text = text.replace(" ","") 
        text = text.replace("\n","XX\n") 
        id = str( base64.urlsafe_b64encode(hashlib.md5( text.encode("utf-8")).digest()),"ascii" )[0:6]
        if profile:
            self.mark("--5")
        return(id)

#****************************************************************************************

    def make_db (self,text):
    
        self.mark("--1")
        text = re.sub(r"(\d\d\d\d\d\d\d\d) +(\d+\.\d\d) +(\S+?) +(\S+?) +(\-?\d+\.\d\d) +(.*?) *","---\\1.\\2.\\3.\\4.\\6",text,99999999)
        text = re.sub(r"(\d\d\d\d\d\d\d\d) +-(\d+\.\d\d) +(\S+?) +(\S+?) +(\-?\d+\.\d\d) +(.*?) *","---\\1.\\3.\\2.\\4.\\6",text,99999999)
        self.mark("--2")
        print(text)
        self.mark("--3")

#****************************************************************************************

    def format_kto (self,text,ktotext_old=[]):

        result = self.parse_ktotext(text.split("\n"),self.pattern,ktotext_old)
        self.mark("B. parse ktotext.")
        if not result:
            return(None)
            
        (ktotext,format_maxa,format_maxb,maxsaldo,ukto) = result
            
        print("UKTO: " + ukto)
        if ukto == "":
            ktotext.sort(key=lambda x:x[0]+str(x[1])+x[3]+x[4])
        else:
#            if ukto.startswith("10-B12-3695-qu"):
#                ktotext.sort(key=lambda x:str(abs(float(x[1])))+str(x[5]+1)+x[0])
#            else:
                ktotext.sort(key=lambda x:str(x[5]+1)+x[0])
        text_match = []
        gesamt     = 0.00
        datum0     = "00000000"
        self.ukto0 = ukto
        salden     = {}

        for zeile in ktotext:
                
            if zeile[5] == -1:
                text_match.append(zeile[1])
            else:
                betrag = float(zeile[1])
                if ukto == "" or zeile[5] == 0:
                    saldo = "         ...."
                elif maxsaldo == 0 or zeile[5] == 1:
                    gesamt = gesamt + betrag
                    saldo  = "%13.2f" % gesamt
                elif zeile[5] == 2:
                    saldo = "         0.00"
                ust = ""
                if "v.H." in zeile[4]:
                    ust = "   "

                ktoa = zeile[2]
                if ktoa[0] == "-":
                    self.rule_executed = 1
                    if ktoa == "-":
                        ktoa = ukto
                    else:
                        ktoa = ukto + ktoa
                self.compute_salden(salden,ktoa,betrag,zeile[0])
                ktob = zeile[3]
                if ktob[0] == "-":
                    self.rule_executed = 1
                    if ktob == "-":
                        ktob = ukto
                    else:
                        ktob = ukto + ktob
                self.compute_salden(salden,ktob,-betrag,zeile[0])

                zeile1 = ( zeile[0] + " " + ("%13.2f" % betrag) + "  " + (format_maxa % ktoa) + "  " +
                           (format_maxb % ktob) + " " + saldo + "  " + ust + re.sub(r" +"," ",zeile[4],9999) )
                text_match.append(zeile1)

        self.ukto = ukto
        if ukto == "":
            self.last_sum = ""
        else:
            self.last_sum = "%20.2f" % gesamt

        ktoliste = list(salden.keys())
        ktoliste.sort()
        text_match.append("")
        
        ktotyp =  ["^[^-]+","xxB12-3695","C13-3751","C13-3759","C13-3740","B12-1361",
                            "C11-3170","C12-3310","B12-1435","B12-1340","B12-3695","Do.-4600","Do.-4610",
                            "Do.-6011","Do.-6111","Do.-6816","Do.-6817","Do.-6818",
                            "Bo.-ver","Bo.-kto","Bo.-umlagen","Bo.-1700",
                            "D..-4100","D..-4105","D..-4106","D..-4400"]
        

        text_match.append("                  " + ("%13.2f" % gesamt))
        
        for kto in ktoliste:

            bed = 0
            if not "-" in kto:
                bed = 1
            else:
                for ktyp in ktotyp:
                    if re.search("^"+ktyp+r"-[^\-]+$",kto):
                        bed = 1
                        break
            if bed == 0:
                continue

            kto_ordnung = max(0,len(re.sub("[^\-]","",kto)))
            if kto_ordnung > 3:
                continue
            kto_ordnung = "%-" + ("%2u"%(20+kto_ordnung*4)) + "s"
            text_match.append( (kto_ordnung % kto) + "  " + ("%13.2f" % salden[kto]["XX"]) )

        self.mark("C. format kto")
        return("\n".join(text_match) + "\n")

#******************************************************************************

    def compute_salden (self,salden,ukto,betrag,datum):

        monat = datum[4:6]
        monat = "XX"

        ukto = re.sub(r"-qu-","-",ukto)

        if ukto.startswith(self.ukto0+"-"):
            ukto = re.sub("^"+self.ukto0+"-","",ukto)
        else:
            return()
#        ukto = re.sub(r"^(.*?)\-(.*)$","\\1",ukto)


        while (0 == 0):
            if not ukto in salden:
                salden[ukto] = {}
            if not monat in salden[ukto]:
                salden[ukto][monat] = 0.00
            salden[ukto][monat] = salden[ukto][monat] + betrag

            m = re.search(r"^(.*)\-(.+)$",ukto)
#            if not m:
#                m = re.search(r"^(.*?)(.+)$",ukto)
            if m:
                ukto = m.group(1)
            else:
                return()

#            return()

#******************************************************************************

    def parse_ktotext (self,ktotext,pattern,ktotext_old=[]):

        buchungen      = []
        unique_strings = {}
        pattern        = pattern.strip().upper()
        if len(pattern) > 0 and pattern[-1] == "-":
            pattern = pattern[:-1]
        maxa           = 10
        maxb           = 10
        maxc           = 0
        maxd           = 0
        maxsaldo       = 0

        ukto = ""
        if pattern == "":
            ukto = None
            
#        ktotext_old.sort()
        
        self.kto_is_up_to_date_until_now = int(not ktotext_old == [])
        
        zaehler = -1
        vvv = re.compile(r"^(\d\d\d\d)(..)(\d\d) +(\S+) +(\S+) +(\S+) +(\-?\d+\.\d\d|\-+|\.+) +(.*?) *$")
#        ktotext.sort()
        for zeile in ktotext:

            mm = vvv.search(zeile)
            if not mm:   #   Einlesen der Kontobezeichnungen
#                buchungen.append(["00000000",zeile,"","","",-1])
                continue

            if mm.group(2) == "MM":
                monate = ["01","02","03","04","05","06","07","08","09","10","11","12"]
            else:
                monate = [mm.group(2)]

            for monat in monate:

                datum  = mm.group(1) + monat + mm.group(3)
                try:
                    betrag = "%3.2f" % eval(mm.group(4))
                except:
                    print(mm.group(4))
                    exit()

                remark   = mm.group(8)
                uniqu    = []
                ktoa     = "^" + mm.group(5)
                ktob     = "^" + mm.group(6)

#                ktoa = self.parse_ktotext_compute_kto(m.group(5),self.ukto,uniqu)
#                ktob = self.parse_ktotext_compute_kto(m.group(6),self.ukto,uniqu)

                if ktoa > ktob:
                    o      = ktoa    #  um Eindeutigkeit zu schaffen. Sonst kann es durch
                    ktoa   = ktob    #  Hin- und Herschwingen zu Endlos-Loops kommen
                    ktob   = o
                    betrag = re.sub(r"^--","","-"+betrag)

                if not ktoa[1] == "-" and not pattern in ktoa.upper() and pattern in ktob.upper():
                    o      = ktoa    #  um das gefundene Konto an den Anfang zu stellen
                    ktoa   = ktob
                    ktob   = o
                    betrag = re.sub(r"^--","","-"+betrag)

                saldo = 0
#                print(zeile)
                if not ukto == None:
                    
                    if ukto == "":
                        if pattern in ktoa.upper() and not ktoa[1] == "-":
                            ukto = ktoa
                    for kto in (ktoa,ktob):
                        if pattern in kto.upper() and not kto[1] == "-":
                            while (0 == 0):
                                if kto.startswith(ukto):
                                    break
                                m = re.search(r"^(.*)\-(.*)$",ukto)
                                if m:
                                    ukto = m.group(1)
                                else:
                                    ukto = ""
                                print("           fit ukto: " + ukto.replace("^",""))
                            if not pattern in ukto.upper():
                                ukto = None
                                print("No ukto found.")
                            break

#                print(123)
                if ukto:
                    while (0 == 0):
#                        print(pattern,ukto)
                        m = re.search(r"^(.*)\-(.*)$",ukto)
                        if not m or not pattern in m.group(1).upper():
                            break
                        ukto = m.group(1)
                

                if ukto or ktoa[1] == "-":
                    saldo = ( int( ukto and ktoa.startswith(ukto) or ktoa[1] == "-") +
                              int( ukto and ktob.startswith(ukto) or ktob[1] == "-") )
#                    print(ktoa,ktob,ukto,saldo,betrag)
                    
                if uniqu == []:
                    uniqu = [ktoa,ktob]

                maxsaldo = max(maxsaldo,saldo)
                uniqu1  = []
                for k in uniqu:
                    uniqu1.append(re.sub(r"\-\d\d\d\d\d$","-BETRAG",k))
                uniqu   = uniqu1

                betrag1 = re.sub("\-","",betrag) + ","
                remark1 = "," + re.sub(r"[\+\- ]","",remark,9999)
                uniqu   = betrag1 + ",".join(uniqu) + remark1

                if datum in unique_strings:  #  to avoid double entries
                    if uniqu in unique_strings[datum]:
                        continue  #  der Eintrag mit diesem unique-String existiert schon, daher nicht nochmal nehmen
                    else:
                        unique_strings[datum].append(uniqu)
                else:
                    unique_strings[datum] = [uniqu]

                ktoa = ktoa.replace("^","")
                ktob = ktob.replace("^","")

                if ktoa[0] == "-":
                    maxc = max(maxc,len(ktoa))
                else:
                    maxa = max(maxa,len(ktoa))
    
                if ktob[0] == "-":
                    maxd = max(maxd,len(ktob))
                else:
                    maxb = max(maxb,len(ktob))

                buchungen.append([datum,betrag,ktoa,ktob,remark,saldo])
#                print(buchungen[-1])
 
#   ---- additional check

                if self.kto_is_up_to_date_until_now:
                    while (0 == 0):
                        zaehler = zaehler + 1
                        if zaehler < len(ktotext_old):
                            line = ktotext_old[zaehler]
                        else:
                            m1   = None
                            break
                        m1 = re.search("^(\d\d\d\d\d\d\d\d) +(\-?\d+\.\d\d) +(\S+) +(\S+) +(\S+) +(.*?) *$",line)
                        if m1:
                            break
                
                    if m1:
                        datum1  = m1.group(1)
                        betrag1 = m1.group(2)
                        ktoa1   = m1.group(3)
                        ktob1   = m1.group(4)
                        remark1 = m1.group(6)
#                        print(line)
#                        print(zeile)
#                        print(datum,datum1)
#                        print(betrag,betrag1)
#                        print(ktoa,ktoa1)
#                        print(ktob,ktob1)
#                        print(remark,remark1)
                        if ( not datum1 == datum or not betrag1 == betrag or not remark1 == remark or
                             not ktoa in (ktoa1,ktob1) or not ktob in (ktoa1,ktob1) ):
                                 self.kto_is_up_to_date_until_now = False
#                                 print(line)
#                                 print(zeile)
                    else:
                        self.kto_is_up_to_date_until_now = False
#                    print(self.kto_is_up_to_date_until_now)
                        
        if self.kto_is_up_to_date_until_now:
            return(None)
        
        
        if ukto == None:
            ukto = ""
        ukto = ukto.replace("^","")

        if maxc > 0:
            maxa = max(maxa,len(ukto)+maxc)
        if maxd > 0:
            maxb = max(maxb,len(ukto)+maxd)

        format_maxa = "%-" + str(maxa) + "s"
        format_maxb = "%-" + str(maxb) + "s"
        return(buchungen,format_maxa,format_maxb,str(maxsaldo),ukto)

#******************************************************************************

    def xxyy (self,file=".",pattern=None):    #   file: Ziel
    
        self.mark("")

        if os.path.isdir(file):    #  file is a dir
            dir  = file
            file = dir + "/standard.kto"
        else:                      #  file is a file
            if pattern:
                dir = file
                try:
                    os.mkdir(file)
                except:
                    pass
                file = dir + "/standard.kto"
            else:            
                m = re.search(r"^(.*)[\\\/](.*)$",file)
                if m:
                    dir = m.group(1)
                else:
                    dir = "."

        files = glob.glob(dir+"/*.kto")
        if len(files) == 0:
            if pattern:
                try:
                    os.mkdir(dir)
                except:
                    pass
                try:
                    open(file,"w").write("")
                except:
                    print("File " + file + " not able to create.")
                    return()
            else:
                print("No ktofile found.")
                return()            
        
        elif len(files) > 1:
            print("More than one ktofile found: " + " ".join(files))
            return()

        else:
            file   = files[0]
            header = open(file).readline()
            header = re.sub(r"\-?\d+\.\d\d *$","",header)
            m = re.search(r"^(\S*) *(\(.*?\)) +(.*?) *$",header)
            if m:
                if pattern:
                    if not m.group(3) == pattern:
                        if os.path.isfile(file):
                            os.unlink(file)
                else:
                    pattern = m.group(3)
                self.mark("Kto " + m.group(1) + " found.")

            m = re.search(r"^(.*[\\\/])(.*?)[\\\/](|pattern_)([^\\\/]+)\.kto$",os.path.abspath(file))
            if m:
                os.system("touch " + m.group(1) + m.group(2) + "/" + "rule.py")
                if not pattern:
                    pattern = re.sub(r"\.\.",":",m.group(4),99)
                    pattern = re.sub(r"^\_","\^",pattern,99)
            
        dir0    = dir    #  find the source kto
        ruledir = None
        if os.path.isfile(dir+"/rule.py") or dir[0:4] == "rule":
            ruledir = dir

        absdir0 = ""
        while (0 == 0):   #   try to find a parent file, starting with the parent directory of dir
            dir0    = dir0 + "/.."
            absdir = os.path.abspath(dir0)
            print("    ... searching parent directory in " + absdir + " ...")  #   + re.sub(r"^(.*)([\\\/].*)$","\\2",file0) )
            if absdir == absdir0:
                print("No parent ktofile found.")
                return()
            absdir0 = absdir
            if not os.path.isdir(dir0):
                break
            files = glob.glob(dir0+"/*.kto")
            for file0 in files:
                if re.search(r"[\\\/]no\.kto$",file0):
                    print("No ktofile directories region from here.\n    ... give it up in " + absdir + ".")
                    return()
                if not pattern:
                    pattern0 = self.find_pattern_from_udir( os.path.relpath(dir0,dir))   #  not yet implemented
                else:
                    pattern0 = pattern
                erg = self.sync(pattern0,file0,file,"",ruledir)
                if not erg == 4:
                    return(erg)
#            print("Failing to find parent kto in " + absdir + ".\n    ... now try next uppermost parent ktofile directory.")
                

#******************************************************************************

    def multisync (self,ktolist):
    
        ktoids      = {}
        kto_in_work = []
        for kto in ktolist:
            if re.search(r"(^|[\\\/])_[^\\\/]+_([\\\/]|$)",kto):
                continue
            kto_in_work.append(re.sub(r"^(.*)[\\\/](.*.kto)$","\\1",kto))
            print(kto_in_work[-1])

        zaehler = 0
        while (0 == 0):
            if len(kto_in_work) == 0:
                break
            zaehler = (zaehler + 1) % len(ktolist)
#            round   = int((zaehler + 1) / len(kto_in_work)) + 1
            kto     = ktolist[zaehler]
            if not kto in kto_in_work:
                continue
            if len(glob.glob(kto+"/*.kto")) == 0:
                continue
#            bed = False
            while (0 == 0):
                id = self.sync(kto)
                if not id: # if not id in ["_rule_","_chng_"]:  #  technische id
                    break
#                if not id in ["_rule_","_chng_"]:

            if kto in kto_in_work:
                kto_in_work.remove(kto)
#            if not id:  
#                continue
            kto_in_work.append(kto)

            if not kto in ktoids:
                ktoids[kto] = []

            ktoids[kto].append(id)
            print(len(ktoids[kto]),"----",id,kto)
            if len(ktoids[kto]) > 1 and ktoids[kto][-2] == ktoids[kto][-1]:
                kto_in_work.remove(kto)
                
#                print(ktoids[kto])
#                if len(ktoids[kto]) == 0:
#                    ktoids[kto].append(id)
#                else:
#                    ktoids[kto] = [  ktoids[kto][-1],id ]
#                if not ktoids[kto][0] == ktoids[kto][1]:
#                    kto_in_work.append(kto)
                
#******************************************************************************

    def xxy (self,pattern=None,par=None):
    
        if par:
            dir     = pattern
            pattern = par
            try:
                os.system("mkdir "+dir)
            except:
                pass
            files = glob.glob(dir+"/*.kto")
            if len(files) > 1:
                print("More than one file in " + dir)
                return()
            if len(files) == 1:
                file = files[0]
                os.unlink(file)
            else:
                file = dir + "/" + pattern + ".kto"
            open(file,"w").write(" ")
            pattern = dir
    
        if pattern and (os.path.isdir(pattern) or os.path.isdir(pattern)):
            self.yy(pattern)   #   pattern is a file or a directory
            return()
            
        if not pattern:
            self.yy()
            return()

#        if not os.path.isdir("99_tmp"):
#            os.mkdir("99_tmp")

        tmp_dir = re.sub(r"\:","__",pattern)
        tmp_dir = "99_tmp/" + re.sub(r"[^0-9a-zA-Z\\\/]","_",tmp_dir)

#        last_dir = ""
#        for file in glob.glob("tmp_*/rule.py"):
#            last_dir = re.sub(r"[\\\/]rule.py","",file)
#            os.unlink(file)

        self.yy(tmp_dir,pattern)
        os.system("joe " + tmp_dir + "/standard.kto")

        for file in glob.glob("99_tmp/*/rule.py"):
            os.unlink(file)
        
        os.system("touch " + tmp_dir + "/rule.py")

        self.yy(tmp_dir,pattern)

#******************************************************************************

    def xxread_file (self,file=None):

        if not file:
            files = glob.glob("*.kto")
            if len(files) == 1:
                file = files[0]
        text = open(file).read()
        
        try:
            pos   = text.index("====")
            text0 = text[0:pos]
            text  = text[pos:]
        except:
            text0 = ""
            
        text1 = []
        for zeile in text.split("\n"):
        
            if zeile.startswith("====") or zeile.strip() == "":
                continue
        
            m = re.search(r"^(\d\d\d\d\d\d\d\d)( +\S+)( +)(\S+ +)(\S+ +)(\-?\d+\.\d\d| +\-+| +\.+)( +)(.*)$",zeile)
            if not m:
                text1.append(zeile)
                continue
                
            datum  = m.group(1)
            betrag = m.group(2)
            zwa    = m.group(3)
            ktoa   = m.group(4)
            ktob   = m.group(5)
            saldo  = m.group(6)
            zwb    = m.group(7)
            remark = m.group(8)
            
            text1.append([datum,betrag,zwa,ktoa,ktob,saldo,zwb,remark])
            
        return(file,text0,text1)
        
#******************************************************************************

    def xxusteuer (self,einnahmenkto,ausgabenkto,gegenkto,file=None):
    
        (file,text0,text1) = self.read_file(file)
        einnahmen = {}
        ausgaben  = {}
        
        text2 = []
        for zeile in text1:
            if type(zeile) == type(""):
                text2.append(zeile)

            remark = zeile[7] 
            if "v.H." in remark:
                continue
                
            text2.append("".join(zeile))
            
            if remark[0:2] == '++':
                steuersatz = 19
                steuerart  = "6"
            elif remark[0:2] == '+-':
                steuersatz = 7
                steuerart  = "7"
            else:
                steuersatz = 0
                steuerart  = ""

            datum  = zeile[0]
            betrag = zeile[1]
            zwa    = zeile[2]
            ktoa   = zeile[3]
            ktob   = zeile[4]
            saldo  = zeile[5]
            zwb    = zeile[6]
            remark = remark[2:]
            jahr   = datum[0:4]

            format_ktoa   = "%-" + str(len(ktoa))   + "s"
            format_ktob   = "%-" + str(len(ktob))   + "s"
            format_betrag = "%"  + str(len(betrag)) + ".2f"
            betrag        = float(betrag)
#            ktoa          = ktoa.strip()
#            ktob          = ktob.strip()

            if not datum[0:4] in einnahmen:
                einnahmen[jahr] = 0.00
            if not datum[0:4] in ausgaben:
                ausgaben[jahr] = 0.00

            netto = betrag - betrag * steuersatz * 0.01 / (1.0 + steuersatz * 0.01)

            if ktoa.strip().startswith(einnahmenkto):
                einnahmen[jahr] = einnahmen[jahr] + netto
                if betrag > 0.0:
                    ktob = format_ktob % (gegenkto + "-I" + steuerart)
                    add  = "Vorst."
                else:
                    ktob = format_ktob % (gegenkto + "-U" + steuerart)
                    add  = "USt."

            elif ktoa.strip().startswith(ausgabenkto):
                ausgaben[jahr] = ausgaben[jahr] + netto
                if betrag < 0.0:
                    ktob = format_ktob % (gegenkto + "-U" + steuerart)
                    add  = "USt."
                else:
                    ktob = format_ktob % (gegenkto + "-I" + steuerart)
                    add  = "Vorst."

            elif ktob.strip().startswith(einnahmenkto):
                einnahmen[jahr] = einnahmen[jahr] - netto 
                if betrag < 0.0:
                    ktoa = format_ktoa % (gegenkto + "-U" + steuerart)
                    add  = "USt."
                else:
                    ktoa = format_ktoa % (gegenkto + "-I" + steuerart)
                    add  = "Vorst."

            elif ktob.strip().startswith(ausgabenkto):
                ausgaben[jahr] = ausgaben[jahr] - netto
                if betrag > 0.0:
                    ktoa = format_ktoa % (gegenkto + "-I" + steuerart)
                    add  = "Vorst."
                else:
                    ktoa = format_ktoa % (gegenkto + "-U" + steuerart)
                    add  = "USt."
                    
            else:
                continue
                
            if steuersatz == 0:
                continue

            ubetrag = format_betrag % (-betrag * steuersatz * 0.01 / (1.0 + steuersatz * 0.01) )

            zeile1 = datum  + ubetrag + zwa + ktoa + ktob + (" "*(len(saldo)-4)) + "0.00" + zwb + "    "
            zeile1 = zeile1 + str(steuersatz) + " v.H. " + add + " von " + '%3.2f' % abs(float(betrag))
            zeile1 = zeile1 + ' (' + remark + ')'
            text2.append(zeile1)
                
        brutto = ""
        jahre = list( einnahmen.keys() )
        jahre.sort()
        for jahr in jahre:
            brutto = brutto + jahr + "  " + ("%20.2f" % einnahmen[jahr] ) + "\n"
        open("einnahmen.txt","w").write(brutto)
        
        brutto = ""
        jahre = list( ausgaben.keys() )
        jahre.sort()
        for jahr in jahre:
            brutto = brutto + jahr + "  " + ("%20.2f" % ausgaben[jahr] ) + "\n"
        open("ausgaben.txt","w").write(brutto)
        
        text2 = "\n".join(text2) 
        if not text0.strip() == "":
            text2 = text0 + '====\n' + text2 + '\n'
        open(file,"w").write(text2)


#**************************************************************************************


    def xxsync (self,file,file1,pattern):

        text  = open(file).read()
        try:
            text1 = open(file1)
        except:
            text1 = None
            
        if text1:
            keyline = text1.readline()
            text1   = text1.read()
            m = re.search(r"\((\S\S\S\S\S\S)(\S\S\S\S\S\S)\)",keyline)
            if m:
                key0 = m.group(1)
                key1 = m.group(2)
            else:
                key0 = ""
                key1 = ""
                text1 = keyline + text1
            id0 = str( base64.urlsafe_b64encode(hashlib.md5( text1.encode("utf-8")).digest()),"ascii" )[0:6]

        text_match = []
        text_rest  = []
        
        for zeile in text.split("\n"):
            if re.search(pattern,zeile,re.IGNORECASE):
                text_match.append(zeile)
            else:
                text_rest.append(zeile)


        text_match.sort(key=lambda x: x[0:8])
        id1 = str( base64.urlsafe_b64encode(hashlib.md5( (pattern+"\n".join(text_match)).encode("utf-8")).digest()),"ascii" )[0:6]

#        print(id1,key1,id0,key0)
        if text1:
            if id1 == key1 or key1 == "":
                if id0 == key0:
                    return(0)
                else:
                    open(file,"w").write("\n".join(text_rest) + "\n" + text1)
                    print("update parent")
                    text1 = re.sub(r"^.*?\n(.*)$","\\1",text1) 
            elif id0 == key0:
                text1 = None
            else:
                print("CONFLICT")
                return(1)

        if not text1:
            text1 = "\n".join(text_match) + "\n"

        id0   = str( base64.urlsafe_b64encode(hashlib.md5( text1.encode("utf-8")).digest()),"ascii" )[0:6]
        text1 = "    ("+id0+id1+")\n" + text1
        open(file1,"w").write(text1)
        print("update ukto")
        return(0)

#******************************************************************************

    def xxsort (self,part,pattern="",file=None):

        if not file:
            files = glob.glob("*.kto")
            if len(files) == 1:
                file = files[0]

        interval      = None
        insertline    = "====  " + pattern + "\n"

        m = re.search(r"^(.*)([\.\:])(.*)$",pattern)
        if m:

            pattern  = m.group(1)
            mode     = m.group(2)
            interval = "20" + m.group(3)[0:2]
            months   = m.group(3)[2:]
            
            if   months == "A":
                months = "10"
            elif months == "B":
                months = "11"
            elif months == "C":
                months = "12"
            elif months == "I":
                months = "0[123]"
            elif months == "J":
                months = "0[456]"
            elif months == "K":
                months = "0[789]"
            elif months == "L":
                months = "1[012]"
            elif months == "M":
                months = "0[123456]"
            elif months == "N":
                months = "[01][789012]"
            elif months == "P":
                months = ""
            elif not months == "":
                months = "0" + months
        
            if mode == ":":
                intervals = []
                jahr      = "2000"
                while (0 == 0):
                    if jahr > interval:
                        break
                    intervals.append(jahr)
                    jahr = str(int(jahr)+1)
                interval = "\\(" + "\\|".join(intervals) + months + "\\)"
                e        = "e"
            else:
                interval = interval + months
                e        = ""
            
        pattern1 = re.sub(r"\^"," ",pattern,9999)

        if part in (1,2):
            if interval:
                if pattern == "":
                    text_match = os.popen(e+"grep ^"+interval + " " + file).read()
                else:
                    text_match = os.popen(e+"grep ^"+interval + " " + file + " | grep '" + pattern1 + "'").read()
            else:
                if pattern == "":
                    text_match = open(file).read()
                else:
                    text_match = os.popen("grep '" + pattern1 + "' " + file).read()

        if part in (1,2):
            if interval:
                if pattern == "":
                    if part in (1,2):
                        text_match = os.popen(e+"grep ^"+interval + " " + file).read()
                    if part in (0,2):
                        text_rest  = os.popen(e+"grep -v ^"+interval + " " + file).read()
                else:
                    if part in (1,2):
                        text_match = os.popen(e+"grep ^"+interval + " " + file + " | grep '" + pattern1 + "'").read()
                    if part in (0,2):
                        text_rest  = ( os.popen(e+"grep -v ^"+interval + " " + file).read() + 
                                       os.popen(e+"grep ^"+interval + " " + file + " | grep -v '" + pattern1 + "'").read() )
            else:
                if pattern == "":
                    text_match = open(file).read()
                    text_rest  = ""
                else:
                    text_match = os.popen("grep '" + pattern1 + "' " + file).read()
                    text_rest  = os.popen("grep -v '" + pattern1 + "' " + file).read()
            self.mark("B1.    grep")
        
            self.text_rest  = re.sub(r"\n====.*","",text_rest,9999)

            if not self.text_rest == "":
                self.text_rest = self.text_rest + insertline
#        self.text_match = re.sub(r"====.*\n","",text_match[0:100],9999) + text_match[100:]
            self.text_match = re.sub(r"====.*\n","",text_match,9999)
            self.mark("B2.    Combine")
            self.pattern = pattern

            self.mark("B1.    grep")
        
            self.text_rest  = re.sub(r"\n====.*","",text_rest,9999)

            if not self.text_rest == "":
                self.text_rest = self.text_rest + insertline
#        self.text_match = re.sub(r"====.*\n","",text_match[0:100],9999) + text_match[100:]
            self.text_match = re.sub(r"====.*\n","",text_match,9999)
            self.mark("B2.    Combine")
            self.pattern = pattern

        if part in (1,2):
            if interval:
                if pattern == "":
                    if part in (1,2):
                        text_match = os.popen(e+"grep ^"+interval + " " + file).read()
                    if part in (0,2):
                        text_rest  = os.popen(e+"grep -v ^"+interval + " " + file).read()
                else:
                    if part in (1,2):
                        text_match = os.popen(e+"grep ^"+interval + " " + file + " | grep '" + pattern1 + "'").read()
                    if part in (0,2):
                        text_rest  = ( os.popen(e+"grep -v ^"+interval + " " + file).read() + 
                                       os.popen(e+"grep ^"+interval + " " + file + " | grep -v '" + pattern1 + "'").read() )
            else:
                if pattern == "":
                    text_match = open(file).read()
                    text_rest  = ""
                else:
                    text_match = os.popen("grep '" + pattern1 + "' " + file).read()
                    text_rest  = os.popen("grep -v '" + pattern1 + "' " + file).read()
            self.mark("B1.    grep")
        
            self.text_rest  = re.sub(r"\n====.*","",text_rest,9999)

            if not self.text_rest == "":
                self.text_rest = self.text_rest + insertline
#        self.text_match = re.sub(r"====.*\n","",text_match[0:100],9999) + text_match[100:]
            self.text_match = re.sub(r"====.*\n","",text_match,9999)
            self.mark("B2.    Combine")
            self.pattern = pattern
        
#******************************************************************************

    def xxsync (self,pattern,file0,file,add_string="",ruledir=None):

        self.mark("A. Sync Start")
        self.sort(pattern,file0)
        self.mark("B. Sorting")
        
        id0 = self.make_id(self.text_match)
        
        self.text_match.replace(" ","")
        id0 = str( base64.urlsafe_b64encode(hashlib.md5( id0.encode("utf-8")).digest()),"ascii" )[0:6]
        self.mark("D. Compute db id")

#        expr = '"^20[0123456789][0123456789][0123456789][0123456789][0123456789][0123456789] " '
        if os.path.isfile(file):

            text    = open(file)
            keyline = text.readline()
            text    = text.read()

            if not re.search(r"\S",text):
            
                key0 = ""
                key  = ""
                id   = ""

            else:

                m = re.search(r"\((\S\S\S\S\S\S)(\S\S\S\S\S\S)\)",keyline)
                if m:
                    key0  = m.group(1)
                    key   = m.group(2)
                else:
                    key0  = id0
                    key   = ""
                    text  = keyline + "\n" + text

                id = text + add_string
                id = str( base64.urlsafe_b64encode(hashlib.md5(  id.encode("utf-8")).digest()),"ascii" )[0:6]

        else:

            key0 = ""
            key  = ""
            id   = ""

        self.mark("E. " + " ".join([id0,key0,id,key]))
        self.ukto     = ""
        self.last_sum = ""
        
        if id0 == key0:
            if id == key:
                open(file0,"w").write(self.text_rest + self.text_match)
                erg = 1   
            else:
                self.mark("F. Update database")
                if ruledir and os.path.isdir(ruledir):

                    dir9  = os.path.relpath(".",ruledir)
                    file1 = re.sub(r"^(.*)[\\\/](.*)$","\\2",file)
                    os.chdir(ruledir)
                    os.popen("python3 rule.py " + file1).read()
                    os.chdir(dir9)
                    self.mark("F1. ... apply rule.py")

                    text    = open(file).read()
                    text    = "\n" + self.format_kto(text.split("\n")[1:]).strip() + "\n"

#                    open(file,"w").write(text)
                    self.mark("F2. ... format kto")
                    id = text + add_string
                    id = str( base64.urlsafe_b64encode(hashlib.md5(  id.encode("utf-8")).digest()),"ascii" )[0:6]
                    self.mark("G. Compute kto id")
                text0 = os.popen("grep ^20 " + file).read()
#                id = text + add_string
#                id = str( base64.urlsafe_b64encode(hashlib.md5(  id.encode("utf-8")).digest()),"ascii" )[0:6]
                id0 = text0.replace(" ","")
                id0 = str( base64.urlsafe_b64encode(hashlib.md5( id0.encode("utf-8")).digest()),"ascii" )[0:6]
                self.mark("H. Compute db id")
                open(file,"w").write(("%-25s" % self.ukto) + "  " + "(" + id0 + id + ")   " +
                                  pattern + " " + self.last_sum + "\n" + text)
                open(file0,"w").write(self.text_rest + text0)
                erg = 2   
        else:
            if id == key:
                self.mark("E. Update ktofile")
                if ruledir and os.path.isdir(ruledir):
                    self.text_match = self.format_kto(self.text_match.split("\n")[:]).strip() + "\n"
                    self.mark("F. Format kto")
                    id0 = self.text_match.replace(" ","")
                    id0 = str( base64.urlsafe_b64encode(hashlib.md5( id0.encode("utf-8")).digest()),"ascii" )[0:6]
                id = "\n" + self.text_match + add_string
                id = str( base64.urlsafe_b64encode(hashlib.md5(  id.encode("utf-8")).digest()),"ascii" )[0:6]
                self.mark("G. Compute kto id")
                open(file,"w").write(("%-25s" % self.ukto) + "  " + "(" + id0 + id + ")   " +
                                  pattern + " " + self.last_sum + "\n\n"+self.text_match)
                open(file0,"w").write(self.text_rest + self.text_match)
                erg = 3   
            else:
                open(file0,"w").write(self.text_rest + self.text_match)
                print("CONFLICT")
                erg = 4
                
        return(erg)   


#******************************************************************************

    def xxsync (self,pattern,file0,file,add_string="",ruledir=None):

        self.parse_pattern(pattern)
        self.mark("A. Sync Start")
        self.kto_match(file0)
        self.mark("B. Find matching lines")
        
        id0 = self.make_id(1,self.text_match)
        self.mark("C. Compute db id")

        if os.path.isfile(file):

            text    = open(file)
            keyline = text.readline()
            text    = text.read()

            if not re.search(r"\S",text):
            
                key0 = ""
                key  = ""
                id   = ""

            else:

                m = re.search(r"\((\S\S\S\S\S\S)(\S\S\S\S\S\S)\)",keyline)
                if m:
                    key0  = m.group(1)
                    key   = m.group(2)
                else:
                    key0  = id0
                    key   = ""
                    text  = keyline + "\n" + text

                id = self.make_id(0,text+add_string)

        else:

            key0 = ""
            key  = ""
            id   = ""

        self.mark("D. " + " ".join([id0,key0,id,key]))
        self.ukto     = ""
        self.last_sum = ""
        
        if id0 == key0:
            if id == key:
#                open(file0,"w").write(self.text_rest + self.text_match)
                erg = 1   
            else:
                self.mark("E. Update database")
                if ruledir and os.path.isdir(ruledir):

                    dir9  = os.path.relpath(".",ruledir)
                    file1 = re.sub(r"^(.*)[\\\/](.*)$","\\2",file)
                    os.chdir(ruledir)
                    os.popen("python3 rule.py " + file1).read()
                    os.chdir(dir9)
                    self.mark("F. ... apply rule.py")

                    text    = open(file).read()
                    text    = "\n" + self.format_kto(text.split("\n")[1:]).strip() + "\n"

#                    open(file,"w").write(text)
                    self.mark("G. ... format kto")
                    id = self.make_id(0,text+add_string)
                    self.mark("H. Compute kto id")
#                text0 = os.popen("grep ^20 " + file + " | grep -o -P '\S+'").read()
                text0 = os.popen("grep -P '^\d\d\d\d\d\d\d\d ' " + file).read()
                id0   = self.make_id(1,text0)
                self.mark("I. Compute db id")
                open(file,"w").write(("%-25s" % self.ukto) + "  " + "(" + id0 + id + ")   " +
                                  pattern + " " + self.last_sum + "\n" + text)
                self.kto_rest(file0)
                open(file0,"w").write(self.text_rest + text0)
                erg = 2   
        else:
            if id == key:
                self.mark("E. Update ktofile")
                if ruledir and os.path.isdir(ruledir):
                    self.text_match = self.format_kto(self.text_match.split("\n")[:]).strip() + "\n"
                    self.mark("F. Format kto")
                    id0 = self.make_id(1,self.text_match)
                id = self.make_id(0,"\n"+self.text_match+add_string)
                self.mark("G. Compute kto id")
                open(file,"w").write(("%-25s" % self.ukto) + "  " + "(" + id0 + id + ")   " +
                                  pattern + " " + self.last_sum + "\n\n"+self.text_match)
#                open(file0,"w").write(self.text_rest + self.text_match)
                erg = 3   
            else:
#                open(file0,"w").write(self.text_rest + self.text_match)
                print("CONFLICT")
                erg = 4
                
        return(erg)   

#******************************************************************************

if __name__ == "__main__":
    
    vars()[sys.argv[1]](*sys.argv[2:])

bypass 1.0, Devloped By El Moujahidin (the source has been moved and devloped)
Email: contact@elmoujehidin.net bypass 1.0, Devloped By El Moujahidin (the source has been moved and devloped) Email: contact@elmoujehidin.net