示例#1
0
void Crypto::Encrypt( const SimpleString& Plaintext, const Array< SimpleString >& Keys, Array< char >& OutCiphertext )
{
	Array< char > PlaintextArray;
	Array< char > KeyArray;
	Array< char > CiphertextArray;

	Plaintext.FillArray( PlaintextArray );

	ConstructKeyFromStrings( Keys, KeyArray );

	Encrypt( PlaintextArray, KeyArray, OutCiphertext );
}
示例#2
0
SimpleString SimpleString::URLEncodeUTF8() const
{
	// First, encode all the usual stuff...
	const SimpleString BasicEncoded = URLEncode();

	Array<char> EncodedArray;
	BasicEncoded.FillArray( EncodedArray, true );

#define PERCENT_ENCODE_CHAR														\
	{																			\
		const char			c				= EncodedArray[ CharIter ];			\
		const uint8			UnsignedChar	= static_cast<uint8>( c );			\
		const SimpleString	Encoded			= PrintF( "%%%02X", UnsignedChar );	\
		const char* const	pEncoded		= Encoded.CStr();					\
		EncodedArray[ CharIter ] = *pEncoded;									\
		EncodedArray.Insert( *( pEncoded + 1 ), CharIter + 1 );					\
		EncodedArray.Insert( *( pEncoded + 2 ), CharIter + 2 );					\
		CharIter += 3;															\
	}

	for( uint CharIter = 0; CharIter < EncodedArray.Size(); )
	{
		const char c = EncodedArray[ CharIter ];
		if( ( c & UTF8_2BYTEMASKHIGH ) == UTF8_2BYTEMARKER )
		{
			// Encode c and following 2 byte
			PERCENT_ENCODE_CHAR;
			PERCENT_ENCODE_CHAR;
		}
		else if( ( c & UTF8_3BYTEMASKHIGH ) == UTF8_3BYTEMARKER )
		{
			// Encode c and following 2 bytes
			PERCENT_ENCODE_CHAR;
			PERCENT_ENCODE_CHAR;
			PERCENT_ENCODE_CHAR;
		}
		else if( ( c & UTF8_4BYTEMASKHIGH ) == UTF8_4BYTEMARKER )
		{
			// Encode c and following 3 bytes
			PERCENT_ENCODE_CHAR;
			PERCENT_ENCODE_CHAR;
			PERCENT_ENCODE_CHAR;
			PERCENT_ENCODE_CHAR;
		}
		else
		{
			++CharIter;
		}
	}

	SimpleString RetVal = EncodedArray;
	return RetVal;
}
示例#3
0
void ConfigParser::Parse( const IDataStream& Stream )
{
	Array< SToken >	Tokens;
	SToken			Token;
	Token.m_TokenType						= SToken::ET_Name;
	char			StrMark					= 0;	// Stores the character (either ' or ") that opened a string
	SToken			MacroToken;
	List<int>		ArrayCounters;
	Array<char>		CounterCharArray;
	int				LineCount				= 1;

	for(;;)
	{
		char c = Stream.ReadInt8();

		// Skip the UTF-8 byte order mark if present.
		if( UTF8_BOM_0 == static_cast<byte>( c ) )
		{
			CHECK( UTF8_BOM_1 == static_cast<byte>( Stream.ReadInt8() ) );
			CHECK( UTF8_BOM_2 == static_cast<byte>( Stream.ReadInt8() ) );
			c = Stream.ReadInt8();
		}

		if( Stream.EOS() )
		{
			if( Token.m_TokenString.Empty() )
			{
				Token.m_TokenType = SToken::ET_None;
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s\n", SToken::m_TokenNames[ Token.m_TokenType ] );
			}
			else
			{
				Token.m_TokenString.PushBack( '\0' );
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();
			}

			break;
		}

		if( c == '&' )
		{
			if( Token.m_TokenType == SToken::ET_Name )
			{
				// Increment the current counter and add it to the current name.
				ASSERT( ArrayCounters.Size() > 0 );
				List<int>::Iterator CounterIter = ArrayCounters.Back();
				( *CounterIter )++;
				SimpleString CounterString = SimpleString::PrintF( "%d", *CounterIter );
				CounterCharArray.Clear();
				CounterString.FillArray( CounterCharArray );
				Token.m_TokenString.Append( CounterCharArray );
			}
			else if( Token.m_TokenType == SToken::ET_None )
			{
				// Add a new counter
				// Push a counter token that will be replaced with the count int later.
				ArrayCounters.PushBack( -1 );
				Token.m_TokenType = SToken::ET_Counter;
			}
			else if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				WARNDESC( "Unexpected character '&' in token." );
			}
		}
		else if( c == '^' )
		{
			if( Token.m_TokenType == SToken::ET_Name )
			{
				// Add the current counter to the current name.
				ASSERT( ArrayCounters.Size() > 0 );
				List<int>::Iterator CounterIter = ArrayCounters.Back();
				ASSERT( ( *CounterIter ) >= 0 );
				SimpleString CounterString = SimpleString::PrintF( "%d", *CounterIter );
				CounterCharArray.Clear();
				CounterString.FillArray( CounterCharArray );
				Token.m_TokenString.Append( CounterCharArray );
			}
			else if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				WARNDESC( "Unexpected character '^' in token." );
			}
		}
		else if( c == ' ' || c == '\t' )
		{
			switch( Token.m_TokenType )
			{
			case SToken::ET_None:
			case SToken::ET_Equals:
				// Ignore whitespace
				break;
			case SToken::ET_Name:
			case SToken::ET_Context:
			case SToken::ET_Macro:
				if( Token.m_TokenString.Empty() )
				{
					// If the name is empty, ignore whitespace (before the name)
				}
				else
				{
					// Close current token, push it, and expect an equals

					// If we're closing a macro, save it as such
					if( Token.m_TokenType == SToken::ET_Macro )
					{
						MacroToken = Token;
					}

					Token.m_TokenString.PushBack( '\0' );
					Tokens.PushBack( Token );
					DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
					Token.m_TokenString.Clear();

					if( Token.m_TokenType == SToken::ET_Name )
					{
						Token.m_TokenType = SToken::ET_Equals;
					}
					else if( Token.m_TokenType == SToken::ET_Context || Token.m_TokenType == SToken::ET_Macro )
					{
						Token.m_TokenType = SToken::ET_Name;
					}
				}
				break;
			case SToken::ET_Bool:
			case SToken::ET_Int:
			case SToken::ET_Float:
				// Close current token, push it, and expect nothing
				Token.m_TokenString.PushBack( '\0' );
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();

				Token.m_TokenType = SToken::ET_None;
				break;
			case SToken::ET_String:
				Token.m_TokenString.PushBack( c );
				break;
			default:
				WARNDESC( "Unexpected token" );
				break;
			}
		}
		else if( c == '=' )
		{
			switch( Token.m_TokenType )
			{
			case SToken::ET_Name:
				// Close current token, push it and an equals
				Token.m_TokenString.PushBack( '\0' );
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();

				Token.m_TokenType = SToken::ET_Equals;
				DEBUGCATPRINTF( "Core", 2, "%s\n", SToken::m_TokenNames[ Token.m_TokenType ] );
				Tokens.PushBack( Token );

				Token.m_TokenType = SToken::ET_None;
				break;
			case SToken::ET_Equals:
				// Already expecting =, just push it
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s\n", SToken::m_TokenNames[ Token.m_TokenType ] );

				Token.m_TokenType = SToken::ET_None;
				break;
			case SToken::ET_String:
				Token.m_TokenString.PushBack( c );
				break;
			default:
				WARNDESC( "Unexpected token" );
				break;
			}
		}
		else if( c == '#' )
		{
			// # starts a comment

			// Allow # inside a string
			if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				c = Stream.ReadInt8();
				
				if( c == '!' )	// #! and !# indicate the start and end of block comments
				{
					while( !Stream.EOS() )
					{
						if( Stream.ReadInt8() == '!' && Stream.ReadInt8() == '#' )
						{
							break;
						}
					}
				}
				else
				{
					// Read to end of line
					while( c != '\n' && c!= '\v' && !Stream.EOS() )	// Vertical tab stupidity again
					{
						c = Stream.ReadInt8();
					}

					// Change the context because we're on a new line
					Token.m_TokenType = SToken::ET_Name;

					++LineCount;
				}
			}
		}
		else if( c == '\\' && Token.m_TokenType == SToken::ET_String )
		{
			// Escape sequence, intended to insert linebreaks (and maybe other things in the future)
			// Config string escape sequences are not the same as C++ escape sequences. They can be
			// \\, \n, \?, \", or \xx (where x are hex digits, to specify any character by hex).

			char next = Stream.ReadInt8();
			if( next == 'n' )
			{
				Token.m_TokenString.PushBack( '\n' );
			}
			else if( next == '\"' )
			{
				Token.m_TokenString.PushBack( '\"' );
			}
			else if( next == '\\' )
			{
				Token.m_TokenString.PushBack( '\\' );
			}
			else if( next == 'x' )
			{
				char Hex = 0;
				for( uint HexIndex = 0; HexIndex < 2; ++HexIndex )
				{
					next = Stream.ReadInt8();
					ASSERT( IsHex( next ) );
					Hex = ( Hex << 4 ) | GetHex( next );
				}
				Token.m_TokenString.PushBack( Hex );
			}
			else if( next == 'u' )
			{
				// First, extract a unicode code point (e.g. \u00d7 for U+00D7)
				// NOTE: This only support the first Unicode plane, and is strict about
				// using four characters, so \ud7 is not a valid substitute for \u00d7.
				unicode_t CodePoint = 0;
				for( uint UnicodeIndex = 0; UnicodeIndex < 4; ++UnicodeIndex )
				{
					next = Stream.ReadInt8();
					ASSERT( IsHex( next ) );
					CodePoint = ( CodePoint << 4 ) | GetHex( next );
				}

				// Then convert the two-byte code point to UTF-8.
				Array<unicode_t> CodePointArray;
				CodePointArray.PushBack( CodePoint );
				const SimpleString UTF8String = SimpleString::SetUTF8( CodePointArray );

				for( uint CharIndex = 0; CharIndex < UTF8String.Length(); ++CharIndex )
				{
					const char NextChar = UTF8String.GetChar( CharIndex );
					Token.m_TokenString.PushBack( NextChar );
				}
			}
			else
			{
				PRINTF( "Unrecognized escape sequence \\%c at line %d\n", next, LineCount );
				WARNDESC( "Unrecognized escape sequence" );
			}
		}
		else if( c == 0x0d )
		{
			// DOS linebreak is 0D 0A, so ignore and expect \n to follow
		}
		else if( c == '\0' )
		{
			// Don't know how these are getting in either, but ignore them
		}
		else if( c == '\n' || c == '\v' )
		{
			if( Token.m_TokenType == SToken::ET_Macro )
			{
				MacroToken = Token;
			}

			// Dunno how vertical tabs are getting in, but treat them as linebreaks
			if( Token.m_TokenString.Empty() )
			{
				if( Token.m_TokenType != SToken::ET_Counter )
				{
					Token.m_TokenType = SToken::ET_None;
				}
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s\n", SToken::m_TokenNames[ Token.m_TokenType ] );

				Token.m_TokenType = SToken::ET_Name;
			}
			else
			{
				Token.m_TokenString.PushBack( '\0' );
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();

				Token.m_TokenType = SToken::ET_Name;
			}

			++LineCount;
		}
		else if( c == '[' )
		{
			if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				// We should only ever open a context when we're expecting a name
				ASSERT( Token.m_TokenType == SToken::ET_Name );
				Token.m_TokenType = SToken::ET_Context;

				// Opening a new context, clear the macro token.
				MacroToken = SToken();
			}
		}
		else if( c == ']' )
		{
			// If we've already closed the context, ignore; else, push token
			if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				ASSERT( Token.m_TokenType == SToken::ET_Context );
				Token.m_TokenString.PushBack( '\0' );
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();
			}
		}
		else if( c == '@' )
		{
			if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				// We should only ever declare or insert a macro when we're expecting a name
				ASSERT( Token.m_TokenType == SToken::ET_Name );
				c = Stream.ReadInt8();
				if( c == '@' )
				{
					// @@... means we're inserting the current macro into a name

					// Make sure there is a current macro. If this fails, a macro probably
					// wasn't opened in the current context.
					ASSERT( MacroToken.m_TokenString.Size() > 0 );

					const uint MacroLength = MacroToken.m_TokenString.Size();
					for( uint MacroIndex = 0; MacroIndex < MacroLength; ++MacroIndex )
					{
						Token.m_TokenString.PushBack( MacroToken.m_TokenString[ MacroIndex ] );
					}
				}
				else
				{
					// @... means we're declaring a new macro
					Token.m_TokenType = SToken::ET_Macro;
					if( c == ' ' || c == '\t' )
					{
						// Ignore whitespace at the front of macro
					}
					else
					{
						Token.m_TokenString.PushBack( c );
					}
				}
			}
		}
		else
		{
			bool ClosedString = false;
			InnerParse( c, StrMark, Token.m_TokenString, LineCount, Token.m_TokenType, &ClosedString );
			if( ClosedString )
			{
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();
				Token.m_TokenType = SToken::ET_None;
			}
		}
	}

	SimpleString Context = "";

	// Tokens are made, now create config vars
	for( uint i = 0; i < Tokens.Size(); ++i )
	{
		SToken& NameToken = Tokens[i];
		SimpleString Name = "";
		const char* ValueString = NULL;
		if( NameToken.m_TokenType == SToken::ET_Name )
		{
			Name = NameToken.m_TokenString.GetData();
			ASSERT( Tokens[ i + 1 ].m_TokenType == SToken::ET_Equals );

			SToken& ValueToken = Tokens[ i + 2 ];
			ValueString = ValueToken.m_TokenString.GetData();

			if( Context != "" )
			{
				CATPRINTF( "Core", 2, "%s:", Context.CStr() );
			}
			CATPRINTF( "Core", 2, "%s: %s: %s\n", Name.CStr(), SToken::m_TokenNames[ ValueToken.m_TokenType ], ValueString );

			switch( ValueToken.m_TokenType )
			{
			case SToken::ET_Bool:
				{
					// Just use the first character to determine truth
					bool Value = false;
					char first = ValueString[0];
					if( first == 't' || first == 'T' )
					{
						Value = true;
					}
					ConfigManager::SetBool( Name, Value, Context );
				}
				break;
			case SToken::ET_Int:
				{
					int Value = atoi( ValueString );
					ConfigManager::SetInt( Name, Value, Context );
				}
				break;
			case SToken::ET_Counter:
				{
					List<int>::Iterator NextCounterIter = ArrayCounters.Front();
					( *NextCounterIter )++;	// Add one to the last value we incremented, and that's the total for this array
					ConfigManager::SetInt( Name, *NextCounterIter, Context );
					ArrayCounters.PopFront();
				}
				break;
			case SToken::ET_Float:
				{
					float Value = (float)atof( ValueString );
					ConfigManager::SetFloat( Name, Value, Context );
				}
				break;
			case SToken::ET_String:
				{
					// Make a permanent copy of the string
					uint Length = (uint)strlen( ValueString );
					char* pString = new char[ Length + 1];
					memcpy_s( pString, Length + 1, ValueString, Length );
					pString[ Length ] = '\0';
					StringManager::AddString( StringManager::ESL_Permanent, pString );

					ConfigManager::SetString( Name, pString, Context );
				}

				break;
			default:
				WARNDESC( "Unexpected token" );
				break;
			}

			i += 2;
		}
		else if( NameToken.m_TokenType == SToken::ET_Context )
		{
			Context = NameToken.m_TokenString.GetData();
			//CATPRINTF( "Core", 2, "Pushed context %s\n", Context.CStr() );
		}
		else
		{
			DEBUGCATPRINTF( "Core", 2, "Skipped unexpected token %s (expected ET_Name)\n", SToken::m_TokenNames[ NameToken.m_TokenType ] );
		}
	}

	// Clean up
	for( uint i = 0; i < Tokens.Size(); ++i )
	{
		Tokens[i].m_TokenString.Clear();
	}
	Tokens.Clear();
}