def forward(srcid, dstid, msgid, header, body, tosrc=False, newsubj=None): origdom, origtext = ftnconfig.get_addr(db, srcid) origdom = db.FTN_backdomains[origdom] destdom, desttext = ftnconfig.get_addr(db, dstid) destdom = db.FTN_backdomains[destdom] tpl = ["From: " + repr(ftnconfig.SYSOP) + "\n"] if tosrc: tpl.append("To: "+repr(header.find("sendername").text)+"\n") else: tpl.append("To: ''\n") if newsubj: tpl.append("Subject: " + repr(newsubj) + "\n") else: tpl.append("Subject: " + repr(header.find("subject").text) + "\n") tpl.append("ReplyTo: " + repr(None) + "\n") if tosrc: tpl.append("Destination: (%s, %s)\n"%(repr(origdom), repr(origtext))) else: tpl.append("Destination: ('', '')\n") tpl.append("Attr: []\n") tpl.append("\n") if tosrc: tpl.append("Hello "+(header.find("sendername").text or "Sysop")+",\n") else: tpl.append("Hello ,\n") tpl.append("\n") tpl.append(" *** Forwarded message:\n") tpl.append("="*79+"\n") tpl.append("From: %s, %s %s\n"%(header.find("sendername").text or '', origdom, origtext)) tpl.append("To : %s, %s %s\n"%(header.find("recipientname").text or '', destdom, desttext)) tpl.append("Subj: %s\n"%(header.find("subject").text or '')) tpl.append("Date: %s\n"%(header.find("date").text or '')) tpl.append("-"*79+"\n") tpl.extend(map(inval, body.splitlines(True))) tpl.append("="*79+"\n") tpl.append("\n") tpl.append("... vim\n") newmsg = "".join(tpl) (fh, fname) = tempfile.mkstemp() fo = os.fdopen(fh, "w") fo.write(newmsg) fo.close() os.system ("vi " + fname) editedmsg = open(fname).read() if newmsg == editedmsg: print("no changes") r = False else: submit(editedmsg) r = True os.unlink(fname) return r
def reply(srcid, dstid, msgid, header, body): nameparts = RE_s.split(header.find("sendername").text.strip()) senderfirstname = nameparts[0] if senderfirstname: qname = senderfirstname[0] else: qname = '' if len(nameparts) > 1: qname += nameparts[-1][0] origdom, origtext = ftnconfig.get_addr(db, srcid) origdom = db.FTN_backdomains[origdom] destdom, desttext = ftnconfig.get_addr(db, dstid) destdom = db.FTN_backdomains[destdom] tpl = ["From: " + repr(ftnconfig.SYSOP) + "\n"] tpl.append("To: " + repr(header.find("sendername").text) + "\n") tpl.append("Subject: " + repr(header.find("subject").text) + "\n") tpl.append("ReplyTo: " + repr(msgid) + "\n") if destdom == 'echo': tpl.append("Destination: " + repr((destdom, desttext)) + "\n") tpl.append("#Destination: " + repr((origdom, origtext)) + "\n") else: tpl.append("Destination: " + repr((origdom, origtext)) + "\n") tpl.append("Attr: []\n") tpl.append("\n") tpl.append(" ".join(("Hello", senderfirstname)) + ",\n") tpl.append("\n") tpl.append("orig.message to %s %s on " % (destdom, desttext) + header.find("date").text.strip() + "\n") tpl.extend(quote(qname, body.splitlines())) tpl.append("\n") tpl.append("Sergey\n") tpl.append("\n") tpl.append("... vim\n") newmsg = "".join(tpl) (fh, fname) = tempfile.mkstemp() fo = os.fdopen(fh, "w") fo.write(newmsg) fo.close() os.system("vi " + fname) editedmsg = open(fname).read() if newmsg == editedmsg: print("no changes") r = False else: submit(editedmsg) r = True os.unlink(fname) return r
def reply(srcid, dstid, msgid, header, body): nameparts = RE_s.split(header.find("sendername").text.strip()) senderfirstname = nameparts[0] if senderfirstname: qname = senderfirstname[0] else: qname = '' if len(nameparts)>1: qname += nameparts[-1][0] origdom, origtext = ftnconfig.get_addr(db, srcid) origdom = db.FTN_backdomains[origdom] destdom, desttext = ftnconfig.get_addr(db, dstid) destdom = db.FTN_backdomains[destdom] tpl = ["From: " + repr(ftnconfig.SYSOP) + "\n"] tpl.append("To: " + repr(header.find("sendername").text) + "\n") tpl.append("Subject: " + repr(header.find("subject").text) + "\n") tpl.append("ReplyTo: " + repr(msgid) + "\n") if destdom == 'echo': tpl.append("Destination: " + repr((destdom, desttext)) + "\n") tpl.append("#Destination: " + repr((origdom, origtext)) + "\n") else: tpl.append("Destination: " + repr((origdom, origtext)) + "\n") tpl.append("Attr: []\n") tpl.append("\n") tpl.append(" ".join(("Hello", senderfirstname))+",\n") tpl.append("\n") tpl.append("orig.message to %s %s on "%(destdom, desttext) + header.find("date").text.strip() + "\n") tpl.extend(quote(qname, body.splitlines())) tpl.append("\n") tpl.append("Sergey\n") tpl.append("\n") tpl.append("... vim\n") newmsg = "".join(tpl) (fh, fname) = tempfile.mkstemp() fo = os.fdopen(fh, "w") fo.write(newmsg) fo.close() os.system ("vi " + fname) editedmsg = open(fname).read() if newmsg == editedmsg: print("no changes") r = False else: submit(editedmsg) r = True os.unlink(fname) return r
def view(mid, srcid, dstid, header, body): print ("="*10 + " %20d "%mid + "="*47) print ("From: %-36s, %s"%(header.find("sendername").text, str(ftnconfig.get_addr(db, srcid)))) print ("To : %-36s, %s"%(header.find("recipientname").text, str(ftnconfig.get_addr(db, dstid)))) print ("Subj: %s"%header.find("subject").text) print ("Date: %s"%header.find("date").text) print ("-"*79) ftn=header.find("FTN") for kl in ftn.findall("KLUDGE"): print ("@"+kl.get("name"), kl.get("value")) print (body) print ("="*79)
def view(mid, srcid, dstid, header, body): print("=" * 10 + " %20d " % mid + "=" * 47) print("From: %-36s, %s" % (header.find("sendername").text, str(ftnconfig.get_addr(db, srcid)))) print("To : %-36s, %s" % (header.find("recipientname").text, str(ftnconfig.get_addr(db, dstid)))) print("Subj: %s" % header.find("subject").text) print("Date: %s" % header.find("date").text) print("-" * 79) ftn = header.find("FTN") for kl in ftn.findall("KLUDGE"): print("@" + kl.get("name"), kl.get("value")) print(body) print("=" * 79)
def output(): if withheader: header = msgdata["header"] ftnheader=header.find("FTN") tzutc = None reply = None for kludge in ftnheader.findall("KLUDGE"): if kludge.get("name")=="TZUTC:": tzutc = kludge.get("value") elif kludge.get("name")=="REPLY:": reply = kludge.get("value") # ..References: msgdate=header.find("date").text if msgdate is not None: date3339 = date_to_RFC3339(msgdate, tzutc) msgdate=time.strftime("%a, %d %b %Y %H:%M:%S", time.strptime(date3339[:-7], "%Y-%m-%d %H:%M:%S")) + \ " " + date3339[-6:-3]+date3339[-2:] else: msgdate=msgdata["receivedtimestamp"].strftime("%a, %d %b %Y %H:%M:%S %z") yield "Date: "+msgdate srcdom, srcname = get_addr(db, msgdata["source"]) if srcdom != db.FTN_domains["node"]: srcname = "Not-a-valid-source-{%d}"%msgdata["source"] yield "From: "+(header.find("sendername").text or '')+" <"+srcname+">" yield "Message-ID: "+nntp_make_messageid(msgdata["msgid"]) if reply is not None: yield "In-Reply-To: "+nntp_make_messageid(reply) destdom, destname = get_addr(db, msgdata["destination"]) if destdom != db.FTN_domains["echo"]: destname = "Not-a-valid-newsgroup-{%d}"%msgdata["destination"] yield "Newsgroups: "+destname yield "Path: "+HOSTNAME yield "Subject: "+(header.find("subject").text or '') if withheader and withbody: yield "" if withbody: for l in msgdata["body"].split("\n")[:-1]: yield l
def do(self): to_poll = set() for d in self.dests: to_poll.update( map(lambda x: x[0], ftnexport.get_subscribers(self.db, d))) self.dests = set() myzone = ftn.addr.str2addr(ftnconfig.ADDRESS)[0] #print (myzone) for a in to_poll: #print("poll", a) a = ftnconfig.get_addr(self.db, a)[1] #print (a) link_id = ftnconfig.find_link(self.db, a) if ftnconfig.get_link_polling(self.db, link_id): print("poll", a) else: #print ("not needed") continue addr = ftn.addr.str2addr(a) if addr[0] == myzone: zonepath = ftnconfig.BINKLEYSTYLE else: zonepath = ftnconfig.BINKLEYSTYLE + ".%d" % addr[0] if addr[3] == 0: pollfilename = "%04x%04x.dlo" % (addr[1], addr[2]) basepath = zonepath else: pollfilename = "0000%04x.dlo" % addr[3] basepath = os.path.join(zonepath, "%04x%04x.pnt" % (addr[1], addr[2])) try: os.makedirs(basepath, exist_ok=True) except FileExistsError: pass except: print("could not create outbound directory") return try: touch = open(os.path.join(basepath, pollfilename), "a") touch.close() except: print("could not poll", a) traceback.print_exc()
def do(self): to_poll = set() for d in self.dests: to_poll.update(map(lambda x: x[0], ftnexport.get_subscribers(self.db,d))) self.dests=set() myzone=ftn.addr.str2addr(ftnconfig.ADDRESS)[0] #print (myzone) for a in to_poll: #print("poll", a) a=ftnconfig.get_addr(self.db, a)[1] #print (a) link_id=ftnconfig.find_link(self.db, a) if ftnconfig.get_link_polling(self.db, link_id): print ("poll",a) else: #print ("not needed") continue addr=ftn.addr.str2addr(a) if addr[0]==myzone: zonepath=ftnconfig.BINKLEYSTYLE else: zonepath=ftnconfig.BINKLEYSTYLE+".%d"%addr[0] if addr[3]==0: pollfilename="%04x%04x.dlo"%(addr[1], addr[2]) basepath=zonepath else: pollfilename="0000%04x.dlo"%addr[3] basepath=os.path.join(zonepath, "%04x%04x.pnt"%(addr[1], addr[2])) try: os.makedirs(basepath, exist_ok=True) except FileExistsError: pass except: print ("could not create outbound directory") return try: touch=open(os.path.join(basepath,pollfilename),"a") touch.close() except: print ("could not poll", a) traceback.print_exc()
if domain == "fileecho": print(area, os.listdir("/tank/home/fido/fareas/" + area.lower())) elif domain == "echo": count = db.prepare( "select count(*) from messages where destination=$1").first(aid) print(area, count) if count: continue else: 1 / 0 # 2. send message to subscribers # 3. remove subscriptions and address with ftnimport.session(db) as sess: for node in [ ftnconfig.get_addr(db, x[0])[1] for x in ftnexport.get_subscribers(db, aid) ]: print(node) input("enter to purge, Ctrl-C to abort") for node in [ ftnconfig.get_addr(db, x[0])[1] for x in ftnexport.get_subscribers(db, aid) ]: print(node) sess.send_message( ftnconfig.SYSOP, ("node", node), "Sysop", None, "Area Expunging notification", """Dear Sysop, %s %s is about to be deleted from node %s.
def forward(srcid, dstid, msgid, header, body, tosrc=False, newsubj=None): origdom, origtext = ftnconfig.get_addr(db, srcid) origdom = db.FTN_backdomains[origdom] destdom, desttext = ftnconfig.get_addr(db, dstid) destdom = db.FTN_backdomains[destdom] tpl = ["From: " + repr(ftnconfig.SYSOP) + "\n"] if tosrc: tpl.append("To: " + repr(header.find("sendername").text) + "\n") else: tpl.append("To: ''\n") if newsubj: tpl.append("Subject: " + repr(newsubj) + "\n") else: tpl.append("Subject: " + repr(header.find("subject").text) + "\n") tpl.append("ReplyTo: " + repr(None) + "\n") if tosrc: tpl.append("Destination: (%s, %s)\n" % (repr(origdom), repr(origtext))) else: tpl.append("Destination: ('', '')\n") tpl.append("Attr: []\n") tpl.append("\n") if tosrc: tpl.append("Hello " + (header.find("sendername").text or "Sysop") + ",\n") else: tpl.append("Hello ,\n") tpl.append("\n") tpl.append(" *** Forwarded message:\n") tpl.append("=" * 79 + "\n") tpl.append("From: %s, %s %s\n" % (header.find("sendername").text or '', origdom, origtext)) tpl.append("To : %s, %s %s\n" % (header.find("recipientname").text or '', destdom, desttext)) tpl.append("Subj: %s\n" % (header.find("subject").text or '')) tpl.append("Date: %s\n" % (header.find("date").text or '')) tpl.append("-" * 79 + "\n") tpl.extend(map(inval, body.splitlines(True))) tpl.append("=" * 79 + "\n") tpl.append("\n") tpl.append("... vim\n") newmsg = "".join(tpl) (fh, fname) = tempfile.mkstemp() fo = os.fdopen(fh, "w") fo.write(newmsg) fo.close() os.system("vi " + fname) editedmsg = open(fname).read() if newmsg == editedmsg: print("no changes") r = False else: submit(editedmsg) r = True os.unlink(fname) return r
# 1. verify that there is nothing there if domain == "fileecho": print (area, os.listdir("/tank/home/fido/fareas/"+area.lower())) elif domain == "echo": count = db.prepare("select count(*) from messages where destination=$1").first(aid) print (area, count) if count: continue else: 1/0 # 2. send message to subscribers # 3. remove subscriptions and address with ftnimport.session(db) as sess: for node in [ftnconfig.get_addr(db, x[0])[1] for x in ftnexport.get_subscribers(db, aid)]: print (node) input("enter to purge, Ctrl-C to abort") for node in [ftnconfig.get_addr(db, x[0])[1] for x in ftnexport.get_subscribers(db, aid)]: print (node) sess.send_message(ftnconfig.SYSOP, ("node", node), "Sysop", None, "Area Expunging notification", """Dear Sysop, %s %s is about to be deleted from node %s. Please find new uplink for the area or expunge it too. """%(domain, area, ftnconfig.ADDRESS)) sess.remove_subscription(domain, area, node)
import ftnconfig import ftnexport import ftnimport db = ftnconfig.connectdb() bydomain = {} for domain in ["echo", "fileecho"]: #print ("domain", domain) for t in ftnexport.get_all_targets(db, domain): tid = ftnconfig.get_addr_id(db, db.FTN_domains[domain], t) ulist = [] for x in ftnexport.get_subscribers(db, tid, True): ulist.append("%d|%s" % ftnconfig.get_addr(db, x[0]) + "!%d" % x[2]) #print ulist.sort() bydomain.setdefault(domain, {}).setdefault(", ".join(ulist), []).append(t) with ftnimport.session(db) as sess: for d, byuplink in bydomain.items(): outp = [] for u, targets in byuplink.items(): outp.append(" uplink = [" + u + "]\n") targets.sort() for t in targets: outp.append(" " + t + "\n") outp.append("\n")
elif cmd == "query": # send areafix request sess.send_message(my_addr, ftnconfig.SYSOP, ("node", subscriber), robot, None, pw, "%QUERY", sendmode="direct") elif cmd == "list": # send areafix request sess.send_message(my_addr, ftnconfig.SYSOP, ("node", subscriber), robot, None, pw, "%LIST", sendmode="direct") elif cmd == "show": # show subscribed areas if area==".": # show for link for x in ftnexport.get_node_subscriptions(db, subscriber, domain): print (x) else: # show from area tid = ftnconfig.get_addr_id(db, db.FTN_domains[domain], area) print (tid) for aid, vital, level in ftnexport.get_subscribers(db, tid): print (ftnconfig.get_addr(db, aid)) elif cmd == "showuplink": # show areas subsribed as vital if area==".": # show for link for x in ftnexport.get_node_subscriptions(db, subscriber, domain, asuplink=True): print (x) else: # show from area tid = ftnconfig.get_addr_id(db, db.FTN_domains[domain], area) print (tid) for x in ftnexport.get_subscribers(db, tid, True): print (x) elif cmd == "verifyuplink": a_uplink = set(ftnexport.get_node_subscriptions(db, subscriber, domain, asuplink=True)) a_all = set(ftnexport.get_node_subscriptions(db, subscriber, domain)) print ("linked not as uplink to:")
def __init__(self, b): self.b = b def feed(self, d): self.b.write(d) print (len(d), "bytes added") db = ftnconfig.connectdb() for lid, addr, conn in db.prepare("select id, address, connection from links"): if conn is not None: ftp = conn.find("FTP") if ftp is not None: #print (addr, ftp.keys(), ftp.get("host")) domain, address = ftnconfig.get_addr(db, addr) link_pkt_format = ftnconfig.get_link_pkt_format(db, address) password = ftnconfig.get_link_password(db, address) print (ftp.get("username"), ftp.get("password"), ftp.get("host"), ftp.get("port", 0)) with ftplib.FTP() as ftpc: ftpc.connect(host=ftp.get("host"), port=int(ftp.get("port", 0))) ftpc.login(user=ftp.get("username"), passwd=ftp.get("password")) #print (ftpc.getwelcome()) ftpc.set_pasv(ast.literal_eval(ftp.get("passive", "False"))) path = ftp.get("getfrom") print (path) if path: ftpc.cwd(path)
import ftnconfig import ftnexport import ftnimport db = ftnconfig.connectdb() bydomain = {} for domain in ["echo", "fileecho"]: #print ("domain", domain) for t in ftnexport.get_all_targets(db, domain): tid = ftnconfig.get_addr_id(db, db.FTN_domains[domain], t) ulist = [] for x in ftnexport.get_subscribers(db, tid, True): ulist.append("%d|%s"%ftnconfig.get_addr(db, x[0])+"!%d"%x[2]) #print ulist.sort() bydomain.setdefault(domain, {}).setdefault(", ".join(ulist), []).append(t) with ftnimport.session(db) as sess: for d, byuplink in bydomain.items(): outp=[] for u, targets in byuplink.items(): outp.append(" uplink = ["+u+"]\n") targets.sort() for t in targets: outp.append(" "+t+"\n") outp.append("\n")
def __init__(self, b): self.b = b def feed(self, d): self.b.write(d) print(len(d), "bytes added") db = ftnconfig.connectdb() for lid, addr, conn in db.prepare("select id, address, connection from links"): if conn is not None: ftp = conn.find("FTP") if ftp is not None: #print (addr, ftp.keys(), ftp.get("host")) domain, address = ftnconfig.get_addr(db, addr) link_pkt_format = ftnconfig.get_link_pkt_format(db, address) password = ftnconfig.get_link_password(db, address) print(ftp.get("username"), ftp.get("password"), ftp.get("host"), ftp.get("port", 0)) with ftplib.FTP() as ftpc: ftpc.connect(host=ftp.get("host"), port=int(ftp.get("port", 0))) ftpc.login(user=ftp.get("username"), passwd=ftp.get("password")) #print (ftpc.getwelcome()) ftpc.set_pasv(ast.literal_eval(ftp.get("passive", "False"))) path = ftp.get("getfrom")
def file_export(db, address, password, what): """ This generator fetches messages from database and yields objects, that contain the file information and instructions how to commit to db inforamtion about successful message delivery """ # first netmail # then requested file # then echoes # then filebox # and at last fileechoes print("export to", repr(address), repr(password), repr(what)) link_id, addr_id, myaddr_id = ftnaccess.check_link(db, address, password, False) if myaddr_id is None: raise FTNWrongPassword() print("password is correct" if link_id else "unprotected session", "local address", myaddr_id) # WARNING! # unprotected sessions never must do queries as it may result in leaking netmail # if address of some hub is spoofed myaddr_text = get_addr(db, myaddr_id)[1] link_pkt_format, link_bundler = get_link_packing(db, link_id) link_my_id, link_pw = ftnaccess.link_password(db, link_id, False) if link_id and ("netmail" in what): explock = postgresql.alock.ExclusiveLock(db, ((EXPORTLOCK["netmail"], addr_id))) if explock.acquire(False): try: print ("exporting netmail") # only vital subscriptions is processed # non-vital (CC) should be processed just like echomail # set password in netmail packets p = pktpacker(link_pkt_format, myaddr_text, address, link_pw or '', lambda: get_pkt_n(db, link_id), lambda: netmailcommitter()) #..firstly send pkts in outbound for id_msg, src, dest, msgid, header, body, origcharset, recvfrom in get_subscriber_messages_n(db, addr_id, db.FTN_domains["node"]): print("netmail %d recvfrom %d pack to %s"%(id_msg, recvfrom, repr(address))) # if exporting to utf8z always use UTF-8 if link_pkt_format == "utf8z": origcharset = "utf-8" myvia = "PyFTN " + ADDRESS + " " + time.asctime() srca=db.prepare("select domain, text from addresses where id=$1").first(src) dsta=db.prepare("select domain, text from addresses where id=$1").first(dest) try: msg, msgcharset = denormalize_message( (db.FTN_backdomains[srca[0]], srca[1]), (db.FTN_backdomains[dsta[0]], dsta[1]), msgid, header, body, origcharset, address, addvia = myvia) except: raise Exception("denormalization error on message id=%d"%id_msg+"\n"+traceback.format_exc()) try: print ("export msg attributes", msg.attr) except: traceback.print_exception() if 'AuditRequest' in ftn.attr.binary_to_text(msg.attr): audit_reply = (db.FTN_backdomains[srca[0]], srca[1]), header.find("sendername").text, address, msg, msgcharset else: audit_reply = None for x in p.add_item(msg, (id_msg, audit_reply)): # add ARQ flag yield x for x in p.flush(): yield x del p finally: explock.release() else: print ("could not acquire netmail lock") if "direct" in what: # available for unprotected sessions # export messages with processed==8 and destination==addr_id explock = postgresql.alock.ExclusiveLock(db, ((EXPORTLOCK["netmail"], addr_id))) if explock.acquire(False): print ("exporting direct netmail") # only vital subscriptions is processed # non-vital (CC) should be processed just like echomail # set password in netmail packets p = pktpacker(link_pkt_format, myaddr_text, address, link_pw or '', lambda: get_pkt_n(db, link_id), lambda: netmailcommitter(newstatus=7)) #..firstly send pkts in outbound for id_msg, src, dest, msgid, header, body, origcharset, recvfrom in get_direct_messages(db, addr_id): print("direct netmail %d recvfrom %d pack to %s"%(id_msg, recvfrom, repr(address))) # if exporting to utf8z always use UTF-8 if link_pkt_format == "utf8z": origcharset = "utf-8" myvia = "PyFTN " + ADDRESS + " DIRECT " + time.asctime() srca=db.prepare("select domain, text from addresses where id=$1").first(src) dsta=db.prepare("select domain, text from addresses where id=$1").first(dest) try: msg, msgcharset = denormalize_message( (db.FTN_backdomains[srca[0]], srca[1]), (db.FTN_backdomains[dsta[0]], dsta[1]), msgid, header, body, origcharset, address, addvia = myvia) except: raise Exception("denormalization error on message id=%d"%id_msg+"\n"+traceback.format_exc()) try: print ("export msg attributes", msg.attr) except: traceback.print_exception() if 'AuditRequest' in ftn.attr.binary_to_text(msg.attr): audit_reply = (db.FTN_backdomains[srca[0]], srca[1]), header.find("sendername").text, address, msg, msgcharset else: audit_reply = None for x in p.add_item(msg, (id_msg, audit_reply)): # add ARQ flag yield x for x in p.flush(): yield x del p explock.release() pass if link_id and ("echomail" in what): explock = postgresql.alock.ExclusiveLock(db, ((EXPORTLOCK["echomail"], addr_id))) if explock.acquire(False): try: print ("exporting echomail") #..firstly send bundles in outbound # if link_bundler: p = pktpacker(link_pkt_format, myaddr_text, address, link_pw or '', lambda: get_pkt_n(db, link_id), lambda: echomailcommitter(), bundlepacker(link_bundler, address, lambda: get_bundle_n(db, link_id), lambda: echomailcommitter())) else: p = pktpacker(link_pkt_format, myaddr_text, address, link_pw or '', lambda: get_pkt_n(db, link_id), lambda: echomailcommitter()) subscache = {} for id_msg, xxsrc, dest, msgid, header, body, origcharset, recvfrom, withsubscr, processed in get_subscriber_messages_e(db, addr_id, db.FTN_domains["echo"]): # ??? "my" addr in subscription - is it used here will_export = True # do we really must send message or just update last_sent pointer #print("echomail %d"%id_msg, repr(dest)) #print("dest %d recvfrom %s subscr %s pack to %s"%(dest, repr(recvfrom), repr(withsubscr), address)) # ignore src - for echomail it is just recv_from # if exporting to utf8z always use UTF-8 if link_pkt_format == "utf8z": origcharset = "utf-8" if recvfrom == addr_id: #print ("Message from this link, will not export") will_export = False if processed == 5: #print ("Archived message, will not export") will_export = False # check commuter - NOT TESTED subscriber_comm = db.FTN_commuter.get(withsubscr) if subscriber_comm is not None: # must check as None==None => no export at all # get subscription through what message was received recvfrom_subscription = db.prepare("select id from subscriptions where target=$1 and subscriber=$2").first(sub_tart, m_recvfrom) recvfrom_comm = db.FTN_commuter.get(recvfrom_subscription) if recvfrom_comm == subscriber_comm: print("commuter %d - %d, will not export"%(withsubscr, recvfrom_subscription)) will_export = False # continue # do not forward between subscriptions in one commuter group (e.g. two uplinks) if dest in subscache: subscribers = subscache[dest] else: subscribers = db.prepare("select a.domain, a.text from subscriptions s, addresses a where s.target=$1 and s.subscriber=a.id")(dest) if not all([x[0]==db.FTN_domains["node"] for x in subscribers]): raise FTNFail("subscribers from wrong domain for "+str(sub_targ)) # print(sub_id, sub_targ, "all subscribers:", [x[1] for x in subscribers]) subscribers = subscache[dest] = [x[1] for x in subscribers] #print("subscribers:", repr(subscribers)) # if withsubscr not in subscribers: # raise Exception("strange: exporting to non-existent subscription", withsubscr) dsta = db.prepare("select domain, text from addresses where id=$1").first(dest) # modify path and seen-by # seen-by's - get list of all subscribers of this target; add subscribers list #... if go to another zone remove path and seen-by's and only add seen-by's of that zone -> ftnexport if will_export: # create MSG else do not bother try: msg, msgcharset = denormalize_message( ("node", ADDRESS), (db.FTN_backdomains[dsta[0]], dsta[1]), msgid, header, body, origcharset, address, addseenby=subscribers, addpath=ADDRESS) except: raise Exception("denormalization error on message id=%d"%id_msg+"\n"+traceback.format_exc()) for x in p.add_item((msg if will_export else None), (withsubscr, id_msg)): yield x for x in p.flush(): yield x finally: explock.release() else: print("could not acquire echomail lock") if link_id and ("filebox" in what): explock = postgresql.alock.ExclusiveLock(db, ((EXPORTLOCK["filebox"], addr_id))) if explock.acquire(False): # ..send freq filebox print ("exporting filebox") dsend = addrdir(DOUTBOUND, address) if os.path.isdir(dsend): print ("exporting daemon outbound") for f in os.listdir(dsend): fname = os.path.join(dsend, f) if os.path.isfile(fname): obj = outfile() obj.data = open(fname, "rb") obj.filename = f obj.length = os.path.getsize(fname) yield obj, filecommitter(fname) explock.release() if link_id and ("fileecho" in what): explock = postgresql.alock.ExclusiveLock(db, ((EXPORTLOCK["fileecho"], addr_id))) if explock.acquire(False): try: print ("exporting fileechoes for", address) subscache = {} tic_password = password t = ticpacker(lambda: get_tic_n(db, link_id), lambda: ticcommitter(db)) latest_post = db.prepare("select max(post_time) from file_post").first() fruitful = False for fp_id, fp_filename, fp_destination, fp_recv_from, fp_recv_as, fp_post_time, fp_filedata, \ fp_origin, fp_other, withsubscr, file_length, file_content, file_lo in \ db.prepare("select fp.id, fp.filename, fp.destination, fp.recv_from, fp.recv_as, fp.post_time, " "fp.filedata, fp.origin, fp.other, s.id, f.length, f.content, f.lo " "from file_post fp, subscriptions s, files f " "where exists(select * from subscriptions ss where ss.target=fp.destination and ss.subscriber=$1) and s.subscriber=$1 and " "fp.post_time>(select lastsent from lastsent where subscriber=$1) and fp.destination=s.target and f.id=fp.filedata " "order by fp.post_time")(addr_id): print (fp_id, fp_filename, fp_destination) will_export = True # do we really must send message or just update last_sent pointer if fp_recv_from == addr_id: #print ("Message from this link, will not export") will_export = False other = json.loads(fp_other) del fp_other seenby = set(other.get("SEENBY", [])) if address in seenby: print ("already in seenby list, not sending") will_export = False # dupe (own address) in path should be checked at import # check commuter - NOT TESTED subscriber_comm = db.FTN_commuter.get(withsubscr) if subscriber_comm is not None: # must check as None==None => no export at all # get subscription through what message was received recvfrom_subscription = db.prepare("select id from subscriptions where target=$1 and subscriber=$2").first(sub_tart, m_recvfrom) recvfrom_comm = db.FTN_commuter.get(recvfrom_subscription) if recvfrom_comm == subscriber_comm: print("commuter %d - %d, will not export"%(withsubscr, recvfrom_subscription)) will_export = False # continue # do not forward between subscriptions in one commuter group (e.g. two uplinks) if fp_destination in subscache: subscribers = subscache[fp_destination] else: subscribers = db.prepare("select a.domain, a.text from subscriptions s, addresses a where s.target=$1 and s.subscriber=a.id")(fp_destination) if not all([x[0]==db.FTN_domains["node"] for x in subscribers]): raise FTNFail("subscribers from wrong domain for "+str(sub_targ)) # print(sub_id, sub_targ, "all subscribers:", [x[1] for x in subscribers]) subscribers = subscache[fp_destination] = [x[1] for x in subscribers] dsta = get_addr(db, fp_destination) # modify path and seen-by # seen-by's - get list of all subscribers of this target; add subscribers list if will_export: fruitful = True # something was exported #print("add seen-by", subscribers, " add path", myaddr_text) other.setdefault("PATH", []).append(myaddr_text+" "+str(fp_post_time)+" "+time.asctime(time.gmtime(fp_post_time))+" PyFTN") seenby.update(subscribers) other["SEENBY"]=list(seenby) if "CRC" in other: file_crc32 = other.pop("CRC")[0] print ("filename %s length %d crc %s"%(fp_filename, file_length, file_crc32)) else: if file_content: file_crc32 = ftntic.sz_crc32s(file_content)[1] else: file_crc32 = ftntic.sz_crc32fd(lo.LOIOReader(db, file_lo))[1] #if fp_origin is None: # print("substitute empty origin with source") # fp_origin = fp_recv_from tic = ftntic.make_tic(myaddr_text, address, tic_password, dsta[1], get_addr(db, fp_origin)[1] if fp_origin else None, fp_filename, file_length, file_crc32, other) # code was migrated from echo export, so it cares about blocked exports to update # per-subscription last-sents for x in t.add_item(((tic, (fp_filename, file_length, file_content or (db, file_lo))) if will_export else None), (addr_id, fp_post_time)): # ordering by post_time yield x if not fruitful: print("empty export, must update per-subscriber lastsent up to", latest_post) for x in t.flush(): yield x finally: explock.release() else: print ("cannot acquire fileecho lock for", addr_id) return
#!/usr/bin/python3 import ftnconfig import ftntic import json files="""litg1336.rar tropoi14.rar tropoi18.rar vert0001.rar vert0104.rar vert0203.rar vert0204.rar vert0301.rar vert0303.rar""".split("\n") db=ftnconfig.connectdb() for f in files: print (f) for (fp,fp_origin,fp_destination,fp_filename, fp_other, f_size) in db.prepare("select fp.id, fp.origin, fp.destination, fp.filename, fp.other, f.length from file_post fp, files f where filename ilike $1 and fp.filedata=f.id")(f): print (fp) other= json.loads(fp_other) crc = other.pop("CRC", "00000000")[0] tic = ftntic.make_tic("2:5020/12000", "2:5059/37", "*", ftnconfig.get_addr(db, fp_destination)[1], ftnconfig.get_addr(db, fp_origin)[1] if fp_origin else None, fp_filename, f_size, crc, other) open("%d.tic"%fp, "wb").write(tic)
ftnconfig.SYSOP, ("node", subscriber), robot, None, pw, "%LIST", sendmode="direct") elif cmd == "show": # show subscribed areas if area == ".": # show for link for x in ftnexport.get_node_subscriptions(db, subscriber, domain): print(x) else: # show from area tid = ftnconfig.get_addr_id(db, db.FTN_domains[domain], area) print(tid) for aid, vital, level in ftnexport.get_subscribers(db, tid): print(ftnconfig.get_addr(db, aid)) elif cmd == "showuplink": # show areas subsribed as vital if area == ".": # show for link for x in ftnexport.get_node_subscriptions(db, subscriber, domain, asuplink=True): print(x) else: # show from area tid = ftnconfig.get_addr_id(db, db.FTN_domains[domain], area) print(tid) for x in ftnexport.get_subscribers(db, tid, True): print(x) elif cmd == "verifyuplink":