#import copy import os #import sys #import base64 #import hashlib import traceback #import re import pprint import docing import filing import lxml.etree as etree from lxml.builder import ElementMaker from nitpo import Nitpo #from sheets import Sheets from profile import Profile from kafik import Kafik from chapro import Chapro from kafik import Kafik from vakis import Vakis from urllib.parse import urlparse, parse_qs class Web(Nitpo): def __init__(self, do_verbose=False): """web class""" super().__init__() self.N = "{%s}" % self.const['ns'] self.E = ElementMaker(nsmap={None: self.const['ns']}) self.env = None #self.sheets = Sheets() self.len_start = 0 if self.has_conf('web', 'pathstart'): self.len_start = len(self.conf['web']['pathstart']) self.diags = [] self.p = Profile() self.k = Kafik() self.c = Chapro() # # web element to be transformed self.web_ele = None # # status code self.status = None # # action code from request self.acod = None # # subscription key self.kisu = None # # current file self.fiken = None # # repcodes to work on self.repcodes = [] self.vakis = Vakis() self.do_verbose = do_verbose def logbug(self, string): if not self.is_dev(): return print(string, flush=True) def output(self, env, preps): self.env = env self.preps = preps web_ele = self.E(self.N + 'web') self.web_ele = web_ele # web_doc = etree.ElementTree(web_ele) # sheet_fufi = self.sheets.get_sheet_fufi('web') # changes self.logbug('b4 check') try: self.check_request(env) except Exception: self.web_ele.attrib['error'] = 'system' error_ele = etree.SubElement(self.web_ele, self.N + 'error') lines = traceback.format_exc().split("\n") for line in lines: if line.isspace(): continue line = line.replace(' ', ' ') line_ele = etree.SubElement(error_ele, self.N + 'line') line_ele.text = line self.logbug(docing.show(web_ele)) self.logbug('after check') #if out['status'] == '301': # return out # out = docing.show(web_ele) web_doc = etree.ElementTree(web_ele) if self.is_dev: etree.cleanup_namespaces(web_doc) etree.register_namespace("n", self.const['ns']) out = etree.tostring(web_doc, pretty_print=True).decode() filing.srite('/tmp/web.xml', out, do_verbose=self.do_verbose) out = str(preps['web_sheet'](web_doc)) return out def check_request(self, env): self.fiken = None raw_uri = env['RAW_URI'] full_uri = env['RAW_URI'] if raw_uri.startswith('//'): # # add the pathstart if self.has_conf('web', 'pathstart'): full_uri = self.conf['web']['pathstart'] + '/' \ + raw_uri[2:] self.web_ele.attrib['raw_uri'] = raw_uri if not self.preps['res']['url_u'].match(raw_uri): self.web_ele.attrib['status'] = '400' self.web_ele.attrib['error'] = 'wrong_url' self.web_ele.attrib['arger'] = raw_uri self.logbug('bad url ' + raw_uri) self.logbug(self.preps['res']['url_u']) return kisu = raw_uri[4:26] self.acod = raw_uri[2:3] self.web_ele.attrib['kisu'] = kisu if kisu not in self.preps['vakis']: # # load by adding kisus to the memory stock # # problem, if we are bombarded by request for an invalid # # kisu, loading will take time and could lead to problems # # thus, it is prudent to introduce a maximum if kisu not in self.preps['count_reload_vakis']: self.preps['count_reload_vakis'][kisu] = 0 self.preps['count_reload_vakis'][kisu] += 1 # # should be configurable but it's hard to describe if self.preps['count_reload_vakis'][kisu] < 100: self.logbug('reload vakis to find ' + kisu + ' ' + str(self.preps['count_reload_vakis'][kisu])) filing.add(self.conf['files']['vakis'], self.preps['vakis']) else: self.logbug('no reload for ' + kisu) if kisu not in self.preps['vakis']: self.web_ele.attrib['status'] = '200' self.web_ele.attrib['error'] = 'unknown_kisu' self.web_ele.attrib['arger'] = kisu self.logbug('bad kisu ' + kisu) return self.kisu = kisu self.logbug('work on ' + kisu) subda = self.preps['vakis'][kisu] self.logbug(str(subda)) emad = subda['emad'] self.web_ele.attrib['emad'] = emad repcode = subda['repcode'] self.web_ele.attrib['repcode'] = repcode query_string = env['QUERY_STRING'] if len(query_string) > 0 and self.acod == 'u': self.parse_query_u(env) fufi = self.p.fufi_from_emad(emad) self.web_ele.attrib['fufi'] = fufi # # suggested fiken to put into the form sugfik = filing.md5(fufi) self.web_ele.attrib['prop_fiken'] = sugfik self.logbug(sugfik) if not os.path.isfile(fufi): print(f"web does not see {fufi}") #if not os.path.isfile(fufi): # # well reads the file twice sub_doc = filing.parse_lax(fufi) ## if there no live subscription of the prime repcode, ## create a failure ele if not self.p.s.has_it_live(sub_doc, repcode): failure_ele = etree.SubElement(self.web_ele, self.N + 'failure') failure_ele.attrib['type'] = 'already_gone' repcode_ele = etree.SubElement(failure_ele, self.N + 'repcode') repcode_ele.text = repcode emad_ele = etree.SubElement(failure_ele, self.N + 'emad') emad_ele.text = emad froom = self.p.s.birth_datim(sub_doc, repcode) from_ele = etree.SubElement(failure_ele, self.N + 'from') from_ele.text = froom return self.web_ele.append(sub_doc.getroot()) if self.fiken is not None: self.web_ele.attrib['fiken'] = self.fiken self.logbug(docing.show(self.web_ele)) self.deal_with_fiken(env) return ## as long as one repcode is alive, just reports all that have ## somthing unsubed def deal_with_fiken(self, env): """deals with the request, really""" subda = self.preps['vakis'][self.kisu] emad = subda['emad'] untils = {} frooms = {} repcodes = self.repcodes if not self.k.is_correct(self.fiken, emad): # # this should show the surkof form again return # # should not load here, but ok doc = self.p.load(emad) ### etree.SubElement(self.web_ele, doc) self.web_ele.append(doc.getroot()) for repcode in repcodes: self.logbug(f"I look at {repcode}") if not self.p.s.has_it_live(doc, repcode): # # delete_report checks this, we do it here for information until = self.p.s.death_datim(doc, repcode) if until is None: continue if until not in untils: untils[until] = [] untils[until].append(repcode) else: # # about to be deleted froom = self.p.s.birth_datim(doc, repcode) if froom is None: continue if froom not in frooms: frooms[froom] = [] frooms[froom].append(repcode) self.logbug(repcode) doc = self.p.delete_report(emad, repcode, doc=doc, dont_write=True) # etree.SubElement(self.web_ele, doc) # looser: reports that are deleted now losers = sorted(frooms.keys()) if len(losers) > 0: losers_ele = etree.SubElement(self.web_ele, self.N + 'losers') for froom in losers: loser_ele = etree.SubElement(losers_ele, self.N + 'loser') loser_ele.attrib['from'] = froom for repcode in frooms[froom]: report_ele = etree.SubElement(loser_ele, self.N + 'repcode') report_ele.text = repcode # goners: reports that were deleted before goners = sorted(untils.keys()) if len(goners) > 0: goners_ele = etree.SubElement(self.web_ele, self.N + 'goners') for until in goners: goner_ele = etree.SubElement(goners_ele, self.N + 'goner') goner_ele.attrib['until'] = until for repcode in untils[until]: report_ele = etree.SubElement(goner_ele, self.N + 'repcode') report_ele.text = repcode for goner in goners: goner_ele = etree.SubElement(goners_ele, self.N + 'goner') goner_ele.attrib['until'] = until for repcode in untils[until]: report_ele = etree.SubElement(goner_ele, self.N + 'repcode') report_ele.text = repcode self.p.write(doc) ## is_doc is None if the surk can not be deleted. #cha_doc = self.c.make(was_doc, is_doc, self.fiken) # return cha_doc return self.web_ele def parse_query_u(self, env): self.repcodes = [] query_string = env['QUERY_STRING'] self.web_ele.attrib['query_string'] = query_string query = parse_qs(query_string) query_ele = etree.SubElement(self.web_ele, self.N + 'query') for name in query: for value in query[name]: name_ele = etree.SubElement(query_ele, self.N + name) name_ele.text = value if name == 'fiken': # # this triggers treatment as as response self.web_ele.attrib['fiken'] = value self.fiken = value continue if name.startswith('check_') and value == 'on': repcode = name[6:] self.repcodes.append(repcode) action_ele = etree.SubElement(self.web_ele, self.N + 'action') action_ele.text = repcode continue if name.startswith('sign_multi'): ## the multiple signoff case continue if name.startswith('not_really'): ## the single signoff case continue if name.startswith('sign_multi'): continue print(f"I don't know about {name}", flush=True)