Welcome To Our Shell

Mister Spy & Souheyl Bypass Shell

Current Path : /home/ift/52_procpy/abbott/

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/52_procpy/abbott/konto.py

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

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

class Konto ():

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

    def __init__ (self,ktotyp=None):


        self.t0              = 0
        self.digits          = 5
        self.dformat         = "%0" + str(self.digits) + "u" 
                            
        self.len_hkey_str    = "12"
        self.len_hkey_nr     = int(self.len_hkey_str)

        self.acc_line_parser = re.compile(r"^(\d\d\d\d)(..)(\d\d) +(\S+) +(\S+) +(\S+) +(\-?\d+\.\d\d|\-+|\.+) +(.*?) *$")

        self.sortieren       = 1
        self.max_offset      = 5

        self.salden_expand   = "(-[^- ]+){0,99},"

        self.dataset         = {}
        
        self.ktotyp          = ktotyp

        ktodir   = os.path.abspath(".")
        
        self.base_dir = ""   #  Search for a base directory with acc and sum files
        pwd0          = ""
        while (0 == 0):      #  check if we are in a directory with acc files
            acc_files = glob.glob("2*.acc") + glob.glob("base/*.acc") + glob.glob(".base/*.acc") + glob.glob("??_ktobase/*.acc")
            if len(acc_files) > 0:
                m = re.search(r"^(.*[\\\/])(.*)$",os.path.abspath(acc_files[0]))
                if m:
                    self.base_dir = m.group(1) 
                break
            pwd = os.path.abspath(".")
            if pwd0 == pwd:
                break
            pwd0 = pwd
            os.chdir("..")

        if not self.base_dir == "":
            self.base_dir = re.sub(r"//$","/",self.base_dir + "/")

        self.mark("---")
        os.chdir(ktodir)

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

    def read_config (self,dir=""):

        if dir == "":
            dir = self.base_dir + "/*.data"


        for config_file in glob.glob(dir):
        
#            print(config_file)
            config1 = open(config_file).read()
#            print(config1)

            try:
                dataset  = json.loads(config1)
            except:
                dataset = None
            
#            print(dataset)
            if dataset:   #   json files
                for o in dataset.keys():
#                    print(o)
                    self.dataset[ o.replace("-","").lower() ] = dataset[o]
                    
            else:         #   proprietary pseudo csv files
                felder = config1.split("\n")
                for zeile in felder:
                    m = re.search(r"^(\S+)\: *(.*?)\"",zeile)
                    if m and not m.group(1).lower() in self.dataset:
                        self.dataset[ m.group(1).lower() ] = m.group(2)
        
        return(self.dataset)


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

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

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

    def kto (self,pattern=None):

        ktodir   = os.path.abspath(".")

        if self.base_dir == "":
            print("No accounting base dir found.")
            return("Error 135")

        if pattern == "SORT":     #   Sortieren aller acc und sum files. Dies ist sinnvoll fuer das syncen
        
            for acc_file in glob.glob(self.base_dir+"*.acc") + glob.glob(self.base_dir+"*.sum"):
                file_text = re.sub(r"\n+$","",open(acc_file).read()).split("\n")
                file_text.sort()
                open(acc_file,"w").write("\n".join(file_text) + "\n")
                return("Accounting base files sorted.")

        ktofile = glob.glob("*.kto") + glob.glob("*.kto.html")
        if len(ktofile) == 1:
            ktofile = ktofile[0]
        else:
            ktofile = None
            

        pattern0 = None
#        print(pattern,pattern0)
        if ktofile:
            ktodir   = re.sub(r"^(.*[\\\/])(.*).(kto|kto.html)$","\\1",os.path.abspath(ktofile))
            ktotext  = open(ktodir+"/"+ktofile).read()
            ktotext  = re.sub(r"^\<PRE\>","",ktotext)
            ktotext  = re.sub(r"\<\/PRE\> *\n *$","",ktotext,re.DOTALL)
            m = re.search(r"^(\.|)(\S+)",ktotext)
            if m:
                if len(m.group(1)) > 0:
                    pattern0 = m.group(2)
                else:
                    pattern0 = "^" + m.group(2)
        else:
            ktotext  = ""
            ktodir   = os.path.abspath(".")

        print(pattern,pattern0)

        self.udir   = ""
        self.stable = 0

        if pattern and len(pattern) > 0 and pattern[0] in ("-",":","."):
            if len(pattern) > 1 and pattern[1] in ("-",":","."):
                pattern = pattern[1:]
                self.stable = 1
            self.udir = pattern[1:]
            if pattern[0] == ":":
                self.udir = "__" + self.udir
            elif pattern[0] == ".":
                self.udir = "_" + self.udir
            if pattern0:
                pattern  = pattern0 + pattern
            else:
                return()

        if not pattern:
            pattern = pattern0

        if not self.udir == "":

            print("UDIR",self.udir)
            try:
                os.mkdir(self.udir)
            except:
                pass
            os.chdir(self.udir)

#        if False and pattern0 and self.udir == "":
#
#            udir = ktodir
#
#            if pattern == None:
#                pattern = pattern0   #  wenn kein pattern angegeben, nimm das pattern aus dem ktofile
#            else:
#
##                if pattern[0] == ".":
##                    pattern = pattern[1:]
##                elif pattern[0] == "-":
##                    pattern = "^" + pattern
#
#                m = re.search(r"^(.*)([\.\:])(.*)",pattern0)
#                if m:
#                    p0 = m.group(1)
#                    m0 = m.group(2)
#                    i0 = m.group(3)
#                else:
#                    p0 = pattern0
#                    m0 = None
#                    i0 = None
#
#                m = re.search(r"^(.*)([\.\:])(.*)",pattern)
#                if m:
#                    p1 = m.group(1)
#                    m1 = m.group(2)
#                    i1 = m.group(3)
#                else:
#                    p1 = pattern
#                    m1 = None
#                    i1 = None
#
#                if not i1:
#                    i1 = i0
#                    m1 = m0
#                    
#                if not i1:
#                    i1 = ""
#                    m1 = ""
#                    
#
#                self.udir = ""
#
#                print("PPP",p1,p0,i1,i0)
#                exit()
#                
#                pattern = p1 + m1 + i1
#                pattern = re.sub(r"\.$","",pattern)

#        print("PATTERN",pattern)
        
        if not pattern:
            return()

        self.update_konto(pattern)
        
        if not self.udir == "":
            if not self.stable:
                while (0 == 0):
                    text1 = open( (glob.glob("*.kto") + glob.glob("*.kto.html"))[0] ).read()
                    os.system("joe *.kto?????")
                    text2 = open( (glob.glob("*.kto") + glob.glob("*.kto.html"))[0] ).read()
                    if text1 == text2:
                        for o in glob.glob("*.kto*"):
                            os.unlink(o)
                        os.chdir("..")
                        try:
                            os.rmdir(self.udir)
                        except:
                            pass
                        return()
                    self.update_konto(pattern)


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

    def update_konto (self,search_pattern,salden_expand=None):  #  Updates an actual konto
        
        self.search_pattern = search_pattern
        if not salden_expand == None:
            self.salden_expand = salden_expand

        self.parse_pattern()
        
#        print(self.search_pattern,self.grep_pattern)


        self.mark("B. Pattern parsed.")

#        self.list_of_sum_files = glob.glob(base_dir+".*sum)
#
#        if not len(self.list_of_acc_files) == len(self.list_of_sum_files):
#            print("Kto database not proper.")
#            return("Error 207.")


        kto_file          = None
        konto_files_found = glob.glob("*.kto") + glob.glob("*.kto.html")
        #print(konto_files_found,os.path.abspath("."))
        
        if len(konto_files_found) > 1:
            print("More than one kto file found.")
            return("Error 120.")

        self.mark("C. Existing ktofiles searched.")

        self.extract_account_lines()   #   Prepare formatted konto and salden
        self.mark("D. Extract lines.")
        
        self.format_kto()
        self.mark("E. ktofile formatted.")

        change_acc_files = 0
        while len(konto_files_found) == 1:
        
            kto_file           = konto_files_found[0]
            text               = open(kto_file).read()
            self.processed_acc = text.split("\n")
            m                  = re.search("^.*? ([012KEP3456789abcdef]{"+self.len_hkey_str+"}) ",text)
        
            if not m:
                break
                
            
            if not (m.group(1) == self.hkey or "KEEP" in m.group(1)):   #  the key which is found in the existing kto-file allows to change
                break                                                   #  the result of the computed sub account so we take the chance
             
            m = re.search("^(.*?)\n *\n(.*\n\d\d\d\d\d\d\d\d +\-?\d+\.\d\d +\S+ .*?\n)",text,re.DOTALL)   #  Check whether processed file has changed
                
            self.mark("F. Processed ktofile hashkey. ")
            if m:
                relevant_text_in_ktofile = m.group(2)
#                print(relevant_text_in_ktofile)
                actual_hkey = hashlib.md5(relevant_text_in_ktofile.encode("utf-8")).hexdigest()[0:self.len_hkey_nr]
                if actual_hkey == self.hkey:
                    return("No change.")        #  Nothing changed at all in the account lines, so do not do anything.
            
            print("... fits.")
            res = self.replace_accountings()    #  the diffs between formatted_acc and processed_acc will be applied to extracted_acc.
            self.mark("G. Replace accounting lines.")
            if res == "null":
                print("-> No action needed.")
                break
            
            self.format_kto(1)               #  make a new formatted_acc from the extracted_acc again.
            self.mark("H. Ktofile formatted again.")
  
            change_acc_files = 1
            break
      
        self.mark("I. Compute salden.")
                    
        if len(konto_files_found) == 0 or re.search(r"([0123456789abcdef]{"+self.len_hkey_str+"})\.kto",kto_file):
            kto_file = self.hkey + ".kto.html"
            
        
        if len(konto_files_found) == 1 and not kto_file == konto_files_found[0]:
            os.unlink(konto_files_found[0])

        self.mark("J. Write result file.")
                    
        open(kto_file,"w").write( "<PRE>" + self.title + "\n\n" + "\n".join(self.formatted_acc) + "\n\n" )

        if change_acc_files:

            self.list_of_acc_files = glob.glob(self.base_dir+"*.acc")
#            print(self.list_of_acc_files)
            self.list_of_acc_files.sort()
            
            self.subtract_account_lines()     #  delete the former lines of the search
            self.mark("K. Delete former accounting lines.")
            self.add_account_lines(kto_file)  #  add the new ones
            self.mark("L. Add changed accounting lines.")
            self.update_sum_files()           #  also update the sumfiles
            self.mark("M. Update sum files.")
            self.extract_account_lines()      #   Prepare formatted konto and salden
            self.mark("N. Reload kto file.")
            self.format_kto()
            self.mark("O. ktofile formatted again.")
            open(kto_file,"w").write( "<PRE>" + self.title + "\n\n" + "\n".join(self.formatted_acc) + "\n\n" )

        self.format_salden()
        open(kto_file,"a").write( "\n".join(self.salden_aktuell) + "\n" + "</PRE>\n")

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

    def read_saldo (self,search_pattern,salden_expand=None):
        
        self.mark("read saldo " + search_pattern)
        self.search_pattern = "^" + search_pattern
        if not salden_expand == None:
            self.salden_expand = salden_expand

#        print(self.search_pattern)
        self.parse_pattern()
        
#        print(self.grep_pattern)
        
        if self.grep_pattern[0] == " ":
            self.ukto = self.grep_pattern[1:]
            self.ukto = re.sub(r"-$","",self.ukto)
#        print(self.ukto)
            
        self.startdatum = (self.startdatum + "00000000")[0:8]
        self.enddatum   = (self.enddatum   + "99999999")[0:8]

        salden_liste = self.format_salden()
#        print(salden_liste)

        if len(salden_liste) == 0:
            return(0.00)

        return(float(salden_liste[0][2]))

#        print(self.startdatum,self.enddatum,self.ukto)
        
#**********************************************************************************

    def salden_text (self):
        return("\n".join(self.salden_aktuell)+"\n")

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

    def extract_account_lines (self):
    
#    This function extracts the matching lines of a request into a sorted array

#        self.mark("A. Compute query for transaction file " + pattern1 + " " + str(interval)[0:40] + " ...")

#        print("111",self.interval_long,"--"+self.grep_pattern+"--")
        
        if not self.interval_long == "":
            if self.grep_pattern == "":
                self.extracted_acc = os.popen(self.egrep + "grep -h -i ^" + self.interval_long + " " + self.base_dir + "*.acc").read().split("\n")
            else:
                self.extracted_acc = os.popen(self.egrep + "grep -h -i ^" + self.interval_long + " " + self.base_dir + "*.acc | grep -h -i '" + self.grep_pattern + "'").read().split("\n")
        else:
            if self.grep_pattern == "":
                self.extracted_acc = os.popen("less " + self.base_dir + "*.acc").read().split("\n")
            else:
                self.extracted_acc = os.popen(self.egrep + "grep -h -i '" + self.grep_pattern + "' " + self.base_dir + "*.acc").read().split("\n")

        self.extracted_acc.sort()        

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

    def parse_pattern (self):    #   parse the search pattern

        self.grep_pattern     = re.sub(r"\^"," ",self.search_pattern,9999)
        self.interval_long    = ""
        self.interval_short   = ""
        self.egrep            = ""
        self.mode             = ""
        self.startdatum       = "00000000"
        self.enddatum         = "99999999"

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

            self.grep_pattern   = m.group(1)
            self.mode           = m.group(2)
            self.interval_long  = "20" + m.group(3)[0:2]
            months              = m.group(3)[2:]
            self.interval_short = m.group(3)
            
            if   months == "A":
                months  = "10"
                first_m = "10"
                last_m  = "10"
            elif months == "B":
                months  = "11"
                first_m = "11"
                last_m  = "11"
            elif months == "C":
                months  = "12"
                first_m = "12"
                last_m  = "12"
            elif months == "I":
                months  = "0[123]"
                first_m = "01"
                last_m  = "03"
            elif months == "J":
                months  = "0[456]"
                first_m = "04"
                last_m  = "06"
            elif months == "K":
                months  = "0[789]"
                first_m = "07"
                last_m  = "09"
            elif months == "L":
                months  = "1[012]"
                first_m = "10"
                last_m  = "12"
            elif months == "M":
                months  = "0[123456]"
                first_m = "01"
                last_m  = "06"
            elif months == "N":
                months  = "\\(07\\|08\\|09\\|10\\|11\\|12\\)" # "[01][789012]"
                first_m = "07"
                last_m  = "12"
                egrep   = "e"
            elif months == "P" or months == "":
                months  = ""
                first_m = "01"
                last_m  = "12"
            elif not months == "":
                months  = "0" + months
                first_m = months
                last_m  = months
       
            if self.mode == ":":
                intervals = []
                jahr      = "2000"
                while (0 == 0):
                    intervals.append(jahr)
                    jahr = str(int(jahr)+1)
                    if jahr == self.interval_long:
                        break
                if last_m == "12":
                    intervals.append(jahr)
                else:
                    month = "01"
                    while (0 == 0):
                        intervals.append(jahr+month)
                        if month in (last_m,"12"):
                            break
                        month = "%02u" % (int(month) + 1)
                self.interval_long = "\\(" + "\\|".join(intervals) + "\\)"
                self.egrep = "e"
                self.startdatum = intervals[0]
                self.enddatum   = intervals[-1]
                

            else:
                self.startdatum    = self.interval_long + first_m + "00"
                self.enddatum      = self.interval_long + last_m  + "99"
                self.interval_long = self.interval_long + months

#        print(self.startdatum,self.enddatum)



                
#        if self.search_pattern[0] == "^":
#            self.start_kto    = re.sub(r"[\^ ]",""self.grep_pattern,9999)
#        else:
#            self.start_kto    = None


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

    def format_kto (self,mode=0):
        
        self.parse_ktotext()
                
#   ktotext:   datum  betrag   kto1   kto2   saldo   bemerkung   original_line
                
        if self.ukto == "":
            self.buchungen.sort(key=lambda x:x[0]+str(x[1])+x[3]+x[4])
        else:
#            ktotext.sort(key=lambda x:str(x[5]+1)+x[0])
            self.buchungen.sort(key=lambda x:x[0]+str(x[5]+1)+x[2]+x[3]+x[4])
            

        gesamt              = 0.00
        self.startdatum     = "00000000"
        self.enddatum       = "00000000"
        dbl_marks           = {}
        self.formatted_acc  = []
        self.extracted_acc  = []    #  das orig-File muss in der neuen Sortierung auch neu geschrieben werden,
                                    #  damit man am Ende den Patch auf das formatierte Konto-File anwenden kann.

        has_doublettes = 0
        datum          = ""
        saldo          = ""
        for zeile in self.buchungen:   #   step through all accounting lines
                
            ust = ""
            if "v.H." in zeile[4]:
                ust = "   "

            betrag = zeile[1]
            ktoa   = zeile[2]
            ktob   = zeile[3]
            datum  = zeile[0]
            
            if not ktoa.startswith(self.ukto):
                o      = ktoa   
                ktoa   = ktob   
                ktob   = o
                betrag = re.sub(r"^--","","-"+betrag)
            
            if mode == 0 and not ktoa.startswith(self.ukto) and self.grep_pattern[0] == " ":
                print("SKIP: ",self.ukto,zeile)
                continue
                
#            print(ukto,zeile)
            betrag = float(betrag)

            if self.ukto == "":
                gesamt = gesamt + betrag
                saldo  = "%13.2f" % gesamt
            else:
                if zeile[5] == 0:            #  zeile[5]: the number of matching ukto in ktoa or ktob
                    if mode == 0:
                        saldo = "         ...."
                    else:
                        saldo = "         0.00"   #  for uploading into acc-files
#                    saldo  = "%13.2f" % gesamt
                elif self.maxsaldo == 0 or zeile[5] == 1:
                    gesamt = gesamt + betrag
                    saldo  = "%13.2f" % gesamt
                elif zeile[5] == 2:
                    saldo  = "%13.2f" % gesamt

            dbl_z    = datum + " " + ("%13.2f" % betrag) + "  " + (self.format_maxa % ktoa) + "  " + (self.format_maxb % ktob)
            rem_z    = ust + re.sub(r" +"," ",zeile[4],9999)
            zeile1   = dbl_z + " " + saldo + "  " + rem_z

            dbl_mark = dbl_z + rem_z   #  wenn Doubletten gefunden werden, diese eindeutig markieren
#            if "abc" in dbl_mark:
#                for oo in dbl_marks:
#                    print(oo)
#                print("--------------------")
            if not (dbl_mark in dbl_marks.keys()):
#                print(">>",dbl_mark,"1235")
                dbl_marks[dbl_mark] = 0
            else:
                dbl_marks[dbl_mark] = dbl_marks[dbl_mark] + 1
                zeile1 = zeile1 + " DOUBLETTE " + str(dbl_marks[dbl_mark])
                has_doublettes = 1
            
            self.extracted_acc.append(zeile[6])
            self.formatted_acc.append(zeile1)
            if "Jahres-Netto" in rem_z:
                self.extracted_acc.append("---")
                self.formatted_acc.append("---")
            if self.startdatum == "00000000":
                self.startdatum = datum

        if not datum == "":
            self.enddatum = datum

        if self.ukto == "":
            self.ukto = "." + self.search_pattern
            interval  = ""
        else:
            interval  = self.mode + self.interval_short
            
        if self.grep_pattern[-1] == "-":
            add_minus = "-"
        else:
            add_minus = ""


        self.hkey   = "\n".join(self.formatted_acc) + "\n"
        self.hkey   = hashlib.md5(self.hkey.encode("utf-8")).hexdigest()[0:12]
        self.title  = ("%-50s"%(re.sub(r"\.$","",self.ukto+add_minus+interval))) + " " + self.hkey + "       " + ("%13.2f"%gesamt)
#        print(self.title)

        if not self.ukto == "":
            print("UKTO: " + self.ukto + saldo)

        if has_doublettes:
            print("Attention: Doublettes!")
            
        return(saldo)

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

    def parse_ktotext (self):

        self.buchungen      = []
        unique_strings      = {}
        self.maxa           = 10
        self.maxb           = 10
        self.maxc           = 0
        self.maxd           = 0
        self.maxsaldo       = 0
        self.ukto           = ""
        ukto0               = ""
        pattern             = self.grep_pattern.strip().upper()
        
        if self.grep_pattern[0] == " ":
            self.ukto = self.grep_pattern[1:]
            self.ukto = re.sub(r"-$","",self.ukto)
        
        if len(pattern) > 0 and pattern[-1] == "-":
            pattern = pattern[:-1]

        zaehler = -1
        vvv = re.compile(r"^(\d\d\d\d)(..)(\d\d) +(\S+) +(\S+) +(\S+) +(\-?\d+\.\d\d|\-+|\.+) +(.*?) *$")
        for zeile in self.extracted_acc:

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

#            if self.start_kto:
#                if mm.group(5).startswith(self.start_kto) or mm.group(6).startswith(self.start_kto) ):
#                    new_extracted_acc.append(zeile)
#                else:
#                    self.remaining_acc.append(zeile)
#                    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:
                    exit()

                remark   = mm.group(8)
                uniqu    = []
                ktoa     = mm.group(5)
                if ktoa == None:
                    print(zeile)
                if ktoa.startswith("-"):
                    ktoa = self.ukto + ktoa
                ktob     = mm.group(6)
                
                if "--" in ktoa or "--" in ktob:
                    continue
                
                turn_kto = 0

#                    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:     #  to avoid swing back anf forth
                    o      = ktoa   
                    ktoa   = ktob   
                    ktob   = o
                    betrag = re.sub(r"^--","","-"+betrag)
                    turn_kto = 1 - turn_kto
                    
                if not ktoa.upper().startswith(pattern):
                    o      = ktoa   
                    ktoa   = ktob   
                    ktob   = o
                    betrag = re.sub(r"^--","","-"+betrag)

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

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

                if self.ukto:
                    saldo = ( int( self.ukto and ktoa.startswith(self.ukto)) +
                              int( self.ukto and ktob.startswith(self.ukto)) )
                    
                if uniqu == []:
                    uniqu = [ktoa,ktob]

                self.maxsaldo = max(self.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] == "-":
                    self.maxc = max(self.maxc,len(ktoa))
                else:
                    self.maxa = max(self.maxa,len(ktoa))

                if ktob[0] == "-":
                    self.maxd = max(self.maxd,len(ktob))
                else:
                    self.maxb = max(self.maxb,len(ktob))

                self.buchungen.append([datum,betrag,ktoa,ktob,remark,saldo,zeile])

        if self.ukto == None:
            self.ukto = ""
        self.ukto = self.ukto.replace("^","")

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

        self.format_maxa = "%-" + str(self.maxa) + "s"
        self.format_maxb = "%-" + str(self.maxb) + "s"
        self.maxsaldo    = str(self.maxsaldo)


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

    def format_salden (self,ktoparse=None):   #   Moeglichkeit zum freien Waehlen von Kontensalden geschaffen

        faktor              = 1
#        kto                 = self.ukto

        self.salden_aktuell = []

        ktofiles1 = glob.glob(self.base_dir+"*.acc")
        ktofiles1.sort()
        ktofiles  = []
        
#        print(self.base_dir)

#        self.mark("A")
        for ktofile in ktofiles1:

#            print(ktofile  + " ...")
            ktofile_sum = ktofile[:-4] + ".sum"
            if not os.path.isfile(ktofile_sum):
                self.mark("    " + ktofile + " not found, so retrieve it:")
                self.update_sum_files(ktofile)
            
            m = re.search(r"(\d+)\.acc$",ktofile)
            if len(ktofiles) < 2:
                if (m.group(1) + "000000")[0:6] < self.startdatum:
                    ktofiles = []
            if (m.group(1) + "000000")[0:6] > self.enddatum:
                break
            else:
                ktofiles.append(ktofile_sum)

        if ktoparse == None:
            if not self.ukto == None and not self.ukto == "" and self.ukto[0] in ("-","."):
                return()
            ktoparse = "^" + self.ukto + self.salden_expand
            len_ukto = len(self.ukto) + 1
        else:
            self.ukto = ""
            len_ukto  = 0
#        print(ktoparse)
            
        self.enddatum   = (self.enddatum   + "99999999")[0:6]
        self.startdatum = (self.startdatum + "00000000")[0:6]

        if self.enddatum[4:6] > "12":
            self.enddatum = self.enddatum[0:4] + "12" 

        ktotexts = []
#        print("KTOPARSE",ktoparse)
        for ktofile in ktofiles:  #  retrieving of the relevant lines via grep
#            print("KTOFILE",ktofile)
            ktotexts.append([])
#            print("grep -P '" + ktoparse + "' " + ktofile)
            for zeile in os.popen("grep -P '" + ktoparse + "' " + ktofile).read().split("\n")[:-1]:
                ktotexts[-1].append(zeile.split(","))

#        for o in ktotexts[0]:
#            print(o)


        salden_liste    = []
        max_offset      = self.max_offset
        max_kto_ordnung = 0
        
        kto0 = " "
        while (0 == 0):   #   alle konten-Salden gleichzeitig nach vorne schieben, dabei auf luecken achten
            kto = None
            for ktotext in ktotexts:
                if len(ktotext) == 0:
                    continue
                if kto == None:
                    kto = ktotext[0][0]
                else:
                    kto = min(ktotext[0][0],kto)
            if kto == None:
                break
                
            betrag = 0.00
            nr     = 0

            if len(ktotexts[0]) > 0 and kto == ktotexts[0][0][0]:   #  in the first line there is the kto. Find in the first file the position
                zeile  = ktotexts[0][0][1:]  #  nicht entfernen!
                datum0 = zeile.pop(0)
                if self.startdatum >= datum0:
                    datpos = 12*( int(self.startdatum[0:4]) - int(datum0[0:4]) ) + int(self.startdatum[4:6]) - int(datum0[4:6]) - 1
#                    print("START",self.startdatum,datum0,kto,datpos)
                    if datpos < 0:
                        betrag = 0.00
                        nr     = 0
                    elif datpos >= len(zeile):
#                        print(kto,zeile)
                        if zeile[-1][-self.digits-1] == "/":
                            betrag = betrag - float(zeile[-1][:-self.digits-1])
                            nr     = nr     - int(zeile[-1][-self.digits:])
                        else:
                            ind    = zeile[-1].index("/")
                            betrag = betrag - float(zeile[-1][:ind-1])
                            nr     = nr     - int(zeile[-1][ind:])
                    else:
                        if zeile[datpos][-self.digits-1] == "/":
                            betrag = betrag - float(zeile[datpos][:-self.digits-1])
                            nr     = nr     - int(zeile[datpos][-self.digits:])
                        else:
                            ind    = zeile[datpos].index("/")
                            betrag = betrag - float(zeile[datpos][:ind-1])
                            nr     = nr     - int(zeile[datpos][ind:])
                
#            print("        ",kto,nr,datpos)

            if len(ktotexts[-1]) > 0 and kto == ktotexts[-1][0][0]:   #  im letzten Salden-File die genaue Monatsspalte finden
#                zeile  = ktotexts[-1][0][1:]  #  nicht entfernen!
                zeile  = ktotexts[-1].pop(0)[1:]
                datum0 = zeile.pop(0)
                if self.enddatum >= datum0:
                    datpos = 12*( int(self.enddatum[0:4]) - int(datum0[0:4]) ) + int(self.enddatum[4:6]) - int(datum0[4:6])

                    if datpos >= len(zeile):
                        if zeile[-1][-self.digits-1] == "/":
                            betrag = betrag + float(zeile[-1][:-self.digits-1])
                            nr     = nr     + int(zeile[-1][-self.digits:])
                        else:
                            ind    = zeile[-1].index("/")
                            betrag = betrag + float(zeile[-1][:ind-1])
                            nr     = nr     + int(zeile[-1][ind:])
                    else:
                        if zeile[datpos][-self.digits-1] == "/":
                            betrag = betrag + float(zeile[datpos][:-self.digits-1])
                            nr     = nr     + int(zeile[datpos][-self.digits:])
                        else:
                            ind    = zeile[datpos].index("/")
                            betrag = betrag + float(zeile[datpos][:ind-1])
                            nr     = nr     + int(zeile[datpos][ind:])

#            print("        ",kto,nr,datpos)
                
            for ktotext in ktotexts[:-1]:   #  nur bei sum-up Werten relevant (Zwischen-sum-Files)
                if len(ktotext) > 0 and ktotext[0][0] == kto:
                    zeile  = ktotext.pop(0)
                    
                    if zeile[-1][-self.digits-1] == "/":
                        betrag = betrag + float(zeile[-1][:-self.digits-1])
                        nr     = nr     + int(zeile[-1][-self.digits:])
                    else:
                        ind    = zeile[-1].index("/")
                        betrag = betrag + float(zeile[-1][:ind-1])
                        nr     = nr     + int(zeile[-1][ind:])
                    
            if nr > 0:
                
                betrag          = "%3.2f" % (faktor*betrag)
                kto             = kto[len_ukto:]
                kto_ordnung     = max(0,len(re.sub("[^\-]","",kto)))
                if kto == "":
                    kto_ordnung = -1
                max_offset      = max(max_offset,len(kto) + len(betrag) - 4*kto_ordnung)
                max_offset      = max(max_offset,len_ukto)
                max_kto_ordnung = max(max_kto_ordnung,kto_ordnung)
                salden_liste.append([kto,kto_ordnung,betrag])
                

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

            kto_ordnung = salden_zeile[1]
            betrag      = salden_zeile[2]
            kto_spacing = "%-" + ("%2u"% (max_offset+kto_ordnung*4-len(betrag)+2) ) + "s"
            if kto_ordnung == 0 and max_kto_ordnung > 0:   #   additional spacing
                self.salden_aktuell.append("")
            self.salden_aktuell.append( (kto_spacing%kto) + betrag )
            if kto_ordnung == -1 and max_kto_ordnung < 1:
                self.salden_aktuell.append("")
                
        return(salden_liste)


#        print(max_kto_ordnung)
#        print(self.salden_aktuell)

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

    def replace_accountings (self):
    
#   Here we create the array add_lines (lines which are added in processed_acc), del_lines (lines which
#   are deleted in processed_acc), line_numbers_of_deleted (the line numbers in the array of the original
#   formatted_acc which have been deleted in  processed_acc).

        self.differences_to_consider()

        if len(self.add_lines) + len(self.del_lines) == 0:
            return("null")
        
#   Now we apply these changes to the original raw file  extracted_acc :

        new_extracted_acc = self.add_lines[:]     #  new version of the text of  extracted_acc. We start with the added lines

#   Deleted lines:
#   Because the line-by-line correspondency of  extracted_acc  and formatted_acc  we can apply the numbers in  line_numbers_of_deleted
#   directly to extracted_acc (by considering an offset of 2 because of the both additional header lines made from the formatting)

        self.dates_of_deleted_lines     = []            #  we collect all months of all lines which have been deleted for later purposes

        zaehler = 0 
        for zeile in self.extracted_acc:
            if zaehler in self.line_numbers_of_deleted:
                if not zeile[0:6] in self.dates_of_deleted_lines:
                    self.dates_of_deleted_lines.append(zeile[0:6])
            else:
                new_extracted_acc.append(zeile)
            zaehler = zaehler + 1
                    
        self.extracted_acc = new_extracted_acc
        self.extracted_acc.sort()
        
#**********************************************************************************

    def differences_to_consider (self):
    
        set_of_formatted_lines = set( self.formatted_acc )
        set_of_processed_lines = set( self.processed_acc )

#       First, we determine the vice versa differences of the sets of lines in formatted_acc and processed_acc:

        set_of_added_lines     = set_of_processed_lines.difference(set_of_formatted_lines)
        set_of_deleted_lines   = set_of_formatted_lines.difference(set_of_processed_lines)
 
#       Changes which may consist simply by changing spaces or the sum in the fith column of an account set
#       should be skipped. So we calculate now all these normalisations and map it to the original line.
#       Also lines which are not an account entry should be skipped.

#       (Actually, we could do it one-step by normalize all the lines in formatted_acc and processed_acc. But it is
#       costly to normalize all this lines, even, if these are not affected by changes. So it is waste of ressources.
#       Hence, it makes sense firstly make a raw difference  set_of_added_lines  and  set_of_deleted_lines  which
#       afterwards can be reduced by normalization.)

        set_of_normalized_added_lines,   dict_of_normalized_added_lines_to_orig_added_lines     = self.normalize_acc_line_set(set_of_added_lines)
        set_of_normalized_deleted_lines, dict_of_normalized_deleted_lines_to_orig_deleted_lines = self.normalize_acc_line_set(set_of_deleted_lines)
        
#        print(dict_of_normalized_added_lines_to_orig_added_lines)
#        print(dict_of_normalized_deleted_lines_to_orig_deleted_lines)


#       The sets of the normalized added and deleted reduced lines sets are calculated by deleted elements common to both of this sets

        reduced_set_of_normalized_added_lines   = set_of_normalized_added_lines.difference(set_of_normalized_deleted_lines)
        reduced_set_of_normalized_deleted_lines = set_of_normalized_deleted_lines.difference(set_of_normalized_added_lines)

#        print(reduced_set_of_normalized_added_lines)
#        print(reduced_set_of_normalized_deleted_lines)


#       As a last step, we find back the original lines by the both dictionaries:

        self.add_lines               = []
        for normalized_line in reduced_set_of_normalized_added_lines:
            orig_zeile = dict_of_normalized_added_lines_to_orig_added_lines[ normalized_line ]
            self.add_lines.append( orig_zeile )

        self.del_lines               = []
        self.line_numbers_of_deleted = []
        for normalized_line in reduced_set_of_normalized_deleted_lines:
            orig_zeile = dict_of_normalized_deleted_lines_to_orig_deleted_lines[ normalized_line ]
            self.del_lines.append("-" +  orig_zeile )
            self.line_numbers_of_deleted.append( self.formatted_acc.index( orig_zeile ) )

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

    def normalize_acc_line_set (self,line_set):
        
        normalized_lines                    = []
        dict_normalized_lines_to_orig_lines = {}
        
        for zeile in line_set:          #  ueber Aequivalenzbeziehung weitere uebereinstimmende Zeilen herausfinden
            m = self.acc_line_parser.search(zeile)
            if m:
                zeile1 = m.group(1) + m.group(2) + m.group(3) + "  " + ("%3.2f"%eval(m.group(4))) + "  " + m.group(5) + "  " + m.group(6) + "  0.00  " + m.group(8)
            else:
                continue      #  nur Buchungszeilen sind zu beruecksichtigen
            normalized_lines.append(zeile1)
            dict_normalized_lines_to_orig_lines[zeile1] = zeile
        
        return(set(normalized_lines),dict_normalized_lines_to_orig_lines)
        
#*******************************************************************************************

    def impacts_acc_file(self,ktofile,mode=0):

        m = re.search(r"(\D|^)(\d+)\.acc",ktofile)
        if not m:
            return(False)
        zeitraum = m.group(2)

        if mode == 1:
            return(zeitraum)

        if zeitraum < self.startdatum[0:len(zeitraum)]:
            return(False)
        if zeitraum > self.enddatum[0:len(zeitraum)]:
            return(False)

        return(zeitraum)

#*******************************************************************************************
        
    def subtract_account_lines (self): 

#   This function deletes accounting lines from the acc-files due to a pattern

        for ktofile in self.list_of_acc_files:

            if not self.impacts_acc_file(ktofile):
                continue

            if not self.interval_long == "":
                if self.grep_pattern == "":
                    os.system(self.egrep + "grep -i -v ^" + self.interval_long + " " + ktofile + " > " + ktofile + "__")
                else:
                    os.system(self.egrep + "grep -i -v ^" + self.interval_long + " " + ktofile + " > " + ktofile +  "__")
                    os.system(self.egrep + "grep -i ^" + self.interval_long + " " + ktofile + " | grep -i -v '" + self.grep_pattern + "' >> " + ktofile + "__")
            else:
                if self.grep_pattern == "":
                    os.system(" > __" + self.base_dir + ktofile)
                else:
                    os.system(self.egrep + "grep -i -v '" + self.grep_pattern + "' "  + ktofile + " > " + ktofile + "__")
                    
            os.system("mv " + ktofile + "__ " + ktofile)

        self.mark("D. Subtract old accounting entries from acc files.")
                
#********************************************************************************************        

    def add_account_lines (self,kto_file):

        for acc_file in self.list_of_acc_files:

            zeitraum = self.impacts_acc_file(acc_file)
            if zeitraum:

                os.system("grep ^" + zeitraum + " " + kto_file + " >> " + acc_file)
                if self.sortieren == 1:    #   hier die acc-Files wieder sortieren
                    file_text = re.sub(r"\n+$","",open(acc_file).read()).split("\n")
                    file_text.sort()
                    open(acc_file,"w").write("\n".join(file_text) + "\n")
#                    self.mark("C. " + ktofile + " sorted.")
#                    os.system("sort " + ktofile + " > " + "__" + ktofile)
#                    os.system("mv __" + ktofile + " " + ktofile)
                
#*************************************************************************

    def update_sum_files (self,acc_file=None):
    
        salden_files = []
        
        if acc_file:
            list_of_changed_lines = open(acc_file).read().split("\n")
            mode                  = 1
            list_of_acc_files     = [acc_file]
        else:
            list_of_changed_lines = self.add_lines + self.del_lines
            mode                  = 0
            list_of_acc_files     = self.list_of_acc_files
#        print("\n".join(list_of_changed_lines))

        for acc_file in list_of_acc_files:

            abschnitt = self.impacts_acc_file(acc_file,mode)
            if not abschnitt:
                continue

            diff_salden          = {}
            buchung_im_lfd_monat = {}

            salden_file  = acc_file[0:-4] + ".sum"
            salden_files.append(salden_file)

            salden_text = []
            if os.path.isfile(salden_file):    
                salden_text = open(salden_file).read().strip().split("\n")   #  update der salden_files

            update_salden = 0
            for diff_buchung in ( list_of_changed_lines ):
#                print("DD",diff_buchung)
                m = re.search("^(\-?)(\d\d\d\d\d\d\d\d) +(\S+) +(\S+) +(\S+) +(\-?\d+\.\d\d|\.+)",diff_buchung)
                if m:
                    if update_salden == 0:
                        update_salden = 1
                        self.mark("--> Check " + acc_file + ".")
                    datum  = m.group(2)
                    if datum.startswith(abschnitt):
                        betrag = eval(m.group(3))
                        ktoa   = m.group(4)
                        if ktoa.startswith("-"):
                            ktoa = self.ukto + ktoa
                        ktob   = m.group(5)
                        add_buchung = 1
                        if m.group(1).startswith("-"):
                            betrag      = -betrag
                            add_buchung = -1
                        self.compute_salden(diff_salden,buchung_im_lfd_monat,ktoa, betrag,add_buchung,datum) 
                        self.compute_salden(diff_salden,buchung_im_lfd_monat,ktob,-betrag,add_buchung,datum)


            kto_to_del    = []
            update_salden = 0

            for kto in list(diff_salden.keys()):

                if update_salden == 0:
                    update_salden = 1
                    self.mark("--> Diff salden computed.")
                    
                interval0 = -1   # suchen, ob es schon eine gueltige Zeile gibt
                interval1 = len(salden_text)
                while (0 == 0):
                    if interval0 + 1 == interval1:  #  not found
                        interval9 = -1
                        break
                    interval9 = interval0 + int((interval1 - interval0)/2)
#                    print(interval0,interval9,interval1,kto)
#                    time.sleep(0.01)
                    if salden_text[interval9].startswith(kto+","):
                        break
                    if (kto + ",") > salden_text[interval9]:
                        interval0 = interval9
                    else:
                        interval1 = interval9
                                    
                if interval9 > -1:   #   wenn es schon eine Konto-Zeile im Salden-File gibt, diese integrieren

                    werte = salden_text[interval9].split(",")
                    werte.pop(0)
                    if len(werte) > 0:
                        monat   = int(werte.pop(0))
                        betrag0 = 0.00
                        nr0     = 0
                        for betrag in werte:
                            if betrag[-self.digits-1] == "/":
                                nr     = int(betrag[-self.digits:])
                                betrag = float(betrag[:-self.digits-1])
                            else:
#                                print(kto,betrag)
                                ind    = betrag.index("/")
                                betrag = int(m.group(1))
                                nr     = float(m.group(2))
                            if not monat in diff_salden[kto]:
                                diff_salden[kto][monat]           = 0.00
                                buchung_im_lfd_monat[kto][monat]  = 0
                            diff_salden[kto][monat]          = diff_salden[kto][monat]          + betrag - betrag0
                            buchung_im_lfd_monat[kto][monat] = buchung_im_lfd_monat[kto][monat] + nr     - nr0
                            betrag0 = betrag
                            nr0     = nr
                            monat   = monat + 1
                            if str(monat)[4:6] == "13":
                                monat = int(str(int(str(monat)[0:4]) + 1) + "01")
                            
                monate   = list(diff_salden[kto].keys())
                monat    = min(monate)
                mmax     = max(monate)
                zeile    = kto + ","
                betraege = []
                sum      = 0.00    #   @@@@
                nr       = 0
                
                while (0 == 0):
#                    nr = 0
                    if monat in diff_salden[kto]:
                        sum = sum + diff_salden[kto][monat]
                        nr  = nr  + buchung_im_lfd_monat[kto][monat]
                    if len(betraege) > 0:
                        betraege.append(("%3.2f"%sum)+"/"+(self.dformat%nr))
                    elif abs(sum) > 0.000001 or nr > 0:    #  just start when something interesting started
                        betraege.append(("%3.2f"%sum)+"/"+(self.dformat%nr))
                        zeile = zeile + str(monat) + ","
                    monat   = monat + 1
                    if str(monat)[4:6] == "13":
                        monat = int(str(int(str(monat)[0:4]) + 1) + "01")
                    if monat > mmax:
                        break

#                while (0 == 0):    #   truncate the tail if there is nothing interesting anymore
#                    if len(betraege) < 2:
#                        break
#                    if not betraege[-1] == betraege[-2]:
#                        break
#                    betraege.pop()

                if len(betraege) == 0:
                    kto_to_del.append(kto)
                else:
                    zeile = zeile + ",".join(betraege)
                    if len(kto_to_del) > 0 and kto in kto_to_del:
                        kto_to_del.remove(kto)

                if interval9 > -1:
                    salden_text[interval9] = zeile   #  update line
                else:
                    salden_text.insert(interval1,zeile)   #  line was not existing, so enter it
                
            if update_salden == 1:
                self.mark("F. Salden list updated.")
                if len(kto_to_del) == 0:
                    salden_text = "\n".join(salden_text) + "\n"
                else:
                    salden_text = "\n" + "\n".join(salden_text) + "\n"
                    self.mark("   ---")
                    for delkto in kto_to_del:
                        ind         = salden_text.index("\n"+delkto+",")
                        salden_text = salden_text[:ind] + salden_text[ind+len(delkto)+2:]
                    salden_text = salden_text[1:]
#                    self.mark("   .... kto s deleted from sum-file:\n" + "\n".join(kto_to_del))
                open(salden_file,"w").write(salden_text)   #  update der salden_files

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

    def compute_salden (self,salden,buchung,ukto,betrag,add_buchung,datum):   #  Splits the accounting entry and
                                                                              #  and computes the cahnges for every
        monat = int(datum[0:6])                                               #  sub-account
        while (0 == 0):
            if not ukto in salden:
                salden[ukto]  = {}
                buchung[ukto] = {}
            if not monat in salden[ukto]:
                salden[ukto][monat]  = 0.00
                buchung[ukto][monat] = 0
            salden[ukto][monat]  = salden[ukto][monat]  + betrag
            buchung[ukto][monat] = buchung[ukto][monat] + add_buchung
            m = re.search(r"^(.*)\-(.+)$",ukto)
            if m:
                ukto = m.group(1)
            else:
                return()

#*************************************************************************
        
    def test_extract_lines (self,basedir,pattern):
    
        self.update_konto(basedir,pattern)
#        print("\n".join(self.formatted_acc)+"\n")
#        print("\n".join(self.salden_aktuell)+"\n")
        
#******************************************************************************

    def sort (self,pattern,file=None):
    
        if file == None:
            files = glob.glob("*.kto") + glob.glob("*.kto.html")
            if len(files) == 1:
                file = files[0]
            else:
                return()

        if pattern == "..":
            self.sort_numbers(file)
            return()

        if pattern == "kto":
            self.sort_numbers1(file)
            return()

        text = open(file).read()
        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 = "\n".join(text_rest) + "\n" + "\n".join(text_match) + "\n"
        if os.path.isfile(file+"~"):
            os.unlink(file+"~")
#        os.rename(file,file+"~")
        open(file,"w").write(text)

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

    def sort_numbers (self,file):
    
        text = open(file).read()
        text_match = []
        text_rest  = []
        
        for zeile in text.split("\n"):
            m = re.search(r"\d\d\d\d\d\d\d\d +\-?(\d+\.\d\d) ",zeile)
            if m:
                text_match.append([zeile,float(m.group(1))])
            else:
                text_rest.append(zeile)
                
        text_match.sort(key=lambda x:x[1])
        text_match1 = []
        for tt in text_match:
            text_match1.append(tt[0])

        text = "\n".join(text_rest) + "\n" + "\n".join(text_match1) + "\n"
        if os.path.isfile(file+"~"):
            os.unlink(file+"~")
#        os.rename(file,file+"~")
        open(file,"w").write(text)

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

    def sort_numbers1 (self,file):
    
        text = open(file).read()
        text_match = []
        text_rest  = []
        
        for zeile in text.split("\n"):
            m = re.search(r"(\d\d\d\d\d\d\d\d) +\-?(\d+\.\d\d) +(\d+?)\-(\S+?)\-(\S+) ",zeile)
            if m:
                text_match.append([zeile,m.group(5)])
            else:
                text_rest.append(zeile)
                
        text_match.sort(key=lambda x:x[1])
        text_match1 = []
        for tt in text_match:
            text_match1.append(tt[0])

        text = "\n".join(text_rest) + "\n" + "\n".join(text_match1) + "\n"
        if os.path.isfile(file+"~"):
            os.unlink(file+"~")
#        os.rename(file,file+"~")
        open(file,"w").write(text)

#*************************************************************************
        
    def xxggg (self):
        
        diff_salden              = {}
        dates_of_deleted_entries = []  #  das wird eine Liste aus Monaten, in denen gar keine Buchungen mehr stehen


#   ----  1.  Vergleich zwischen dem originalen result.format und result.kto

        add_lines       = []
        del_lines       = []

        if os.path.isfile(file+".format") and os.path.isfile(file+".kto"):   

            sortierte_zeilen   = open(file + ".format").read().split("\n")
            text0              = set(open(file + ".kto").read().split("\n"))

            diff_sort_z        = set(sortierte_zeilen).difference(text0)  #  erstmal die Differenzen ohne Aequivalenzbildung berechnen
            diff_text0         = text0.difference(set(sortierte_zeilen))
            
            equivalent_zeilen  = {}
            diff_sort_z_reduce = []
            diff_text0_reduce  = []
            
            vvv = re.compile(r"^(\d\d\d\d)(..)(\d\d) +(\S+) +(\S+) +(\S+) +(\-?\d+\.\d\d|\-+|\.+) +(.*?) *$")  #  zweiter Schritt:
            for zeile in diff_sort_z:          #  ueber Aequivalenzbeziehung weitere uebereinstimmende zeilen herausfinden
                m = vvv.search(zeile)
                if m:
                    zeile1 = m.group(1) + m.group(2) + m.group(3) + "  " + ("%3.2f"%eval(m.group(4))) + "  " + m.group(5) + "  " + m.group(6) + "  0.00  " + m.group(8)
                else:
                    continue      #  nur Buchungszeilen sind zu beruecksichtigen
                equivalent_zeilen[zeile1] = zeile
                diff_sort_z_reduce.append(zeile1)
            diff_sort_z_reduce = set(diff_sort_z_reduce)
            for zeile in diff_text0:
                m = vvv.search(zeile)
                if m:
                    zeile1 = m.group(1) + m.group(2) + m.group(3) + "  " + ("%3.2f"%eval(m.group(4))) + "  " + m.group(5) + "  " + m.group(6) + "  0.00  " + m.group(8)
                else:
                    continue      #  nur Buchungszeilen sind zu beruecksichtigen
                diff_text0_reduce.append(zeile1)
            diff_text0_reduce = set(diff_text0_reduce)
                
            diff_sort_z_reduce_diff = diff_sort_z_reduce.difference(diff_text0_reduce)
            diff_text0_reduce_diff  = diff_text0_reduce.difference(diff_sort_z_reduce)

#            print(diff_sort_z_reduce_diff)
#            print(diff_text0_reduce_diff)

            
            #  In diff_sort_z_reduce_diff stehen die reduzierten Zeilen aus der result.format, die geloescht werden muessen
            
            lines_to_delete = []
            for zeile1 in diff_sort_z_reduce_diff:
                zeile = equivalent_zeilen[zeile1]
                lines_to_delete.append(sortierte_zeilen.index(zeile)-2)
                del_lines.append("< " + zeile)

            #  Jetzt die neue result.orig schreiben:
            
#            print(lines_to_delete)

            result_orig = []
            zaehler     = 0
            del_datum   = {}
            for zeile in open(file+".orig").read().split("\n"):
                if zaehler in lines_to_delete:
#                    print("DEL",zeile)
                    del_datum[zeile[0:6]] = 1
                else:
                    result_orig.append(zeile)
                zaehler = zaehler + 1

            for zeile in diff_text0_reduce_diff:
                add_lines.append("> " + zeile)
                result_orig.insert(-1,zeile)
           
            result_orig = "\n".join(result_orig)
                                       
            dates_of_deleted_entries = []

            for ddatum in del_datum.keys():
                if re.search(r"^\d\d\d\d\d\d$",ddatum):
                    if "\n" + ddatum in result_orig:
                        continue
                    if result_orig.startswith(ddatum):
                        continue
                    dates_of_deleted_entries.append(ddatum)
        
            if len(del_lines) > 0 or len(add_lines) > 0:
                open(file+".orig","w").write(result_orig)
            else:
                os.unlink(file+".orig")
                os.unlink(file+".par")
                return()

#            print("-----------")
#            print(result_orig)
#            print("-----------")


#  ---  2. Jetzt zusammensetzen


        (startdate,enddate) = self.sort_transaction(file+".orig")
        if os.path.isfile(file+".par"):
            m = re.search(r"(\S*?),(\S*?),(\S*?)",open(file+".par").read())
            if m:                           #  In der result.par stehen die urspruenglichen Request-Daten.
                pattern   = m.group(1)      #  Diese Abfrage wiederholen, und die erhaltenen Buchungssaetze aus
                interval  = m.group(2)      #  den acc-Dateien ABZIEHEN
                egrep     = m.group(3)
                if interval == "None":
                    interval = None       
                self.split_subtract([startdate,enddate,pattern,interval,egrep],file)
        
        list_of_files = glob.glob("*.acc")
        list_of_files.sort()
        for ktofile in list_of_files:     #  hier die geaenderte result.orig auf die acc-Files richtig verteilen

            salden_file = re.sub(r"\.acc$",".sum",ktofile)
            abschnitt   = re.sub(r"\.acc$","",ktofile)

            m = re.search(r"^(\d+)\.acc",ktofile)
            if not m:
                continue

            zeitraum = m.group(1)
#            print(zeitraum,startdate,enddate)
            if os.path.isfile(salden_file):
                if zeitraum < startdate[0:len(zeitraum)]:
                    continue
                if zeitraum > enddate[0:len(zeitraum)]:
                    continue

            os.system("grep ^" + m.group(1) + " " + file + ".orig >> " + ktofile)
            if sortieren == 1:    #   hier die acc-Files wieder sortieren
                file_text = re.sub(r"\n+$","",open(ktofile).read()).split("\n")
                file_text.sort()
                open(ktofile,"w").write("\n".join(file_text) + "\n")
                self.mark("C. " + ktofile + " sorted.")
#                os.system("sort " + ktofile + " > " + "__" + ktofile)
#                os.system("mv __" + ktofile + " " + ktofile)
                

#       ------ 3.  Jetzt die Salden-Files nachziehen:

            diff_salden = {}
            is_buchung  = {}
            init_salden = ""
            salden_text = []
            if os.path.isfile(salden_file):    
                salden_text = open(salden_file).read().strip().split("\n")   #  update der salden_files
            else:
                init_salden = open(ktofile).read()

            update_salden = 0
            for diff_buchung in ( init_salden.split("\n") + add_lines + del_lines ):
                m = re.search("^([\<\>] +|)(\d\d\d\d\d\d\d\d) +(\S+) +(\S+) +(\S+) +(\-?\d+\.\d\d|\.+)",diff_buchung)
                if m:
                    if update_salden == 0:
                        update_salden = 1
                        self.mark("D. Update " + ktofile + ".")
                    datum  = m.group(2)
                    if datum.startswith(abschnitt):
                        betrag = eval(m.group(3))
                        ktoa   = m.group(4)
                        ktob   = m.group(5)
                        if m.group(1).startswith("<"):
                            betrag = -betrag
                        self.compute_salden(diff_salden,is_buchung,ktoa, betrag,datum) 
                        self.compute_salden(diff_salden,is_buchung,ktob,-betrag,datum)

            tt = 0
#            tt = 1

#            if tt == 1:
#                for kt in list(diff_salden.keys()):
#                    for monat in diff_salden[kt]:
#                        if "ger-LOHN-AN" in kt:
#                            print(kt,monat,diff_salden[kt][monat])

            salden_text.sort()
            salden_text1  = []
            del_element   = []
            update_salden = 0
            for kto in list(diff_salden.keys()):

#                if tt == 1:
#                    print(kto)
                if update_salden == 0:
                    update_salden = 1
                    self.mark("E. Diff salden computed.")
                    
                interval0 = 0   # suchen, ob es schon eine gueltige Zeile gibt
                interval1 = len(salden_text) - 1
                while (0 == 0):
                    if interval0 > interval1:
                        interval9 = -1
                        break
                    interval9 = interval0 + int((interval1 - interval0)/2)
#                    if tt == 1:
#                        print(interval0,interval9,interval1,kto)
#                    if tt == 1:
#                        print("    ",salden_text[interval9])
#                    print(kto)
                    if salden_text[interval9].startswith(kto+","):
                        break
                    if (kto + ",") > salden_text[interval9]:
                        interval0 = interval9 + 1
                    else:
                        interval1 = interval9 - 1
                                    
                if interval9 > -1:   #   wenn es schon eine Konto-Zeile im Salden-File gibt, diese integrieren
#                    if tt == 1:
#                        print(salden_text[interval9])
                    werte = salden_text[interval9].split(",")
#                    if tt == 1:
#                        print(werte)
                    werte.pop(0)
                    if len(werte) > 0:
                        monat   = int(werte.pop(0))
                        betrag0 = 0.00
                        nr0     = 0
                        for betrag in werte:
                            nr     = int(betrag[-self.max_months:])
                            betrag = float(betrag[:-self.max_months])
                            if not monat in diff_salden[kto]:
                                diff_salden[kto][monat] = 0.00
                                is_buchung[kto][monat]  = 0
                            diff_salden[kto][monat] = diff_salden[kto][monat] + betrag - betrag0
                            if monat in dates_of_deleted_entries:
                                is_buchung[kto][monat]  = 0
                            else:
                                is_buchung[kto][monat]  = 1
                            betrag0 = betrag
                            nr0     = nr
                            monat   = monat + 1
                            if str(monat)[4:6] == "13":
                                monat = int(str(int(str(monat)[0:4]) + 1) + "01")
                            
                monate   = list(diff_salden[kto].keys())
                monat    = min(monate)
                mmax     = max(monate)
                zeile    = kto + "," + str(monat) + ","
                betraege = []
                sum      = 0.00
                nr       = 0
                while (0 == 0):
                    if monat in diff_salden[kto]:
                        sum = sum + diff_salden[kto][monat]
                        nr  = nr  + is_buchung[kto][monat]
                    betraege.append(("%3.2f"%sum)+("%04u"%nr))
                    monat   = monat + 1
                    if str(monat)[4:6] == "13":
                        monat = int(str(int(str(monat)[0:4]) + 1) + "01")
                    if monat > mmax:
                        break
                while (0 == 0):
                    if len(betraege) < 2:
                        break
                    if not betraege[-1] == betraege[-2]:
                        break
                    betraege.pop()
                zeile = zeile + ",".join(betraege)
                if len(betraege) == 1 and float(betraege[0][:-self.max_months]) == 0.00:
                    if interval9 > -1:
                        salden_text[interval9] = "---DELETE---"   #  loesche die Zeile
                    else:
                        pass                                      #  Zeile ist Null, gar nicht erst eintragen
                else:
                    if interval9 > -1:
                        salden_text[interval9] = zeile   #  Zeile updaten
                    else:
                        salden_text1.append(zeile)       #  Zeile existierte nicht, also eintragen
                
            if update_salden == 1:
                self.mark("F. Salden list updated.")
     
#            while len(del_element) > 0:
#                salden_text.pop( del_element.pop() )

            salden_text = salden_text + salden_text1
            salden_text.sort()
            salden_text = "\n".join(salden_text) + "\n"
            salden_text = re.sub(r"---DELETE---\n","",salden_text,99999999)
            open(salden_file,"w").write(salden_text)   #  update der salden_files

        os.system("mv " + file + ".orig " + file + ".old")
        self.mark("G. ... closed.")

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

    def xxsort_transaction (self,file):

        os.system("sort " + file + " > " + "__" + file)
        os.system("mv __" + file + " " + file)
        startdate = os.popen("head -n 1 " + file).read()[0:8]
        enddate   = os.popen("tail -n 1 " + file).read()[0:8]
        if not re.search(r"^\d\d\d\d\d\d\d\d$",startdate):
            startdate = "00000000"
        if not re.search(r"^\d\d\d\d\d\d\d\d$",enddate):
            enddate = "99999999"

        return(startdate,enddate)
        
#**********************************************************************************

    def xxsplit (self,pattern="",file="result"):

        if os.path.isfile(file+".orig"):
            self.add()
            return()

        split_pars = self.split1(pattern,file)
        self.split_subtract(split_pars,file)

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

    def xxsplit1 (self,pattern="",file="result"):

        self.mark("")
        pattern1 = re.sub(r"\^"," ",pattern,9999)
        (pattern1,interval,egrep,interval0) = self.parse_pattern(pattern1)

        self.mark("A. Compute query for transaction file " + pattern1 + " " + str(interval)[0:40] + " ...")
        if interval:
            if pattern1 == "":
                os.system(egrep + "grep -h -i ^" + interval + " *.acc > " + file + ".orig")
            else:
                os.system(egrep + "grep -h -i ^" + interval + " *.acc | grep -h -i '" + pattern1 + "' > " + file + ".orig")
        else:
            if pattern1 == "":
                os.system("less *.acc > " + file + ".orig")
            else:
                os.system(egrep + "grep -h -i '" + pattern1 + "' *.acc > " + file + ".orig")
                

        (startdate,enddate) = self.sort_transaction(file + ".orig")


#        text0 = open(file+".orig").read().split("\n")   #   Doubletten-Vermeidung
#        if len(text0) > len(set(text0)):
#            print("Attention: Doublettes!")
#            text0.sort()
#            zeile0  = "-----"
#            text1   = []
#            zaehler = 0
#            for zeile in text0:
#                if len(zeile) == 0:
#                    continue
#                zeile1 = zeile.replace(" ","")
#                if zeile1 == zeile0:
#                    zaehler = zaehler + 1
#                    text1.append(zeile + " DOUBLETTE " + str(zaehler))
#                else:
#                    text1.append(zeile)
#                    zaehler = 0
#                    zeile0  = zeile1
#            open(file+".orig","w").write("\n".join(text1)+"\n")
        
        open(file+".par","w").write(pattern1+","+str(interval)+","+egrep+"\n")

        self.mark("B. Transaction file generated.")

        if len(glob.glob("*.acc")) == len(glob.glob("*.sum")):
            self.format_kto(pattern1,interval0,pattern)
            self.mark("C. ... and formatted.")
        
        return([startdate,enddate,pattern1,interval,egrep])

#**********************************************************************************
        
    def xxsplit_subtract (self,pars,file="result"): 

        startdate = pars[0]
        enddate   = pars[1]
        pattern   = pars[2]
        interval  = pars[3]
        egrep     = pars[4]

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


        list_of_files = glob.glob("*.acc")
        for ktofile in list_of_files:

            m = re.search(r"^(\d+)\.acc",ktofile)
            if not m:
                continue
            zeitraum = m.group(1)
            if zeitraum < startdate[0:len(zeitraum)]:
                continue
            if zeitraum > enddate[0:len(zeitraum)]:
                continue

            if interval:
                if pattern1 == "":
                    os.system(egrep + "grep -i -v ^" + interval + " " + ktofile + " > __" + ktofile)
                else:
                    os.system(egrep + "grep -i -v ^" + interval + " " + ktofile + " > __" + ktofile)
                    os.system(egrep + "grep -i ^" + interval + " " + ktofile + " | grep -i -v '" + pattern1 + "' >> __" + ktofile)
            else:
                if pattern1 == "":
                    os.system(" > __" + ktofile)
                else:
                    os.system(egrep + "grep -i -v '" + pattern1 + "' " + ktofile + " > __" + ktofile)
                    
            os.system("mv __" + ktofile + " " + ktofile)

        self.mark("D. Clear acc files.")
                
#**********************************************************************************

    def xxxxformat_kto (self,pattern,interval,pattern0,file="result"):

        if interval:
            interval = interval
        else:
            interval = ""

        try:
            text = open(file+".orig").read()
        except Exception as e:
            print(e)
            return()

        result = self.parse_ktotext(text.split("\n"),pattern)
        if not result:
            return(None)
                
        (ktotext,self.format_maxa,self.format_maxb,self.maxsaldo,ukto) = result
                
#        print("UKTO: " + ukto)
        if False and ukto == "":
            ktotext.sort(key=lambda x:x[0]+str(x[1])+x[3]+x[4])
        else:
#            ktotext.sort(key=lambda x:str(x[5]+1)+x[0])
            ktotext.sort(key=lambda x:x[0]+str(x[5]+1)+x[2]+x[3]+x[4])

        text_match1  = []
        text_match2  = []
        result_match = []
        gesamt       = 0.00
        datum        = "00000000"
        datum0       = "00000000"

        orig_text_new_sorted = []   #  das orig-File muss in der neuen Sortierung auch neu geschrieben werden,
                                    #  damit man am Ende den Patch auf das formatierte Konto-File anwenden kann.
        dbl_marks = {}

        has_doublettes = 0
        for zeile in ktotext:
                
            ust = ""
            if "v.H." in zeile[4]:
                ust = "   "

            ktoa   = zeile[2]
            ktob   = zeile[3]
            datum  = zeile[0]
            
            
#            print(ukto,zeile)
            betrag = float(zeile[1])
            if ukto == "" or zeile[5] == 0:
                saldo = "         ...."
#                saldo  = "%13.2f" % gesamt
            elif self.maxsaldo == 0 or zeile[5] == 1:
#                print("hier")
                gesamt = gesamt + betrag
                saldo  = "%13.2f" % gesamt
            elif zeile[5] == 2:
#                saldo = "         ----"
                saldo  = "%13.2f" % gesamt

            dbl_z    = datum + " " + ("%13.2f" % betrag) + "  " + (self.format_maxa % ktoa) + "  " + (self.format_maxb % ktob)
            rem_z    = ust + re.sub(r" +"," ",zeile[4],9999)
            zeile1   = dbl_z + " " + saldo + "  " + rem_z

            dbl_mark = dbl_z + rem_z   #  wenn Doubletten gefunden werden, diese eindeutig markieren
            if not dbl_mark in dbl_marks:
                dbl_marks[dbl_mark] = 0
            else:
                dbl_marks[dbl_mark] = dbl_marks[dbl_mark] + 1
                zeile1 = zeile1 + " DOUBLETTE " + str(dbl_marks[dbl_mark])
                has_doublettes = 1
            
#            print(zeile1)

            if True or zeile[5] == 1:
                text_match1.append(zeile1)
            else:
                text_match2.append(zeile1)
            if datum0 == "00000000":
                datum0 = datum

            orig_text_new_sorted.append(zeile[6])

#        text_match1  = "" + ("%-50s"%(pattern0)) + ("%13.2f"%gesamt) + "\n\n" + "\n".join(text_match1) + "\n"
        text_match1  = "" + ("%-50s"%(re.sub(r"\.$","",ukto+interval))) + ("%13.2f"%gesamt) + "\n\n" + "\n".join(text_match1) + "\n"
        text_match2  = "\n".join(text_match2) + "\n"
        
        salden_text = self.format_salden(ukto,datum,datum0,"^"+ukto+"(-[^- ]+){0,99},")
        text_match1 = text_match1 + "\n" + re.sub(ukto+"(-| )","","\n".join(salden_text),99999999) + "\n\n" + text_match2
            
        open(file+".format","w").write(text_match1)
        open(file+".kto","w").write(text_match1)
        open(file+".orig","w").write("\n".join(orig_text_new_sorted)+"\n")
        
        if has_doublettes:
            print("Attention: Doublettes!")

#        exit()


    def xxxxapply_patch (self,file,patch,offset=0):  #  verbessern! Kann der patch Befehl auch direkt auf result.txt angewendet werden?

        text0     = open(file).read()
        text0     = re.sub("\n","--CR--\n",text0,99999999)
        text      = text0.split("\n")

        del_datum = {}
        nr        = -1
        bed       = False

        for zeile in open(patch).read().split("\n"):
            if len(zeile) == 0:
                continue
            if zeile[0] == ">" and nr < len(text):                #  Zeile einzufuegen
                if len(zeile) > 9 and not " " in zeile[2:10]:     #  das ist tatsaechlich eine Buchungszeile,
                    bed = True                                    #  denn sie faengt mit einem Datum an        
                text[nr] = text[nr] + zeile[2:] + "--CR--"
            elif zeile[0] == "<":                                 #  Zeile zu loeschen
                if len(zeile) > 9 and not " " in zeile[2:10]:     #  das ist tatsaechlich eine Buchungszeile,
                    bed = True                                    #  denn sie faengt mit einem Datum an
                del_datum[zeile[2:8]] = 1                         #  vormerken, dass in diesem Monat eine Buchung geloescht wurde
                continue
            else:
                m = re.search(r"^(\d+)(,\d+|)([acd])",zeile)  #  eine Zeile, in der eine Update-Information steht,
                if m:                                         #  (diese Info wirkt sich dann aus auf die naechsten Zeilen)
#                    print(zeile)
                    act = m.group(3)
                    nr1 = int(m.group(1)) - 1 - offset
                    nr2 = nr1
                    if len(m.group(2)) > 0:
                        nr2 = int(m.group(2)[1:]) - 1 - offset
                    if act in "ac":
                        nr = max(0,min(nr1,len(text)-1))
                    if act in "dc":   #  Zeilen entfernen
                        while (nr1 < len(text)):
#                            print("ZZZ",zeile,nr1)
#                            print("DDD",text[nr1],nr1)
                            text[nr1] = ""
                            nr1 = nr1 + 1
                            if nr1 > nr2:
                                break

        text = "".join(text)
        text = re.sub(r"--CR--","\n",text,99999999)
        text = re.sub(r"\n$","",text,re.DOTALL)

        if not bed:
            return(None)

        dates_of_deleted_entries = []
        for ddatum in del_datum.keys():
            if re.search(r"^\d\d\d\d\d\d$",ddatum):
                if "\n" + ddatum in text:
                    continue
                if text.startswith(ddatum):
                    continue
                dates_of_deleted_entries.append(ddatum)
        
        open(file,"w").write(text)

        return(dates_of_deleted_entries)   #  die Monate, in denen jetzt gar keine Buchungen mehr sind, werden zurueckgegeben
        
#****************************************************************************************************************

    def xxkto (self,pattern=""):

        ktodir = os.path.abspath(".")

        if pattern == "SORT":     #   Sortieren aller acc und sum files. Dies ist sinnvoll fuer das syncen
        
            for acc_file in glob.glob("*.acc") + glob.glob("*.sum"):
                file_text = re.sub(r"\n+$","",open(acc_file).read()).split("\n")
                file_text.sort()
                open(acc_file,"w").write("\n".join(file_text) + "\n")
                return()

        ktofile = []
        for kfile in glob.glob("*.kto"):
            if not ".db." in kfile and "result.kto" not in kfile:
                ktofile.append(kfile)
        
        if len(ktofile) > 1:
            print("More than one ktofile.")
            return()

        if len(ktofile) == 1:
            ktofile = ktofile[0]
        else:
            ktofile = None

        if ktofile:
            ktodir   = re.sub(r"^(.*)[\\\/](.*).kto$","\\1",os.path.abspath(ktofile))
            ktotext  = open(ktodir+"/"+ktofile).read()
            pattern0 = "^" + re.sub(r"^(\S*) (.*)$","\\1",ktotext[0:50])
        else:
            ktotext  = ""
            ktodir   = re.sub(r"[\\\/]$","",os.path.abspath("."))


        while (0 == 0):   #  check if we are in a directory with acc files
            x = glob.glob("2*.acc") + glob.glob("base/*.acc") + glob.glob(".base/*.acc")
            if len(x) > 0:
                y = glob.glob("2*.sum") + glob.glob("base/*.sum") + glob.glob(".base/*.sum")
                m = re.search(r"^(.*)[\\\/](.*)$",x[0])
                if m:
                    os.chdir(m.group(1))
                break
            os.chdir("..")
            
#        os.system("ls")

        if os.path.isfile("result.orig"):
            hkey = os.popen("md5sum result.kto").read()[0:12]
            if hkey + ".kto" == ktofile or hkey in ktotext[0:200]:
                open("result.kto","w").write(ktotext)
                    
        udir = None
        if ktofile:
            udir = ktodir
            if pattern == "":
                pattern = pattern0   #  wenn kein pattern angegeben, nimm das pattern aus dem ktofile
            else:
                m = re.search(r"^(.*)([\.\:])(.*)",pattern0)
                if m:
                    p0 = m.group(1)
                    m0 = m.group(2)
                    i0 = m.group(3)
                else:
                    p0 = pattern0
                    m0 = None
                    i0 = None
                m = re.search(r"^(.*)([\.\:])(.*)",pattern)
                if m:
                    p1 = m.group(1)
                    m1 = m.group(2)
                    i1 = m.group(3)
                else:
                    p1 = pattern
                    m1 = None
                    i1 = None
                if not i1:
                    i1 = i0
                if not i1:
                    i1 = ""
                if p1 in p0:
                    p1 = ""
                p2 = re.sub(r"-$","",p0 + "-" + p1)
                if p0 == "" or not p2[1:] in ktotext:
                    p2 = p1
                if len(p0) > 0 and p2.startswith(p0):
                    udir = ktodir + "/" + p1
#                    p2   = "^" + p2
                    print("UDIR",udir)
                    try:
                        os.mkdir(udir)
                    except:
                        pass

                if m0 == m1:
                    if not m1:
                        m1 = ""
                    pattern = p2 + m1 + i1
                pattern = re.sub(r"\.$","",pattern)

        print("PATTERN",pattern)

        if os.path.isfile("result.orig"):
            if pattern == "":
                self.add(1)
            else:
                self.add()
            if os.path.isfile("result.kto"):
                os.unlink("result.kto")
                
        if pattern == "":
            os.chdir(ktodir)
            return()
            

        split_pars = self.split1(pattern)

        if os.path.isfile(ktodir+"/result.orig"):
            os.chdir(ktodir)
            return()

        if os.path.isfile("result.orig"):
            
            if udir:
                for kfile in glob.glob(udir+"/*.kto"):
                    os.unlink(kfile)
            else:
                udir = ktodir

            hkey = os.popen("md5sum result.kto").read()[0:12]
            
            ktotext = open("result.kto").read()
            ktotext = re.sub(r"^(\S+  )( +\S+)","\\1 " + hkey + "\\2",ktotext)
            if ktofile == None or re.search(r"^[abcdef0123456789]{12}\.kto$",ktofile):
                open(udir+"/"+hkey+".kto","w").write(ktotext)
            else:
                open(udir+"/"+ktofile,"w").write(ktotext)

        os.chdir(ktodir)


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

if __name__ == "__main__":
        
#    Konto.__dict__[sys.argv[1]](Konto(),*sys.argv[2:])

    if len(sys.argv) > 1 and sys.argv[1].startswith("test"):
        Konto.__dict__[sys.argv[1]](Konto(),*sys.argv[2:])
    elif len(sys.argv) > 1 and sys.argv[1] == "sort":
        Konto.__dict__["sort"](Konto(),*sys.argv[2:])
    elif len(sys.argv) > 1 and sys.argv[1] == "saldo":
        print(Konto.__dict__["read_saldo"](Konto(),*sys.argv[2:]))
    else:
        Konto.__dict__["kto"](Konto(),*sys.argv[1:])

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