#!/usr/bin/python3
# *-* coding:utf-8 *-*

#***************************************************************************
# This file is part of the CRYPTO BONE
# File     : cryptobone-webdrop  installed in /usr/bin
# Version  : 1.7 (ALL-IN-ONE)
# License  : BSD-3-Clause
# Date     : 17 Feb 2025
# Contact  : Please send enquiries and bug-reports to innovation@senderek.ie
#
#
# Copyright (c) 2015-2025
#	Ralf Senderek, Ireland.  All rights reserved. (https://senderek.ie)
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#	   This product includes software developed by Ralf Senderek.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND  ANY EXPRESS OR 
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  IMPLIED WARRANTIES 
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
# ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
# POSSIBILITY OF SUCH DAMAGE.
#****************************************************************************

import os
import sys
import base64
import time

# debugging off
DEBUG_DISPLAY = False
DEBUG = False
# DEBUG_DISPLAY = True
# DEBUG = True
DISPLAYKEYS = False

OS = os.name

# find out askpass path
ASKPASS = "/usr/bin/systemd-ask-password"
if os.path.isfile ("/usr/libexec/openssh/gnome-ssh-askpass"):
     ASKPASS="/usr/libexec/openssh/gnome-ssh-askpass"
else:
     if os.path.isfile ("/usr/lib64/seahorse/seahorse-ssh-askpass"):
          ASKPASS="/usr/lib64/seahorse/seahorse-ssh-askpass"
     else:
          if os.path.isfile("/usr/lib/openssh/gnome-ssh-askpass"):
               ASKPASS = "/usr/lib/openssh/gnome-ssh-askpass"

	 

GUI = False
try:
    from tkinter import *
    from tkinter import font as tkFont
    GUI = True
except:
    print ("The GUI cannot be run. \nMaybe Tkinter is not installed?")
    sys.exit(4)


Name="none"
StatusCount=3
MaxCount=0
Masterkey = False
MODE = "read"
Allinone = True
MessageID = "None"
Recipient = "None"
Attachment = "None"

# GUI result of yes-no dialog
REPLY = False

# GUI constants
BACKGROUND = "#ddd"
GRAY       = "#ccc"
LABEL      = "#eee"
GREEN      = "#cfc"
DEBUGCOLOR = "#aaa"

INFO       = "#ddd"
ERRORCOLOR = "#800"
OKCOLOR    = "#080"
INFOCOLOR  = "#008"
KEYCOLOR   = "#efe"
YESCOLOR   = "#afa"
NOCOLOR    = "#faa"

###############################################################
def unix (command) :
     if OS == "posix":
          Pipe = os.popen(command, "r")
          Result = Pipe.read()
          Pipe.close()
     return Result


###############################################################
def askyesno(Header, Msg):
     global REPLY

     # create a pop-up Toplevel window to receive a choice in REPLY

     def returnyes():
          global REPLY
          REPLY = True
          dialog.destroy()
          return REPLY

     def returnno():
          global REPLY
          REPLY = False
          dialog.destroy()
          return REPLY

     dialog = Toplevel()
     dialog.title (Header)
     L = Label(dialog, text=Msg, font=Bold )
     ReplyFrame = Frame(dialog, bg=BACKGROUND, pady=5)
     Yes = Button(ReplyFrame, text= "  Yes  ", font=BFont, width=16, bg=YESCOLOR, command=returnyes)
     No  = Button(ReplyFrame, text= "  No   ", font=BFont, width=16, bg=NOCOLOR, command=returnno)

     L.pack(padx=30, pady=10)
     Yes.pack(padx=8, side=LEFT, pady=10)
     No.pack(padx=8, side=LEFT, pady=10)
     ReplyFrame.pack()
     dialog.transient(Window)
     try:
         dialog.grab_set()
     except:
         pass
     dialog.wait_window()

###############################################################
def clean ():
     Text.delete("0.0","end")

###############################################################
def clear_Keyarea():
     Keyarea.configure(text="")
     DisplayFrame.forget()
     
###############################################################
def clear_error():
     ErrorFrame.configure(bg=INFO)
     ErrorLabel.configure(bg=INFO)
     ErrorLabel.configure(text="")
     clear_Keyarea()
     Window.update_idletasks()

###############################################################
def is_active():
     Result = send_command("STATUS")
     if Result[:6] == "active":
          return True
     return False	  

###############################################################
def format_error(e):
     E = ""
     i = 0
     for C in e :
          if C == '\n':
               E = E + C
               i = 0
          else:
               if i < 67 :
                    E = E + C
                    i += 1
               else: 
                    E = E + C +'\n'
                    i = 0
     return E

###############################################################
def check_webdrop(user, server):
     Result = send_command("CHECKWEBDROP OUT " + user + " " + server)
     if (user and ("TESTMAIL sent" in Result)) :
           message = "Test message is sent out successfully.\n" + "Please be patient, as receiving the message may take a minute!"
           print(message)
           InfoPanel.configure(fg="darkgreen")
           InfoPanel.configure( text=format_error(message) ) 
           Window.update_idletasks()
     else:
           print("Test message cannot be sent out !")
           InfoPanel.configure(fg="red")
           InfoPanel.configure( text=format_error(Result) ) 
           Window.update_idletasks()
     unix("sleep 3")
     Result = send_command("CHECKWEBDROP IN")
     if ("unencrypted test email from root" in Result) :
           print("Test message received successfully")
           InfoPanel.configure(fg="darkgreen")
           InfoPanel.configure( text=format_error("Test message received successfully") ) 
           Window.update_idletasks()
     else:
           print("No webdrop received !")
           InfoPanel.configure(fg="red")
           InfoPanel.configure( text=format_error(Result) ) 
           Window.update_idletasks()
     print ()

###############################################################
def check_status():
     global Allinone, Name, StatusCount, MaxCount
     
     if StatusCount > MaxCount:
          StatusCount = 0
          Result = send_command("STATUS")
     else:
          Result = "none"
     StatusCount += 1
     if  "waiting" in Result:
          StatusLabel.configure(text="waiting")
          StatusLabel.configure(bg="orange")
     if "active" in Result:
          MaxCount=10
          StatusLabel.configure(text="active")
          StatusLabel.configure(bg="lightgreen")
          if Name == "none":
               Result = send_command("SETUP WID")
               if not "failed" in Result:
                    ID.configure(text=Result[:-1])
                    Name=Result[:-1]
     else:
          MaxCount = 0

###           StatusLabel.configure(text="inactive")
###           StatusLabel.configure(bg="yellow")
###           showinfo("EXTERNAL Crypto Bone is inactive","You need to reboot your computer while the EXTERNAL Crypto Bone is running to transfer the master key.")
###      if "boneless" in Result:
###           StatusLabel.configure(text="cut off")
###           StatusLabel.configure(bg="yellow")
###           showinfo("EXTERNAL Crypto Bone is inactive","The IP address of your EXTERNAL Crypto Bone is unknown.")
###      if "ssh key not available" in Result:
###           StatusLabel.configure(text="cut off")
###           StatusLabel.configure(bg="yellow")
###           showinfo("EXTERNAL Crypto Bone is inactive","You need to store your EXTERNAL keys in your computer first. Please use SETUP to copy these keys.")
	
     Linkstatus = send_command("GETALLINONE")
     if "ALLINONE" in Linkstatus :
          Allinone = True
          IPLabel.configure(text="ALL-IN-ONE")
     else:
          Allinone = False
          IPLabel.configure(text=Linkstatus)

###############################################################
def contact():
     import subprocess

     Content = InputField.get().split(" ")
     args = ["sudo", "-A", "/usr/lib/cryptobone/cbcontrol"]
     for Word in Content:
          args.append(Word)
     ENV = os.environ.copy()	  
     ENV['SUDO_ASKPASS'] =  ASKPASS
     p = subprocess.Popen(args, bufsize=-1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=False, env=ENV)
     if DEBUG_DISPLAY:
          print (InputField.get())
     (out,err) =  p.communicate()
     if err != None:
          print ("error:",str(err.decode('utf-8')))
     if DEBUG_DISPLAY:	   
          Text.insert("end",str(out.decode('utf-8')))
          Text.insert("end", "\n")

###############################################################
def send_command(Command):
     import subprocess

     # do NOT sanitize input
     Content = Command.split(" ")	       
     args = ["sudo", "-A", "/usr/lib/cryptobone/cbcontrol"]
     for Word in Content:
          args.append(Word)
     ENV = os.environ.copy()	  
     ENV['SUDO_ASKPASS'] =  ASKPASS
     p = subprocess.Popen(args, bufsize=-1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=False, env=ENV)
     if DEBUG_DISPLAY:
           print (Command)
     (out,err) =  p.communicate()
     if err != None:
           print ("error:",str(err.decode('utf-8')))
     if DEBUG_DISPLAY:	   
           print (out.decode('utf-8'))
           Text.insert("end",str(out.decode('utf-8')))
           Text.insert("end", "\n")
     return str(out.decode('utf-8'))

###############################################################
def set_select_box():
     List = []
     if MODE == "write":
          List = send_command("KEY RECIPIENTLIST").split("\n")
     if MODE == "read":
          List = send_command("READ MESSAGELIST").split("\n")
     if MODE == "setup":
          List = send_command("READ EMAILLIST").split("\n")
     SBox.delete(0,20)   
     Count = 0
     SBox.delete(0,END)
     for Item in List:
          if Item :
               if Item != "ssh key not available" :	  
                    SBox.insert(Count, str(Item))
          Count += 1

###############################################################
def set_attach_box():
     List = []
     if MODE == "read":
          List = send_command("ATTACHMENT LIST").split("\n")
     AttachSBox.delete(0,20)   
     Count = 0
     AttachSBox.delete(0,END)
     for Item in List:
          if Item :
               if Item != "ssh key not available" :	  
                    AttachSBox.insert(Count, str(Item))
          Count += 1


###############################################################
def set_read():
     global MODE, MessageID
     MODE = "read"
     Mode.configure(text="READ")
     L.configure(text="Messages")
     ControlFrame.pack_forget()
     Key1.pack_forget()
     Key2.pack_forget()
     Key3.pack_forget()
     Setup1.pack_forget()
     Setup2.pack_forget()
     Box2.pack_forget()
     ConsoleButton.pack_forget()
     FillRightLong.pack_forget() 
     clean()
     TextFrame.pack()
     ControlFrame.pack()
     Button1.configure(text="Reply")
     Button2.configure(text="Check for new")
     Button3.configure(text="Destroy")
     Button2.pack(padx=8, side=LEFT)
     Button3.pack(padx=8, side=RIGHT)
     SelectBox.pack()
     AttachBox.pack()
     set_attach_box()	 
     set_select_box()
     MessageID = "None"
     L1.configure(text=MessageID)
     L2.configure(text="NEW")
     clear_error()
     check_status()

###############################################################
def set_write():
     global MODE, Recipient
     MODE = "write"
     Mode.configure(text="WRITE")
     L.configure(text="Recipients")
     ControlFrame.pack_forget()
     Key1.pack_forget()
     Key2.pack_forget()
     Key3.pack_forget()
     Setup1.pack_forget()
     Setup2.pack_forget()
     ConsoleButton.pack_forget()
     AttachBox.pack_forget()
     FillRightLong.pack_forget() 
     clean()
     TextFrame.pack()
     ControlFrame.pack()
     Button1.configure(text="Send Message")
     Button2.configure(text="Clear")
     Button2.pack(padx=8, side=LEFT)
     Button3.pack_forget()
     set_select_box()
     SelectBox.pack()
     clear_attachment()
     Box2.pack()
     Recipient = "None"
     L1.configure(text=Recipient)
     L2.configure(text="NEW")
     clear_error()
     check_status()

###############################################################
def set_reply():
     global MODE
     MODE = "write"
     Mode.configure(text="WRITE")
     ControlFrame.pack_forget()
     Key1.pack_forget()
     Key2.pack_forget()
     Key3.pack_forget()
     Setup1.pack_forget()
     Setup2.pack_forget()
     ConsoleButton.pack_forget()
     AttachBox.pack_forget()
     FillRightLong.pack_forget() 
     clean()
     TextFrame.pack()
     ControlFrame.pack()
     Button1.configure(text="Send Message")
     Button2.configure(text="Clear")
     Button3.pack_forget()
     L1.configure(text="Recipient")
     L2.configure(text="REPLY")
     clear_error()
     clear_attachment()
     Box2.pack()

###############################################################
def set_key():
     global MODE
     MODE = "key"
     Mode.configure(text="KEYS")
     SelectBox.pack_forget()
     Box2.pack_forget()
     TextFrame.pack_forget()
     ControlFrame.pack_forget()
     DebugFrame.pack_forget()
     Setup1.pack_forget()
     Setup2.pack_forget()
     ConsoleButton.pack_forget()
     ClearButton.pack_forget() 
     AttachBox.pack_forget()
     Key1.pack()
     Key2.pack()
     Key3.pack()
     Keyarea.configure(bg=BACKGROUND)
     Keyarea.pack(pady=5)
     DisplayFrame.pack()
     clear_display()
     FillRightLong.pack(pady=429) 
     L1.configure(text="")
     L2.configure(text="")
     check_status()
     clear_error()

###############################################################
def set_setup():
     global MODE, Allinone
     MODE = "setup"
     Mode.configure(text="SETUP")
     SelectBox.pack_forget()
     Box2.pack_forget()
     TextFrame.pack_forget()
     ControlFrame.pack_forget()
     Key1.pack_forget()
     Key2.pack_forget()
     Key3.pack_forget()
     AttachBox.pack_forget()
     FillRightLong.pack_forget() 
     Setup1.pack()
     Setup2.pack()
     ControlFrame.pack()
     Linkstatus = send_command("GETALLINONE")
     if "ALLINONE" in Linkstatus :
          Button1.configure(text="Use EXTERNAL")
          Button2.pack_forget()
          Button3.pack_forget()
###     else:
###          Button1.configure(text="Use ALL-IN-ONE")
###          Button2.configure(text="Set EXTERNAL Keys")
###          Button3.configure(text="Dismiss IP Addr")
###          Button1.pack(side=LEFT, padx=8)
###          Button2.pack(side=LEFT, padx=8)
###          Button3.pack(side=LEFT, padx=8)
     L1.configure(text="")
     L2.configure(text="")
     set_select_box()
     L.configure(text="INCOMING Safe Webdrops")
     SelectBox.pack()
     ConsoleButton.pack(side=BOTTOM, pady=133) 
     clear_error()

###############################################################
def action1():
    global Recipient, MessageID, Allinone, Name, StatusCount
    ### global PoweroffButton, Fill2
    if MODE == "read":
         # reply to the selected message
         MESSAGE = Text.get("0.0","end").split("\n")
         
         set_reply()
         Text.insert("end","\n\n\n")
         for Line in MESSAGE:
               if Line:
                    Text.insert("end", "> "+Line+"\n")
         if len(MessageID) > 4 :
               while MessageID[len(MessageID)-1] != '.':
                     MessageID = MessageID[:-1]
               Recipient = MessageID[:-1]		   
         L1.configure(text=Recipient)     
         L2.configure(text="REPLY")     

    elif MODE == "write":
         MESSAGE = Text.get("0.0","end")
         # do NOT sanitize message, all characters allowed
         
         ENCODEDMESSAGE = MESSAGE.encode('utf-8')
         MESSAGE = base64.b64encode(ENCODEDMESSAGE).decode('utf-8')
         if Recipient != "None" and  Recipient != "Recipient":
              if Attachment == "None":
                   Result = send_command("WEBDROP "+Recipient+" "+MESSAGE+ " none")
                   print("GUI " +Result)		   
                   if ("WEBDROP MESSAGE SAVED" in Result) :
                        Text.insert("end", "\n\n"+Result)
                        showinfo("Sending Message Out","Message is sent out successfully")
                   else:	   
                        showinfo("Sending Message Out","Message is not sent out!")
              else:
                   # send an attachment with the message
                   Result = send_command("WEBDROP "+Recipient+" " + MESSAGE + " " + Attachment)
                   print (Result)
                   print (Attachment)
                   if ("WEBDROP MESSAGE+ATTACHMENT SAVED" in Result) :
                        Text.insert("end", "\n\n"+Result)
                        showinfo("Sending Message Out","Message and attachment are sent out successfully")
                   else:	   
                        showinfo("Sending Message Out","Message and attachment are not sent out!")
         else:     
              showinfo("Missing Information","Please select a recipient from the menu before sending the message")

    elif MODE == "key":
        print ("action one key not implemented")

    elif MODE == "setup":
        ### FillRight.pack_forget()
        if not Allinone:
             Allinone = True
             Button1.configure(text="Use EXTERNAL")
             IPLabel.configure(text="ALL-IN-ONE")
             send_command("USEALLINONE")
             Fill2.pack(pady=11)
             ### PoweroffButton.pack_forget()
        else:
             Allinone = False
             Button1.configure(text="Use ALL-IN-ONE")
             showinfo("IMPORTANT","The external CryptoBone is not available with SafeWebdrop transport at the moment.\nPlease use the email-based CryptoBone if you wish to use an external device.")
###             IPLabel.configure(text="EXTERNAL CRYPTO BONE")
###             send_command("USECRYPTOBONE")
###             Fill2.pack_forget()
###             PoweroffButton.pack(pady=5) 
        FillRight.pack()     
        StatusCount = 100
        Name = "none"
        ID.configure(text="")
        time.sleep(3)
        set_setup()		  
        check_status()

###############################################################
def action2():
    global Recipient, MessageID

    if MODE == "read":
         # check for new messages
         send_command("FETCH")
         set_attach_box()	 
         set_select_box()

    elif MODE == "write":
         # forget message
         MessageID = "none"
         Recipient = "Recipient"
         L1.configure(text=Recipient)
         L2.configure(text="NEW")
         clean()
         set_select_box()
         SelectBox.pack()

    elif MODE == "key":
         print ("action two key not implemented")
   
    elif MODE == "setup":
         print ("action two key not implemented")
         
### temporarily suspended ###
###          List = unix("df 2> /dev/null | cut -f1 -d' '| grep /dev").split()
###          BootDev = ""
###          SD = False
###          for Device in List:
###               BootDir = unix("df -a 2> /dev/null | grep "+Device+" | grep media | grep BOOT | cut -f2 -d%")
###               if BootDir:
###                    if BootDir[0] == " ":
###                         BootDir = BootDir[1:]
###                    if BootDir[-1:] == "\n":
###                         BootDir = BootDir[:-1] 
###               RES=unix("ls "+BootDir+"/master.key 2>/dev/null")
###               if BootDir and RES:
###                    # this device holds a master key
###                    BootDev = unix("df -a 2> /dev/null | grep "+Device+" | grep media | grep BOOT | cut -f1 -d' '")
###                    if BootDev[-1:] == "\n":
###                         BootDev = BootDev[:-1]
###                    SD = True
###                    print ("Using ",BootDev," to copy external keys to this machine.")
###          if SD:
###               print ("Copying keys from "+BootDev+" to this computer's hard disk")      
###               askyesno("Moving Keys From SD/USB","Copying keys from "+BootDev+" to this computer's hard disk\n\nProceed?")
###               if REPLY:
###                    askyesno("Moving Keys From SD/USB","You will now replace the keys that are used to access your EXTERNAL Crypto Bone.\n\nIf your EXTERNAL Crypto Bone is already working, you will DESTROY\n the keys used to access this working EXTERNAL Crypto Bone\n by replacing the old keys with new keys from the SD card or USB stick.\n\nOnce you have replaced the external keys, this action\n cannot be undone.\n\n You will continue with a new EXTERNAL Crypto Bone, if you proceed here.\n\nDo your really want to do that?\n\nThink twice.")
###                    if REPLY: 
###                         RES = send_command("COPYSDCARD "+BootDev)
###                         if "success" in RES :
###                              showinfo("Moving Keys From SD/USB","Your Crypto Bone keys have been moved successfully to your computer.\nNow you can insert the SD card (or USB stick) into your Beagle Bone or Raspberry Pi (or Linux computer) again and reboot it.\nYou need to reboot this main computer as well in order to activate the new keys.")
###                         elif "failed" in RES :
###                              showinfo("Moving Keys From SD/USB","The secrets on your SDCARD or USB stick have not been transferred completely.\n\nPlease try again.")
###                         elif "nokeys" in RES :
###                              showinfo("Moving Keys From SD/USB","There are no keys on your SD card or USB stick!\nPlease check your SD card image and insert it for a first boot into your Beagle Bone or Raspberry Pi to create the master key.\nIf you use a USB stick, make sure that it contains a file system labelled BOOT.")
### 
###          else:
###                         showinfo("Moving Keys From SD/USB","There is no SD card with a valid Crypto Bone image or a valid USB stick.")


###############################################################
def action3():
    if MODE == "read":
         select()
         # destroy selected message
         askyesno("Destroy Message", "Do you really want to destroy this message: "+MessageID)
         if REPLY:
              send_command("READ DESTROY "+MessageID)
              clean()
              set_select_box()
###    elif MODE == "setup":
###         # destroy selected message
###         askyesno("Delete IP Address", "Do you really want to delete the stored IP address\n for your EXTERNAL Crypto Bone? ")
###         if REPLY:
###              send_command("DELETE CONFIG")
###              IPLabel.configure(text="unknown")

###############################################################
def select():
    global MessageID, Recipient

    index = 0
    if len(SBox.curselection()) > 0:
         index = SBox.curselection()[0]
    Selection = SBox.get(index)
    L1.configure(text=Selection)
    if MODE == "read":
        MessageID = Selection
        MESSAGE = send_command("READ MESSAGE "+MessageID)
        if MESSAGE:
             clean()
             Plaintext = base64.b64decode(MESSAGE).decode('utf-8')
             Text.insert("end",Plaintext)
    elif MODE == "write":
        Recipient = Selection
    elif MODE == "setup":
        Setup1.pack_forget()
        Setup2.pack_forget()
        Button2.pack_forget()
        Button3.pack_forget()
        TextFrame.pack()
        Recipient = Selection
        MessageID = Selection
        MESSAGE = send_command("READ EMAIL "+MessageID)
        if MESSAGE:
             clean()
             Plaintext = base64.b64decode(MESSAGE)
             Text.insert("end",Plaintext)

###############################################################
def attach() :
     global Attachment
 
     empty = False
     FileName = AttachFilename.get()
     if FileName == "":
         empty = True
     FileName = os.path.expanduser("~/" + FileName)
     if os.path.isfile( FileName ) :
         AttachFilename.configure(bg="lightgreen")
         showinfo( "", FileName + " will be attached to your message." )
         Attachment = FileName
     else:
         Attachment = "None"
         AttachFilename.configure(bg="white")
         if (not empty) :
               showerror( "", FileName + " : does not exist" )

###############################################################
def clear_attachment():
     global Attachment
     Attachment = "None"
     AttachFilename.delete(0,END)
     AttachFilename.configure(bg="white")

###############################################################
def attachment_move():
    index = 0
    if len(AttachSBox.curselection()) > 0:
        index = AttachSBox.curselection()[0]
    Filename = AttachSBox.get(index)
    if MODE == "read":
        askyesno("","Do you want to move " + Filename + " into your home directory?")
        if REPLY :
             RES = send_command( "ATTACHMENT MOVE " + Filename )
             if ("MOVED" in RES) :
                  showinfo("", Filename + " has been moved into the directory .safewebdrop")
                  set_attach_box()

###############################################################
def is_message_key(NewKey):
     if NewKey == "none":
          return False
     if len(NewKey) > 19:
          return True
     return False

###############################################################
def register():
     if not is_active():
         showerror("", "Your Crypto Bone is not active! ")
         return "failed"
     K = InitKey.get()
     ID = Email.get()
     if "@" in ID :
          showerror('Contact Registration', "This is an EMAIL ID, please use % instead of @")
     elif is_message_key(K) :
          # todo: check if email address is stored already
          RES = send_command("KEY USE "+ ID +" "+K)
          if "failed" in RES :
               showerror('Contact Registration', RES[8:])
          if "deleted" in RES :
               showinfo('Deleted Contact', RES)
          if "success" in RES :     
               showinfo('Contact Registration', ID + "\nis now registered and can be used.")
     else:
          showerror('Contact Registration', "The message key is too short.")
         

###############################################################
###def change_email():
###     if not is_active():
###         showerror("", "Your Crypto Bone is not active! ")
###         return "failed"
###     Name =  OldName.get()
###     Email = OldEmail.get()
###     Email = Email.lower()
###     New = NewEmail.get()
###     New = New.lower()
###     if not (Name == "Contact Email Address"):
###          Email = Name
###     if (Email != "" ) and (New != "") :	 
###          RES = send_command("KEY CHANGEEMAIL "+Email+" "+New)
###          print (RES)
###          if "success" in RES :
###               showinfo('Email Address Change', 'The new email address is now active.')
###          else:
###               if "failed" in RES :
###                     showinfo('Email Address Change', RES[8:])
###     else:
###          if (len(Email) < 6):
###               if (Name == "Contact Email Address"):
###                    showerror('Email Address Change', "The email address is invalid.")
###          else:
###               if (len(New) < 6):
###                    showerror('Email Address Change', "The new email address is invalid.")


###############################################################
def clear_display():
     
     DisplayLabel.configure(text="", bg=BACKGROUND)
     Keyarea.configure(text="", bg=BACKGROUND)
     ClearButton.pack_forget() 

###############################################################
def print_secrets():

     if is_active():  
          clear_error()
          RES = send_command("KEY NEWSECRETS")
          Message = ""
          Keys = RES.split()
          if Keys:
                DISPLAYKEYS = True
          for Line in Keys:
                List = Line.split(":")
                if len(List) > 1:
                     Message += "Initial key for " +List[0][4:-4] + " :  "
                     Message += List[1] + "\n"

          if DISPLAYKEYS:
               Keyarea.configure(bg="#eee", text=Message)
               DisplayLabel.configure(text="These are three keys that can be used by your contacts", width=60,         height=2, font=Bold, bg=KEYCOLOR)
               Keyarea.configure(bg=KEYCOLOR)
               ClearButton.pack() 
               DisplayFrame.pack()
     else:
          showerror("", "Your Crypto Bone is not active! ")

###############################################################
def show_webdrop_setup():
     Result = send_command("SETUP WEBDROP")
     if Result:
          List = Result.split("\n")
          for Line in List:
               Secretvalue = Line.split(":")
               if Secretvalue[0] == "webdropserver":
                    Hostname.delete(0,END)		       
                    Hostname.insert(0,Secretvalue[1])		       
               if Secretvalue[0] == "webdropuser":
                    Username.delete(0,END)		       
                    Username.insert(0,Secretvalue[1])		 
	       # never show the webdropsecret	    
               CODE=send_command("SETUP REGISTRATION")
               RegistrationCode.delete(0,END)           
               RegistrationCode.insert(0,CODE[:-1])           
     InfoPanel.configure(text="")

###############################################################
def webdrop_setup():
     H = Hostname.get()
     U = Username.get()
     if H :
          send_command("SETUP WEBDROPSERVER "+H)
     if U :
          send_command("SETUP WEBDROPUSER "+U)
     InfoPanel.configure( text="" ) 
     Window.update_idletasks()
     check_webdrop(U,H)

###############################################################
def register_webdrop_account():
     CODE=send_command("SETUP REGISTRATION")
     RegistrationCode.delete(0,END)           
     RegistrationCode.insert(0,CODE[:-1])           
     print ("Registration")
     askyesno("New Safe Webdrop Account Registration", "Do you really want to register a new Safe Webdrop account?\n This will destroy any Safe Webdrop account you have registered before!\n\nYou need to enter your Safe Webdrop ID and the Safe Webdrop server name in the setup above.\nIf your registration goes through you will find a different registation code below.\nYou must show the new registration code to your Safe Webdrop administrator in order to enable your new account.")
     if REPLY:
           Result = send_command("SETUP CLEARREG")
           show_webdrop_setup()
           CODE=send_command("SETUP REGISTRATION")
           RegistrationCode.delete(0,END)           
           RegistrationCode.insert(0,CODE[:-1])           
           askyesno("New Safe Webdrop Account Registration", "Is the setup information (webdrop server and ID) korrect?")
           if REPLY:
                 Result = send_command("SETUP REGISTER")
                 CODE=send_command("SETUP REGISTRATION")
                 RegistrationCode.delete(0,END)           
                 RegistrationCode.insert(0,CODE[:-1])           

###############################################################
def terminate_GUI():
     Window.destroy()     

###############################################################
def toggle_console():
     global DEBUG, DEBUG_DISPLAY, DebugFrame
     DEBUG = not DEBUG
     DEBUG_DISPLAY = not DEBUG_DISPLAY
     if DEBUG:
          if MODE == "read" or MODE == "write" or MODE == "setup" : 
               DebugFrame.pack(fill=X)
     else:
          DebugFrame.forget()

###############################################################
def do_poweroff():
     print("suspended")
###     if not "ALLINONE" in send_command("GETALLINONE"):     
###          X = send_command("POWEROFF")
###          print (X)
###          check_status()

###############################################################
def readuser():
     USER = InputField.get()
     clear_error()
     # check if this is a valid user
     if USER and (USER in unix("grep \"^"+USER+":\" /etc/passwd")):
          RET=unix("/usr/bin/pkexec /usr/bin/activate-cryptobone " + USER)
          print (RET)
          if RET == "success":
               showsuccess( "SUCCESS","Your Crypto Bone can now be used.\nPlease reboot your computer to create the secrets that are missing.")
               unix("sleep 10")
               sys.exit(0)
          if RET == "initialised":
               showerror( "ERROR","This Crypto Bone is already set up.\nYour Crypto Bone Daemon is not enabled.\nTry: systemctl enable cryptoboned")
               unix("sleep 10")
               sys.exit(1)
          if RET == "nosuchuser":
               showerror( "ERROR","No such user. Please try again.")
          if RET == "noparameter":
               showerror( "ERROR","You must specify a user name.")
     else:
          showerror( "ERROR","No such user. Please try again.")
	  
###############################################################
def showinfo(Title, Text):
     ErrorFrame.configure(bg=INFO)
     ErrorLabel.configure(text=Text)
     ErrorLabel.configure(fg=INFOCOLOR, bg=INFO)
     Window.update_idletasks()

###############################################################
def showsuccess(Title, Text):
     ErrorFrame.configure(bg=INFO)
     ErrorLabel.configure(text=Text)
     ErrorLabel.configure(fg=OKCOLOR, bg=INFO)
     Window.update_idletasks()

###############################################################
def showerror(Title, Text):
     ErrorFrame.configure(bg=INFO)
     ErrorLabel.configure(text="ERROR: "+Text)
     ErrorLabel.configure(fg=ERRORCOLOR, bg=INFO)
     Window.update_idletasks()


###############################################################
def OpenHelpUrl():
     import webbrowser
     webbrowser.open_new("https://crypto-bone.com/help")
     
###############################################################
def OpenHomeUrl():
     import webbrowser
     webbrowser.open_new("https://crypto-bone.com")
     
###############################################################
def HelpPage():
     import webbrowser
     if MODE == "read" :
          webbrowser.open_new("https://crypto-bone.com/help/safewebdrop/read")
     elif MODE == "write" :
          webbrowser.open_new("https://crypto-bone.com/help/safewebdrop/write")
     elif MODE == "key" :
          webbrowser.open_new("https://crypto-bone.com/help/safewebdrop/keys")
     elif MODE == "setup" :
          webbrowser.open_new("https://crypto-bone.com/help/safewebdrop/setup")
     else :
          webbrowser.open_new("https://crypto-bone.com/help/safewebdrop")
     

###############################################################
# Main
###############################################################

if GUI:
     Window = Tk()
     Window.title("Crypto Bone Control")

     DebugFrame = Frame(Window, bg=DEBUGCOLOR, pady=10)
     ErrorFrame = Frame(Window, bg=DEBUGCOLOR, pady=10)
     MainFrame = Frame(Window, bg=BACKGROUND)
     LeftFrame = Frame(MainFrame,  bg=BACKGROUND, padx=5, pady=2)
     HeadFrame = Frame(LeftFrame, bg=BACKGROUND, padx=0, pady=0)
     HeadRightFrame = Frame(HeadFrame, bg=BACKGROUND,padx=0, pady=0)
     StatusFrame = Frame(HeadRightFrame, bg=BACKGROUND, padx=0, pady=5)
     ModeFrame = Frame(HeadRightFrame, bg=BACKGROUND, padx=0, pady=5)
     TopFrame = Frame(LeftFrame, bg=BACKGROUND, padx=10, pady=10)
     TextFrame = Frame(LeftFrame, bg=BACKGROUND)
     ControlFrame = Frame(LeftFrame,bg=BACKGROUND, pady=5)
     RightFrame = Frame(MainFrame, bg=BACKGROUND, padx=15, pady=2)
     DisplayFrame = Frame(LeftFrame, bg=BACKGROUND, pady=2)
     

     Big = tkFont.Font(family="utopia", size=16)
     Title = tkFont.Font(family="utopia", size=12)
     Info  = tkFont.Font(family="arial", size=10, slant="italic")
     Bold  = tkFont.Font(family="arial", size=11, weight="bold")
     BFont = tkFont.Font(family="utopia", size=12, weight="normal")
     TextFont = tkFont.Font(family="arial", size=11, weight="normal")
     MonoFont = tkFont.Font(family="monospace", size=11, weight="normal")
     
     # ERROR frame
     ErrorLabel = Label(ErrorFrame, text="", font=Bold,  bg=BACKGROUND)
     ErrorLabel.pack(side=LEFT, padx=10)

     # DEBUG frame
     ConsoleLabel = Label(DebugFrame, text="Console", font=Bold, width=16, bg=DEBUGCOLOR)
     CleanButton = Button(master=DebugFrame, text="Clean", command=clean)
     InputField = Entry(master=DebugFrame, font=Bold, width=54) 
     ExecButton = Button(master=DebugFrame, text="Send Command", command=contact)
     ConsoleLabel2 = Label(DebugFrame, text="", font=Bold, width=16, bg=DEBUGCOLOR)
     ConsoleLabel.pack(side=LEFT, pady=10)
     CleanButton.pack(side=LEFT) 
     InputField.pack(padx=20,side=LEFT) 
     ExecButton.pack(side=LEFT) 
     ConsoleLabel2.pack(side=LEFT, padx=10)
     if DEBUG:
          DebugFrame.pack(fill=X)

     # DISPLAY frame
     DisplayLabel = Label(DisplayFrame, text="These are three keys that can be used by your contacts", width=60, height=2, font=Bold, bg=KEYCOLOR)
     Keyarea  = Label(DisplayFrame, width=53, height=4, font=MonoFont, bg=KEYCOLOR)
     ClearButton = Button(master=DisplayFrame, text=" Clear ", bg=GRAY, font=BFont, width=16, command=clear_display)
     if DISPLAYKEYS:
          # skip the heading line to make space
          DisplayLabel.pack(pady=10)
          Keyarea.pack(pady=5)
          ClearButton.pack(pady=5)
          DisplayFrame.pack()

     # Left Frame 
     # Status
     CBS_btn_img = PhotoImage(file='/usr/share/icons/default/logo-cryptobone-safewebdrop.png')
     CBSButton = Button(HeadFrame, image=CBS_btn_img, bg=GRAY,  width=180, height=150)
     CBSButton.bind("<Button-1>",lambda c: OpenHomeUrl())
     CBSButton.bind("<Enter>", lambda c: CBSButton.configure(bg="#eee"))
     CBSButton.bind("<Leave>", lambda c: CBSButton.configure(bg=BACKGROUND))

     BoneLabel = Label(StatusFrame, text="CRYPTO BONE 1.7", font=Big, width=18, bg=BACKGROUND)
     BoneLabel.bind("<Button-1>",lambda e: OpenHelpUrl())
     BoneLabel.bind("<Enter>", lambda e: BoneLabel.configure(bg="#eee"))
     BoneLabel.bind("<Leave>", lambda e: BoneLabel.configure(bg=BACKGROUND))
     IPLabel = Label(StatusFrame, text="", width=26, height=1, font=Bold, bg="#eeffee")
     StatusLabel = Label(StatusFrame, text="cut off", font=Bold, width=12, height=1, bg="yellow")
     ID = Label(RightFrame, text="", font=Bold, width=30, height=1, bg="#eeffee")
     CBSButton.pack(padx=5, side=LEFT, pady=5) 
     BoneLabel.pack(side=LEFT)
     IPLabel.pack(side=LEFT)
     StatusLabel.pack(side=LEFT)
     ID.pack(pady=10)


     # Labels
     Mode = Label(TopFrame, text="READ", font=Bold, bg="yellow", width=10)
     L1 = Label(TopFrame, text="None", font=Bold, width=56, bg=LABEL)
     L2 = Label(TopFrame, text="None", font=Bold, width=10, bg=LABEL)
     Mode.pack(side=LEFT, padx=0)
     L1.pack(side=LEFT, padx=0)
     L2.pack(side=LEFT, padx=0)

     Scroll  = Scrollbar(TextFrame)
     Text    = Text(TextFrame, width=75, height=25, font=TextFont, borderwidth=8, relief=FLAT, yscrollcommand = Scroll.set)
     Scroll.pack( side = RIGHT, fill=Y )
     Text.pack()
     Scroll.config( command = Text.yview )


     ReadButton = Button(master=ModeFrame, text="READ", bg=GRAY, font=BFont, command=set_read)
     WriteButton = Button(master=ModeFrame, text="WRITE", bg=GRAY, font=BFont, command=set_write)
     KeyButton = Button(master=ModeFrame, text="KEYS", bg=GRAY, font=BFont, command=set_key)
     SetupButton = Button(master=ModeFrame, text="SETUP", bg=GRAY, font=BFont, command=set_setup)
     Help_btn_img = PhotoImage(file='/usr/share/icons/default/question-mark.png')
     HelpButton = Button(master=ModeFrame, image=Help_btn_img, bg=GRAY,  width=60, height=60,  command=HelpPage)
     ReadButton.pack(padx=20, side=LEFT, pady=5)
     WriteButton.pack(padx=20, side=LEFT, pady=5)
     KeyButton.pack(padx=20, side=LEFT, pady=5)
     SetupButton.pack(padx=20, side=LEFT, pady=5)
     HelpButton.pack(padx=20, side=LEFT, pady=5) 


     # control buttons
     Button1 = Button(master=ControlFrame, text="", bg=GRAY, font=BFont, width=16, command=action1)
     Button2 = Button(master=ControlFrame, text="", bg=GRAY, font=BFont, width=16, command=action2)
     Button3 = Button(master=ControlFrame, text="", bg=GRAY, font=BFont, width=16, command=action3)
     Button1.pack(padx=8, side=LEFT)
     Button2.pack(padx=8, side=LEFT)
     Button3.pack(padx=8, side=LEFT)


     # Right frame
     
     TransportLabel = Label(RightFrame, text="  Transport: SAFE WEBDROP  ", font=Bold, height=1, bg=BACKGROUND)
     if os.path.islink("/etc/systemd/system/multi-user.target.wants/cryptoboned.service"):
          if "ALLINONE" in send_command("GETALLINONE"):
               TransportLabel.pack(pady=10)
     
     # FillRight enables an empty RightFrame
     FillRight = Label(RightFrame, text="   ", height=1, width=32, bg=BACKGROUND)
     FillRight.pack(pady=14)
     FillRightLong = Label(RightFrame, text="   ", height=1, width=32, bg=BACKGROUND)
     
     ### Select Box
     SelectBox = Frame(RightFrame, bg=BACKGROUND)
     L = Label(SelectBox, text="", bg="yellow",font=Bold,  width=30)
     L.pack()
     BoxFrame = Frame(master=SelectBox)
     XScroll  = Scrollbar(BoxFrame, orient=HORIZONTAL)
     SBox = Listbox(BoxFrame, height=13, width=29, font=TextFont, borderwidth=5, relief=FLAT, xscrollcommand = XScroll.set)
     XScroll.config(command=SBox.xview)
     XScroll.pack(side=BOTTOM, fill=X )
     SBox.pack()
     BoxFrame.pack()
     SelectButton = Button(master=SelectBox, text="Select", bg=GRAY, font=BFont, command=select)
     SBox.bind('<Double-Button-1>', lambda e: SelectButton.invoke())
     SelectButton.pack(pady=5)
     
     ### Attachment Box
     AttachBox = Frame(RightFrame, bg=BACKGROUND)
     AttachBoxFrame = Frame(master=AttachBox)
     LAttach = Label(AttachBoxFrame, text="Attachments", bg="yellow",font=Bold,  width=30)
     AttachXScroll  = Scrollbar(AttachBoxFrame, orient=HORIZONTAL)
     AttachSBox = Listbox(AttachBoxFrame, height=5, width=29, font=TextFont, borderwidth=5, relief=FLAT, xscrollcommand = XScroll.set)
     AttachSBox.bind('<Double-Button-1>', lambda e: attachment_move())
     AttachXScroll.config(command=AttachSBox.yview)
     AttachXScroll.pack(side=BOTTOM, fill=X )
     LAttach.pack()
     AttachBoxFrame.pack(pady=40)
     AttachSBox.pack()
     
     ### Attachment Select Box
     Box2 = Frame(RightFrame, bg=BACKGROUND)
     FillBox2 = Label(Box2, text="   ", height=1, width=30, bg=BACKGROUND)
     Box2Info = Label(Box2, text="Send this file in your \nhome directory securely:", height=2, fg="black", font=Bold, width=30, bg=BACKGROUND)
     FillBox2.pack(pady=10)
     Box2Info.pack()
     AttachLabel = Label(Box2, text="Attachment", bg="yellow",font=Bold,  width=30)
     AttachLabel.pack(pady=5)
     AttachFilename = Entry(Box2, font=Bold, width=30)
     AttachFilename.pack()
     AttachButton = Button(master=Box2, text="Add File", bg=GRAY, font=BFont, command=attach)
     AttachButton.pack(pady=5)

     SelectBox.pack()
     AttachBox.pack()
     Box2.pack(pady=30)

     # Key Management
     Key1 = Frame(LeftFrame, height=110, pady=10, bg=BACKGROUND)
     Key2 = Frame(LeftFrame, height=110, pady=10, bg=BACKGROUND)
     Key3 = Frame(LeftFrame, height=110, pady=10, bg=BACKGROUND)
     KL1 = Label(Key1, text="Register a New Contact", font=Title, bg="yellow", width=30)
     # KL2 = Label(Key2, text="Change Email Address", font=Title, bg="yellow", width=30)
     KL3 = Label(Key3, text="Print New Keys",font=Title, bg="yellow", width=30)
     

     # first Key frame 
     SubKL1 = Label(Key1, text="S-Webdrop-ID % Server", font=Bold, bg="white", width=27)
     SubKL2 = Label(Key1, text="Initial Secret", font=Bold, bg="white", width=27)
     KL1Info = Label(Key1, text="            Enter an initial secret for a new contact SafeWebdrop ID that is not yet registered           ", font=Info, bg=BACKGROUND)
     Email   = Entry(Key1, font=Bold, width=40) 
     InitKey = Entry(Key1, font=Bold, width=40) 
     K1Button = Button(master=Key1, text="Register", bg=GRAY, font=BFont, command=register)
     
     KL1.grid(row=0, column=0, columnspan=2)
     KL1Info.grid(row=1, column=0, columnspan=2, padx=3, pady=8)
     SubKL1.grid(row=2, column=0, padx=3, pady=2)
     Email.grid(row=2, column=1, padx=3, pady=2)
     SubKL2.grid(row=3,column=0, padx=3, pady=2)
     InitKey.grid(row=3, column=1, padx=3, pady=2)
     K1Button.grid(row=4, column=0, columnspan=2, padx=3, pady=15)
     
     # second Key frame 

     # third Key frame 
     KL3.grid(row=0, column=0)
     K3Button = Button(master=Key3, text="Generate new secrets", bg=GRAY, font=BFont, command=print_secrets)
     K3Button.grid(row=1, column=0, pady=5)
    
     # Setup frame
     Setup1 = Frame(LeftFrame, height=100, pady=10, bg=BACKGROUND)
     Setup2 = Frame(LeftFrame, height=100, pady=10, bg=BACKGROUND)

     SL1 = Label(Setup1, text="Setup the SAFE WEBDROP Server for Message Exchange", font=Title, bg="yellow", width=50)
     InfoPanel = Label(Setup2, text="" , width=60, height=8, bg=BACKGROUND, fg="red", pady=4, justify="left")
     SubSL1 = Label(Setup1, text="Safe Webdrop Server Name", font=Bold, bg="white", width=27)
     SubSL2 = Label(Setup1, text="Safe Webdrop User ID", font=Bold, bg="white", width=27)
     SL1Info = Label(Setup1, text="  Please enter your SAFE WEBDROP address  (no spaces) and give it to your contacts ", font=Info)
     Hostname = Entry(Setup1, width=40, font=Bold) 
     Username = Entry(Setup1, width=40, font=Bold) 
     S1Button = Button(master=Setup1, text="Update SAFE WEBDROP Setup", bg=GRAY, font=BFont, command=webdrop_setup)
     ShowButton = Button(master=Setup1, text="Show Setup", bg=GRAY, font=BFont, command=show_webdrop_setup)
     REGButton  = Button(master=Setup2, text="Registration", bg=GRAY, font=BFont, command=register_webdrop_account)
     
     # setup 2
     SL2 = Label(Setup2, text="Registration of a new Safe Webdrop account (if you don't have one already)", font=Title, bg="yellow", width=64)
     SL2Info = Label(Setup2, text="In order to send safe webdrops you need a registered account on your safe webdrop server", font=Info)
     SubSL5 = Label(Setup2, text="Registration code", font=Bold, bg="white", width=27)
     RegistrationCode = Entry(Setup2, width=26, font=Bold ) 

     SL1.grid(row=0, column=0, columnspan=2)
     SL1Info.grid(row=1, column=0, columnspan=2, padx=3, pady=8)
     SubSL1.grid(row=2, column=0, padx=3, pady=2)
     Hostname.grid(row=2, column=1, padx=3, pady=2)
     SubSL2.grid(row=3,column=0, padx=3, pady=2)
     Username.grid(row=3, column=1, padx=3, pady=2)
     ShowButton.grid(row=4, column=0,  padx=3, pady=15)
     S1Button.grid(row=4, column=1,  padx=3, pady=15)
     
     SL2.grid(row=0, column=0, columnspan=2)
     SL2Info.grid(row=1, column=0, columnspan=2, padx=3, pady=8)
     SubSL5.grid(row=2, column=0, padx=3, pady=2)
     RegistrationCode.grid(sticky="W",row=2, column=1, padx=3, pady=2, ipadx=10)
     REGButton.grid(row=3, column=1,  padx=3, pady=15)

     InfoPanel.grid(row=5, column=0, columnspan=2)
     
     QuitButton = Button(master=RightFrame, text="Exit!", bg=GRAY, font=BFont, command=terminate_GUI, width=14)
     ConsoleButton = Button(master=RightFrame, text="Console", bg=GRAY, font=BFont, command=toggle_console, width=14)
     
     QuitButton.pack(side=BOTTOM, pady=15) 
     
     
     if not os.path.islink("/etc/systemd/system/multi-user.target.wants/cryptoboned.service"):
          AdminFrame = Frame(Window)
          AdminFill = Label(AdminFrame, text="",  height=2)
          AdminLabel = Label(AdminFrame, text="You want to activate your Crypto Bone?", width=60, height=1, font=Bold, bg="#eeffee")
          Text1 = Label(AdminFrame, text="Please input the login name of the user that\n will be using the Crypto Bone:")
          Text2 = Label(AdminFrame,text="This user will be listed in the sudoers file.")
          ExecButton = Button(master=AdminFrame, text=" Enable this user ", bg=GREEN, font=BFont, command=readuser)
          InputField = Entry(master=AdminFrame, width=15) 
          AdminFill2= Label(AdminFrame, text="",  height=1)
          AdminFill.pack()
          AdminLabel.pack(pady=10)
          Text1.pack(pady=5)
          Text2.pack(pady=5)
          InputField.pack(pady=10) 
          ExecButton.pack() 
          AdminFill2.pack()

          AdminFrame.pack()
          ErrorFrame.pack(fill=X)
          clear_error()
          Window.mainloop()


     # pack frames
     HeadFrame.pack()
     HeadRightFrame.pack()
     StatusFrame.pack()
     ModeFrame.pack()
     TopFrame.pack()
     TextFrame.pack()
     LeftFrame.pack(side=LEFT, padx=10, fill=Y)
     RightFrame.pack(side=LEFT, fill=Y)
     MainFrame.pack(fill=X)
     ErrorFrame.pack(fill=X)
     
     Name = "none"
     
     set_read()
     
     RESULT = unix("pidof /usr/lib/cryptobone/cryptoboned")
     if "x"+RESULT == "x" :
          # crypto bone daemon is not running
          showerror('Crypto Bone Daemon failed', "You need to reboot your computer because the Crypto Bone Daemon is not running.")
          unix("sleep 10")
          sys.exit(2)
     Text.insert("end", "Reading messages and attachments, please be patient!")
     Window.update_idletasks()
     send_command("FETCH")
     TRANSPORT=send_command("SETUP TRANSPORT WEBDROP")
     print(send_command("SETUP GETTRANSPORT"))
     RESULT = send_command("EXTERNAL STATUS")
     RESULT2 = send_command("GETALLINONE")
     ### if ("ALLINONE" in RESULT2) and ("is an EXTERNAL" in RESULT):
     ###     showerror('Warning!', "This computer is running an EXTERNAL Cryptobone. Please use the GUI on your main Linux computer to access it.")
     Window.mainloop()

##############################################################
