/*************************************************************************** * PacketReader.cs * ------------------- * begin : May 1, 2002 * copyright : (C) The RunUO Software Team * email : info@runuo.com * * $Id$ * ***************************************************************************/ /*************************************************************************** * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * ***************************************************************************/ using System; using System.Text; using System.IO; namespace Server.Network { public class PacketReader { private int m_Index; public PacketReader( byte[] data, int size, bool fixedSize ) { Buffer = data; Size = size; m_Index = fixedSize ? 1 : 3; } public byte[] Buffer { get; } public int Size { get; } public void Trace( NetState state ) { try { using ( StreamWriter sw = new StreamWriter( "Packets.log", true ) ) { byte[] buffer = Buffer; if ( buffer.Length > 0 ) sw.WriteLine( "Client: {0}: Unhandled packet 0x{1:X2}", state, buffer[0] ); using ( MemoryStream ms = new MemoryStream( buffer ) ) Utility.FormatBuffer( sw, ms, buffer.Length ); sw.WriteLine(); sw.WriteLine(); } } catch { } } public int Seek( int offset, SeekOrigin origin ) { switch ( origin ) { case SeekOrigin.Begin: m_Index = offset; break; case SeekOrigin.Current: m_Index += offset; break; case SeekOrigin.End: m_Index = Size - offset; break; } return m_Index; } public int ReadInt32() { if ( (m_Index + 4) > Size ) return 0; return (Buffer[m_Index++] << 24) | (Buffer[m_Index++] << 16) | (Buffer[m_Index++] << 8) | Buffer[m_Index++]; } public short ReadInt16() { if ( (m_Index + 2) > Size ) return 0; return (short)((Buffer[m_Index++] << 8) | Buffer[m_Index++]); } public byte ReadByte() { if ( (m_Index + 1) > Size ) return 0; return Buffer[m_Index++]; } public uint ReadUInt32() { if ( (m_Index + 4) > Size ) return 0; return (uint)((Buffer[m_Index++] << 24) | (Buffer[m_Index++] << 16) | (Buffer[m_Index++] << 8) | Buffer[m_Index++]); } public ushort ReadUInt16() { if ( (m_Index + 2) > Size ) return 0; return (ushort)((Buffer[m_Index++] << 8) | Buffer[m_Index++]); } public sbyte ReadSByte() { if ( (m_Index + 1) > Size ) return 0; return (sbyte)Buffer[m_Index++]; } public bool ReadBoolean() { if ( (m_Index + 1) > Size ) return false; return ( Buffer[m_Index++] != 0 ); } public string ReadUnicodeStringLE() { StringBuilder sb = new StringBuilder(); int c; while ( (m_Index + 1) < Size && (c = (Buffer[m_Index++] | (Buffer[m_Index++] << 8))) != 0 ) sb.Append( (char)c ); return sb.ToString(); } public string ReadUnicodeStringLESafe( int fixedLength ) { int bound = m_Index + (fixedLength << 1); int end = bound; if ( bound > Size ) bound = Size; StringBuilder sb = new StringBuilder(); int c; while ( (m_Index + 1) < bound && (c = (Buffer[m_Index++] | (Buffer[m_Index++] << 8))) != 0 ) { if ( IsSafeChar( c ) ) sb.Append( (char)c ); } m_Index = end; return sb.ToString(); } public string ReadUnicodeStringLESafe() { StringBuilder sb = new StringBuilder(); int c; while ( (m_Index + 1) < Size && (c = (Buffer[m_Index++] | (Buffer[m_Index++] << 8))) != 0 ) { if ( IsSafeChar( c ) ) sb.Append( (char)c ); } return sb.ToString(); } public string ReadUnicodeStringSafe() { StringBuilder sb = new StringBuilder(); int c; while ( (m_Index + 1) < Size && (c = ((Buffer[m_Index++] << 8) | Buffer[m_Index++])) != 0 ) { if ( IsSafeChar( c ) ) sb.Append( (char)c ); } return sb.ToString(); } public string ReadUnicodeString() { StringBuilder sb = new StringBuilder(); int c; while ( (m_Index + 1) < Size && (c = ((Buffer[m_Index++] << 8) | Buffer[m_Index++])) != 0 ) sb.Append( (char)c ); return sb.ToString(); } public bool IsSafeChar( int c ) { return ( c >= 0x20 && c < 0xFFFE ); } public string ReadUTF8StringSafe( int fixedLength ) { if ( m_Index >= Size ) { m_Index += fixedLength; return string.Empty; } int bound = m_Index + fixedLength; //int end = bound; if ( bound > Size ) bound = Size; int count = 0; int index = m_Index; int start = m_Index; while ( index < bound && Buffer[index++] != 0 ) ++count; index = 0; byte[] buffer = new byte[count]; int value = 0; while ( m_Index < bound && (value = Buffer[m_Index++]) != 0 ) buffer[index++] = (byte)value; string s = Utility.UTF8.GetString( buffer ); bool isSafe = true; for ( int i = 0; isSafe && i < s.Length; ++i ) isSafe = IsSafeChar( (int) s[i] ); m_Index = start + fixedLength; if ( isSafe ) return s; StringBuilder sb = new StringBuilder( s.Length ); for ( int i = 0; i < s.Length; ++i ) if ( IsSafeChar( (int) s[i] ) ) sb.Append( s[i] ); return sb.ToString(); } public string ReadUTF8StringSafe() { if ( m_Index >= Size ) return string.Empty; int count = 0; int index = m_Index; while ( index < Size && Buffer[index++] != 0 ) ++count; index = 0; byte[] buffer = new byte[count]; int value = 0; while ( m_Index < Size && (value = Buffer[m_Index++]) != 0 ) buffer[index++] = (byte)value; string s = Utility.UTF8.GetString( buffer ); bool isSafe = true; for ( int i = 0; isSafe && i < s.Length; ++i ) isSafe = IsSafeChar( (int) s[i] ); if ( isSafe ) return s; StringBuilder sb = new StringBuilder( s.Length ); for ( int i = 0; i < s.Length; ++i ) { if ( IsSafeChar( (int) s[i] ) ) sb.Append( s[i] ); } return sb.ToString(); } public string ReadUTF8String() { if ( m_Index >= Size ) return string.Empty; int count = 0; int index = m_Index; while ( index < Size && Buffer[index++] != 0 ) ++count; index = 0; byte[] buffer = new byte[count]; int value = 0; while ( m_Index < Size && (value = Buffer[m_Index++]) != 0 ) buffer[index++] = (byte)value; return Utility.UTF8.GetString( buffer ); } public string ReadString() { StringBuilder sb = new StringBuilder(); int c; while ( m_Index < Size && (c = Buffer[m_Index++]) != 0 ) sb.Append( (char)c ); return sb.ToString(); } public string ReadStringSafe() { StringBuilder sb = new StringBuilder(); int c; while ( m_Index < Size && (c = Buffer[m_Index++]) != 0 ) { if ( IsSafeChar( c ) ) sb.Append( (char)c ); } return sb.ToString(); } public string ReadUnicodeStringSafe( int fixedLength ) { int bound = m_Index + (fixedLength << 1); int end = bound; if ( bound > Size ) bound = Size; StringBuilder sb = new StringBuilder(); int c; while ( (m_Index + 1) < bound && (c = ((Buffer[m_Index++] << 8) | Buffer[m_Index++])) != 0 ) { if ( IsSafeChar( c ) ) sb.Append( (char)c ); } m_Index = end; return sb.ToString(); } public string ReadUnicodeString( int fixedLength ) { int bound = m_Index + (fixedLength << 1); int end = bound; if ( bound > Size ) bound = Size; StringBuilder sb = new StringBuilder(); int c; while ( (m_Index + 1) < bound && (c = ((Buffer[m_Index++] << 8) | Buffer[m_Index++])) != 0 ) sb.Append( (char)c ); m_Index = end; return sb.ToString(); } public string ReadStringSafe( int fixedLength ) { int bound = m_Index + fixedLength; int end = bound; if ( bound > Size ) bound = Size; StringBuilder sb = new StringBuilder(); int c; while ( m_Index < bound && (c = Buffer[m_Index++]) != 0 ) { if ( IsSafeChar( c ) ) sb.Append( (char)c ); } m_Index = end; return sb.ToString(); } public string ReadString( int fixedLength ) { int bound = m_Index + fixedLength; int end = bound; if ( bound > Size ) bound = Size; StringBuilder sb = new StringBuilder(); int c; while ( m_Index < bound && (c = Buffer[m_Index++]) != 0 ) sb.Append( (char)c ); m_Index = end; return sb.ToString(); } } }