# dasbbs.py - a diebox-like frontend for vjbox
# (c) 1997 Hans-Peter Zorn, DG4IAD

import vjbox 
import posix 
import pwd
import string
import sys
import regex
import time

# some globals...
board=""
boxname=""
letztenummer=1
username=""
_version="0.1"
fertig=0
stdin=sys.stdin
ParseError="Syntax-Fehler in Bereich"
NichtdaError="Keine Nachrichten gefunden"
commands=["quit","version","list","dir","read","send","check","usage","mybbs","readlock","help"]
global board,boxname,username,_version,fertig,box

# These are the pattern for the list/read/erase/header -commands
muster=regex.symcomp("\(\(<rubrik>[0-9]*[a-zA-Z]+[0-9]*[A-Za-z]*\)\)?\(\([ ]*\(<start>[0-9]+\)\)?\(\W*-\(<stop>[0-9]+\)\)?\)?\(\W<\(<search>.*\)\)?")
muster2=regex.symcomp("\(\(<rubrik>[0-9]*[a-zA-Z]+[0-9]*[a-zA-Z]*\)\)?\([ ]*\(<start>[0-9]+\)-\)\(\W*\(<stop>[0-9]+\)\)?\(\(\W<\(<search>.*\)\)\)?")
sendmuster=regex.symcomp("\(<ziel>[0-9]*[a-zA-Z]+[0-9]*\)\([ ]+@[ ]*\(<address>[0-9]*[a-zA-Z]+[0-9]*\)\)?\([ ]+#[ ]*\(<lt>[0-9]+\)\)?\([ ]+\(<titel>.*\)\)")
# give a prompt...
def prompt():
  sys.stdout.write( "(%s) %s de %s>"  % (board,string.upper(username)
                  ,string.upper(string.splitfields(box.boxname,".")[0])))
  #print "(%s) %s de %s>" % ("a","b","c")
  
def version(parms):
  for line in box.version():
    print line
  
def usage(parms):
  if parms=="":
    liste=box.showlogin()
    for nr in range(1,len(liste)+1): 
      line=liste[nr-1]
      call=string.upper(string.split(line)[1])
      sys.stdout.write("%.2d:%.6s " % (nr,call))
      if nr % 10 == 0 : sys.stdout.write("\n")
    if len(liste)+1 % 10 !=0: sys.stdout.write("\n") 
  else:
    info=box.getinfo(parms)
    if info==None:
      print "User %s unknown" % parms
      return
    for line in info:
      print line
   
def parsebereich(parms):
  m=muster
  if muster.match(parms)!=len(parms):
    if muster2.match(parms)!=len(parms):
      raise ParseError
      return None
    else: m=muster2  
  rub=m.group("rubrik")
  if rub==None: rub=board
  if rub=="": rub=username
  rub=string.upper(rub)
  boards=box.boardlist()
  max=0
  for line in boards:
    [bo,typ,anzahl]=string.split(line)[:3]
    
    if bo==string.lower(rub):
      max=string.atoi(anzahl)
      break
  if max==0:
    print "Keine Nachrichten fuer %s" % rub
    raise NichtdaError
    return None
  astart=m.group("start")
  if astart==None: start=1
  else : start=string.atoi(astart)
  astop=m.group("stop")
  if astop==None: 
     if (astart==None) or (m is muster2):
       stop=max
     else:  
       stop=start
  else : stop=string.atoi(astop)
  if stop>max: stop=max 
  return rub,start,stop
     

def list(parms):
  try:
    rub,start,stop=parsebereich(parms)
  except ParseError:
    print "Eingabefehler"
    return
  except NichtdaError:return
  data=box.list(rub,start,stop)
  print "Inhaltsverzeichnis fuer %s:" % rub  
  print
  print "  Nr Call   Datum    Zeit   Bytes  Titel"
  for nr in range(0,stop-start+1):
    bid=data[(nr*3)]
    [board,mbx,sender,date,size,lt,idxnr]=string.split(data[(nr*3)+1])
    numr=(nr / 3)+1
    a=string.atoi
    g=string.upper 
    dt=time.strftime("%d.%m.%y %H:%M",time.gmtime(a(date)))
    print "%4d %-6s %s %6d  %s" % (a(idxnr),g(sender),dt,a(size),data[(nr*3)+2])  
  global board
  board=rub 

def dir(parms):
  data=box.boardlist()
  parms=string.upper(parms)
  spalte=0
  for line in data:
     [bo,typ,anzahl]=string.split(line)[:3]
     if typ=="u" and (parms=="U" or parms=="A"):
       print "%-8s %4d" % (bo,string.atoi(anzahl)),
     elif typ=="b" and (parms=="" or parms=="A"):
       print "%-8s %4d" % (bo,string.atoi(anzahl)),
     spalte=spalte+1
     if spalte==7:
       spalte=0
       print
  print
  
def read(parms):
  try:
    rub,start,stop=parsebereich(parms)
  except ParseError:
    print "Eingabefehler"
    return
  except NichtdaError: return
  for nr in range(start,stop+1):  
    data=box.read(rub,nr);
    for line in data:
      print line
  global board
  board=rub
  
def send(parms): 
  p=string.split(parms)
  lt=-1
  adresse=string.upper(string.splitfields(box.boxname,".")[0])
  if p==[]:
    print "Ziel?>"
    ziel=stdin.readline()[0:-1]
    if string.find(ziel,"@")!=-1:
      [ziel,adresse]=string.splitfields(ziel,"@")
      if ziel=="":
        print "eingabefehler"
	return
      if adresse=="":
        print "eingabefehler"
	return
  if len(p)>=1:
    if string.find(p[0],"@")!=-1:
      [ziel,adresse]=string.splitfields(p[0],"@")
      if ziel=="":
        print "eingabefehler"
	return
      if adresse=="":
        if len(p)<2:
	  print "eingabefehler"
	  return
	adresse=p[1]
	p[1:1]=[]
    else:	
      ziel=p[0]
  if len(p)>1:    
    if string.find(p[1],"#")!=-1:
      if len(p[1])==1:
        lta=p[2]
        lta[1:2]=[]
      else:
        lta=p[1][1:]
        lta[1:1]=[]
      try:
        lt=string.atoi(lta)
      except ValueError:
        print "eingabefehler"
        return
  if len(p)<2:
    print "Titel?>"
    titel=stdin.readline()[0:-1]
  else:
    titel=string.join(p[1:])
  ziel=string.upper(ziel)  
  adresse=string.upper(adresse)
  board=ziel
  print "bitte text eingeben fuer %s @ %s mit LT %d, titel:" % (ziel,adresse,lt)
  print titel
  print "beenden mit ^Z,NNNN,***END,/EX oder einem einzelnen ."
  line=stdin.readline()
  mailinhalt=[]
  while (string.upper(line)!="NNNN\n") and (string.upper(line)!="***END\n"):
     mailinhalt.append(line)
     line=stdin.readline()
  box.putmail(username,ziel,adresse,titel,mailinhalt,lt)   
  print "gespeichert."

def check(parms):
  if parms=="":
    data=box.newmail(string.atoi(box.property["lastquit"]),"*","long")
  elif parms[0]=="<":
    data=box.newmail(0,"*","long")
  else:
    try: count=string.atoi(parms)
    except ValueError: 
       print "Sorry, invalider literat. (Invalid literal ;-)"
       return 
    data=box.newmail(0,"*","long")
    data=data[:(count*3)]
  print "   # Call     File     Nr.  Datum   @MBX   Bytes #LT Titel"  
  for nr in range(0,len(data),3):
    bid=data[nr]
    [board,mbx,sender,date,size,lt,idxnr]=string.split(data[nr+1])
    numr=(nr / 3)+1
   # print "%.4d %.6s > %.8s %.4d %.5d %.3d %s" % (numr,sender,board,idxnr,size,lt,data[nr+2])
    a=string.atoi
    g=string.upper 
    dt=time.strftime("%d.%m.%y",time.gmtime(a(date)))
    print "%4d %-6s > %-8s%4d %s %-6s %5d %3d %s" % (numr,g(sender),g(board),a(idxnr),dt,g(mbx),a(size),a(lt),data[nr+2])  

def mybbs(parms):
  try:
    box.mybbs(parms)
  except VJerror:
    print "Fehler..."
  else:
    print "Alla gut, doi Moi-BiBi-Ess is jetzat", parms
    
def readlock(parms):
  if parms=="":
    print "READLOCK [0|1|2]"
    return
  if regex.match("[0-2]",parms)==len(parms):
    box.readlock(string.atoi(parms))
    if parms=="0" : print "Ok, Readlock abgeschaltet"
    else : print "Readlock aktiviert"
  else : print "READLOCK [0|1|2]"  

def help(parms):
    print "Folgende Befehle sind bereits verfuegbar:"
    for line in commands:print line

# get a command from standard-input
def getcommand():
   s=string.split(stdin.readline()[0:-1])
   if s==[]: return -1,""
   for cmd in range(0,len(commands)):
     try: 
       if regex.match("^"+string.lower(s[0])+"*",commands[cmd])==len(s[0]):
         return cmd,string.join(s[1:])
     except regex.error:
       return -1,""
   return -1,""

   
# switch to different command-procedures
def docommand(nr,parms):
  if nr==-1:
    print "Haee, des kabbier isch ned..."
  elif nr==0:
    print "Alla, bis denn..."
    box.quit()
    global fertig
    fertig=1
  elif nr==1:
    version(parms)
  elif nr==2:
    list(parms)
  elif nr==3:
    dir(parms)
  elif nr==4:
    read(parms)
  elif nr==5:
    send(parms)
  elif nr==6:
    check(parms)
  elif nr==7:
    usage(parms)
  elif nr==8:
    mybbs(parms)
  elif nr==9:
    readlock(parms)
  elif nr==10:
    help(parms)    

username=pwd.getpwuid(posix.getuid())[0] 
box=vjbox.vj("localhost",4711,username)
boxname=string.upper(string.splitfields(box.boxname,":")[0])
print "dasbbs.py v%s by dg4iad" % _version
print time.strftime("Du warst zuletzt am %d.%m um %H:%M eingeloggt",time.gmtime(string.atoi(box.property["lastquit"])))
list(username)
while fertig == 0:
  prompt()
  nr,parms=getcommand()
  docommand(nr,parms)
del box
