/*
 * This file is part of DesktopBSD, see the README file.
 *
 * Author: Peter Hofer <ph@desktopbsd.net>
 *			(C) 2004, 2005
 *
 * Copyright: BSD, see the COPYING file included in this distribution
 *
 */

#include <wlan.h>

#include <qstringlist.h>

#include <ctype.h>

/** Constructs a WLAN object with given network
  * and wireless settings.
  */
WLAN::WLAN(const IPv4Addr &			  ip,
			  const IPv4Netmask &		  netmask,
			  const IPv4Addr &			  gateway,
			  const QPtrList<IPv4Addr> & ns,
			  const QString &				ssID,
			  WEPMode						  wepMode,
			  const QString &				wepKey)
		: LAN(ip, netmask, gateway, ns),

		ssID(ssID),
		wepMode(wepMode),
wepKey(wepKey) {}

/** Constructs a WLAN object with the given
  * wireless settings that uses DHCP for
  * network configuration.
  */
WLAN::WLAN(const QString & ssID,  WEPMode  wepMode,  const  QString & wepKey)

		: ssID(ssID),
		wepMode(wepMode),
wepKey(wepKey) {}

/** Constructs a WLAN object from an Access Point. */
WLAN::WLAN(const AccessPoint & ap,  const QString & wepKey) {
	setAP(ap);
	this->wepKey = wepKey;
}

/** Returns a string that can be used to create
  * a WLAN object using ::fromString().
  *
  * Format: [LAN-Format]|SSID|WEPMODE|WEPKEY
  */
QString  WLAN::toString() {
	static const QString format = "%1|%2|%3|%4";

	return  format.arg(LAN::toString())
					  .arg(ssID)
					  .arg(wepMode)
					  .arg(wepKey);
}

WLAN  WLAN::fromString(const QString & str) {
	QStringList  substrs = QStringList::split('|', str, true);

	/* DHCP? */
	if(substrs[0].toInt())
		return  WLAN(substrs[5],  (WEPMode) substrs[6].toInt(),  substrs[7]);

	QPtrList<IPv4Addr>  nsList;
	QStringList  nsStrList = QStringList::split(',', substrs[4]);
	QStringList::ConstIterator  it = nsStrList.begin();
	while(it != nsStrList.end())
		nsList.append(new IPv4Addr(*it++));

	return  WLAN(substrs[1],
					 substrs[2],
					 substrs[3],
					 nsList,
					 substrs[5],
					 (WEPMode) substrs[6].toInt(),
					 substrs[7]);
}


/** Uses the SSID, WEP-Mode etc. from an Access-Point.
  * The stored WEP key is not changed.
  */
void  WLAN::setAP(const  AccessPoint & ap) {
	bssID = ap.getBSSID();
	ssID = ap.getSSID();
	wepMode = (ap.getCapInfo() & AccessPoint::WEP) ? WEPOn : WEPOff;
}

bool  WLAN::setSSID(const QString & ssid) {
	uint  length = ssid.length();

	/** SSID must be 1..32 characters */
	if(length == 0 || length > 32)
		return  false;

	for(uint i = 0; i < length; ++i)
	{
		if (!isascii(ssid[i]))
		{
			// Not an ASCII character (0..127)
			return false;
		}
	}

	ssID = ssid;
	return  true;
}

void  WLAN::setWEPMode(WEPMode  mode) {
	wepMode = mode;
}

void  WLAN::setWEPKeyNull() {
	wepKey = QString::null;
}

bool  WLAN::setWEPKey(const QString & key) {
	/* 64, 128 and 256-bit hex WEP key lengths, without
	 * and with initialisation vector, in that order.
	 */
	uint lengths[] = { 10, 16, 26, 32, 58, 64 };
	uint length = key.length();

	bool lenMatch = false;
	for(uint i = 0; !lenMatch && i < (sizeof lengths / sizeof lengths[0]); ++i)
		lenMatch = (lengths[i] == length);

	if(!lenMatch)
		return false;

	for(uint i = 0; i < length; ++i)
	{
		char c = key[i];
		if (!isxdigit(c))
		{
			// Not a hexadecimal digit
			return false;
		}
	}

	wepKey = key;
	return  true;
}
