| 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