Prepare fixtures
This commit is contained in:
parent
797e5ea192
commit
9c94356263
6021 changed files with 722805 additions and 22 deletions
62
kf_sources/UWeb/Classes/HelloWeb.uc
Normal file
62
kf_sources/UWeb/Classes/HelloWeb.uc
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
class HelloWeb extends WebApplication;
|
||||
|
||||
/* Usage:
|
||||
This is a sample web application, to demonstrate how to program for the web server.
|
||||
|
||||
|
||||
[UWeb.WebServer]
|
||||
Applications[0]="UWeb.HelloWeb"
|
||||
ApplicationPaths[0]="/hello"
|
||||
bEnabled=True
|
||||
|
||||
http://server.ip.address/hello
|
||||
|
||||
*/
|
||||
|
||||
event Query(WebRequest Request, WebResponse Response)
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(Request.Username != "test" || Request.Password != "test")
|
||||
{
|
||||
Response.FailAuthentication("HelloWeb");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(Request.URI)
|
||||
{
|
||||
case "/form.html":
|
||||
Response.SendText("<form method=post action=submit.html>");
|
||||
Response.SendText("<input type=edit name=TestEdit>");
|
||||
Response.SendText("<p><select multiple name=selecter>");
|
||||
Response.SendText("<option value=\"one\">Number One");
|
||||
Response.SendText("<option value=\"two\">Number Two");
|
||||
Response.SendText("<option value=\"three\">Number Three");
|
||||
Response.SendText("<option value=\"four\">Number Four");
|
||||
Response.SendText("</select><p>");
|
||||
Response.SendText("<input type=submit name=Submit value=Submit>");
|
||||
Response.SendText("</form>");
|
||||
break;
|
||||
case "/submit.html":
|
||||
Response.SendText("Thanks for submitting the form.<br>");
|
||||
Response.SendText("TestEdit was \""$Request.GetVariable("TestEdit")$"\"<p>");
|
||||
Response.SendText("You selected these items:<br>");
|
||||
for(i=Request.GetVariableCount("selecter")-1;i>=0;i--)
|
||||
Response.SendText("\""$Request.GetVariableNumber("selecter", i)$"\"<br>");
|
||||
break;
|
||||
case "/include.html":
|
||||
Response.Subst("variable1", "This is variable 1");
|
||||
Response.Subst("variable2", "This is variable 2");
|
||||
Response.Subst("variable3", "This is variable 3");
|
||||
Response.IncludeUHTM("testinclude.html");
|
||||
break;
|
||||
default:
|
||||
Response.SendText("Hello web! The current level is "$Level.Title);
|
||||
Response.SendText("<br>Click <a href=\"form.html\">this link</a> to go to a test form");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
||||
36
kf_sources/UWeb/Classes/ImageServer.uc
Normal file
36
kf_sources/UWeb/Classes/ImageServer.uc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
class ImageServer extends WebApplication;
|
||||
|
||||
/* Usage:
|
||||
[UWeb.WebServer]
|
||||
Applications[0]="UWeb.ImageServer"
|
||||
ApplicationPaths[0]="/images"
|
||||
bEnabled=True
|
||||
|
||||
http://server.ip.address/images/test.jpg
|
||||
*/
|
||||
|
||||
event Query(WebRequest Request, WebResponse Response)
|
||||
{
|
||||
local string Image;
|
||||
|
||||
Image = Request.URI;
|
||||
if( Right(Caps(Image), 4) == ".JPG" || Right(Caps(Image), 5) == ".JPEG" )
|
||||
{
|
||||
Response.SendStandardHeaders("image/jpeg", true);
|
||||
}
|
||||
else if( Right(Caps(Image), 4) == ".GIF" )
|
||||
{
|
||||
Response.SendStandardHeaders("image/gif", true);
|
||||
}
|
||||
else if( Right(Caps(Image), 4) == ".BMP" )
|
||||
{
|
||||
Response.SendStandardHeaders("image/bmp", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Response.HTTPError(404);
|
||||
return;
|
||||
}
|
||||
Response.IncludeBinaryFile( Path $ Image );
|
||||
}
|
||||
|
||||
4
kf_sources/UWeb/Classes/UWeb.upkg
Normal file
4
kf_sources/UWeb/Classes/UWeb.upkg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[Flags]
|
||||
AllowDownload=False
|
||||
ClientOptional=False
|
||||
ServerSideOnly=True
|
||||
26
kf_sources/UWeb/Classes/WebApplication.uc
Normal file
26
kf_sources/UWeb/Classes/WebApplication.uc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
class WebApplication extends Object;
|
||||
|
||||
// Set by the webserver
|
||||
var LevelInfo Level;
|
||||
var WebServer WebServer;
|
||||
var string Path;
|
||||
|
||||
function Init();
|
||||
|
||||
// This is a dummy function which should never be called
|
||||
// Here for backwards compatibility
|
||||
final function Cleanup();
|
||||
|
||||
function CleanupApp()
|
||||
{
|
||||
if (Level != None)
|
||||
Level = None;
|
||||
|
||||
if (WebServer != None)
|
||||
WebServer = None;
|
||||
}
|
||||
|
||||
function bool PreQuery(WebRequest Request, WebResponse Response) { return true; }
|
||||
function Query(WebRequest Request, WebResponse Response);
|
||||
function PostQuery(WebRequest Request, WebResponse Response);
|
||||
|
||||
274
kf_sources/UWeb/Classes/WebConnection.uc
Normal file
274
kf_sources/UWeb/Classes/WebConnection.uc
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
/*=============================================================================
|
||||
WebConnection is the bridge that will handle all communication between
|
||||
the web server and the client's browser.
|
||||
=============================================================================*/
|
||||
|
||||
class WebConnection extends TcpLink;
|
||||
|
||||
var WebServer WebServer;
|
||||
var string ReceivedData;
|
||||
|
||||
var WebRequest Request;
|
||||
var WebResponse Response;
|
||||
var WebApplication Application;
|
||||
|
||||
var bool bDelayCleanup;
|
||||
|
||||
var int RawBytesExpecting;
|
||||
|
||||
var config int MaxValueLength;
|
||||
var config int MaxLineLength;
|
||||
|
||||
// MC: Debug
|
||||
// var int ConnId;
|
||||
|
||||
event Accepted()
|
||||
{
|
||||
WebServer = WebServer(Owner);
|
||||
SetTimer(30, False);
|
||||
// ConnId = WebServer.ConnId++;
|
||||
// Log("Connection"@ConnId@"Accepted");
|
||||
}
|
||||
|
||||
event Closed()
|
||||
{
|
||||
// Log("Connection"@ConnId@"Closed");
|
||||
Destroy();
|
||||
}
|
||||
|
||||
event Timer()
|
||||
{
|
||||
bDelayCleanup = False;
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
event ReceivedText( string Text )
|
||||
{
|
||||
local int i;
|
||||
local string S;
|
||||
|
||||
ReceivedData $= Text;
|
||||
if(RawBytesExpecting > 0)
|
||||
{
|
||||
RawBytesExpecting -= Len(Text);
|
||||
CheckRawBytes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// remove a LF which arrived in a new packet
|
||||
// and thus didn't get cleaned up by the code below
|
||||
if(Left(ReceivedData, 1) == Chr(10))
|
||||
ReceivedData = Mid(ReceivedData, 1);
|
||||
i = InStr(ReceivedData, Chr(13));
|
||||
while(i != -1)
|
||||
{
|
||||
S = Left(ReceivedData, i);
|
||||
i++;
|
||||
// check for any LF following the CR.
|
||||
if(Mid(ReceivedData, i, 1) == Chr(10))
|
||||
i++;
|
||||
|
||||
ReceivedData = Mid(ReceivedData, i);
|
||||
|
||||
ReceivedLine(S);
|
||||
|
||||
if(LinkState != STATE_Connected)
|
||||
return;
|
||||
if(RawBytesExpecting > 0)
|
||||
{
|
||||
CheckRawBytes();
|
||||
return;
|
||||
}
|
||||
|
||||
i = InStr(ReceivedData, Chr(13));
|
||||
}
|
||||
}
|
||||
|
||||
function ReceivedLine(string S)
|
||||
{
|
||||
if (S == "") EndOfHeaders();
|
||||
else
|
||||
{
|
||||
// Log(S,'WebServer');
|
||||
if(Left(S, 4) ~= "GET ") ProcessGet(S);
|
||||
else if(Left(S, 5) ~= "POST ") ProcessPost(S);
|
||||
else if(Left(S, 5) ~= "HEAD ") ProcessHead(S);
|
||||
else if(Request != None)
|
||||
{
|
||||
Request.ProcessHeaderString(S);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ProcessHead(string S)
|
||||
{
|
||||
Log("Received Header: "$S,'Header');
|
||||
}
|
||||
|
||||
function ProcessGet(string S)
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(Request == None)
|
||||
CreateResponseObject();
|
||||
|
||||
Request.RequestType = Request_GET;
|
||||
S = Mid(S, 4);
|
||||
while(Left(S, 1) == " ")
|
||||
S = Mid(S, 1);
|
||||
|
||||
i = InStr(S, " ");
|
||||
|
||||
if(i != -1)
|
||||
S = Left(S, i);
|
||||
|
||||
i = InStr(S, "?");
|
||||
if(i != -1)
|
||||
{
|
||||
Request.DecodeFormData(Mid(S, i+1));
|
||||
S = Left(S, i);
|
||||
}
|
||||
|
||||
Application = WebServer.GetApplication(S, Request.URI);
|
||||
if(Application != None && Request.URI == "")
|
||||
{
|
||||
Response.Redirect(S$"/");
|
||||
Cleanup();
|
||||
}
|
||||
else
|
||||
if(Application == None && Webserver.DefaultApplication != -1)
|
||||
{
|
||||
Response.Redirect(Webserver.ApplicationPaths[Webserver.DefaultApplication]$"/");
|
||||
Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
function ProcessPost(string S)
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(Request == None)
|
||||
CreateResponseObject();
|
||||
|
||||
Request.RequestType = Request_POST;
|
||||
|
||||
S = Mid(S, 5);
|
||||
while(Left(S, 1) == " ")
|
||||
S = Mid(S, 1);
|
||||
|
||||
i = InStr(S, " ");
|
||||
|
||||
if(i != -1)
|
||||
S = Left(S, i);
|
||||
|
||||
i = InStr(S, "?");
|
||||
if(i != -1)
|
||||
{
|
||||
Request.DecodeFormData(Mid(S, i+1));
|
||||
S = Left(S, i);
|
||||
}
|
||||
Application = WebServer.GetApplication(S, Request.URI);
|
||||
if(Application != None && Request.URI == "")
|
||||
{
|
||||
// Response.Redirect(WebServer.ServerURL$S$"/");
|
||||
Response.Redirect(S$"/");
|
||||
Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
function CreateResponseObject()
|
||||
{
|
||||
Request = new(None) class'WebRequest';
|
||||
|
||||
Response = new(None) class'WebResponse';
|
||||
Response.Connection = Self;
|
||||
}
|
||||
|
||||
function EndOfHeaders()
|
||||
{
|
||||
if(Response == None)
|
||||
{
|
||||
CreateResponseObject();
|
||||
Response.HTTPError(400); // Bad Request
|
||||
Cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
if(Application == None)
|
||||
{
|
||||
Response.HTTPError(404); // FNF
|
||||
Cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
if(Request.ContentLength != 0 && Request.RequestType == Request_POST)
|
||||
{
|
||||
RawBytesExpecting = Request.ContentLength;
|
||||
RawBytesExpecting -= Len(ReceivedData);
|
||||
CheckRawBytes();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Application.PreQuery(Request, Response))
|
||||
{
|
||||
Application.Query(Request, Response);
|
||||
Application.PostQuery(Request, Response);
|
||||
}
|
||||
Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
function CheckRawBytes()
|
||||
{
|
||||
if(RawBytesExpecting <= 0)
|
||||
{
|
||||
if(!(Request.ContentType ~= "application/x-www-form-urlencoded"))
|
||||
{
|
||||
Log("WebConnection: Unknown form data content-type: "$Request.ContentType);
|
||||
Response.HTTPError(400); // Can't deal with this type of form data
|
||||
}
|
||||
else
|
||||
{
|
||||
Request.DecodeFormData(ReceivedData);
|
||||
if (Application.PreQuery(Request, Response))
|
||||
{
|
||||
Application.Query(Request, Response);
|
||||
Application.PostQuery(Request, Response);
|
||||
}
|
||||
ReceivedData = "";
|
||||
}
|
||||
Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
function Cleanup()
|
||||
{
|
||||
if (bDelayCleanup)
|
||||
return;
|
||||
|
||||
if(Request != None)
|
||||
Request = None;
|
||||
|
||||
if(Response != None)
|
||||
{
|
||||
Response.Connection = None;
|
||||
Response = None;
|
||||
}
|
||||
|
||||
if (Application != None)
|
||||
Application = None;
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
final function bool IsHanging()
|
||||
{
|
||||
return bDelayCleanup;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MaxValueLength=512 // Maximum size of a variable value
|
||||
MaxLineLength=4096
|
||||
}
|
||||
147
kf_sources/UWeb/Classes/WebRequest.uc
Normal file
147
kf_sources/UWeb/Classes/WebRequest.uc
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
class WebRequest extends Object
|
||||
native
|
||||
noexport;
|
||||
|
||||
enum ERequestType
|
||||
{
|
||||
Request_GET,
|
||||
Request_POST
|
||||
};
|
||||
|
||||
var string URI;
|
||||
var string Username;
|
||||
var string Password;
|
||||
var int ContentLength;
|
||||
var string ContentType;
|
||||
var ERequestType RequestType;
|
||||
var private native const TMultiMap VariableMap; // C++ placeholder.
|
||||
|
||||
native final function string DecodeBase64(string Encoded);
|
||||
native final function AddVariable(string VariableName, coerce string Value);
|
||||
native final function string GetVariable(string VariableName, optional string DefaultValue);
|
||||
native final function int GetVariableCount(string VariableName);
|
||||
native final function string GetVariableNumber(string VariableName, int Number, optional string DefaultValue);
|
||||
|
||||
|
||||
native final function Dump(); // only works in dev mode
|
||||
|
||||
function ProcessHeaderString(string S)
|
||||
{
|
||||
local int i;
|
||||
|
||||
if(Left(S, 21) ~= "Authorization: Basic ")
|
||||
{
|
||||
S = DecodeBase64(Mid(S, 21, 256));
|
||||
i = InStr(S, ":");
|
||||
if(i != -1)
|
||||
{
|
||||
Username = Left(S, i);
|
||||
Password = Mid(S, i+1);
|
||||
}
|
||||
}
|
||||
else
|
||||
if(Left(S, 16) ~= "Content-Length: ")
|
||||
ContentLength = Int(Mid(S, 16, 64));
|
||||
else
|
||||
if(Left(S, 14) ~= "Content-Type: ")
|
||||
ContentType = Mid(S, 14, 512);
|
||||
}
|
||||
|
||||
function DecodeFormData(string Data)
|
||||
{
|
||||
local string Token[2], ch;
|
||||
local int i, H1, H2, limit;
|
||||
local int t;
|
||||
|
||||
t = 0;
|
||||
for( i = 0; i < Len(Data); i++ )
|
||||
{
|
||||
if ( limit > class'WebConnection'.default.MaxValueLength || i > class'WebConnection'.default.MaxLineLength )
|
||||
break;
|
||||
|
||||
ch = mid(Data, i, 1);
|
||||
switch(ch)
|
||||
{
|
||||
case "+":
|
||||
Token[t] $= " ";
|
||||
limit++;
|
||||
break;
|
||||
|
||||
case "&":
|
||||
case "?":
|
||||
if(Token[0] != "")
|
||||
AddVariable(Token[0], Token[1]);
|
||||
|
||||
Token[0] = "";
|
||||
Token[1] = "";
|
||||
t = 0;
|
||||
|
||||
limit=0;
|
||||
break;
|
||||
|
||||
case "=":
|
||||
if(t == 0)
|
||||
{
|
||||
limit = 0;
|
||||
t = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Token[1] $= "=";
|
||||
limit++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "%":
|
||||
H1 = GetHexDigit(Mid(Data, ++i, 1));
|
||||
if ( H1 != -1 )
|
||||
{
|
||||
limit++;
|
||||
H1 *= 16;
|
||||
H2 = GetHexDigit(Mid(Data,++i,1));
|
||||
if ( H2 != -1 )
|
||||
Token[t] $= Chr(H1 + H2);
|
||||
}
|
||||
|
||||
limit++;
|
||||
break;
|
||||
|
||||
default:
|
||||
Token[t] $= ch;
|
||||
limit++;
|
||||
}
|
||||
}
|
||||
|
||||
if(Token[0] != "")
|
||||
AddVariable(Token[0], Token[1]);
|
||||
}
|
||||
|
||||
function int GetHexDigit(string D)
|
||||
{
|
||||
switch(caps(D))
|
||||
{
|
||||
case "0": return 0;
|
||||
case "1": return 1;
|
||||
case "2": return 2;
|
||||
case "3": return 3;
|
||||
case "4": return 4;
|
||||
case "5": return 5;
|
||||
case "6": return 6;
|
||||
case "7": return 7;
|
||||
case "8": return 8;
|
||||
case "9": return 9;
|
||||
case "A": return 10;
|
||||
case "B": return 11;
|
||||
case "C": return 12;
|
||||
case "D": return 13;
|
||||
case "E": return 14;
|
||||
case "F": return 15;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
||||
131
kf_sources/UWeb/Classes/WebResponse.uc
Normal file
131
kf_sources/UWeb/Classes/WebResponse.uc
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/*=============================================================================
|
||||
WebResponse is used by WebApplication to handle most aspects of sending
|
||||
http information to the client. It serves as a bridge between WebApplication
|
||||
and WebConnection.
|
||||
=============================================================================*/
|
||||
|
||||
class WebResponse extends Object
|
||||
native
|
||||
noexport;
|
||||
|
||||
var private native const TMultiMap ReplacementMap; // C++ placeholder.
|
||||
var const config string IncludePath;
|
||||
var localized string CharSet;
|
||||
var WebConnection Connection;
|
||||
var bool bSentText; // used to warn headers already sent
|
||||
var bool bSentResponse;
|
||||
|
||||
native final function Subst(string Variable, coerce string Value, optional bool bClear);
|
||||
native final function ClearSubst();
|
||||
native final function IncludeUHTM(string Filename);
|
||||
native final function IncludeBinaryFile(string Filename);
|
||||
native final function string LoadParsedUHTM(string Filename); // For templated web items, uses Subst too
|
||||
native final function string GetHTTPExpiration(optional int OffsetSeconds);
|
||||
|
||||
native final function Dump(); // only works in dev mode
|
||||
|
||||
event SendText(string Text, optional bool bNoCRLF)
|
||||
{
|
||||
if(!bSentText)
|
||||
{
|
||||
SendStandardHeaders();
|
||||
bSentText = True;
|
||||
}
|
||||
|
||||
if(bNoCRLF)
|
||||
Connection.SendText(Text);
|
||||
else
|
||||
Connection.SendText(Text$Chr(13)$Chr(10));
|
||||
}
|
||||
|
||||
event SendBinary(int Count, byte B[255])
|
||||
{
|
||||
Connection.SendBinary(Count, B);
|
||||
}
|
||||
|
||||
function SendCachedFile(string Filename, optional string ContentType)
|
||||
{
|
||||
if(!bSentText)
|
||||
{
|
||||
SendStandardHeaders(ContentType, true);
|
||||
bSentText = True;
|
||||
}
|
||||
IncludeUHTM(Filename);
|
||||
}
|
||||
|
||||
function FailAuthentication(string Realm)
|
||||
{
|
||||
HTTPError(401, Realm);
|
||||
}
|
||||
|
||||
function HTTPResponse(string Header)
|
||||
{
|
||||
HTTPHeader(Header);
|
||||
bSentResponse = True;
|
||||
}
|
||||
|
||||
function HTTPHeader(string Header)
|
||||
{
|
||||
if(bSentText)
|
||||
Log("Can't send headers - already called SendText()");
|
||||
|
||||
Connection.SendText(Header$Chr(13)$Chr(10));
|
||||
}
|
||||
|
||||
function HTTPError(int ErrorNum, optional string Data)
|
||||
{
|
||||
switch(ErrorNum)
|
||||
{
|
||||
case 400:
|
||||
HTTPResponse("HTTP/1.1 400 Bad Request");
|
||||
SendText("<TITLE>400 Bad Request</TITLE><H1>400 Bad Request</H1>If you got this error from a standard web browser, please mail jack@epicgames.com and submit a bug report.");
|
||||
break;
|
||||
case 401:
|
||||
HTTPResponse("HTTP/1.1 401 Unauthorized");
|
||||
HTTPHeader("WWW-authenticate: basic realm=\""$Data$"\"");
|
||||
SendText("<TITLE>401 Unauthorized</TITLE><H1>401 Unauthorized</H1>");
|
||||
break;
|
||||
case 404:
|
||||
HTTPResponse("HTTP/1.1 404 Object Not Found");
|
||||
SendText("<TITLE>404 File Not Found</TITLE><H1>404 File Not Found</H1>The URL you requested was not found.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function SendStandardHeaders( optional string ContentType, optional bool bCache )
|
||||
{
|
||||
if(ContentType == "")
|
||||
ContentType = "text/html";
|
||||
if(!bSentResponse)
|
||||
HTTPResponse("HTTP/1.1 200 OK");
|
||||
|
||||
// if _RO_
|
||||
HTTPHeader("Server: UnrealEngine UWeb Web Server Build "$Connection.Level.ROVersion);
|
||||
// else
|
||||
//HTTPHeader("Server: UnrealEngine UWeb Web Server Build "$Connection.Level.EngineVersion);
|
||||
HTTPHeader("Content-Type: "$ContentType);
|
||||
if (bCache)
|
||||
{
|
||||
HTTPHeader("Cache-Control: max-age="$Connection.WebServer.ExpirationSeconds);
|
||||
// Need to compute an Expires: tag .... arrgggghhh
|
||||
HTTPHeader("Expires:"@GetHTTPExpiration(Connection.WebServer.ExpirationSeconds));
|
||||
}
|
||||
HTTPHeader("Connection: Close");
|
||||
HTTPHeader("");
|
||||
}
|
||||
|
||||
function Redirect(string URL)
|
||||
{
|
||||
HTTPResponse("HTTP/1.1 302 Document Moved");
|
||||
HTTPHeader("Location: "$URL);
|
||||
SendText("<head><title>Document Moved</title></head>");
|
||||
SendText("<body><h1>Object Moved</h1>This document may be found <a HREF=\""$URL$"\">here</a>.");
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
IncludePath="/Web"
|
||||
CharSet="iso-8859-1"
|
||||
}
|
||||
149
kf_sources/UWeb/Classes/WebServer.uc
Normal file
149
kf_sources/UWeb/Classes/WebServer.uc
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*=============================================================================
|
||||
WebServer is responsible for listening to requests on the selected http
|
||||
port and will guide requests to the correct application.
|
||||
=============================================================================*/
|
||||
|
||||
class WebServer extends TcpLink;
|
||||
|
||||
var config string ServerName;
|
||||
var config string Applications[10];
|
||||
var config string ApplicationPaths[10];
|
||||
var config bool bEnabled;
|
||||
var config int ListenPort;
|
||||
var config int MaxConnections;
|
||||
var config int DefaultApplication;
|
||||
var config int ExpirationSeconds; // How long images can be cached .. default is 24 hours
|
||||
|
||||
var string ServerURL;
|
||||
var WebApplication ApplicationObjects[10];
|
||||
|
||||
var int ConnectionCount;
|
||||
// MC: Debug
|
||||
// var int ConnId;
|
||||
|
||||
function BeginPlay()
|
||||
{
|
||||
local int i;
|
||||
local class<WebApplication> ApplicationClass;
|
||||
local IpAddr l;
|
||||
local string s;
|
||||
|
||||
// Destroy if not a server
|
||||
if (Level.NetMode == NM_StandAlone || Level.NetMode == NM_Client)
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!bEnabled)
|
||||
{
|
||||
Log("Webserver is not enabled. Set bEnabled to True in Advanced Options.");
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
Super.BeginPlay();
|
||||
|
||||
for(i=0;i<10;i++)
|
||||
{
|
||||
if(Applications[i] == "")
|
||||
break;
|
||||
|
||||
ApplicationClass = class<WebApplication>(DynamicLoadObject(Applications[i], class'Class'));
|
||||
if(ApplicationClass != None)
|
||||
{
|
||||
ApplicationObjects[i] = New(None) ApplicationClass;
|
||||
ApplicationObjects[i].Level = Level;
|
||||
ApplicationObjects[i].WebServer = Self;
|
||||
ApplicationObjects[i].Path = ApplicationPaths[i];
|
||||
ApplicationObjects[i].Init();
|
||||
}
|
||||
}
|
||||
|
||||
if(ServerName == "")
|
||||
{
|
||||
GetLocalIP(l);
|
||||
s = IpAddrToString(l);
|
||||
i = InStr(s, ":");
|
||||
if(i != -1)
|
||||
s = Left(s, i);
|
||||
ServerURL = "http://"$s;
|
||||
}
|
||||
else
|
||||
ServerURL = "http://"$ServerName;
|
||||
|
||||
if(ListenPort != 80)
|
||||
ServerURL = ServerURL $ ":"$string(ListenPort);
|
||||
|
||||
BindPort( ListenPort );
|
||||
Listen();
|
||||
}
|
||||
|
||||
event Destroyed()
|
||||
{
|
||||
local int i;
|
||||
|
||||
for(i = 0; i < ArrayCount(ApplicationObjects); i++)
|
||||
if (ApplicationObjects[i] != None)
|
||||
ApplicationObjects[i].CleanupApp();
|
||||
|
||||
Super.Destroyed();
|
||||
}
|
||||
|
||||
event GainedChild( Actor C )
|
||||
{
|
||||
Super.GainedChild(C);
|
||||
ConnectionCount++;
|
||||
|
||||
// if too many connections, close down listen.
|
||||
if(MaxConnections > 0 && ConnectionCount > MaxConnections && LinkState == STATE_Listening)
|
||||
{
|
||||
Log("WebServer: Too many connections - closing down Listen.");
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
event LostChild( Actor C )
|
||||
{
|
||||
Super.LostChild(C);
|
||||
ConnectionCount--;
|
||||
|
||||
// if closed due to too many connections, start listening again.
|
||||
if(ConnectionCount <= MaxConnections && LinkState != STATE_Listening)
|
||||
{
|
||||
Log("WebServer: Listening again - connections have been closed.");
|
||||
Listen();
|
||||
}
|
||||
}
|
||||
|
||||
function WebApplication GetApplication(string URI, out string SubURI)
|
||||
{
|
||||
local int i, l;
|
||||
|
||||
SubURI = "";
|
||||
for(i=0;i<10;i++)
|
||||
{
|
||||
if(ApplicationPaths[i] != "")
|
||||
{
|
||||
l = Len(ApplicationPaths[i]);
|
||||
if(Left(URI, l) == ApplicationPaths[i] && (Len(URI) == l || Mid(URI, l, 1) == "/"))
|
||||
{
|
||||
SubURI = Mid(URI, l);
|
||||
return ApplicationObjects[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Applications(0)="xWebAdmin.UTServerAdmin"
|
||||
Applications(1)="xWebAdmin.UTImageServer"
|
||||
ApplicationPaths(0)="/ServerAdmin"
|
||||
ApplicationPaths(1)="/images"
|
||||
ListenPort=8075
|
||||
MaxConnections=30
|
||||
ExpirationSeconds=86400
|
||||
AcceptClass=Class'UWeb.WebConnection'
|
||||
}
|
||||
14
kf_sources/UWeb/Classes/index.html
Normal file
14
kf_sources/UWeb/Classes/index.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<html>
|
||||
<head><title>Index of /kf_sources/UWeb/Classes/</title></head>
|
||||
<body>
|
||||
<h1>Index of /kf_sources/UWeb/Classes/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="HelloWeb.uc">HelloWeb.uc</a> 06-Oct-2019 10:27 1929
|
||||
<a href="ImageServer.uc">ImageServer.uc</a> 06-Oct-2019 10:28 763
|
||||
<a href="UWeb.upkg">UWeb.upkg</a> 06-Oct-2019 10:27 73
|
||||
<a href="WebApplication.uc">WebApplication.uc</a> 06-Oct-2019 10:27 601
|
||||
<a href="WebConnection.uc">WebConnection.uc</a> 06-Oct-2019 10:27 5156
|
||||
<a href="WebRequest.uc">WebRequest.uc</a> 06-Oct-2019 10:27 2746
|
||||
<a href="WebResponse.uc">WebResponse.uc</a> 06-Oct-2019 10:27 3858
|
||||
<a href="WebServer.uc">WebServer.uc</a> 06-Oct-2019 10:27 3518
|
||||
</pre><hr></body>
|
||||
</html>
|
||||
7
kf_sources/UWeb/index.html
Normal file
7
kf_sources/UWeb/index.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<html>
|
||||
<head><title>Index of /kf_sources/UWeb/</title></head>
|
||||
<body>
|
||||
<h1>Index of /kf_sources/UWeb/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="Classes/">Classes/</a> 29-Jun-2025 19:43 -
|
||||
</pre><hr></body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue