Commit 2f94d1ca authored by urbant's avatar urbant
Browse files

decoding support for content-disposition

improved decoding of semicolon-separated parameter list
parent d2665741
Loading
Loading
Loading
Loading
+54 −66
Original line number Diff line number Diff line
@@ -178,7 +178,19 @@ bool is_tel_scheme (const char * pszScheme) {
#define SIPREG_TELPARAM_VALUE	"([\\x21\\x23-\\x3A\\x3C-\\x7E]+|(" SIPREG_QUOTED_STRING "))"
#define SIPREG_TELPARAMS		"([;]" SIPREG_TELPARAM_NAME "([=]" SIPREG_TELPARAM_VALUE ")?)+"

#define SIPREG_CPARAM "[\\x21\\x23-\\x2B\\x2D-\\x3C\\x3E-\\x7E]"
#define SIPREG_GPARAM_VALUE "(([" SIPCHARS_ALFANUM ".!%*_+`'~\\-:]+)|(" SIPREG_QUOTED_STRING "))"

bool decode_comma_separated(RecordOfSetOf * pRecordOf, Buffer & buffer) throw (DecodeError)
{
	static Regex reg_separator ("^" SIPREG_COMMA);
	if (!buffer.GetBitsLeft() || pRecordOf->GetSize() == 0)
		return true;
	else if (reg_separator.Match(buffer))
		buffer.SetPosition(buffer.GetPosition() + reg_separator.GetMatchedLength());
	else
		return false;
	return true;
}

void SipUrl::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
@@ -369,13 +381,7 @@ void AmpersandParam_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeE

void CommaParam_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_separator ("^" SIPREG_COMMA);
	
	if (!buffer.GetBitsLeft() || GetSize() == 0)
		return;
	if (reg_separator.Match(buffer))
		buffer.SetPosition(buffer.GetPosition() + reg_separator.GetMatchedLength());
	else
	if (!decode_comma_separated (this, buffer))
		SetHypSize(-2);
}

@@ -392,10 +398,10 @@ void GenericParam::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
	static Regex reg_telparname ("^" SIPREG_TELPARAM_NAME);
	static Regex reg_telparvalue ("^" SIPREG_TELPARAM_VALUE);

	static Regex reg_cparname ("^" SIPREG_CPARAM "+");
	static Regex reg_cparvalue ("^(" SIPREG_CPARAM "+)|(" SIPREG_QUOTED_STRING ")");
	static Regex reg_gparname ("^" SIPREG_TOKEN);
	static Regex reg_gparvalue ("^" SIPREG_GPARAM_VALUE);

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

@@ -404,19 +410,22 @@ void GenericParam::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
		throw DecodeError (this, "Parent type cannot be null");
	const char * pszParName = parent->GetTypeName();
	if (strcmp(pszParName, "SemicolonParam_List") == 0){
		bool bTel = false;
		parent = parent->GetParent();
		if (parent != NULL && strcmp (parent->GetTypeName(), "SipUrl") == 0) {
			SipUrl * pSipUrl = dynamic_cast<SipUrl*>(parent);
			const char * pszScheme = pSipUrl->Get_scheme().GetValue();
			bTel = is_tel_scheme(pszScheme);
			if (is_sip_scheme(pszScheme)) {
				preg_name = &reg_pparname;
				preg_value = &reg_pparvalue;
			}
		if (bTel) {
			else if (is_tel_scheme(pszScheme)) {
				preg_name = &reg_telparname;
				preg_value = &reg_telparvalue;
		} else {
			preg_name = &reg_pparname;
			preg_value = &reg_pparvalue;
			}
		}
		if (preg_name == NULL) {
			preg_name = &reg_gparname;
			preg_value = &reg_gparvalue;
		}
	}
	else if (strcmp(pszParName, "AmpersandParam_List") == 0){
@@ -425,8 +434,8 @@ void GenericParam::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
		bMandatoryParam = true;
	}
	else if (strcmp(pszParName, "CommaParam_List") == 0){
		preg_name = &reg_cparname;
		preg_value = &reg_cparvalue;
		preg_name = &reg_gparname;
		preg_value = &reg_gparvalue;
	}
	else {
		std::string message ("Unexpected parent type of parameter record: '");
@@ -672,6 +681,7 @@ private:
		SIP_HEADER_ADD (Authentication-Info,	,	authenticationInfo,	AUTHENTICATION_INFO_E);
		SIP_HEADER_ADD (Authorization,	,	authorization,	AUTHORIZATION_E);
		SIP_HEADER_ADD (Call-Info,		,	callInfo,		CALL_INFO_E);
		SIP_HEADER_ADD (Content-Disposition,	,	contentDisposition,	CONTENT_DISPOSITION_E);
		{
			mEntries.push_back(Entry("", "", MessageHeader::id_undefinedHeader_List, ""));
			Entry& e = *mEntries.rbegin();
@@ -848,15 +858,7 @@ void ContactBody::PreDecode (Buffer& buffer) throw (DecodeError)

void ContactAddress_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_separator ("^" SIPREG_COMMA);

	if (!buffer.GetBitsLeft())
		return;
	if (GetSize() == 0)
		return; // at least one element must be present
	else if (reg_separator.Match(buffer))
		buffer.SetPosition(buffer.GetPosition() + reg_separator.GetMatchedLength());
	else
	if (!decode_comma_separated (this, buffer))
		SetHypSize(-2);
}

@@ -927,15 +929,7 @@ void AcceptBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)

void AcceptBody_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_separator ("^" SIPREG_COMMA);

	if (!buffer.GetBitsLeft())
		return;
	if (GetSize() == 0)
		return; // at least one element must be present
	else if (reg_separator.Match(buffer))
		buffer.SetPosition(buffer.GetPosition() + reg_separator.GetMatchedLength());
	else
	if (!decode_comma_separated (this, buffer))
		SetHypSize(-2);
}

@@ -999,15 +993,7 @@ void LanguageBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)

void LanguageBody_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_separator ("^" SIPREG_COMMA);

	if (!buffer.GetBitsLeft())
		return;
	if (GetSize() == 0)
		return; // at least one element must be present
	else if (reg_separator.Match(buffer))
		buffer.SetPosition(buffer.GetPosition() + reg_separator.GetMatchedLength());
	else
	if (!decode_comma_separated (this, buffer))
		SetHypSize(-2);
}

@@ -1057,15 +1043,7 @@ void AlertInfoBody::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)

void AlertInfoBody_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_separator ("^" SIPREG_COMMA);

	if (!buffer.GetBitsLeft())
		return;
	if (GetSize() == 0)
		return; // at least one element must be present
	else if (reg_separator.Match(buffer))
		buffer.SetPosition(buffer.GetPosition() + reg_separator.GetMatchedLength());
	else
	if (!decode_comma_separated (this, buffer))
		SetHypSize(-2);
}

@@ -1166,18 +1144,28 @@ void CallInfoBody::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)

void CallInfoBody_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_separator ("^" SIPREG_COMMA);

	if (!buffer.GetBitsLeft())
		return;
	if (GetSize() == 0)
		return; // at least one element must be present
	else if (reg_separator.Match(buffer))
		buffer.SetPosition(buffer.GetPosition() + reg_separator.GetMatchedLength());
	else
	if (!decode_comma_separated (this, buffer))
		SetHypSize(-2);
}

void ContentDisposition::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
{
	static Regex reg_disposition_type ("^" SIPREG_TOKEN);
	static Regex reg_semicolon ("^" SIPREG_SEMI);
	switch (id){
		case id_dispositionType:
			reg_disposition_type.AssertMatch (buffer, this);
			SetHypFieldLength(id, reg_disposition_type.GetMatchedLength());
			break;
		case id_dispositionParams:
			if (reg_semicolon.Match (buffer)) {
				SetHypFieldIsPresent(id, 1);
			} else {
				SetHypFieldIsPresent(id, 0);
			}
	}
}


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