Commit 85d82243 authored by urbant's avatar urbant
Browse files

SIP URI update (semicolon list and ampersand list)

parent c0b9caac
Loading
Loading
Loading
Loading
+121 −10
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ public:
	}

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

	void Error (Variable* v, Buffer& buffer) throw (DecodeError) {
@@ -67,18 +67,30 @@ private:
#define SIPCHARS_UNRESERVED	SIPCHARS_ALFANUM SIPCHARS_MARK
#define SIPCHARS_USER_UNRESERVED "&=+$,;?/"
#define SIPCHARS_ESCAPED	"(%[0-9A-F]{2})"

// host name
#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

// IPv4

#define SIPCHARS_PPARAM_UNRESERVED "][/:&+$"
#define SIPCHARS_PPARAM		"([" SIPCHARS_PPARAM_UNRESERVED SIPCHARS_UNRESERVED "]|" SIPCHARS_ESCAPED "])"
#define SIPCHARS_PPARAM_ALLOWED	"[" SIPCHARS_PPARAM_UNRESERVED SIPCHARS_UNRESERVED ";=%]+"

#define SIPCHARS_HPARAM_UNRESERVED "][/?:+$"
#define SIPCHARS_HPARAM		"([" SIPCHARS_HPARAM_UNRESERVED SIPCHARS_UNRESERVED "]|" SIPCHARS_ESCAPED "])"
#define SIPCHARS_HPARAM_ALLOWED	"[" SIPCHARS_HPARAM_UNRESERVED SIPCHARS_UNRESERVED ";=%]+"

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

	static Regex reg_scheme ("^sip:", 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);
	static Regex reg_userinfo ("^([:" SIPCHARS_UNRESERVED SIPCHARS_USER_UNRESERVED "]|" SIPCHARS_ESCAPED "])+@", REG_ICASE);
	static Regex reg_hostport ("^[:." SIPCHARS_ALFANUM "\\-]+", REG_ICASE);
	static Regex reg_urlParams ("^;" SIPCHARS_PPARAM_ALLOWED, REG_ICASE);
	static Regex reg_headers ("^[?]" SIPCHARS_PPARAM_ALLOWED, REG_ICASE);

	switch (id) {
	case id_scheme:
@@ -101,20 +113,35 @@ void SipUrl::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
		}
		if (reg_hostport.Match (buffer)) {
			SetHypFieldIsPresent (id,  1);
			char c = reg_hostport.GetLastMatchedChar();
			SetHypFieldLength(id, reg_hostport.GetMatchedLength() - (c == ';' || c == '&' ? 8 : 0));
			SetHypFieldLength(id, reg_hostport.GetMatchedLength());
		} else if (IsPresent (id_userInfo)) {
			reg_hostport.Error(this, buffer);
		} else {
			SetHypFieldIsPresent (id,  0);
		}
		break;
	case id_urlParameters:		
		if(buffer.GetBitsLeft() && reg_urlParams.Match (buffer)){
			SetHypFieldIsPresent (id,  1);
			SetHypFieldLength(id, reg_urlParams.GetMatchedLength());
		} else {
			SetHypFieldIsPresent(id, 0);
		}
		break;
	case id_headers:
		if(buffer.GetBitsLeft() && reg_headers.Match (buffer)){
			SetHypFieldIsPresent (id,  1);
			SetHypFieldLength(id, reg_headers.GetMatchedLength());
		} 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_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:
@@ -136,7 +163,7 @@ void UserInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)

void HostPort::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_host1 (SIPCHARS_HOSTNAME "$", REG_ICASE);
	static Regex reg_host1 (SIPCHARS_HOSTNAME, REG_ICASE);
	static Regex reg_host2 (SIPCHARS_HOSTNAME ":", REG_ICASE);
	switch (id) {
	case id_host:
@@ -158,4 +185,88 @@ void HostPort::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
	}
}

void SemicolonParam_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_separator ("^;");
	if (!buffer.GetBitsLeft())
		return;
	if (reg_separator.Match(buffer))
		Unsigned(8).Decode(buffer);
	else
		SetHypSize(-2);
}

void AmpersandParam_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_start ("^[?]");
	static Regex reg_separator ("^[&]");

	if (!buffer.GetBitsLeft())
		return;
	if (GetSize() == 0){
		reg_start.AssertMatch(buffer, this);
		Unsigned(8).Decode(buffer);
	}
	else if (reg_separator.Match(buffer))
		Unsigned(8).Decode(buffer);
	else
		SetHypSize(-2);
}

void GenericParam::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_equals ("^=", REG_ICASE);

	static Regex reg_pparname ("^" SIPCHARS_PPARAM "+", REG_ICASE);
	static Regex reg_pparvalue ("^" SIPCHARS_PPARAM "*", REG_ICASE);

	static Regex reg_hparname ("^" SIPCHARS_HPARAM "+", REG_ICASE);
	static Regex reg_hparvalue ("^" SIPCHARS_HPARAM "*", REG_ICASE);

	Regex * preg_name;
	Regex * preg_value;
	bool bMandatoryParam = false;

	Variable* parent = GetParent();
	if (parent == NULL)
		throw DecodeError (this, "Parent type cannot be null");
	const char * pszParName = parent->GetTypeName();
	if (strcmp(pszParName, "SemicolonParam_List") == 0){
		preg_name = &reg_pparname;
		preg_value = &reg_pparvalue;
	}
	else if (strcmp(pszParName, "AmpersandParam_List") == 0){
		preg_name = &reg_hparname;
		preg_value = &reg_hparvalue;
		bMandatoryParam = true;
	}
	else if (strcmp(pszParName, "CommaParam_List") == 0){
	}
	else {
		std::string message ("Unexpected parent type of parameter record: '");
		message += pszParName;
		throw DecodeError (this, message);
	}
	
	char c;
	switch (id) {
	case id_id:
		preg_name->AssertMatch (buffer, this);
		SetHypFieldLength (id, preg_name->GetMatchedLength());
		break;
	case id_paramValue:
		if (bMandatoryParam)
			reg_equals.AssertMatch(buffer, this);
		if(bMandatoryParam || (buffer.GetBitsLeft() && reg_equals.Match(buffer))) {
			Unsigned(8).Decode(buffer);
			preg_value->AssertMatch (buffer, this);
			SetHypFieldIsPresent (id, 1);
			SetHypFieldLength (id, preg_value->GetMatchedLength());
		} else {
			SetHypFieldIsPresent (id, 0);
		}
		break;
	}
}

}} // namespaces