status_t
BNetworkCookieJar::AddCookie(BNetworkCookie* cookie)
{
    if (cookie == NULL)
        return B_BAD_VALUE;

    HashString key(cookie->Domain());

    BNetworkCookieList* list = fCookieHashMap->fHashMap.Get(key);
    if (list == NULL) {
        list = new(std::nothrow) BNetworkCookieList();
        if (list == NULL || fCookieHashMap->fHashMap.Put(key, list) != B_OK)
            return B_NO_MEMORY;
    }

    for (int32 i = 0; i < list->CountItems(); i++) {
        BNetworkCookie* c
            = reinterpret_cast<BNetworkCookie*>(list->ItemAt(i));

        if (c->Name() == cookie->Name() && c->Path() == cookie->Path()) {
            list->RemoveItem(i);
            break;
        }
    }

    if (cookie->ShouldDeleteNow())
        delete cookie;
    else
        list->AddItem(cookie);

    return B_OK;
}
uint32
BNetworkCookieJar::PurgeForExit()
{
    int32 deleteCount = 0;
    BNetworkCookie* cookiePtr;

    for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) {
        if (cookiePtr->ShouldDeleteAtExit()) {
            delete it.Remove();
            deleteCount++;
        }
    }

    return deleteCount;
}
uint32
BNetworkCookieJar::DeleteOutdatedCookies()
{
    int32 deleteCount = 0;
    BNetworkCookie* cookiePtr;

    for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) {
        if (cookiePtr->ShouldDeleteNow()) {
            delete it.Remove();
            deleteCount++;
        }
    }

    return deleteCount;
}
status_t
BNetworkCookieJar::Archive(BMessage* into, bool deep) const
{
    status_t error = BArchivable::Archive(into, deep);

    if (error == B_OK) {
        BNetworkCookie* cookiePtr;

        for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) {
            BMessage subArchive;

            error = cookiePtr->Archive(&subArchive, deep);
            if (error != B_OK)
                return error;

            error = into->AddMessage(kArchivedCookieMessageName, &subArchive);
            if (error != B_OK)
                return error;
        }
    }

    return error;
}
void
BNetworkCookieJar::_DoFlatten() const
{
    fFlattened.Truncate(0);

    BNetworkCookie* cookiePtr;
    for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) {
        fFlattened 	<< cookiePtr->Domain() << '\t' << "TRUE" << '\t'
                    << cookiePtr->Path() << '\t'
                    << (cookiePtr->Secure()?"TRUE":"FALSE") << '\t'
                    << (int32)cookiePtr->ExpirationDate() << '\t'
                    << cookiePtr->Name() << '\t' << cookiePtr->Value() << '\n';
    }
}
예제 #6
0
	CookieRow(BColumnListView* list, const BNetworkCookie& cookie)
		:
		BRow(),
		fCookie(cookie)
	{
		list->AddRow(this);
		SetField(new BStringField(cookie.Name().String()), 0);
		SetField(new BStringField(cookie.Path().String()), 1);
		time_t expiration = cookie.ExpirationDate();
		SetField(new BDateField(&expiration), 2);
		SetField(new BStringField(cookie.Value().String()), 3);

		BString flags;
		if (cookie.Secure())
			flags = "https ";
		if (cookie.HttpOnly())
			flags = "http ";

		if (cookie.IsHostOnly())
			flags += "hostOnly";
		SetField(new BStringField(flags.String()), 4);
	}
void
BUrlProtocolHttp::_AddHeaders()
{
	// HTTP 1.1 additional headers
	if (fHttpVersion == B_HTTP_11) {
		fOutputHeaders.AddHeader("Host", Url().Host());
		
		fOutputHeaders.AddHeader("Accept", "*/*");
		fOutputHeaders.AddHeader("Accept-Encoding", "chunked");
			//  Allow the remote server to send dynamic content by chunks
			// rather than waiting for the full content to be generated and
			// sending us data.
		
		fOutputHeaders.AddHeader("Connection", "close");
			//  Let the remote server close the connection after response since
			// we don't handle multiple request on a single connection
	}

	// Classic HTTP headers
	if (fOptUserAgent.CountChars() > 0)
		fOutputHeaders.AddHeader("User-Agent", fOptUserAgent.String());
	
	if (fOptReferer.CountChars() > 0)
		fOutputHeaders.AddHeader("Referer", fOptReferer.String());
		
	// Authentication
	if (fAuthentication.Method() != B_HTTP_AUTHENTICATION_NONE) {
		BString request;
		switch (fRequestMethod) {			
			case B_HTTP_POST:
				request = "POST";
				break;
			
			case B_HTTP_PUT:
				request = "PUT";
				break;
				
			default:
			case B_HTTP_GET:
				request = "GET";
				break;
		}
		
		fOutputHeaders.AddHeader("Authorization", 
			fAuthentication.Authorization(fUrl, request));
	}
		
	// Required headers for POST data
	if (fOptPostFields != NULL && fRequestMethod == B_HTTP_POST) {
		BString contentType;
		
		switch (fOptPostFields->GetFormType()) {
			case B_HTTP_FORM_MULTIPART:
				contentType << "multipart/form-data; boundary="
					<< fOptPostFields->GetMultipartBoundary() << "";
				break;
				
			case B_HTTP_FORM_URL_ENCODED:
				contentType << "application/x-www-form-urlencoded";
				break;
		}
		
		fOutputHeaders.AddHeader("Content-Type", contentType);
		fOutputHeaders.AddHeader("Content-Length", 
			fOptPostFields->ContentLength());
	} else if (fOptInputData != NULL 
		&& (fRequestMethod == B_HTTP_POST || fRequestMethod == B_HTTP_PUT))
		fOutputHeaders.AddHeader("Transfer-Encoding", "chunked");
	
	// Request headers	
	for (int32 headerIndex = 0; 
		headerIndex < fRequestHeaders.CountHeaders(); 
		headerIndex++) {
		BHttpHeader& optHeader = fRequestHeaders[headerIndex];
		int32 replaceIndex = fOutputHeaders.HasHeader(optHeader.Name());
			
		//  Add or replace the current option header to the
		// output header list
		if (replaceIndex == -1)
			fOutputHeaders.AddHeader(optHeader.Name(), optHeader.Value());
		else				
			fOutputHeaders[replaceIndex].SetValue(optHeader.Value());
	}
	
	// Optional headers specified by the user
	if (fOptHeaders != NULL) {		
		for (int32 headerIndex = 0; 
			headerIndex < fOptHeaders->CountHeaders(); 
			headerIndex++) {
			BHttpHeader& optHeader = (*fOptHeaders)[headerIndex];
			int32 replaceIndex = fOutputHeaders.HasHeader(optHeader.Name());
			
			//  Add or replace the current option header to the
			// output header list
			if (replaceIndex == -1)
				fOutputHeaders.AddHeader(optHeader.Name(), optHeader.Value());
			else
				fOutputHeaders[replaceIndex].SetValue(optHeader.Value());
		}
	}
		
	// Context cookies
	if (fOptSetCookies && (fContext != NULL)) {
		BNetworkCookie* cookie;
		
		for (BNetworkCookieJar::UrlIterator 
			it(fContext->GetCookieJar().GetUrlIterator(fUrl));
			(cookie = it.Next()) != NULL;
			)
				fOutputHeaders.AddHeader("Cookie", cookie->RawCookie(false));
	}
	
	// Write output headers to output stream
	for (int32 headerIndex = 0;
		headerIndex < fOutputHeaders.CountHeaders(); 
		headerIndex++)
		_AddOutputBufferLine(fOutputHeaders.HeaderAt(headerIndex).Header());
}
예제 #8
0
void
BHttpRequest::_SendHeaders()
{
	// HTTP 1.1 additional headers
	if (fHttpVersion == B_HTTP_11) {
		fOutputHeaders.AddHeader("Host", Url().Host());

		fOutputHeaders.AddHeader("Accept", "*/*");
		fOutputHeaders.AddHeader("Accept-Encoding", "gzip,deflate");
			// Allow the remote server to send dynamic content by chunks
			// rather than waiting for the full content to be generated and
			// sending us data.

		fOutputHeaders.AddHeader("Connection", "close");
			// Let the remote server close the connection after response since
			// we don't handle multiple request on a single connection
	}

	// Classic HTTP headers
	if (fOptUserAgent.CountChars() > 0)
		fOutputHeaders.AddHeader("User-Agent", fOptUserAgent.String());

	if (fOptReferer.CountChars() > 0)
		fOutputHeaders.AddHeader("Referer", fOptReferer.String());

	// Authentication
	if (fContext != NULL) {
		BHttpAuthentication& authentication = fContext->GetAuthentication(fUrl);
		if (authentication.Method() != B_HTTP_AUTHENTICATION_NONE) {
			if (fOptUsername.Length() > 0) {
				authentication.SetUserName(fOptUsername);
				authentication.SetPassword(fOptPassword);
			}

			BString request(fRequestMethod);
			fOutputHeaders.AddHeader("Authorization",
				authentication.Authorization(fUrl, request));
		}
	}

	// Required headers for POST data
	if (fOptPostFields != NULL && fRequestMethod == B_HTTP_POST) {
		BString contentType;

		switch (fOptPostFields->GetFormType()) {
			case B_HTTP_FORM_MULTIPART:
				contentType << "multipart/form-data; boundary="
					<< fOptPostFields->GetMultipartBoundary() << "";
				break;

			case B_HTTP_FORM_URL_ENCODED:
				contentType << "application/x-www-form-urlencoded";
				break;
		}

		fOutputHeaders.AddHeader("Content-Type", contentType);
		fOutputHeaders.AddHeader("Content-Length",
			fOptPostFields->ContentLength());
	} else if (fOptInputData != NULL
			&& (fRequestMethod == B_HTTP_POST
			|| fRequestMethod == B_HTTP_PUT)) {
		if (fOptInputDataSize >= 0)
			fOutputHeaders.AddHeader("Content-Length", fOptInputDataSize);
		else
			fOutputHeaders.AddHeader("Transfer-Encoding", "chunked");
	}

	// Optional headers specified by the user
	if (fOptHeaders != NULL) {
		for (int32 headerIndex = 0; headerIndex < fOptHeaders->CountHeaders();
				headerIndex++) {
			BHttpHeader& optHeader = (*fOptHeaders)[headerIndex];
			int32 replaceIndex = fOutputHeaders.HasHeader(optHeader.Name());

			// Add or replace the current option header to the
			// output header list
			if (replaceIndex == -1)
				fOutputHeaders.AddHeader(optHeader.Name(), optHeader.Value());
			else
				fOutputHeaders[replaceIndex].SetValue(optHeader.Value());
		}
	}

	// Context cookies
	if (fOptSetCookies && fContext != NULL) {
		BString cookieString;

		BNetworkCookieJar::UrlIterator iterator
			= fContext->GetCookieJar().GetUrlIterator(fUrl);
		BNetworkCookie* cookie = iterator.Next();
		if (cookie != NULL) {
			while (true) {
				cookieString << cookie->RawCookie(false);
				cookie = iterator.Next();
				if (cookie == NULL)
					break;
				cookieString << "; ";
			}
	
			fOutputHeaders.AddHeader("Cookie", cookieString);
		}
	}

	// Write output headers to output stream
	for (int32 headerIndex = 0; headerIndex < fOutputHeaders.CountHeaders();
			headerIndex++) {
		const char* header = fOutputHeaders.HeaderAt(headerIndex).Header();
		fSocket->Write(header, strlen(header));
		fSocket->Write("\r\n", 2);

		_EmitDebug(B_URL_PROTOCOL_DEBUG_HEADER_OUT, "%s", header);
	}
}
예제 #9
0
status_t
BNetworkCookieJar::Unflatten(type_code, const void* buffer, ssize_t size)
{
	BString flattenedCookies;
	flattenedCookies.SetTo(reinterpret_cast<const char*>(buffer), size);

	while (flattenedCookies.Length() > 0) {
		BNetworkCookie tempCookie;
		BString tempCookieLine;

		int32 endOfLine = flattenedCookies.FindFirst('\n', 0);
		if (endOfLine == -1)
			tempCookieLine = flattenedCookies;
		else {
			flattenedCookies.MoveInto(tempCookieLine, 0, endOfLine);
			flattenedCookies.Remove(0, 1);
		}

		if (tempCookieLine.Length() != 0 && tempCookieLine[0] != '#') {
			for (int32 field = 0; field < 7; field++) {
				BString tempString;

				int32 endOfField = tempCookieLine.FindFirst('\t', 0);
				if (endOfField == -1)
					tempString = tempCookieLine;
				else {
					tempCookieLine.MoveInto(tempString, 0, endOfField);
					tempCookieLine.Remove(0, 1);
				}

				switch (field) {
					case 0:
						tempCookie.SetDomain(tempString);
						break;

					case 1:
						// TODO: Useless field ATM
						break;

					case 2:
						tempCookie.SetPath(tempString);
						break;

					case 3:
						tempCookie.SetSecure(tempString == "TRUE");
						break;

					case 4:
						tempCookie.SetExpirationDate(atoi(tempString));
						break;

					case 5:
						tempCookie.SetName(tempString);
						break;

					case 6:
						tempCookie.SetValue(tempString);
						break;
				} // switch
			} // for loop

			AddCookie(tempCookie);
		}
	}

	return B_OK;
}
예제 #10
0
void
CookieTest::ExplodeTest()
{
	struct Test {
		const char* cookieString;
		const char*	url;
		struct
		{
			bool		valid;
			const char* name;
			const char* value;
			const char* domain;
			const char* path;
			bool 		secure;
			bool 		httponly;
			bool		session;
			BDateTime	expire;
		} expected;
	};

	Test tests[] = {
	//     Cookie string      URL
	//     ------------- -------------
	//		   Valid     Name     Value	       Domain         Path      Secure  HttpOnly Session  Expiration
	//       --------- -------- --------- ----------------- ---------  -------- -------- -------  ----------
		// Normal cookies
		{ "name=value", "http://www.example.com/path/path",
			{  true,    "name",  "value", "www.example.com", "/path",   false,   false,   true,   BDateTime() } },
		{ "name=value; domain=example.com; path=/; secure", "http://www.example.com/path/path",
			{  true,    "name",  "value",   "example.com",   "/"    ,   true,    false,   true,   BDateTime() } },
		{ "name=value; httponly; secure", "http://www.example.com/path/path",
			{  true,    "name",  "value", "www.example.com", "/path",   true,    true,    true,   BDateTime() } },
		{ "name=value; expires=Wed, 20-Feb-2013 20:00:00 UTC", "http://www.example.com/path/path",
			{  true,    "name",  "value", "www.example.com", "/path",   false,   false,   false,
				BDateTime(BDate(2013, 2, 20), BTime(20, 0, 0, 0)) } },
		// Valid cookie with bad form
		{ "name=  ;  domain   =example.com  ;path=/;  secure = yup  ; blahblah ;)", "http://www.example.com/path/path",
			{  true,    "name",  "",   "example.com",   "/"    ,   true,    false,   true,   BDateTime() } },
		// Invalid path
		{ "name=value; path=invalid", "http://www.example.com/path/path",
			{  false,    "name",  "value", "www.example.com", "/path",   false,   false,   true,   BDateTime() } },
		// Setting for other subdomain (invalid)
		{ "name=value; domain=subdomain.example.com", "http://www.example.com/path/path",
			{  false,   "name",  "value", "www.example.com", "/path",   false,   false,   true,   BDateTime() } },
		// Various invalid cookies
		{ "name", "http://www.example.com/path/path",
			{  false,   "name",  "value", "www.example.com", "/path",   false,   false,   true,   BDateTime() } },
		{ "; domain=example.com", "http://www.example.com/path/path",
			{  false,   "name",  "value", "www.example.com", "/path",   false,   false,   true,   BDateTime() } }
	};
	
	BNetworkCookie cookie;

	for (uint32 i = 0; i < (sizeof(tests) / sizeof(Test)); i++) {
		NextSubTest();

		BUrl url(tests[i].url);
		cookie.ParseCookieString(tests[i].cookieString, url);

		CPPUNIT_ASSERT(tests[i].expected.valid == cookie.IsValid());

		if (!tests[i].expected.valid)
			continue;

		CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected.name), cookie.Name());
		CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected.value), cookie.Value());
		CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected.domain),
			cookie.Domain());
		CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected.path), cookie.Path());
		CPPUNIT_ASSERT(tests[i].expected.secure == cookie.Secure());
		CPPUNIT_ASSERT(tests[i].expected.httponly == cookie.HttpOnly());
		CPPUNIT_ASSERT(tests[i].expected.session == cookie.IsSessionCookie());

		if (!cookie.IsSessionCookie())
			CPPUNIT_ASSERT_EQUAL(tests[i].expected.expire.Time_t(),
				cookie.ExpirationDate());
	}
}
예제 #11
0
void
CookieTest::PathMatchingTest()
{
	const BUrl url("http://testsuites.opera.com/cookies/302/302.php");
	const BUrl url1("http://testsuites.opera.com/cookies/302-5.php");
	const BUrl url2("http://testsuites.opera.com/cookies/302/302-3.php");
	const BUrl url3("http://testsuites.opera.com/cookies/302/sub/302-4.php");
	const BUrl url4("http://testsuites.opera.com/cookies/302-2/302-6.php");
	BNetworkCookie cookie;
	status_t result;

	BString bigData("302-24=1; Path=\"/cookies/302/");
	for (int i = 0; i < 1500; i++)
		bigData << "abcdefghijklmnopqrstuvwxyz";
	bigData << "\";";

	struct Test {
		const char* cookieString;
		bool canSet;
		bool url1;
		bool url2;
		bool url3;
		bool url4;
	};

	const Test tests[] = {
		{ "302-01=1; Path=\"/\"",
			true, true, true, true, true },
		{ "302-02=1; Path=\"/cookies\"",
			true, true, true, true, true },
		{ "302-03=1; Path=\"/cookies/\"",
			true, true, true, true, true },
		{ "302-04=1; Path=\"/cookies/302\"",
			true, false, true, true, true },
		{ "302-05=1; Path=\"/cookies/302/\"",
			true, false, true, true, false },
		{ "302-06=1; Path=\"/cookies/302/.\"",
			false, false, false, false, false },
		{ "302-07=1; Path=\"/cookies/302/../302\"",
			false, false, false, false, false },
		{ "302-08=1; Path=\"/cookies/302/../302-2\"",
			false, false, false, false, false },
		{ "302-09=1; Path=\"/side\"",
			false, false, false, false, false },
		{ "302-10=1; Path=\"/cookies/302-2\"",
			true, false, false, false, true },
		{ "302-11=1; Path=\"/cookies/302-2/\"",
			true, false, false, false, true },
		{ "302-12=1; Path=\"sub\"",
			false, false, false, false, false },
		{ "302-13=1; Path=\"sub/\"",
			false, false, false, false, false },
		{ "302-14=1; Path=\".\"",
			false, false, false, false, false },
		{ "302-15=1; Path=\"/cookies/302/sub\"",
			true, false, false, true, false },
		{ "302-16=1; Path=\"/cookies/302/sub/\"",
			true, false, false, true, false },
		{ "302-17=1; Path=\"/cookies/302/sub/..\"",
			false, false, false, false, false },
		{ "302-18=1; Path=/",
			true, true, true, true, true },
		{ "302-19=1; Path=/ /",
			false, false, false, false, false },
		{ "302-20=1; Path=\"/",
			false, false, false, false, false },
		{ "302-21=1; Path=/\"",
			false, false, false, false, false },
		{ "302-22=1; Path=\\/",
			false, false, false, false, false },
		{ "302-23=1; Path=\n/",
			false, false, false, false, false },
		{ bigData,
			false, false, false, false, false },
	};

	for (unsigned int i = 0; i < sizeof(tests) / sizeof(Test); i++)
	{
		NextSubTest();

		result = cookie.ParseCookieString(tests[i].cookieString, url);

		CPPUNIT_ASSERT_EQUAL_MESSAGE("Allowed to set cookie",
			tests[i].canSet, result == B_OK);
		CPPUNIT_ASSERT_EQUAL(tests[i].url1, cookie.IsValidForUrl(url1));
		CPPUNIT_ASSERT_EQUAL(tests[i].url2, cookie.IsValidForUrl(url2));
		CPPUNIT_ASSERT_EQUAL(tests[i].url3, cookie.IsValidForUrl(url3));
		CPPUNIT_ASSERT_EQUAL(tests[i].url4, cookie.IsValidForUrl(url4));
	}
}
예제 #12
0
void
CookieTest::ExpireParsingTest()
{
	BUrl url("http://testsuites.opera.com/cookies/301.php");
	BNetworkCookie cookie;
	status_t result;

	BString bigData("301-16=1; Expires=\"");
	for (int i = 0; i < 1500; i++)
		bigData << "abcdefghijklmnopqrstuvwxyz";
	bigData << "\";";

	struct Test {
		const char* cookieString;
		bool canParse;
		bool sessionOnly;
		bool expired;
	};

	Test tests[] = {
		{ "301-01=1; Expires=\"notAValidValue\";",
			true, true, false }, // Obviously invalid date
		{ "301-02=1; Expires=\"Wed, 08-Nov-2035 01:04:33\";",
			true, false, false }, // Valid date
		{ "301-03=1; Expires=\"Tue, 19-Jan-2038 03:14:06\";",
			true, false, false }, // Valid date, after year 2038 time_t overflow
		{ "301-04=1; Expires=\"Fri, 13-Dec-1901 20:45:51\";",
			true, false, true }, // Valid date, in the past
		{ "301-05=1; Expires=\"Thu, 33-Nov-2035 01:04:33\";",
			true, true, false }, // Invalid day
		{ "301-06=1; Expires=\"Wed, 08-Siz-2035 01:04:33\";",
			true, true, false }, // Invalid month
		{ "301-07=1; Expires=\"Wed, 08-Nov-9035 01:04:33\";",
			true, false, false }, // Very far in the future
			// NOTE: Opera testsuite considers it should be a session cookie.
		{ "301-08=1; Expires=\"Wed, 08-Nov-2035 75:04:33\";",
			true, true, false }, // Invalid hour
		{ "301-09=1; Expires=\"Wed, 08-Nov-2035 01:75:33\";",
			true, true, false }, // Invalid minute
		{ "301-10=1; Expires=\"Wed, 08-Nov-2035 01:04:75\";",
			true, true, false }, // Invalid second
		{ "301-11=1; Expires=\"XXX, 08-Nov-2035 01:04:33\";",
			true, true, false }, // Invalid weekday
		{ "301-12=1; Expires=\"Thu, XX-Nov-2035 01:04:33\";",
			true, true, false }, // Non-digit day
		{ "301-13=1; Expires=\"Thu, 08-Nov-XXXX 01:04:33\";",
			true, true, false }, // Non-digit year
		{ "301-14=1; Expires=\"Thu, 08-Nov-2035 XX:XX:33\";",
			true, true, false }, // Non-digit hour and minute
		{ "301-15=1; Expires=\"Thu, 08-Nov-2035 01:04:XX\";",
			true, true, false }, // Non-digit second
		{ bigData.String(),
			true, true, false }, // Very long invalid string
			// NOTE: Opera doesn't register the cookie at all.
		{ "301-17=1; Expires=\"Thu, 99999-Nov-2035 01:04:33\";",
			true, true, false }, // Day with many digits
		{ "301-18=1; Expires=\"Thu, 25-Nov-99999 01:04:33\";",
			true, true, false }, // Year with many digits
			// NOTE: Opera tests 301-17 twice and misses this test.
		{ "301-19=1; Expires=\"Thu, 25-Nov-2035 99999:04:33\";",
			true, true, false }, // Hour with many digits
		{ "301-20=1; Expires=\"Thu, 25-Nov-2035 01:99999:33\";",
			true, true, false }, // Minute with many digits
		{ "301-21=1; Expires=\"Thu, 25-Nov-2035 01:04:99999\";",
			true, true, false }, // Second with many digits
		{ "301-22=1; Expires=\"99999999999999999999\";",
			true, true, false }, // Huge number
		{ "301-23=1; Expires=\"Fri, 13-Dec-101 20:45:51\";",
			true, false, true }, // Very far in the past
		{ "301-24=1; EXPiReS=\"Wed, 08-Nov-2035 01:04:33\";",
			true, false, false }, // Case insensitive key parsing
		{ "301-25=1; Expires=Wed, 08-Nov-2035 01:04:33\";",
			true, true, false }, // Missing opening quote
			// NOTE: unlike Opera, we accept badly quoted values for cookie
			// attributes. This allows to handle unquoted values from the early
			// cookie spec properly. However, a date with a quote inside it
			// should not be accepted, so this will be a session cookie.
		{ "301-26=1; Expires=\"Wed, 08-Nov-2035 01:04:33;",
			true, true, false }, // Missing closing quote
		{ "301-27=1; Expires:\"Wed, 08-Nov-2035 01:04:33\";",
			true, true, false }, // Uses : instead of =
			// NOTE: unlike Opera, we allow this as a cookie with a strange
			// name and no value
		{ "301-28=1; Expires;=\"Wed, 08-Nov-2035 01:04:33\";",
			true, true, false }, // Extra ; after name
		{ "301-29=1; Expired=\"Wed, 08-Nov-2035 01:04:33\";",
			true, true, false }, // Expired instead of Expires
		{ "301-30=1; Expires=\"Wed; 08-Nov-2035 01:04:33\";",
			true, true, false }, // ; in value
		{ "301-31=1; Expires=\"Wed,\\r\\n 08-Nov-2035 01:04:33\";",
			true, true, false }, // escaped newline in value
			// NOTE: Only here for completeness. This is what the Opera
			// testsuite sends in test 31, but I suspect they were trying to
			// test the following case.
		{ "301-31b=1; Expires=\"Wed,\r\n 08-Nov-2035 01:04:33\";",
			true, false, false }, // newline in value
			// NOTE: This can't really happen when we get cookies from HTTP
			// headers. It could happen when the cookie is set from meta html
			// tags or from JS.
	};

	for (unsigned int i = 0; i < sizeof(tests) / sizeof(Test); i++)
	{
		NextSubTest();

		result = cookie.ParseCookieString(tests[i].cookieString, url);
		CPPUNIT_ASSERT_EQUAL_MESSAGE("Cookie can be parsed",
			tests[i].canParse, result == B_OK);
		CPPUNIT_ASSERT_EQUAL_MESSAGE("Cookie is session only",
			tests[i].sessionOnly, cookie.IsSessionCookie());
		CPPUNIT_ASSERT_EQUAL_MESSAGE("Cookie has expired",
			tests[i].expired, cookie.ShouldDeleteNow());
	}
}
예제 #13
0
void stressTest(int32 domainNumber, int32 totalCookies, char** flat, ssize_t* size)
{
	char **domains = new char*[domainNumber];
	
	cout << "Creating random domains" << endl;
	srand(time(NULL));
	for (int32 i = 0; i < domainNumber; i++) {
		int16 charNum = (rand() % 16) + 1;
		
		domains[i] = new char[charNum + 5];
		
		// Random domain
		for (int32 c = 0; c < charNum; c++) 
			domains[i][c] = (rand() % 26) + 'a';
		
		domains[i][charNum] = '.';
		
		// Random tld
		for (int32 c = 0; c < 3; c++) 
			domains[i][charNum+1+c] = (rand() % 26) + 'a';
			
		domains[i][charNum+4] = 0;
	}
	
	BNetworkCookieJar j;
	BStopWatch* watch = new BStopWatch("Cookie insertion");
	for (int32 i = 0; i < totalCookies; i++) {
		BNetworkCookie c;
		int16 domain = (rand() % domainNumber);
		BString name("Foo");
		name << i;
		
		c.SetName(name);
		c.SetValue("Bar");
		c.SetDomain(domains[domain]);
		c.SetPath("/");
		
		j.AddCookie(c);
	}
	delete watch;
	
	BNetworkCookie* c;
	int16 domain = (rand() % domainNumber);
	BString host("http://");
	host << domains[domain] << "/";
	
	watch = new BStopWatch("Cookie filtering");
	BUrl url(host);
	int32 count = 0;
	for (BNetworkCookieJar::UrlIterator it(j.GetUrlIterator(url)); (c = it.Next()); ) {
	//for (BNetworkCookieJar::Iterator it(j.GetIterator()); c = it.Next(); ) {
		count++;
	}
	delete watch;
	cout << "Count for " << host << ": " << count << endl;
	
	
	cout << "Flat view of cookie jar is " << j.FlattenedSize() << " bytes large." << endl;
	*flat = new char[j.FlattenedSize()];
	*size = j.FlattenedSize();
	
	if (j.Flatten(*flat, j.FlattenedSize()) == B_OK)
		cout << "Flatten() success!" << endl;
	else
		cout << "Flatten() error!" << endl;
	
	delete[] domains;
}
예제 #14
0
void explodeImplodeTest()
{
	uint8 testIndex;
	BNetworkCookie cookie;

	for (testIndex = 0; testIndex < (sizeof(kTestExplode) / sizeof(ExplodeTest)); testIndex++)
	{
		cookie.ParseCookieString(kTestExplode[testIndex].cookieString);

		ASSERT(testIndex, BString(kTestExplode[testIndex].expected.name) == BString(cookie.Name()));
		ASSERT(testIndex, BString(kTestExplode[testIndex].expected.value) == BString(cookie.Value()));
		ASSERT(testIndex, BString(kTestExplode[testIndex].expected.domain) == BString(cookie.Domain()));
		ASSERT(testIndex, BString(kTestExplode[testIndex].expected.path) == BString(cookie.Path()));
		ASSERT(testIndex, kTestExplode[testIndex].expected.secure == cookie.Secure());
		ASSERT(testIndex, kTestExplode[testIndex].expected.discard == cookie.Discard());
		ASSERT(testIndex, kTestExplode[testIndex].expected.session == cookie.IsSessionCookie());

		if (!cookie.IsSessionCookie())
			ASSERT(testIndex, kTestExplode[testIndex].expected.maxAge == cookie.MaxAge());
	}
}