| Home Page | Recent Changes | Preferences

ProfileImporter

UT2003 :: Object >> Actor >> Info >> InternetInfo >> InternetLink >> TcpLink >> ProfileImporter (Ladder1.46)
00001  //-----------------------------------------------------------
00002  //  Ladder.ProfileImporter
00003  //
00004  //  Handles all communication with foreign servers containing
00005  //  exported profile information
00006  //  Stores remote profile URL locations
00007  //-----------------------------------------------------------
00008  class ProfileImporter extends TcpLink config(LadderProfiles);
00009  
00010  const LOGTAG = 'ProfileImport';
00011  
00012  var enum EImportResult
00013  {
00014      IMPORT_BadURL,          // Incorrect URL format
00015      IMPORT_ResolveError,    // Couldn't resolve URL
00016      IMPORT_BindError,       // Couldn't bind port
00017      IMPORT_InvalidProfile,  // File was not a profile
00018      IMPORT_TimeOut,         // Timed out waiting
00019      IMPORT_ServerError,     // Unspecified Foreign Host Error
00020      IMPORT_BadRequest,      // Receieved 400 Error
00021      IMPORT_Unauthorized,    // Receieved 401 Error
00022      IMPORT_Forbidden,       // Receieved 403 Error
00023      IMPORT_NotFound,        // Receieved 404 Error
00024      IMPORT_Success          // Profile Successfully Imported
00025  } ImportResult;
00026  
00027  var bool                bWaiting;       //Waiting for ImportResult
00028  
00029  struct ZipLocation
00030  {
00031      var string ProfileURL;
00032      var string ZipName;
00033      var string ZipURL;
00034  };
00035  
00036  var IpAddr              ServerIP;
00037  var LadderGameRules     LadderRules;
00038  var ProfileConfigSet    RemoteProfile;
00039  var LadderQuery         QueryPage;
00040  
00041  var Session             ImportS;
00042  var WebRequest          QueryRequest;
00043  var WebResponse         QueryResponse;
00044  
00045  var string              Buffer;
00046  var string              Header;
00047  var string              LF;     // Line Feed
00048  var string              CR;     // Carriage Return
00049  var string              Token;  // Token Delimiter
00050  
00051  var string              ProfileServerAddress;
00052  var string              RemoteProfilePath;
00053  
00054  // Localized strings
00055  var localized string    BeginImportText;
00056  
00057  // Localized error messages
00058  var localized string    ErrorText;
00059  var localized string    ErrorURLText;
00060  var localized string    ErrorResolvingText;
00061  var localized string    ErrorBindingText;
00062  var localized string    ErrorTimeoutText;
00063  var localized string    ErrorFNFText;
00064  var localized string    ErrorBadRequestText;
00065  var localized string    ErrorUnauthorizedText;
00066  var localized string    ErrorForbiddenText;
00067  var localized string    ErrorNoSession;
00068  var localized string    ErrorNoBuffer;
00069  
00070  var localized string    BadImportURLText;
00071  
00072  var config array<ZipLocation>   RemoteZips; // Remote profile zips locations
00073  
00074  function PostBeginPlay()
00075  {
00076      Super.PostBeginPlay();
00077      Disable('Tick');
00078  
00079      LF = Chr(10);
00080      CR = Chr(13);
00081      Token = Chr(21);
00082  }
00083  
00084  function Tick(float DeltaTime)
00085  {
00086      Super.Tick(DeltaTime);
00087  
00088      if (!bWaiting)
00089      {
00090          // Finish importing profile data, let LadderQuery finish sending page
00091          QueryPage.RemoteImport(Self);
00092          Disable('Tick');
00093      }
00094  }
00095  
00096  function Timer()
00097  {
00098      log(ErrorTimeoutText @ ProfileServerAddress,LOGTAG);
00099      ImportResult = IMPORT_Timeout;
00100      bWaiting = False;
00101  
00102  // Manually close the connection since
00103  // we didn't receive a response
00104      Close();
00105  }
00106  
00107  // Called from the Management Portal page
00108  function bool Connect(string ProfileURL, Session TempS)
00109  {
00110      local string L, R;
00111  
00112      bWaiting = True;
00113      Enable('Tick');
00114  
00115      log( BeginImportText @ ProfileURL, LOGTAG);
00116      if ( Left(ProfileURL, 7) ~= "http://")
00117          ProfileServerAddress = ParseDelimited(ProfileURL,"/",3);
00118      else
00119      {
00120          log( ErrorURLText @ "\"http://\"!", LOGTAG);
00121          ImportResult = IMPORT_BadURL;
00122          bWaiting = False;
00123          return false;
00124      }
00125  
00126      ServerIP.Port = 80;
00127      if (InStr(ProfileServerAddress, ":") != -1)
00128      {
00129          Divide(ProfileServerAddress, ":", L, R);
00130          ProfileServerAddress = L;
00131          ServerIP.Port = int(R);
00132      }
00133  
00134      RemoteProfilePath = "/" $ ParseDelimited(ProfileURL,"/",4,True);
00135  
00136      Buffer = "";
00137      SetTimer(20.0, False);
00138      ImportS = TempS;
00139      Resolve( ProfileServerAddress );
00140      return true;
00141  }
00142  
00143  event ResolveFailed()
00144  {
00145      log( ErrorResolvingText @ ProfileServerAddress, LOGTAG);
00146      ImportResult = IMPORT_ResolveError;
00147      bWaiting = False;
00148  }
00149  
00150  event Resolved(IpAddr NumericIP)
00151  {
00152      if( NumericIP.Addr == 0 )
00153      {
00154          log( ErrorResolvingText @ ProfileServerAddress, LOGTAG);
00155          ImportResult = IMPORT_ResolveError;
00156          bWaiting = False;
00157          return;
00158      }
00159      ServerIP.Addr = NumericIP.Addr;
00160  
00161      // Bind the local port.
00162      if( BindPort() == 0 )
00163      {
00164          log( ErrorBindingText, LOGTAG);
00165          ImportResult = IMPORT_BindError;
00166          bWaiting = False;
00167          return;
00168      }
00169  // Everything went OK - proceed to open connection
00170      Open( ServerIP );
00171  }
00172  
00173  event Opened()
00174  {
00175      if (LinkMode != MODE_Line)
00176          LinkMode = MODE_Line;
00177  
00178      SetTimer(0.0, False);       // Stop timeout counter
00179  
00180      // Check header of file first, to make sure it's a valid file
00181      RequestFile(0);
00182  }
00183  
00184  // Connection was closed by foreign host - Check header for response code
00185  event Closed()
00186  {
00187      local string Result;
00188  
00189  // First find header and respond accordingly
00190      if (SeperateHeaders(Buffer))
00191          Result = ProcessHeaders();
00192      else
00193      {
00194          ImportResult = IMPORT_ServerError;
00195          bWaiting = False;
00196          return;
00197      }
00198  
00199      if (Result == "")
00200      {
00201          ImportResult = IMPORT_ServerError;
00202          bWaiting = False;
00203          return;
00204      }
00205  
00206   /*    Possible Response Codes:
00207          "200"   ; OK
00208          "201"   ; Created
00209          "202"   ; Accepted
00210          "204"   ; No Content
00211          "301"   ; Moved Permanently
00212          "302"   ; Moved Temporarily
00213          "304"   ; Not Modified
00214          "400"   ; Bad Request
00215          "401"   ; Unauthorized
00216          "403"   ; Forbidden
00217          "404"   ; Not Found
00218          "500"   ; Internal Server Error
00219          "501"   ; Not Implemented
00220          "502"   ; Bad Gateway
00221          "503"   ; Service Unavailable
00222  */
00223      switch (Result)
00224      {
00225      case "200":
00226      // Buffer should now only contain the actual document
00227      // Fill ImportS from document info
00228          if (FillSessionInfo())
00229              ImportResult = IMPORT_Success;
00230          break;
00231      case "400":
00232          log( ErrorBadRequestText, LOGTAG);
00233          ImportResult = IMPORT_BadRequest;
00234          break;
00235      case "401":
00236          log( ErrorUnauthorizedText, LOGTAG);
00237          ImportResult = IMPORT_Unauthorized;
00238          break;
00239      case "403":
00240          log( ErrorForbiddenText, LOGTAG);
00241          ImportResult = IMPORT_Forbidden;
00242          break;
00243      default:
00244          log( ErrorFNFText, LOGTAG);
00245          ImportResult = IMPORT_NotFound;
00246      }
00247      bWaiting = False;
00248  }
00249  
00250  function bool FillSessionInfo()
00251  {
00252      local string Line;
00253      local string Type;
00254      local string Info;
00255      local bool bValidProfile;
00256  
00257      local string Token1, Token2, Token3, Token4, Token5, Token6, Token7;
00258  
00259      if (ImportS == None)
00260      {
00261          log( ErrorNoSession, LOGTAG);
00262          ImportResult = IMPORT_ServerError;
00263          return false;
00264      }
00265  
00266      if (Buffer == "")
00267      {
00268          log(ErrorNoBuffer, LOGTAG);
00269          ImportResult = IMPORT_ServerError;
00270          return False;
00271      }
00272      else
00273      {
00274          while ( (Left(Buffer,1) ~= CR) || (Left(Buffer,1) ~= LF) )
00275              Buffer = Mid(Buffer,1);
00276      }
00277  
00278      while (ReadBufferedLine(Line))
00279      {
00280          Divide(Line,Chr(58),Type,Info);
00281  
00282          Token1 = ParseDelimited(Info,Token,1);
00283          Token2 = ParseDelimited(Info,Token,2);
00284          Token3 = ParseDelimited(Info,Token,3);
00285          Token4 = ParseDelimited(Info,Token,4);
00286          Token5 = ParseDelimited(Info,Token,5);
00287          Token6 = ParseDelimited(Info,Token,6);
00288          Token7 = ParseDelimited(Info,Token,7);
00289  
00290          switch (Type)
00291          {
00292          case "Profile":
00293              ImportS.setValue("ProfileName",Token1,True);
00294              ImportS.setValue("GameType",Token2,True);
00295              ImportS.setValue("MaxMaps",Token3,True);
00296              ImportS.setValue("GameName",Token4,True);
00297              ImportS.setValue("ACClass",Token5,True);
00298              if (Token6 != "") ImportS.setValue("CustomGameLoc",Token6,True);
00299              if (Token7 != "") ImportS.setValue("CustomACLoc",Token7,True);
00300              bValidProfile = True;
00301              break;
00302  
00303          case "Map":
00304              ImportS.setMap(Token1,int(Token2),True,bool(Token3));
00305              if (Token4 != "") AddRemoteZipLocation(Token1,Token4);
00306              break;
00307  
00308          case "Mutator":
00309              ImportS.setMutator(Token2,True,bool(Token3));
00310              if (Token4 != "") AddRemoteZipLocation(Token2,Token4);
00311  
00312          case "Data":
00313              ImportS.setValue(Token1,Token2,True);
00314              break;
00315          }
00316      }
00317  
00318      if (bValidProfile)
00319          return true;
00320  
00321      ImportResult = IMPORT_InvalidProfile;
00322      return false;
00323  }
00324  
00325  function AddRemoteZipLocation(string PackageName, string PackageLocation)
00326  {
00327      local int i;
00328      local bool ZipFound;
00329  
00330      local ZipLocation Zip;
00331  
00332      i = InStr(PackageName, ".");
00333      if (i != -1)
00334          PackageName = Left(PackageName,i);
00335  
00336      Zip.ProfileURL = ProfileServerAddress $ RemoteProfilePath;
00337      Zip.ZipName = PackageName;
00338      Zip.ZipURL = PackageLocation;
00339  
00340      for (i = 0; i < RemoteZips.Length; i++)
00341      {
00342          if (RemoteZips[i].ProfileURL ~= Zip.ProfileURL && RemoteZips[i].ZipName ~= Zip.ZipName)
00343          {
00344              ZipFound = True;
00345              break;
00346          }
00347      }
00348  
00349      if (ZipFound) RemoteZips[i] = Zip;
00350      else RemoteZips[RemoteZips.Length] = Zip;
00351  
00352      SaveConfig();
00353  }
00354  
00355  function string FindRemoteZipLocation(string PackageName, string ProfileURL, optional bool bAllowOtherLocations)
00356  {
00357      local int i;
00358  
00359      i = InStr(PackageName, ".");
00360      if (i != -1) PackageName = Left(PackageName,i);
00361  
00362      for (i = 0;i < RemoteZips.Length; i++)
00363          if ((RemoteZips[i].ZipName ~= PackageName) && ((RemoteZips[i].ProfileURL ~= ProfileURL) || (bAllowOtherLocations)) )
00364              return RemoteZips[i].ZipURL;
00365  
00366      return "";
00367  }
00368  
00369  function bool SeperateHeaders(string WebPage)
00370  {
00371      local int i;
00372  
00373      //CR$LF$CR$LF seperates header and document
00374      i = InStr(WebPage, CR$LF$CR$LF);
00375  
00376      if (i == -1)
00377          return false;
00378  
00379      Header = Left(WebPage, i);
00380      Buffer = Mid(WebPage, i + 3);
00381      return true;
00382  }
00383  
00384  function string ProcessHeaders()
00385  {
00386      if (Header == "")
00387          return "";
00388  
00389      //Remove all CR, leaving only LF
00390      Header = RemoveStr(Header,CR);
00391  
00392      //Parse Response Code from server, ex. HTTP/1.1 200 OK
00393      return Mid(ParseDelimited(Header,LF,1),9,3);
00394  }
00395  
00396  event ReceivedText(string Text)
00397  {
00398      Buffer = Buffer $ Text;
00399  }
00400  
00401  event ReceivedLine(string Line)
00402  {
00403      local string Result;
00404  
00405      if (SeperateHeaders(Line))
00406          Result = ProcessHeaders();
00407  
00408      if (Result == "200")
00409      {
00410          Result = FindContentType(Line);
00411          if (Result ~= "text/plain")
00412          {
00413              RequestFile(1);
00414              LinkMode = Mode_Text;
00415          }
00416          else
00417          {
00418              ImportResult = IMPORT_InvalidProfile;
00419              bWaiting = False;
00420          }
00421      }
00422  
00423      else
00424      {
00425          ImportResult = IMPORT_NotFound;
00426          bWaiting = False;
00427      }
00428  }
00429  
00430  function string FindContentType(string Text)
00431  {
00432      local array<string> Lines;
00433      local string Tmp;
00434      local int i, j;
00435  
00436      Buffer = Text;
00437      while (ReadBufferedLine(Tmp))
00438          Lines[Lines.Length] = Tmp;
00439  
00440      for (i=0;i<Lines.Length;i++)
00441      {
00442          if (Left(Lines[i],13) ~= "Content-Type:")
00443          {
00444              Tmp = Mid(Lines[i],14);
00445              j = InStr(Tmp,";");
00446              if (j >= 0)
00447                  Tmp = Left(Tmp,j);
00448          }
00449      }
00450  
00451      return Tmp;
00452  }
00453  
00454  function RequestFile(int RequestType)
00455  {
00456      local string RequestMethod, ControlText;
00457  
00458      if (RequestType == 0)
00459      {
00460          RequestMethod = "HEAD";
00461          ControlText = "Keep-Alive";
00462      }
00463      else
00464      {
00465          RequestMethod = "GET";
00466          ControlText = "close";
00467      }
00468  
00469      SendText(RequestMethod@RemoteProfilePath@"HTTP/1.1");
00470      SendText("Host:"@ProfileServerAddress);
00471      SendText("Accept: text/plain");                 // Accept only plain txt files
00472      SendText("User-agent: ProfileManager; UT2003"@Level.EngineVersion);
00473      SendText("Pragma: no-cache");                   // Do not allow proxies to send cached information
00474      SendText("Cache-control: no-cache");
00475      SendText("Connection:"@ControlText);                    // No further information to be sent
00476      SendText("");
00477  }
00478  
00479  function bool ReadBufferedLine(out string Text)
00480  {
00481      local int i;
00482  
00483      i = InStr(Buffer, LF);
00484  
00485      if(i == -1)
00486          return False;
00487  
00488      if (Mid(Buffer, i-1, 1) == CR)
00489          Text = Left(Buffer, i-1);
00490      else Text = Left(Buffer, i);
00491  
00492      Buffer = Mid(Buffer, i+1);
00493      return True;
00494  }
00495  
00496  // Copied from BufferedTcpLink
00497  function string ParseDelimited(string Text, string Delimiter, int Count, optional bool bToEndOfLine)
00498  {
00499      local string Result;
00500      local int Found, i;
00501      local string s;
00502  
00503      Result = "";
00504      Found = 1;
00505  
00506      for(i=0;i<Len(Text);i++)
00507      {
00508          s = Mid(Text, i, 1);
00509          if(InStr(Delimiter, s) != -1)
00510          {
00511              if(Found == Count)
00512              {
00513                  if(bToEndOfLine)
00514                      return Result$Mid(Text, i);
00515                  else
00516                      return Result;
00517              }
00518  
00519              Found++;
00520          }
00521          else
00522          {
00523              if(Found >= Count)
00524                  Result = Result $ s;
00525          }
00526      }
00527  
00528      return Result;
00529  }
00530  
00531  function string RemoveStr(string Source,string mask)
00532  {
00533      local int i;
00534      local string left,right;
00535  
00536      i = InStr(Source,mask);
00537      while (i != -1)
00538      {
00539          Divide(Source,mask,left,right);
00540          Source = Left$Right;
00541          i = InStr(Source,Mask);
00542      }
00543  
00544      return Source;
00545  }

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Image Uploads

Random Page

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

Mapping Topics

Mapping Lessons

UnrealEd Interface

Questions&Answers

Scripting Topics

Scripting Lessons

Making Mods

Class Tree

Questions&Answers

Modeling Topics

Questions&Answers

Log In