123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- unit sdlweb;
- {******************************************************************************}
- {
- $Id: sdlweb.pas,v 1.2 2005/01/02 19:03:15 savage Exp $
-
- }
- { }
- { Borland Delphi SDL_Net - A x-platform network library for use with SDL.}
- { Conversion of the Simple DirectMedia Layer Network Headers }
- { }
- { Portions created by Sam Lantinga <[email protected]> are }
- { Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga }
- { 5635-34 Springhouse Dr. }
- { Pleasanton, CA 94588 (USA) }
- { }
- { All Rights Reserved. }
- { }
- { The original files are : SDL_net.h }
- { }
- { The initial developer of this Pascal code was : }
- { Dean Ellis <[email protected]> }
- { }
- { Portions created by Dean Ellis are }
- { Copyright (C) 2000 - 2001 Dean Ellis. }
- { }
- { }
- { Contributor(s) }
- { -------------- }
- { }
- { }
- { Obtained through: }
- { Joint Endeavour of Delphi Innovators ( Project JEDI ) }
- { }
- { You may retrieve the latest version of this file at the Project }
- { JEDI home page, located at http://delphi-jedi.org }
- { }
- { The contents of this file are used with permission, subject to }
- { the Mozilla Public License Version 1.1 (the "License"); you may }
- { not use this file except in compliance with the License. You may }
- { obtain a copy of the License at }
- { http://www.mozilla.org/MPL/MPL-1.1.html }
- { }
- { Software distributed under the License is distributed on an }
- { "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
- { implied. See the License for the specific language governing }
- { rights and limitations under the License. }
- { }
- { Description }
- { ----------- }
- { }
- { }
- { }
- { }
- { }
- { }
- { }
- { Requires }
- { -------- }
- { sdl.pas and sdl_net.pas somehere in your search path }
- { }
- { Programming Notes }
- { ----------------- }
- { }
- { }
- { }
- { }
- { Revision History }
- { ---------------- }
- {
- $Log: sdlweb.pas,v $
- Revision 1.2 2005/01/02 19:03:15 savage
- Slight Bug fix due to stray closed comment ( Thanks Michalis Kamburelis )
- Revision 1.1 2004/12/31 00:30:12 savage
- Initial release of Dean's excellent SDL Web classes. Demo coming soon.
- }
- {******************************************************************************}
- interface
- uses
- SysUtils,
- sdl,
- sdl_net;
- const
- MAX_TIMEOUT = 5000;
- type
- TWebConnection = ( wcDefault, wcHTTP, wcFTP );
- TWebProgressEvent = procedure( Progress, Total : UInt32 ); cdecl;
- TSDLWebConnection = record
- Host : TIPAddress;
- HostName, Proxy : string;
- Port : UInt32;
- Socket : PTCPSocket;
- Type_ : TWebConnection;
- IsProxy : Boolean;
- ProxyUser, ProxyPassword : string;
- end;
- procedure SDLWeb_Init;
- procedure SDLWeb_Quit;
- // Connection Functions
- function SDLWeb_ConnectToSite( URL : string; AType : TWebConnection;
- var Connection : TSDLWebConnection ) : Boolean;
- function SDLWeb_ConnectToSiteViaProxy( URL, Proxy, Username, Password : string; AType : TWebConnection;
- var Connection : TSDLWebConnection ) : Boolean;
- function SDLWeb_Connected( var Connection : TSDLWebConnection ) : Boolean;
- procedure SDLWeb_Disconnect( var Connection : TSDLWebConnection );
- function SDLWeb_SendRequest( var Connection : TSDLWebConnection;
- Request : string ) : Boolean;
- function SDLWeb_ReadResponse( var Connection : TSDLWebConnection;
- var Response : string ) : UInt32;
- // Utility Functions
- function SDLWeb_IPToString( ip : TIPAddress ) : string;
- function SDLWeb_StringToIP( ip : string ) : TIPAddress;
- function SDLWeb_Pos( const SubString, Source : string; Count : SInt32 ) : SInt32;
- procedure SDLWeb_ParseURL( const url : string; var proto, user, pass, host, port, path : string );
- function SDLWeb_EncodeBase64( Value : string ) : string;
- function SDLWeb_DecodeBase64( Value : string ) : string;
- implementation
- const
- DefaultPorts : array[ TWebConnection ] of UInt32 = ( 80, 80, 21 );
- procedure SDLWeb_Init;
- begin
- SDLNet_Init;
- end;
- procedure SDLWeb_Quit;
- begin
- SDLNet_Quit;
- end;
- function SDLWeb_ConnectToSite( URL : string; AType : TWebConnection;
- var Connection : TSDLWebConnection ) : Boolean;
- var
- Protocol, User, Password, Host, Port, Path : string;
- begin
- Result := False;
- SDLWeb_ParseURL( URL, Protocol, User, Password, Host, Port, Path );
- Connection.IsProxy := False;
- Connection.HostName := Host;
- if SDLNet_ResolveHost( Connection.Host, PChar( Host ), DefaultPorts[ AType ] ) = 0 then
- begin
- Connection.Socket := SDLNet_TCP_Open( Connection.Host );
- Connection.Port := DefaultPorts[ AType ];
- if AType = wcDefault then
- begin
- if UpperCase( Protocol ) = 'HTTP' then
- Connection.Type_ := wcHTTP;
- if UpperCase( Protocol ) = 'FTP' then
- Connection.Type_ := wcFTP;
- end
- else
- Connection.Type_ := AType;
- Result := SDLWeb_Connected( Connection );
- end;
- end;
- function SDLWeb_ConnectToSiteViaProxy( URL, Proxy, Username, Password : string; AType : TWebConnection;
- var Connection : TSDLWebConnection ) : Boolean;
- begin
- Result := SDLWeb_ConnectToSite( Proxy, AType, Connection );
- if Result then
- begin
- Connection.Proxy := Proxy;
- Connection.HostName := URL;
- Connection.ProxyUser := Username;
- Connection.ProxyPassword := Password;
- Connection.IsProxy := True;
- end;
- end;
- function SDLWeb_Connected( var Connection : TSDLWebConnection ) : Boolean;
- begin
- Result := Connection.Socket <> nil;
- end;
- procedure SDLWeb_Disconnect( var Connection : TSDLWebConnection );
- begin
- SDLNet_TCP_Close( Connection.Socket );
- Connection.Socket := nil;
- end;
- function SDLWeb_SendRequest( var Connection : TSDLWebConnection;
- Request : string ) : Boolean;
- var
- Error, Len : UInt32;
- cdata : array[ 0..255 ] of char;
- begin
- StrPCopy( cdata, Request + #13#10 );
- Len := StrLen( cdata );
- Error := SDLNet_TCP_Send( Connection.Socket, @cdata, Len );
- Result := Error = Len;
- end;
- function SDLWeb_ReadResponse( var Connection : TSDLWebConnection;
- var Response : string ) : UInt32;
- var
- SocketSet : PSDLNet_SocketSet;
- function ReadLine : string;
- var
- Done : Boolean;
- C : Char;
- Error, SocketResult : Sint32;
- begin
- Result := EmptyStr;
- Done := False;
- SDLNet_TCP_AddSocket( SocketSet, Connection.Socket );
- while not Done do
- begin
- SocketResult := SDLNet_CheckSockets( SocketSet, MAX_TIMEOUT );
- if ( SocketResult <= 0 ) then
- begin
- Result := 'HTTP/1.1 400 Socket Timeout';
- Exit;
- end;
- if SDLNet_SocketReady( PSDLNet_GenericSocket( Connection.Socket ) ) then
- begin
- Error := SDLNet_TCP_Recv( Connection.Socket, @C, 1 );
- Done := ( Error < 1 );
- if C = #13 then
- else if C = #10 then
- Done := True
- else
- Result := Result + C;
- end;
- end;
- end;
- begin
- SocketSet := SDLNet_AllocSocketSet( 1 );
- try
- Response := ReadLine;
- Result := Length( Response );
- finally
- SDLNet_FreeSocketSet( SocketSet );
- end;
- end;
- function SDLWeb_IPToString( ip : TIPAddress ) : string;
- var
- IpAddress : UInt32;
- begin
- IpAddress := SDL_Swap32( ip.host );
- // output the IP address nicely
- Result := format( '%d.%d.%d.%d', [ IpAddress shr 24, ( IpAddress shr 16 ) and $000000FF,
- ( IpAddress shr 8 ) and $000000FF, IpAddress and $000000FF ] );
- end;
- function SDLWeb_StringToIP( ip : string ) : TIPAddress;
- begin
- SDLNet_ResolveHost( Result, PChar( ip ), 0 );
- end;
- function SDLWeb_Pos( const SubString, Source : string; Count : SInt32 ) : SInt32;
- var
- i, h, last : integer;
- u : string;
- begin
- u := Source;
- if count > 0 then
- begin
- result := length( Source );
- for i := 1 to count do
- begin
- h := pos( SubString, u );
- if h > 0 then
- u := copy( u, pos( SubString, u ) + 1, length( u ) )
- else
- begin
- u := '';
- inc( result );
- end;
- end;
- result := result - length( u );
- end
- else if count < 0 then
- begin
- last := 0;
- for i := length( Source ) downto 1 do
- begin
- u := copy( Source, i, length( Source ) );
- h := pos( SubString, u );
- if ( h <> 0 ) and ( h + i <> last ) then
- begin
- last := h + i - 1;
- inc( count );
- if count = 0 then
- BREAK;
- end;
- end;
- if count = 0 then
- result := last
- else
- result := 0;
- end
- else
- result := 0;
- end;
- procedure SDLWeb_ParseURL( const url : string; var proto, user, pass, host, port, path : string );
- var
- p, p2 : integer;
- s : string;
- begin
- host := '';
- path := '';
- proto := 'http';
- port := '80';
- p := Pos( '://', url );
- if p > 0 then
- begin
- // get protocol
- proto := Copy( url, 1, p - 1 );
- inc( p, 2 );
- s := copy( url, p + 1, length( url ) );
- // get path
- p := pos( '/', s );
- if p = 0 then
- p := length( s ) + 1;
- path := copy( s, p, length( s ) );
- s := copy( s, 1, p - 1 );
- // get host
- p := pos( ':', s );
- if p > Length( s ) then
- p := 0;
- p2 := SDLWeb_Pos( '@', s, -1 );
- if p2 > length( s ) then
- p2 := 0;
- if ( p = 0 ) and ( p2 = 0 ) then
- begin (* no user, password or port *)
- host := s;
- exit;
- end
- else if p2 < p then
- begin (* a port given *)
- port := copy( s, p + 1, length( s ) );
- host := copy( s, p2 + 1, p - p2 - 1 );
- if p2 = 0 then
- exit; (* no user, password *)
- s := copy( s, 1, p2 - 1 );
- end
- else
- begin
- host := copy( s, p2 + 1, length( s ) );
- s := copy( s, 1, p2 - 1 );
- end;
- p := pos( ':', s );
- if p = 0 then
- user := s
- else
- begin
- user := copy( s, 1, p - 1 );
- pass := copy( s, p + 1, length( s ) );
- end;
- end;
- end;
- function SDLWeb_EncodeBase64( Value : string ) : string;
- var
- Position, Total, Remaining : Integer;
- InBlock : array[ 0..2 ] of Byte;
- OutBlock : array[ 0..3 ] of Char;
- const
- Base64Chars : array[ 0..63 ] of Char = ( 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
- 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
- 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
- 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
- '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' );
- begin
- Result := '';
- Total := Length( Value );
- Position := 1;
- while True do
- begin
- Remaining := Total - Position + 1;
- if Remaining <= 0 then
- Break;
- FillChar( InBlock, SizeOf( InBlock ), #0 );
- InBlock[ 0 ] := Ord( Value[ Position + 0 ] );
- if Remaining >= 2 then
- InBlock[ 1 ] := Ord( Value[ Position + 1 ] );
- if Remaining >= 3 then
- InBlock[ 2 ] := Ord( Value[ Position + 2 ] );
- Inc( Position, 3 );
- FillChar( OutBlock, SizeOf( OutBlock ), '=' );
- OutBlock[ 0 ] := Base64Chars[ ( InBlock[ 0 ] and $FC ) shr 2 ];
- OutBlock[ 1 ] := Base64Chars[ ( ( InBlock[ 0 ] and $03 ) shl 4 ) or
- ( ( InBlock[ 1 ] and $F0 ) shr 4 ) ];
- if Remaining >= 2 then
- OutBlock[ 2 ] := Base64Chars[ ( ( InBlock[ 1 ] and $0F ) shl 2 ) or
- ( ( InBlock[ 2 ] and $C0 ) shr 6 ) ];
- if Remaining >= 3 then
- OutBlock[ 3 ] := Base64Chars[ InBlock[ 2 ] and $3F ];
- Result := Result + OutBlock;
- end;
- end;
- function SDLWeb_DecodeBase64( Value : string ) : string;
- var
- Position, Total, Remaining : Integer;
- InBlock : array[ 0..3 ] of Byte;
- OutBlock : array[ 0..2 ] of Char;
- function Base64Ord( Value : Char ) : Byte;
- const
- BASE64_FIRST_UPPER = 0;
- BASE64_FIRST_LOWER = 26;
- BASE64_FIRST_NUMBER = 52;
- BASE64_PLUS = 62;
- BASE64_SLASH = 63;
- begin
- if ( Ord( Value ) >= Ord( 'A' ) ) and ( Ord( Value ) <= Ord( 'Z' ) ) then
- Result := Ord( Value ) - Ord( 'A' ) + BASE64_FIRST_UPPER
- else if ( Ord( Value ) >= Ord( 'a' ) ) and ( Ord( Value ) <= Ord( 'z' ) ) then
- Result := Ord( Value ) - Ord( 'a' ) + BASE64_FIRST_LOWER
- else if ( Ord( Value ) >= Ord( '0' ) ) and ( Ord( Value ) <= Ord( '9' ) ) then
- Result := Ord( Value ) - Ord( '0' ) + BASE64_FIRST_NUMBER
- else if Ord( Value ) = Ord( '+' ) then
- Result := BASE64_PLUS
- else if Ord( Value ) = Ord( '/' ) then
- Result := BASE64_SLASH
- else
- Result := 0;
- end;
- begin
- Result := '';
- Total := Length( Value );
- Position := 1;
- while True do
- begin
- Remaining := Total - Position + 1;
- if Remaining <= 0 then
- Break;
- FillChar( InBlock, SizeOf( InBlock ), #0 );
- InBlock[ 0 ] := Base64Ord( Value[ Position + 0 ] );
- if Remaining >= 2 then
- InBlock[ 1 ] := Base64Ord( Value[ Position + 1 ] );
- if Remaining >= 3 then
- InBlock[ 2 ] := Base64Ord( Value[ Position + 2 ] );
- if Remaining >= 4 then
- InBlock[ 3 ] := Base64Ord( Value[ Position + 3 ] );
- Inc( Position, 4 );
- OutBlock[ 0 ] := Chr( ( ( InBlock[ 0 ] and $3F ) shl 2 ) or
- ( ( InBlock[ 1 ] and $30 ) shr 4 ) );
- OutBlock[ 1 ] := Chr( ( ( InBlock[ 1 ] and $0F ) shl 4 ) or
- ( ( InBlock[ 2 ] and $3C ) shr 2 ) );
- OutBlock[ 2 ] := Chr( ( ( InBlock[ 2 ] and $03 ) shl 6 ) or
- ( InBlock[ 3 ] and $3F ) );
- Result := Result + OutBlock;
- end;
- end;
- end.
|