I don't need to test my programs. I have an error-correcting modem.
Legacy:ProfileImporter
From Unreal Wiki, The Unreal Engine Documentation Site
UT2003 :: Object >> Actor >> Info >> InternetInfo >> InternetLink >> TcpLink >> ProfileImporter (Ladder1.46)
-
//-----------------------------------------------------------
-
// Ladder.ProfileImporter
-
//
-
// Handles all communication with foreign servers containing
-
// exported profile information
-
// Stores remote profile URL locations
-
//-----------------------------------------------------------
-
class ProfileImporter extends TcpLink config(LadderProfiles);
-
-
const LOGTAG = 'ProfileImport';
-
-
var enum EImportResult
-
{
-
IMPORT_BadURL, // Incorrect URL format
-
IMPORT_ResolveError, // Couldn't resolve URL
-
IMPORT_BindError, // Couldn't bind port
-
IMPORT_InvalidProfile, // File was not a profile
-
IMPORT_TimeOut, // Timed out waiting
-
IMPORT_ServerError, // Unspecified Foreign Host Error
-
IMPORT_BadRequest, // Receieved 400 Error
-
IMPORT_Unauthorized, // Receieved 401 Error
-
IMPORT_Forbidden, // Receieved 403 Error
-
IMPORT_NotFound, // Receieved 404 Error
-
IMPORT_Success // Profile Successfully Imported
-
} ImportResult;
-
-
var bool bWaiting; //Waiting for ImportResult
-
-
struct ZipLocation
-
{
-
var string ProfileURL;
-
var string ZipName;
-
var string ZipURL;
-
};
-
-
var IpAddr ServerIP;
-
var LadderGameRules LadderRules;
-
var ProfileConfigSet RemoteProfile;
-
var LadderQuery QueryPage;
-
-
var Session ImportS;
-
var WebRequest QueryRequest;
-
var WebResponse QueryResponse;
-
-
var string Buffer;
-
var string Header;
-
var string LF; // Line Feed
-
var string CR; // Carriage Return
-
var string Token; // Token Delimiter
-
-
var string ProfileServerAddress;
-
var string RemoteProfilePath;
-
-
// Localized strings
-
var localized string BeginImportText;
-
-
// Localized error messages
-
var localized string ErrorText;
-
var localized string ErrorURLText;
-
var localized string ErrorResolvingText;
-
var localized string ErrorBindingText;
-
var localized string ErrorTimeoutText;
-
var localized string ErrorFNFText;
-
var localized string ErrorBadRequestText;
-
var localized string ErrorUnauthorizedText;
-
var localized string ErrorForbiddenText;
-
var localized string ErrorNoSession;
-
var localized string ErrorNoBuffer;
-
-
var localized string BadImportURLText;
-
-
var config array<ZipLocation> RemoteZips; // Remote profile zips locations
-
-
function PostBeginPlay()
-
{
-
Super.PostBeginPlay();
-
Disable('Tick');
-
-
LF = Chr(10);
-
CR = Chr(13);
-
Token = Chr(21);
-
}
-
-
function Tick(float DeltaTime)
-
{
-
Super.Tick(DeltaTime);
-
-
if (!bWaiting)
-
{
-
// Finish importing profile data, let LadderQuery finish sending page
-
QueryPage.RemoteImport(Self);
-
Disable('Tick');
-
}
-
}
-
-
function Timer()
-
{
-
log(ErrorTimeoutText @ ProfileServerAddress,LOGTAG);
-
ImportResult = IMPORT_Timeout;
-
bWaiting = False;
-
-
// Manually close the connection since
-
// we didn't receive a response
-
Close();
-
}
-
-
// Called from the Management Portal page
-
function bool Connect(string ProfileURL, Session TempS)
-
{
-
local string L, R;
-
-
bWaiting = True;
-
Enable('Tick');
-
-
log( BeginImportText @ ProfileURL, LOGTAG);
-
if ( Left(ProfileURL, 7) ~= "http://")
-
ProfileServerAddress = ParseDelimited(ProfileURL,"/",3);
-
else
-
{
-
log( ErrorURLText @ "\"http://\"!", LOGTAG);
-
ImportResult = IMPORT_BadURL;
-
bWaiting = False;
-
return false;
-
}
-
-
ServerIP.Port = 80;
-
if (InStr(ProfileServerAddress, ":") != -1)
-
{
-
Divide(ProfileServerAddress, ":", L, R);
-
ProfileServerAddress = L;
-
ServerIP.Port = int(R);
-
}
-
-
RemoteProfilePath = "/" $ ParseDelimited(ProfileURL,"/",4,True);
-
-
Buffer = "";
-
SetTimer(20.0, False);
-
ImportS = TempS;
-
Resolve( ProfileServerAddress );
-
return true;
-
}
-
-
event ResolveFailed()
-
{
-
log( ErrorResolvingText @ ProfileServerAddress, LOGTAG);
-
ImportResult = IMPORT_ResolveError;
-
bWaiting = False;
-
}
-
-
event Resolved(IpAddr NumericIP)
-
{
-
if( NumericIP.Addr == 0 )
-
{
-
log( ErrorResolvingText @ ProfileServerAddress, LOGTAG);
-
ImportResult = IMPORT_ResolveError;
-
bWaiting = False;
-
return;
-
}
-
ServerIP.Addr = NumericIP.Addr;
-
-
// Bind the local port.
-
if( BindPort() == 0 )
-
{
-
log( ErrorBindingText, LOGTAG);
-
ImportResult = IMPORT_BindError;
-
bWaiting = False;
-
return;
-
}
-
// Everything went OK - proceed to open connection
-
Open( ServerIP );
-
}
-
-
event Opened()
-
{
-
if (LinkMode != MODE_Line)
-
LinkMode = MODE_Line;
-
-
SetTimer(0.0, False); // Stop timeout counter
-
-
// Check header of file first, to make sure it's a valid file
-
RequestFile(0);
-
}
-
-
// Connection was closed by foreign host - Check header for response code
-
event Closed()
-
{
-
local string Result;
-
-
// First find header and respond accordingly
-
if (SeperateHeaders(Buffer))
-
Result = ProcessHeaders();
-
else
-
{
-
ImportResult = IMPORT_ServerError;
-
bWaiting = False;
-
return;
-
}
-
-
if (Result == "")
-
{
-
ImportResult = IMPORT_ServerError;
-
bWaiting = False;
-
return;
-
}
-
-
/* Possible Response Codes:
-
"200" ; OK
-
"201" ; Created
-
"202" ; Accepted
-
"204" ; No Content
-
"301" ; Moved Permanently
-
"302" ; Moved Temporarily
-
"304" ; Not Modified
-
"400" ; Bad Request
-
"401" ; Unauthorized
-
"403" ; Forbidden
-
"404" ; Not Found
-
"500" ; Internal Server Error
-
"501" ; Not Implemented
-
"502" ; Bad Gateway
-
"503" ; Service Unavailable
-
*/
-
switch (Result)
-
{
-
case "200":
-
// Buffer should now only contain the actual document
-
// Fill ImportS from document info
-
if (FillSessionInfo())
-
ImportResult = IMPORT_Success;
-
break;
-
case "400":
-
log( ErrorBadRequestText, LOGTAG);
-
ImportResult = IMPORT_BadRequest;
-
break;
-
case "401":
-
log( ErrorUnauthorizedText, LOGTAG);
-
ImportResult = IMPORT_Unauthorized;
-
break;
-
case "403":
-
log( ErrorForbiddenText, LOGTAG);
-
ImportResult = IMPORT_Forbidden;
-
break;
-
default:
-
log( ErrorFNFText, LOGTAG);
-
ImportResult = IMPORT_NotFound;
-
}
-
bWaiting = False;
-
}
-
-
function bool FillSessionInfo()
-
{
-
local string Line;
-
local string Type;
-
local string Info;
-
local bool bValidProfile;
-
-
local string Token1, Token2, Token3, Token4, Token5, Token6, Token7;
-
-
if (ImportS == None)
-
{
-
log( ErrorNoSession, LOGTAG);
-
ImportResult = IMPORT_ServerError;
-
return false;
-
}
-
-
if (Buffer == "")
-
{
-
log(ErrorNoBuffer, LOGTAG);
-
ImportResult = IMPORT_ServerError;
-
return False;
-
}
-
else
-
{
-
while ( (Left(Buffer,1) ~= CR) || (Left(Buffer,1) ~= LF) )
-
Buffer = Mid(Buffer,1);
-
}
-
-
while (ReadBufferedLine(Line))
-
{
-
Divide(Line,Chr(58),Type,Info);
-
-
Token1 = ParseDelimited(Info,Token,1);
-
Token2 = ParseDelimited(Info,Token,2);
-
Token3 = ParseDelimited(Info,Token,3);
-
Token4 = ParseDelimited(Info,Token,4);
-
Token5 = ParseDelimited(Info,Token,5);
-
Token6 = ParseDelimited(Info,Token,6);
-
Token7 = ParseDelimited(Info,Token,7);
-
-
switch (Type)
-
{
-
case "Profile":
-
ImportS.setValue("ProfileName",Token1,True);
-
ImportS.setValue("GameType",Token2,True);
-
ImportS.setValue("MaxMaps",Token3,True);
-
ImportS.setValue("GameName",Token4,True);
-
ImportS.setValue("ACClass",Token5,True);
-
if (Token6 != "") ImportS.setValue("CustomGameLoc",Token6,True);
-
if (Token7 != "") ImportS.setValue("CustomACLoc",Token7,True);
-
bValidProfile = True;
-
break;
-
-
case "Map":
-
ImportS.setMap(Token1,int(Token2),True,bool(Token3));
-
if (Token4 != "") AddRemoteZipLocation(Token1,Token4);
-
break;
-
-
case "Mutator":
-
ImportS.setMutator(Token2,True,bool(Token3));
-
if (Token4 != "") AddRemoteZipLocation(Token2,Token4);
-
-
case "Data":
-
ImportS.setValue(Token1,Token2,True);
-
break;
-
}
-
}
-
-
if (bValidProfile)
-
return true;
-
-
ImportResult = IMPORT_InvalidProfile;
-
return false;
-
}
-
-
function AddRemoteZipLocation(string PackageName, string PackageLocation)
-
{
-
local int i;
-
local bool ZipFound;
-
-
local ZipLocation Zip;
-
-
i = InStr(PackageName, ".");
-
if (i != -1)
-
PackageName = Left(PackageName,i);
-
-
Zip.ProfileURL = ProfileServerAddress $ RemoteProfilePath;
-
Zip.ZipName = PackageName;
-
Zip.ZipURL = PackageLocation;
-
-
for (i = 0; i < RemoteZips.Length; i++)
-
{
-
if (RemoteZips[i].ProfileURL ~= Zip.ProfileURL && RemoteZips[i].ZipName ~= Zip.ZipName)
-
{
-
ZipFound = True;
-
break;
-
}
-
}
-
-
if (ZipFound) RemoteZips[i] = Zip;
-
else RemoteZips[RemoteZips.Length] = Zip;
-
-
SaveConfig();
-
}
-
-
function string FindRemoteZipLocation(string PackageName, string ProfileURL, optional bool bAllowOtherLocations)
-
{
-
local int i;
-
-
i = InStr(PackageName, ".");
-
if (i != -1) PackageName = Left(PackageName,i);
-
-
for (i = 0;i < RemoteZips.Length; i++)
-
if ((RemoteZips[i].ZipName ~= PackageName) && ((RemoteZips[i].ProfileURL ~= ProfileURL) || (bAllowOtherLocations)) )
-
return RemoteZips[i].ZipURL;
-
-
return "";
-
}
-
-
function bool SeperateHeaders(string WebPage)
-
{
-
local int i;
-
-
//CR$LF$CR$LF seperates header and document
-
i = InStr(WebPage, CR$LF$CR$LF);
-
-
if (i == -1)
-
return false;
-
-
Header = Left(WebPage, i);
-
Buffer = Mid(WebPage, i + 3);
-
return true;
-
}
-
-
function string ProcessHeaders()
-
{
-
if (Header == "")
-
return "";
-
-
//Remove all CR, leaving only LF
-
Header = RemoveStr(Header,CR);
-
-
//Parse Response Code from server, ex. HTTP/1.1 200 OK
-
return Mid(ParseDelimited(Header,LF,1),9,3);
-
}
-
-
event ReceivedText(string Text)
-
{
-
Buffer = Buffer $ Text;
-
}
-
-
event ReceivedLine(string Line)
-
{
-
local string Result;
-
-
if (SeperateHeaders(Line))
-
Result = ProcessHeaders();
-
-
if (Result == "200")
-
{
-
Result = FindContentType(Line);
-
if (Result ~= "text/plain")
-
{
-
RequestFile(1);
-
LinkMode = Mode_Text;
-
}
-
else
-
{
-
ImportResult = IMPORT_InvalidProfile;
-
bWaiting = False;
-
}
-
}
-
-
else
-
{
-
ImportResult = IMPORT_NotFound;
-
bWaiting = False;
-
}
-
}
-
-
function string FindContentType(string Text)
-
{
-
local array<string> Lines;
-
local string Tmp;
-
local int i, j;
-
-
Buffer = Text;
-
while (ReadBufferedLine(Tmp))
-
Lines[Lines.Length] = Tmp;
-
-
for (i=0;i<Lines.Length;i++)
-
{
-
if (Left(Lines[i],13) ~= "Content-Type:")
-
{
-
Tmp = Mid(Lines[i],14);
-
j = InStr(Tmp,";");
-
if (j >= 0)
-
Tmp = Left(Tmp,j);
-
}
-
}
-
-
return Tmp;
-
}
-
-
function RequestFile(int RequestType)
-
{
-
local string RequestMethod, ControlText;
-
-
if (RequestType == 0)
-
{
-
RequestMethod = "HEAD";
-
ControlText = "Keep-Alive";
-
}
-
else
-
{
-
RequestMethod = "GET";
-
ControlText = "close";
-
}
-
-
SendText(RequestMethod@RemoteProfilePath@"HTTP/1.1");
-
SendText("Host:"@ProfileServerAddress);
-
SendText("Accept: text/plain"); // Accept only plain txt files
-
SendText("User-agent: ProfileManager; UT2003"@Level.EngineVersion);
-
SendText("Pragma: no-cache"); // Do not allow proxies to send cached information
-
SendText("Cache-control: no-cache");
-
SendText("Connection:"@ControlText); // No further information to be sent
-
SendText("");
-
}
-
-
function bool ReadBufferedLine(out string Text)
-
{
-
local int i;
-
-
i = InStr(Buffer, LF);
-
-
if(i == -1)
-
return False;
-
-
if (Mid(Buffer, i-1, 1) == CR)
-
Text = Left(Buffer, i-1);
-
else Text = Left(Buffer, i);
-
-
Buffer = Mid(Buffer, i+1);
-
return True;
-
}
-
-
// Copied from BufferedTcpLink
-
function string ParseDelimited(string Text, string Delimiter, int Count, optional bool bToEndOfLine)
-
{
-
local string Result;
-
local int Found, i;
-
local string s;
-
-
Result = "";
-
Found = 1;
-
-
for(i=0;i<Len(Text);i++)
-
{
-
s = Mid(Text, i, 1);
-
if(InStr(Delimiter, s) != -1)
-
{
-
if(Found == Count)
-
{
-
if(bToEndOfLine)
-
return Result$Mid(Text, i);
-
else
-
return Result;
-
}
-
-
Found++;
-
}
-
else
-
{
-
if(Found >= Count)
-
Result = Result $ s;
-
}
-
}
-
-
return Result;
-
}
-
-
function string RemoveStr(string Source,string mask)
-
{
-
local int i;
-
local string left,right;
-
-
i = InStr(Source,mask);
-
while (i != -1)
-
{
-
Divide(Source,mask,left,right);
-
Source = Left$Right;
-
i = InStr(Source,Mask);
-
}
-
-
return Source;
-
}