#include <qfile.h>
#include <qmsgbox.h>
#include <qstring.h>

#include <kapp.h>
#include <kconfig.h>
#include <klocale.h>

#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>

#include "mytypes.h"	
#include <string.h>

#include "kISDNdata.h"

kISDNData ISDNData;


IP::IP(const char *ip)
{
  strncpy(data, ip, IPNMSIZE);
  data[IPNMSIZE] = '\0';
}


bool IP::isValidIP(void)
{
  char *bufferp = data;
  uint   temp;
  
  isnull = false;
   
  for (ushort i = 0; i < 4; i++)
  {
    while (*bufferp == ' ') bufferp++;
    if (!isdigit(*bufferp)) return (false);
    temp = 0;
    while (isdigit(*bufferp))
    {
      temp *= 10;
      temp += *(bufferp++)-'0';
      if (temp > 255) return (false);
    }
    isnull = isnull || (temp != 0);
    
    while (*bufferp == ' ') bufferp++;
    if ((i < 3) && (*bufferp != '.')) return (false);
    else bufferp++;
  }
  bufferp--;
  while (*bufferp == ' ') bufferp++;
  if (*bufferp != '\0') return (false);
  return (true);
}


PhoneData::PhoneData(void)
{
  prev   = (PhoneData *) 0L;
  next   = (PhoneData *) 0L;
  number = "";
}


DNSData::DNSData(void)
{
  prev      = (DNSData *) 0L;
  next      = (DNSData *) 0L;
  ipaddress = "0.0.0.0";
}


DevData::DevData(void)
{
  prev       = (DevData *) 0L;
  next       = (DevData *) 0L; 
  FirstPhone = (PhoneData *) 0L;
  LastPhone  = (PhoneData *) 0L;
  
  DialAttempts = 1;
  HupTimeout   = 600;
  Delay        = 30;
  Encaps       = 0;
  Layer2       = 0;
  Layer3       = 0;
  Name         = "Dummy";
}


void DevData::Backup(void)
{
  tmp_DialAttempts = DialAttempts;
  tmp_HupTimeout   = HupTimeout;
  tmp_Delay        = Delay;
  tmp_Encaps       = Encaps;
  tmp_Layer2       = Layer2;
  tmp_Layer3       = Layer3;
}


void DevData::Restore(void)
{
  DialAttempts = tmp_DialAttempts;
  HupTimeout   = tmp_HupTimeout;
  Delay        = tmp_Delay;
  Encaps       = tmp_Encaps;
  Layer2       = tmp_Layer2;
  Layer3       = tmp_Layer3;
}


bool DevData::Load(KConfig *kc, uint accindex, ushort devindex, bool master)
{
  char       buffer[32];
  ushort     phcnt = 0;
  PhoneData  *phone = (PhoneData *) 0L, *old;

  if (master) sprintf(buffer, "Account%i/Master", accindex);
  else sprintf(buffer, "Account%i/Slave%i", accindex, devindex);
  
  kc->setGroup(buffer);
  HupTimeout   = kc->readNumEntry("HupTimeOut", 600);
  DialAttempts = kc->readNumEntry("DialAttempts", 1);
  
  if (!master)
  {
    Name  = kc->readEntry("Identifier", klocale->translate("(unknown)"));
    Delay = kc->readNumEntry("Delay", 60);
  }
  
  Encaps = kc->readNumEntry("Encapsulation", 0);
  Layer2 = kc->readNumEntry("Layer2", 0);
  Layer3 = kc->readNumEntry("Layer3", 0);
  
  phcnt  = kc->readNumEntry("NumPhone", 0);
  
  if (phcnt > 0)
  {
    for (ushort i = 0; i < phcnt; i++)
    {
      old = phone;
      phone = new PhoneData();
      sprintf(buffer, "Phone%i", i);
      phone->number = kc->readEntry(buffer, "0");
      if (i == 0) FirstPhone = phone;
      else
      {
        old->next   = phone;
	phone->prev = old;
      }
    }
    LastPhone = phone;
  }
  
  return (true); 		// We're optimists :-)
}


void DevData::Save(KConfig *kc, uint accindex, ushort devindex, bool master)
{
  char       buffer[32];
  ushort     phcnt = 0;
  PhoneData  *phone;
  
  if (master) sprintf(buffer, "Account%i/Master", accindex);
  else sprintf(buffer, "Account%i/Slave%i", accindex, devindex);
  
  kc->setGroup(buffer);
  kc->writeEntry("HupTimeOut", HupTimeout);
  kc->writeEntry("DialAttempts", DialAttempts);
  
  if (!master) 
  {
    kc->writeEntry("Identifier", Name);
    kc->writeEntry("Delay", Delay);
  }
  
  kc->writeEntry("Encapsulation", Encaps);
  kc->writeEntry("Layer2", Layer2);
  kc->writeEntry("Layer3", Layer3);
  
  phone = FirstPhone;
  while (phone != (PhoneData *) 0L)
  {
    sprintf(buffer, "Phone%i", phcnt++);
    kc->writeEntry(buffer, phone->number);
    phone = phone->next;
  }
  
  kc->writeEntry("NumPhone", phcnt);
}


AccData::AccData(void)
{
  prev       = (AccData *) 0L;
  next       = (AccData *) 0L;
  FirstSlave = (DevData *) 0L;
  LastSlave  = (DevData *) 0L;
  FirstDNS   = (DNSData *) 0L;
  LastDNS    = (DNSData *) 0L;
  
  providername = "";
  device       = 0;
  bundle       = false;
  ipdynamic    = true;    
  iplocaddress = "0.0.0.0";  
  ipremaddress = "0.0.0.0";  
  subnetmask   = "0.0.0.0";  
  domain       = ""; 
  UsePAP       = true;
  UseCHAP      = false;
  username     = "";
  password     = "";   
}


void AccData::Backup(void)
{
  MasterDevice.Backup();
  tmp_providername = providername.copy();
  tmp_device       = device;
  tmp_bundle       = bundle;
  tmp_ipdynamic    = ipdynamic;  
  tmp_iplocaddress = iplocaddress.copy();  
  tmp_ipremaddress = ipremaddress.copy();  
  tmp_subnetmask   = subnetmask.copy();
  tmp_domain       = domain.copy();
  tmp_UsePAP       = UsePAP;
  tmp_UseCHAP      = UseCHAP;
  tmp_username     = username.copy();
  tmp_password     = password.copy();
}


void AccData::Restore(void)
{
  MasterDevice.Restore();
  providername = tmp_providername.copy();
  device       = tmp_device;
  bundle       = tmp_bundle;
  ipdynamic    = tmp_ipdynamic; 
  iplocaddress = tmp_iplocaddress.copy();
  ipremaddress = tmp_ipremaddress.copy();
  subnetmask   = tmp_subnetmask.copy();
  domain       = tmp_domain.copy();
  UsePAP       = tmp_UsePAP;
  UseCHAP      = tmp_UseCHAP;
  username     = tmp_username.copy();
  password     = tmp_password.copy();
}


bool AccData::Load(KConfig *kc, uint index)
{
  char     AccGroup[16], buffer[16];
  ushort   dnscnt, devcnt;
  DNSData  *dns = (DNSData *) 0L, *old;
  DevData  *dev = (DevData *) 0L, *olddev;
  bool     DevLoadSuccess = true;
  
  printf("Try to load account #%i\n", index);
  
  sprintf(AccGroup, "Account%i", index);

  kc->setGroup(AccGroup);
  providername = kc->readEntry("Provider", klocale->translate("(unknown)"));
  device       = kc->readNumEntry("Device", 0);

  if (kc->readEntry("Bundle") == "yes") bundle = true;
  else bundle = false;
  if (kc->readEntry("IPDynamic") == "yes") ipdynamic = true; 
  else ipdynamic = false;
  
  iplocaddress = kc->readEntry("LocalIPAddress", "");
  ipremaddress = kc->readEntry("RemoteIPAddress", "");
  subnetmask   = kc->readEntry("SubNetMask", "");
  domain       = kc->readEntry("Domain", "");
  
  if (kc->readEntry("UsePAP") == "yes") UsePAP = true; 
  else UsePAP = false;
  if (kc->readEntry("UseCHAP") == "yes") UseCHAP = true; 
  else UseCHAP = false;
  
  username = kc->readEntry("UserName", "");
  password = kc->readEntry("Password", "");			// CAUTION !!!!

  dnscnt = kc->readNumEntry("NumDNS", 0);
  
  if (dnscnt > 0)
  {
    for (ushort i = 0; i < dnscnt; i++)
    {
      old = dns;
      dns = new DNSData();
      sprintf(buffer, "DNS%i", i);
      dns->ipaddress = kc->readEntry(buffer, "0.0.0.0");
      if (i == 0) FirstDNS = dns;
      else
      {
        old->next = dns;
	dns->prev = old;
      }
    }
    LastDNS = dns;
  }

  MasterDevice.Load(kc, index, 0, true);
  
  kc->setGroup(AccGroup);
  devcnt = kc->readNumEntry("NumSlaves", 0);
  
  if (devcnt > 0)
  {
    printf("We've got %i slaves to load\n", devcnt);
    for (uint i = 0; (i < devcnt) && DevLoadSuccess; i++)
    {
      olddev = dev;
      dev    = new DevData();
      DevLoadSuccess = DevLoadSuccess && dev->Load(kc, index, i, false);
      if (i == 0) FirstSlave = dev;
      else
      {
        olddev->next = dev;
	dev->prev    = olddev;
      }
    }
    LastSlave = dev;
  }   
  
  return (DevLoadSuccess);	
}


void AccData::Save(KConfig *kc, uint index)
{
  char     AccGroup[16], buffer[16];
  ushort   dnscnt = 0, devcnt = 0;
  DNSData  *dns;
  DevData  *dev;
  
  sprintf(AccGroup, "Account%i", index);
  
  kc->setGroup(AccGroup);
  kc->writeEntry("Provider", providername);
  kc->writeEntry("Device", device);
  kc->writeEntry("Bundle", bundle ? "yes" : "no");
  kc->writeEntry("IPDynamic", ipdynamic ? "yes" : "no");
  kc->writeEntry("LocalIPAddress", iplocaddress);
  kc->writeEntry("RemoteIPAddress", ipremaddress);
  kc->writeEntry("SubNetMask", subnetmask);
  kc->writeEntry("Domain", domain);
  kc->writeEntry("UsePAP", UsePAP ? "yes" : "no");
  kc->writeEntry("UseCHAP", UseCHAP ? "yes" : "no");
  kc->writeEntry("UserName", username);
  kc->writeEntry("Password", password);			// CAUTION !!!!
  
  dns = FirstDNS;
  while (dns != (DNSData *) 0L)
  {
    sprintf(buffer, "DNS%i", dnscnt++);
    kc->writeEntry(buffer, dns->ipaddress);
    dns = dns->next;
  }  
  kc->writeEntry("NumDNS", dnscnt);
 
  MasterDevice.Save(kc, index, 0, true);
  
  dev = FirstSlave;
  while(dev != (DevData *) 0L)
  {
    dev->Save(kc, index, devcnt++, false);
    dev = dev->next;
  }  
  kc->setGroup(AccGroup);
  kc->writeEntry("NumSlaves", devcnt);

  kc->setGroup("General");
  kc->writeEntry("NumAccounts", buffer);
}
  
  
AdvData::AdvData(void)
{
  bsdcomp  = false;
  incdebug = false;
  dbglevel = 0;
}


void AdvData::Backup(void)
{
  tmp_bsdcomp  = bsdcomp;
  tmp_incdebug = incdebug;
  tmp_dbglevel = dbglevel;
}


void AdvData::Restore(void)
{
  bsdcomp  = tmp_bsdcomp;
  incdebug = tmp_incdebug;
  dbglevel = tmp_dbglevel;
}


bool AdvData::Load(KConfig *kc)
{
  kc->setGroup("AdvancedIPPPDOptions");

  if (kc->readEntry("DisableBSDCompression") == "yes" ) bsdcomp = true;
  else bsdcomp = false;
  if (kc->readEntry("IncreaseDebugLevel") == "yes" ) incdebug = true;
  else incdebug = false;
  dbglevel = kc->readNumEntry("KernelDebugLevel", 0);
  return (true);
}


void AdvData::Save(KConfig *kc)
{
  kc->setGroup("AdvancedIPPPDOptions");

  kc->writeEntry("DisableBSDCompression", bsdcomp ? "yes" : "no");
  kc->writeEntry("IncreaseDebugLevel", incdebug ? "yes" : "no");
  kc->writeEntry("KernelDebugLevel", dbglevel);
}


GenData::GenData(void)
{
  ipppdpath    = "/sbin/ipppd";
  ctrlpath     = "/sbin/isdnctrl";
  ifconpath    = "/sbin/ifconfig";
  prefix       = "";
  msn          = "";
  showclock    = false;
  docking      = false;
  disconnect   = true;
  loadasmodule = false;
  modprobepath = "/sbin/modprobe";
  adapter      = 4;
  iobase0      = "0x0160";
  iobase1      = "";
  membase      = "";
  interrupt    = 5;
  isdnlogpath  = "/sbin/isdnlog";
  isdnreppath  = "/sbin/isdnrep";
  protocol     = 1;			/* Euro DSS1 */
  audioEnabled = false;
  wavonlinepath   = kapp->kdedir() + "/share/sounds/beep.wav";
  wavofflinepath  = kapp->kdedir() + "/share/sounds/beep.wav";
}

  
bool GenData::Load(KConfig *kc)
{
  kc->setGroup("General");
  
  ipppdpath = kc->readEntry("IpppdPath", "/sbin/ipppd");
  ctrlpath  = kc->readEntry("IsdnctrlPath", "/sbin/isdnctrl");
  ifconpath = kc->readEntry("IfconfigPath", "/sbin/ifconfig");
  prefix    = kc->readEntry("Prefix", "");
  msn       = kc->readEntry("Msn", "");
  
  if (kc->readEntry("ShowClock") == "yes") showclock = true;
  else showclock = false;
  
  if ( kc->readEntry("DockInPanel" ) == "yes" ) docking = true;
  else docking = false;

  if (kc->readEntry("DisconnectOnShutdown") == "no") disconnect = false;
  else disconnect = true;

  if (kc->readEntry("LoadDriverAsModule") == "no") loadasmodule = false;
  else loadasmodule = true;

  if (loadasmodule)
  {
    modprobepath = kc->readEntry("ModprobePath", "/sbin/modprobe");
    adapter      = kc->readNumEntry("Adapter", 4);
    iobase0      = kc->readEntry("IOBase0", "");
    iobase1      = kc->readEntry("IOBase1", "");
    interrupt    = kc->readNumEntry("Interrupt", 5);
    membase      = kc->readEntry("MemBase", "");
    protocol     = kc->readNumEntry("Protocol", 1);    
  }
   
  isdnlogpath = kc->readEntry("ISDNLogPath", "/sbin/isdnlog");
  isdnreppath = kc->readEntry("ISDNRepPath", "/sbin/isdnrep");
  
  if ( kc->readEntry("EnableAudio" ) == "yes" ) audioEnabled = true;
  else audioEnabled = false;
  
  wavonlinepath  = kc->readEntry("WavConnect", kapp->kdedir() + "/share/sounds/beep.wav");
  wavofflinepath = kc->readEntry("WavDisconnect", kapp->kdedir() + "/share/sounds/beep.wav");
    
  Advanced.Load(kc);  
  return (true); 
}


void GenData::Save(KConfig *kc)
{
  kc->setGroup("General");
  kc->writeEntry("IpppdPath", ipppdpath);
  kc->writeEntry("IsdnctrlPath", ctrlpath);
  kc->writeEntry("IfconfigPath", ifconpath);
  kc->writeEntry("Prefix", prefix);
  kc->writeEntry("Msn", msn);
  kc->writeEntry("ShowClock", showclock ? "yes" : "no");
  kc->writeEntry("DockInPanel", docking ? "yes" : "no");
  kc->writeEntry("DisconnectOnShutdown", disconnect ? "yes" : "no");
  kc->writeEntry("LoadDriverAsModule", loadasmodule ? "yes" : "no");
  if (loadasmodule)
  {
    kc->writeEntry("ModprobePath", modprobepath);
    kc->writeEntry("Adapter", adapter);
    kc->writeEntry("IOBase0", iobase0);
    kc->writeEntry("IOBase1", iobase1);
    kc->writeEntry("Interrupt", interrupt);
    kc->writeEntry("MemBase", membase);
    kc->writeEntry("Protocol", protocol);
  }
  
  kc->writeEntry("ISDNLogPath", isdnlogpath);
  kc->writeEntry("ISDNRepPath", isdnreppath);

  kc->writeEntry("EnableAudio", audioEnabled ? "yes" : "no");
  kc->writeEntry("WavConnect", wavonlinepath);
  kc->writeEntry("WavDisconnect", wavofflinepath);
  
  Advanced.Save(kc);
}


void GenData::Backup(void)
{
  tmp_ipppdpath	     = ipppdpath.data();
  tmp_ctrlpath	     = ctrlpath.data();
  tmp_ifconpath	     = ifconpath.data();
  tmp_prefix         = prefix.data();
  tmp_msn	     = msn.data();
  tmp_showclock      = showclock;
  tmp_docking        = docking;
  tmp_disconnect     = disconnect;
  tmp_loadasmodule   = loadasmodule;
  tmp_modprobepath   = modprobepath.data();
  tmp_adapter        = adapter;
  tmp_protocol       = protocol;
  tmp_membase        = membase.data();
  tmp_iobase0        = iobase0.data();
  tmp_iobase1        = iobase1.data();
  tmp_interrupt      = interrupt;
  tmp_isdnlogpath    = isdnlogpath.data();
  tmp_isdnreppath    = isdnreppath.data();
  tmp_audioEnabled   = audioEnabled;
  tmp_wavonlinepath  = wavonlinepath.data();
  tmp_wavofflinepath = wavofflinepath.data();

  tmp_Advanced.bsdcomp  = Advanced.bsdcomp;
  tmp_Advanced.incdebug = Advanced.incdebug;
  tmp_Advanced.dbglevel = Advanced.dbglevel;
}


void GenData::Restore(void)
{
  ipppdpath      = tmp_ipppdpath.data();
  ctrlpath       = tmp_ctrlpath.data();
  ifconpath      = tmp_ifconpath.data();
  prefix         = tmp_prefix.data();
  msn	         = tmp_msn.data();
  showclock      = tmp_showclock;
  docking        = tmp_docking;
  disconnect     = tmp_disconnect;
  loadasmodule   = tmp_loadasmodule;
  modprobepath   = tmp_modprobepath.data();
  adapter        = tmp_adapter;
  protocol       = tmp_protocol;
  membase        = tmp_membase.data();
  iobase0        = tmp_iobase0.data();
  iobase1        = tmp_iobase1.data();
  interrupt      = tmp_interrupt;
  isdnlogpath    = tmp_isdnlogpath.data();
  isdnreppath    = tmp_isdnreppath.data();
  audioEnabled   = tmp_audioEnabled;
  wavonlinepath  = tmp_wavonlinepath.data();
  wavofflinepath = tmp_wavofflinepath.data();

  Advanced.bsdcomp  = tmp_Advanced.bsdcomp;
  Advanced.incdebug = tmp_Advanced.incdebug;
  Advanced.dbglevel = tmp_Advanced.dbglevel;
}


kISDNData::kISDNData()
{
  General      = new GenData();
  FirstAccount = (AccData *) 0L;
  LastAccount  = (AccData *) 0L;
  AccIndex[0]  = 0;
  AccIndex[1]  = 0;
}


kISDNData::~kISDNData()
{
  AccData *Actual = FirstAccount, *ToDestroy;
  
  delete General;

  if (Actual != (AccData *) 0L)
  {
    do
    {
      ToDestroy = Actual;
      Actual    = Actual->next;
      delete (ToDestroy);     
    } while (Actual != (AccData *) 0L);
  }
}
  

bool kISDNData::Load(void)
{
  KConfig  *kc = kapp->getConfig();
  uint     numacc;
  bool     GenLoadSuccess, AccLoadSuccess = true;
  AccData  *acc = (AccData *) 0L, *old;
  
  GenLoadSuccess = General->Load(kc);
  
  kc->setGroup("Configuration");
  AccIndex[0] = kc->readNumEntry("ISP0", 0);
  AccIndex[1] = kc->readNumEntry("ISP1", 0);
  kc->setGroup("General");
  numacc = kc->readNumEntry("NumAccounts", 0);
  
  if (numacc > 0)
  {
    printf("We've got %i accounts to load\n", numacc);
    for (uint i = 0; (i < numacc) && AccLoadSuccess; i++)
    {
      old = acc;
      acc = new AccData();
      AccLoadSuccess = AccLoadSuccess && acc->Load(kc, i);
      if (i == 0) FirstAccount = acc;
      else
      {
        old->next = acc;
		acc->prev = old;
      }
    }
    LastAccount = acc;
  }
  for (ushort i = 0; i < 2; i++) if (AccIndex[i] > numacc) AccIndex[i] = 0;
  return (GenLoadSuccess && AccLoadSuccess);
}


void kISDNData::Save(void)
{
  KConfig  *kc = kapp->getConfig();
  uint     numacc = 0;
  AccData  *acc;
  
  kc->setGroup("Configuration");
  kc->writeEntry("ISP0", AccIndex[0]);
  kc->writeEntry("ISP1", AccIndex[1]);
   
  General->Save(kc);
  
  acc = FirstAccount;
  while(acc != (AccData *) 0L)
  {
    acc->Save(kc, numacc++);
    acc = acc->next;
  }  
  kc->setGroup("General");
  kc->writeEntry("NumAccounts", numacc);
  kc->sync();
}


void kISDNData::Backup(void)
{
  General->Backup();
  // FirstAccount->Backup();
}


void kISDNData::Restore(void)
{
  General->Restore();
  // FirstAccount->Restore();
}
