Commit c0b9caac authored by urbant's avatar urbant
Browse files

SipUrl - basic decoding methods

parent 7a073990
Loading
Loading
Loading
Loading
+83 −9
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ class Regex {
public:
	Regex(const char* regex, int flags = 0) {

		flags |= REG_EXTENDED;
		if (regcomp (&mRegex, regex, flags)) 
		{
			std::cerr << "bad regex: " << regex << endl;
@@ -18,9 +19,9 @@ public:

	bool Match (Buffer& buffer) {

		const char* start =  buffer.GetValue().c_str() + (buffer.GetPosition() / 8);
		mStart =  buffer.GetValue().c_str() + (buffer.GetPosition() / 8);

		return !regexec (&mRegex, start, 16, mMatches, 0);
		return !regexec (&mRegex, mStart, 16, mMatches, 0);
	}

	void AssertMatch (Buffer& buffer, Variable* v) throw (DecodeError) {
@@ -29,8 +30,20 @@ public:
		}
	}

	int GetMatchedLength() {
		return (mMatches[0].rm_eo - mMatches[0].rm_so)*8;
	int GetMatchedLength(int id = 0) {
		return (mMatches[id].rm_eo - mMatches[id].rm_so)*8;
	}

	std::string GetMatchedString(int id = 0) {
		return std::string (mStart + mMatches[id].rm_so, mMatches[id].rm_eo - mMatches[id].rm_so);
	}

	const char* GetMatchedPosition(int id = 0) {
		return mStart + mMatches[id].rm_so;
	}

	const char GetLastMatchedChar(int id = 0) {
		return *(mStart + mMatches[id].rm_eo);
	}

	void Error (Variable* v, Buffer& buffer) throw (DecodeError) {
@@ -45,23 +58,32 @@ public:
private:
	regex_t		mRegex;
	regmatch_t	mMatches[16];
	const char*	mStart;
};

#define SIPCHARS_MARK		"\\-_.!~*'()"
#define SIPCHARS_UNRESERVED	"A-Za-z0-9" SIPCHARS_MARK
#define SIPCHARS_ALFA		"A-Za-z"
#define SIPCHARS_ALFANUM	"0-9" SIPCHARS_ALFA
#define SIPCHARS_UNRESERVED	SIPCHARS_ALFANUM SIPCHARS_MARK
#define SIPCHARS_USER_UNRESERVED "&=+$,;?/"
#define SIPCHARS_ESCAPED	"%0-9"
#define SIPCHARS_ESCAPED	"(%[0-9A-F]{2})"
#define SIPCHARS_TOPLABEL	"[" SIPCHARS_ALFA "]([" SIPCHARS_ALFANUM "\\-]*[" SIPCHARS_ALFANUM "])?"
#define SIPCHARS_DOMAINLABEL	"[" SIPCHARS_ALFANUM "]([" SIPCHARS_ALFANUM "\\-]*[" SIPCHARS_ALFANUM "])?"
#define SIPCHARS_HOSTNAME	"(" SIPCHARS_DOMAINLABEL "\\.)*" SIPCHARS_TOPLABEL "\\.?"
//#define SIPCHARS_HOSTNAME	SIPCHARS_TOPLABEL

void SipUrl::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{

	static Regex reg_scheme ("^sip:", REG_ICASE);
	static Regex reg_userinfo ("^[:" SIPCHARS_UNRESERVED SIPCHARS_USER_UNRESERVED SIPCHARS_ESCAPED  "]*@", REG_ICASE);
	//static Regex reg_userinfo ("^([" SIPCHARS_USER_UNRESERVED SIPCHARS_UNRESERVED ":])*@", REG_ICASE);
	static Regex reg_userinfo ("^([:" SIPCHARS_UNRESERVED SIPCHARS_USER_UNRESERVED "]|" SIPCHARS_ESCAPED "])*@", REG_ICASE);
	static Regex reg_hostport ("^[:." SIPCHARS_ALFANUM "\\-]*([;&]|$)", REG_ICASE);

	switch (id) {
	case id_scheme:
		reg_scheme.AssertMatch (buffer, this);
		SetHypFieldLength (id_scheme, reg_scheme.GetMatchedLength());
		SetHypFieldLength (id, reg_scheme.GetMatchedLength());
		break;

	case id_userInfo:
@@ -77,11 +99,63 @@ void SipUrl::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
		if (IsPresent (id_userInfo)) {
			Unsigned(8).Decode(buffer);
		}

		if (reg_hostport.Match (buffer)) {
			SetHypFieldIsPresent (id,  1);
			char c = reg_hostport.GetLastMatchedChar();
			SetHypFieldLength(id, reg_hostport.GetMatchedLength() - (c == ';' || c == '&' ? 8 : 0));
		} else if (IsPresent (id_userInfo)) {
				reg_hostport.Error(this, buffer);
		} else {
			SetHypFieldIsPresent (id,  0);
		}
		break;
	}
}

void UserInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_username ("^([" SIPCHARS_UNRESERVED SIPCHARS_USER_UNRESERVED "]|" SIPCHARS_ESCAPED ")*:", REG_ICASE);
	static Regex reg_password ("^([&=+$," SIPCHARS_UNRESERVED "]|" SIPCHARS_ESCAPED ")*", REG_ICASE);
	switch (id) {
	case id_userOrTelephoneSubscriber:
		if (reg_username.Match (buffer)) {
			SetHypFieldLength (id, reg_username.GetMatchedLength() - 8);
		}
		break;
	case id_password:
		if(buffer.GetBitsLeft()) {
			Unsigned(8).Decode(buffer);
			SetHypFieldIsPresent (id, 1);
			reg_password.AssertMatch (buffer, this);
		} else {
			SetHypFieldIsPresent (id, 0);
		}
		break;
	}
}

void HostPort::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_host1 (SIPCHARS_HOSTNAME "$", REG_ICASE);
	static Regex reg_host2 (SIPCHARS_HOSTNAME ":", REG_ICASE);
	switch (id) {
	case id_host:
		SetHypFieldIsPresent(id, 1);
		if (reg_host2.Match(buffer)){
			SetHypFieldLength(id, reg_host2.GetMatchedLength() - 8);
		} else {
			reg_host1.AssertMatch(buffer, this);
		}
		break;
	case id_portField:
		if(buffer.GetBitsLeft()) {
			Unsigned(8).Decode(buffer);
			SetHypFieldIsPresent (id, 1);
		} else {
			SetHypFieldIsPresent (id, 0);
		}
		break;
	}
}

}} // namespaces