/*
 * Copyright (C) 2003  Justin Karneges
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#include "xmpp/sasl/digestmd5proplist.h"

namespace XMPP {

DIGESTMD5PropList::DIGESTMD5PropList() : QList<DIGESTMD5Prop>()
{
}

void DIGESTMD5PropList::set(const QByteArray &var, const QByteArray &val) {
	DIGESTMD5Prop p;
	p.var = var;
	p.val = val;
	append(p);
}

QByteArray DIGESTMD5PropList::get(const QByteArray &var) const
{
	for(ConstIterator it = begin(); it != end(); ++it) {
		if((*it).var == var)
			return (*it).val;
	}
	return QByteArray();
}

QByteArray DIGESTMD5PropList::toString() const
{
	QByteArray str;
	bool first = true;
	for(ConstIterator it = begin(); it != end(); ++it) {
		if(!first)
			str += ',';
		if ((*it).var == "realm" || (*it).var == "nonce" || (*it).var == "username" || (*it).var == "cnonce" || (*it).var == "digest-uri" || (*it).var == "authzid")
			str += (*it).var + "=\"" + (*it).val + '\"';
		else
			str += (*it).var + "=" + (*it).val;
		first = false;
	}
	return str;
}

bool DIGESTMD5PropList::fromString(const QByteArray &str)
{
	DIGESTMD5PropList list;
	int at = 0;
	while(1) {
		while (at < str.length() && (str[at] == ',' || str[at] == ' ' || str[at] == '\t'))
				++at;
		int n = str.indexOf('=', at);
		if(n == -1)
			break;
		QByteArray var, val;
		var = str.mid(at, n-at);
		at = n + 1;
		if(str[at] == '\"') {
			++at;
			n = str.indexOf('\"', at);
			if(n == -1)
				break;
			val = str.mid(at, n-at);
			at = n + 1;
		}
		else {
			n = at;
			while (n < str.length() && str[n] != ',' && str[n] != ' ' && str[n] != '\t')
				++n;
			val = str.mid(at, n-at);
			at = n;
		}
		DIGESTMD5Prop prop;
		prop.var = var;
		if (var == "qop" || var == "cipher") {
			int a = 0;
			while (a < val.length()) {
				while (a < val.length() && (val[a] == ',' || val[a] == ' ' || val[a] == '\t'))
					++a;
				if (a == val.length())
					break;
				n = a+1;
				while (n < val.length() && val[n] != ',' && val[n] != ' ' && val[n] != '\t')
					++n;
				prop.val = val.mid(a, n-a);
				list.append(prop);
				a = n+1;
			}
		}
		else {
			prop.val = val;
			list.append(prop);
		}

		if(at >= str.size() - 1 || (str[at] != ',' && str[at] != ' ' && str[at] != '\t'))
			break;
	}

	// integrity check
	if(list.varCount("nonce") != 1)
		return false;
	if(list.varCount("algorithm") != 1)
		return false;
	*this = list;
	return true;
}

int DIGESTMD5PropList::varCount(const QByteArray &var) const
{
	int n = 0;
	for(ConstIterator it = begin(); it != end(); ++it) {
		if((*it).var == var)
			++n;
	}
	return n;
}

}
