| Home Page | Recent Changes

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

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

FAQs

Help Desk

Mapping Topics

Mapping Lessons

UnrealEd Interface

UnrealScript Topics

UnrealScript Lessons

Making Mods

Class Tree

Modeling Topics

Chongqing Page

Log In