| Home Page | Recent Changes | Preferences

# LadderQuery

UT2003 :: Object >> XAdminBase? >> xWebQueryHandler? >> LadderQuery (Ladder1.46)

    00001  //-----------------------------------------------------------
    00002  //  Ladder.LadderQuery
    00003  //  QueryHandler for webadmin interface
    00004  //-----------------------------------------------------------
    00005  class LadderQuery extends xWebQueryHandler
    00006      DependsOn(ProfileConfigSet)
    00007      config(System);
    00008
    00009  const LOGNAME       = 'LadderQuery';
    00010  const EPICNUMBER    = 85;
    00011
    00012  var LadderGameRules LadderRules;
    00013
    00014  // Profile Tracking Variables
    00015  var SessionMaster           SMaster;
    00016  var ConfigMaster            ConfigM;
    00017  var string                  EpicPackages[EPICNUMBER];
    00018
    00019  // Active Profile Variables
    00020  var StringArray         ProfileMaps;
    00021  var ProfileExporter     ExportMaster;
    00022  var ProfileConfigSet    CurrentProfile;
    00023  var StringArray         ProfileMutators;
    00024
    00025  var string              DefaultProfileName;
    00026
    00027  // Physical page that will be served
    00028  var config string       MasterPage; // This is main html page for Ladder
    00029  var config string       SubFrame;   // Manage sub-frame
    00030  var config string       SubFrameMenu;   // Sub-menu (GameType, Mutators, Maps, PlayInfo, Review)
    00031  var config string       SubFrameContent;
    00032
    00033
    00034  // Include Files
    00035  var config string       IncludeTable;
    00036  var config string       IncludeSection;
    00037  var config string       IncludeRows;
    00038  var config string       IncludeCaptionButton;
    00039  var config string       IncludeMapSelect;
    00040  var config string       IncludeProfileName;
    00041  var config string       IncludeGameType;
    00042  var config string       IncludeCheckBox;
    00043  var config string       IncludeSwitch;
    00044
    00045  // Virtual paths that will be requested from clients
    00046  var config string       ProfileViewURI;
    00047  var config string       ProfileEditURI;
    00048  var config string       ProfileMenuURI;
    00049  var config string       ProfileSwitchURI;
    00050  var config string       ProfileManageURI;
    00051
    00052  var config string       SubFrameURI;    // accessed through manage link - linked to SubFrame page
    00053  var config string       SubFrameMenuURI;
    00054  var config string       SubMapsURI;
    00055  var config string       SubSavedURI;
    00056  var config string       SubRulesURI;
    00057  var config string       SubReviewURI;
    00058  var config string       SubGametypeURI;
    00059  var config string       SubMutatorsURI;
    00060  var config string       SubImportURI;
    00061  var config string       SubExportURI;
    00062
    00063  // Localized Page Help texts
    00064  var localized string    HelpViewProfile;
    00065  var localized string    HelpEditProfile;
    00066  var localized string    HelpSwitchProfile;
    00067  var localized string    HelpManageProfile;
    00068  var localized string    HelpImportProfile;
    00069  var localized string    HelpExportProfile;
    00070  // Subpage help text
    00071  var localized string    HelpGameType;
    00072  var localized string    HelpMutators;
    00073  var localized string    HelpMaps;
    00074  var localized string    HelpPlayInfo;
    00075  var localized string    HelpReview;
    00076
    00077  // Localized Menu Link Text
    00078  var localized string    LinkEditProfile;
    00079  var localized string    LinkViewProfile;
    00080  var localized string    LinkSwitchProfile;
    00081  var localized string    LinkManageProfile;
    00082  var localized string    LinkImportProfile;
    00083  var localized string    LinkExportProfile;
    00084
    00085  // for AddProfilePage/ManageProfilePage
    00086  var localized string    TableTitle[9];
    00087  var localized string    PageCaption[9];
    00088  var localized string    ProfileButtonName[9];
    00089  var localized string    ProfileButtonValue[9];
    00090
    00091  // Section Headers & Text
    00092  var localized string    MapText;
    00093  var localized string    ErrorText;
    00094  var localized string    MutatorText;
    00095  var localized string    RequiredText;
    00096  var localized string    AvailableText;
    00097  var localized string    UnlimitedText;
    00098  var localized string    FollowingMaps;
    00099  var localized string    AreAssignedText;
    00100  var localized string    AreAvailableText;
    00101  var localized string    FollowingMutators;
    00102  var localized string    CommandLineOptionsTitle;
    00103
    00104  // Button Values
    00105  var localized string    ButtonLoadProfile;          // Label for "switch immediately" button
    00106  var localized string    ButtonDeleteProfile;
    00107  var localized string    ButtonPreviewProfile;       // Label for previewing remote profile button
    00108  var localized string    ButtonApplyImportProfile;
    00109  var localized string    ButtonApplyExportProfile;
    00110  var localized string    ButtonApplyProfileChanges;
    00111
    00112  // Input form labels
    00113  var localized string    LabelCopyProfile;
    00114  var localized string    LabelDeleteProfile;
    00115  var localized string    LabelImportProfile;
    00116  var localized string    LabelExportProfile;
    00117  var localized string    LabelAddProfile;
    00118  var localized string    LabelSelectActions;
    00119  var localized string    LabelTextboxActions;
    00120
    00121  var localized string    LabelPlayInfo;
    00122  var localized string    LabelGeneralProfile;
    00123  var localized string    LabelGameType;
    00124  var localized string    LabelProfileName;
    00125  var localized string    LabelAccessControl;
    00126  var localized string    LabelChooseAction;
    00127  var localized string    LabelManagement;
    00128  var localized string    LabelInputDescription;
    00129
    00130  var localized string    LabelMaxMaps;
    00131  var localized string    LabelNumberGames;
    00132  var localized string    LabelCheckAllMap;
    00133  var localized string    LabelRequiredMaps;
    00134  var localized string    LabelUncheckAllMap;
    00135  var localized string    LabelChangeMaplist;
    00136  var localized string    LabelCheckAllMutator;
    00137  var localized string    LabelRequiredMutators;
    00138  var localized string    LabelNumberMatchesLeft;
    00139  var localized string    LabelUncheckAllMutator;
    00140  var localized string    LabelDelayProfileChange;
    00141  var localized string    LabelApplyImportProfile;
    00142  var localized string    LabelApplyExportProfile;
    00143  var localized string    LabelModifyProfile;
    00144
    00145  // Success Messages
    00146  var localized string    SuccessText;
    00147  var localized string    SuccessDeleteProfile;
    00148  var localized string    SuccessExportProfile;
    00149  var localized string    SuccessImportProfile;
    00150  var localized string    SuccessImportProfileTitle;
    00151  var localized string    SuccessCopyProfile;
    00152  var localized string    SuccessSwitchProfile;
    00153
    00154  // Profile Errors
    00155  var localized string    ErrorLoadingPlayInfoText[5];
    00156  var localized string    ErrorGameRulesNotFound;
    00157  var localized string    ErrorGameClassText;
    00158  var localized string    ErrorGameClassTitle;
    00159  var localized string    ErrorAccessControlText;
    00160  var localized string    ErrorAccessControlTitle;
    00161  var localized string    ErrorSameProfileName;
    00162  var localized string    ErrorRemoteMutator;
    00163  var localized string    ErrorRemoteServerActor;
    00164  var localized string    ErrorSavingProfile;
    00165  var localized string    ErrorDeletingProfile;
    00166  var localized string    ErrorExportingProfile;
    00167  var localized string    ErrorNoProfilesExist;
    00168  var localized string    ErrorCopyFrom;
    00169  var localized string    ErrorCopyNoName;
    00170  var localized string    ErrorExcludeMapNotFound;
    00171  var localized string    ErrorIncludeMapNotFound;
    00172  var localized string    ErrorReplacingWebConnection;
    00173  var localized string    ImportClassSpawnError;
    00174  var localized string    ImportProfileFailText;
    00175  var localized string    ImportProfileFailTitle;
    00176
    00177  // Import errors
    00178  var localized string    ErrorBind;
    00179  var localized string    ErrorBadURL;
    00180  var localized string    ErrorServer;
    00181  var localized string    ErrorResolve;
    00182  var localized string    ErrorProfile;
    00183  var localized string    ErrorTimeout;
    00184  var localized string    ErrorNotFound;
    00185  var localized string    ErrorForbidden;
    00186  var localized string    ErrorBadRequest;
    00187  var localized string    ErrorUnauthorized;
    00188
    00189  function bool Init()
    00190  {
    00191      local GameRules GR;
    00192
    00193      for (GR=Level.Game.GameRulesModifiers;GR!=None;GR=GR.NextGameRules)
    00194          if (LadderGameRules(GR) != None)
    00195              LadderRules = LadderGameRules(GR);
    00196
    00197      if (LadderRules == None)
    00198      {
    00199          Cleanup();
    00200          return false;
    00201      }
    00202
    00203      if (ConfigM == None && ConfigMaster(Level.Game.BaseMutator.NextMutator) != None)
    00204          ConfigM = ConfigMaster(Level.Game.BaseMutator.NextMutator);
    00205
    00206      GetCurrentConfigSet();
    00207      ExportMaster            = new class'ProfileExporter';
    00208      DefaultProfileName      = LadderRules.DefaultProfileName;
    00209
    00210      SMaster                 = new(None) class'SessionMaster';
    00211      ProfileMaps             = new(None) class'SortedStringArray';
    00212      ProfileMutators         = new(None) class'SortedStringArray';
    00213
    00214      Assert(Level.Game.AccessControl != None);
    00215      return true;
    00216  }
    00217
    00218  //////////////////////////////////////////////////////////////
    00219  //////////////////////////////////////////////////////////////
    00220  // Session Manipulation Functions
    00221  //
    00222
    00223  // Load profile information into session object
    00224  function CreateSessionInfo(coerce int ProfileIndex, string SID, optional bool bIncludeNonActive, optional bool bSave, optional bool bQuiet)
    00225  {
    00226      local int                                       i;
    00227      local Session                                   CurS;
    00228      local string                                    TempStr;
    00229      local array<string>                             TempArr;
    00230      local ProfileConfigSet                          TempPCS;
    00231      local array<ProfileConfigSet.ProfileMutator>    AllPCSMutators;
    00232      local array<ProfileConfigSet.ProfileMap>        AllPCSMaps;
    00233      local array<ProfileConfigSet.ProfileSA> AllPCSServerActors;
    00234
    00235      if (SID == "")
    00236          return;
    00237
    00238      CurS = SMaster.getSession(SID,true);
    00239      TempPCS = LadderRules.LadderProfiles[ProfileIndex];
    00240      TempPCS.StartEdit();
    00241
    00242  // General profile information
    00243      CurS.setValue("ProfileIndex", string(ProfileIndex), true);
    00244      CurS.setValue("ProfileName",LadderRules.Profiles[ProfileIndex].ProfileName,true);
    00245      CurS.setValue("GameType", string(TempPCS.GetGameClass()), True);
    00246      CurS.setValue("ACClass", TempPCS.GetAccessControl(), True);
    00247      CurS.setValue("MaxMaps", string(TempPCS.GetMaxMaps()), True);
    00248
    00249      AllPCSMutators = TempPCS.GetProfileMutators();
    00250      AllPCSMaps = TempPCS.GetProfileMaps();
    00251      AllPCSServerActors = TempPCS.GetProfileServerActors();
    00252
    00253      TempArr = LadderRules.GetProfileMutators(string(ProfileIndex));
    00254      TempStr = class'wUtils103.wArray'.static.Join(TempArr,",");
    00255
    00256  // Load profile mutator information
    00257      CurS.ClearMutators();
    00258      for (i=0;i<AllPCSMutators.Length;i++)
    00259         if (AllPCSMutators[i].bRequired || (InStr(TempStr,AllPCSMutators[i].MutatorName)!=-1) || bIncludeNonActive)
    00260             CurS.setMutator(AllPCSMutators[i].MutatorName,True,AllPCSMutators[i].bRequired);
    00261
    00262      TempArr = LadderRules.GetProfileMaps(string(ProfileIndex));
    00263      TempStr = class'wUtils103.wArray'.static.Join(TempArr,",");
    00264
    00265  // Load profile map information
    00266      CurS.ClearMaps();
    00267      for (i=0;i<AllPCSMaps.Length;i++)
    00268         if (AllPCSMaps[i].bRequired || (InStr(TempStr,AllPCSMaps[i].MapName)!=-1) || bIncludeNonActive)
    00269             CurS.setMap(AllPCSMaps[i].MapName,AllPCSMaps[i].MapListOrder,True,AllPCSMaps[i].bRequired);
    00270
    00271      TempArr = LadderRules.GetProfileServerActors(string(ProfileIndex));
    00272      TempStr = class'wUtils103.wArray'.static.Join(TempArr,",");
    00273
    00274  // Load ServerActor info
    00275      CurS.ClearServerActors();
    00276      for (i=0;i<AllPCSServerActors.Length;i++)
    00277          if (AllPCSServerActors[i].bRequired || InStr(TempStr,AllPCSServerActors[i].ActorClass)!=-1 || bIncludeNonActive)
    00278              CurS.setServerActor(AllPCSServerActors[i].ActorClass, True, AllPCSServerActors[i].bRequired);
    00279
    00280  // Load profile PlayInfo data
    00281      for (i=0;i<TempPCS.Count();i++)
    00282          CurS.setValue(TempPCS.GetProfileParamName(i),TempPCS.GetProfileParam(i),True);
    00283
    00284      TempPCS.EndEdit(bSave,bQuiet);
    00285  }
    00286
    00287  // Initialize session data for recently imported profile
    00288  function ProfileConfigSet CreateImportSessionInfo(Session CurS)
    00289  {
    00290      local int                       i;
    00291      local string                    TempStr, Tmp;
    00292      local PlayInfo                  TempPI;
    00293      local ProfileConfigSet          TempPCS;
    00294
    00295      local class<Mutator>            MutClass;
    00296      local class<GameInfo>           GIClass;
    00297      local class<AccessControl>      ACClass;
    00298      local class<Info>               ServerActorClass;
    00299      local array<class<Info> >       SAClass;
    00300      local array<class<Mutator> >    MClass;
    00301
    00302      TempPCS = LadderRules.AddProfile(CurS.getValue("ProfileName"),CurS.getValue("GameType"));
    00303      if (TempPCS.StartEdit())
    00304      {
    00305          TempStr = CurS.getValue("GameType");
    00306          if (TempStr != "")
    00307              GIClass = class<GameInfo>(DynamicLoadObject(TempStr,class'Class'));
    00308          if (GIClass == None) return None;
    00309
    00310          TempStr = CurS.getValue("ACClass",Level.Game.AccessControlClass);
    00311          if (TempStr != "")
    00312              ACClass = class<AccessControl>(DynamicLoadObject(TempStr,class'Class'));
    00313          if (ACClass == None) return None;
    00314
    00315          TempPI = new(None) class'PlayInfo';
    00316
    00317  // Mutators
    00318          for (i=0;i<CurS.getMutatorLength();i++)
    00319          {
    00320              TempStr = CurS.getMutator(i);
    00321              MutClass = class<Mutator>(DynamicLoadObject(TempStr, class'Class'));
    00322              if (MutClass != None)
    00323              {
    00324                  MClass[MClass.Length] = MutClass;
    00325                  TempPCS.AddProfileMutator(TempStr,CurS.MutRequired(TempStr));
    00326              }
    00327
    00328              else log(ErrorRemoteMutator@TempStr,LOGNAME);
    00329          }
    00330
    00331          for (i=0;i<CurS.getSALength();i++)
    00332          {
    00333              TempStr = CurS.getServerActor(i);
    00334              ServerActorClass = class<Info>(DynamicLoadObject(TempStr,class'Class'));
    00335              if (ServerActorClass != None)
    00336              {
    00337                  SAClass[SAClass.Length] = ServerActorClass;
    00338                  TempPCS.AddProfileServerActor(TempStr,CurS.SARequired(TempStr));
    00339              }
    00340              else log(ErrorRemoteServerActor@TempStr,LOGNAME);
    00341          }
    00342
    00343          LoadThisPlayInfo(TempPI, GIClass, ACClass, MClass, SAClass);
    00344
    00345  // Maps
    00346          for (i=0;i<CurS.getMapLength();i++)
    00347          {
    00348              TempStr = CurS.getMap(i);
    00349              TempPCS.AddProfileMap(TempStr,CurS.MapRequired(TempStr));
    00350          }
    00351
    00352  // PlayInfo
    00353          for (i=0;i<TempPI.Settings.Length;i++)
    00354          {
    00355              TempStr = ""; Tmp="";
    00356              if (CurS.getIdValue(i,TempStr,Tmp) == -1)
    00357                  break;
    00358              if ( !SettingIsAllowed(TempPI.Settings[i].SecLevel) ) continue;
    00359              if (!TempPCS.SetProfileNamedParam(TempPI.Settings[i].SettingName, CurS.getValue(TempPI.Settings[i].SettingName,TempPI.Settings[i].Value)))
    00360                  TempPCS.SetProfileParam(TempPCS.Count(),TempPI.Settings[i].SettingName,CurS.getValue(TempPI.Settings[i].SettingName,TempPI.Settings[i].Value));
    00361          }
    00362
    00363          TempPCS.EndEdit(True);
    00364          return TempPCS;
    00365      }
    00366
    00367      else log(ErrorServer,LOGNAME);
    00368
    00369      return None;
    00370  }
    00371
    00372  // Clear session data and optionally create new session object
    00373  function string ResetSessionID(Session CurS, optional bool bDestroySession)
    00374  {
    00375      local string OldSID;
    00376
    00377      if (bDestroySession) SMaster.destroySession(CurS);
    00378      else CurS.ResetSession();
    00379
    00380      CurS = SMaster.getSession(OldSID,true);
    00381      return CurS.GetHash();
    00382  }
    00383
    00384
    00385  ////////////////////////////////////////////////////////////
    00386  ////////////////////////////////////////////////////////////
    00387  // Profile manipulation methods
    00388  //
    00389
    00390  function int LoadThisPlayInfo(PlayInfo PI, class<GameInfo> ThisGameInfo, class<AccessControl> ThisAccessControl, array<class<Mutator> > ThisMutator, array<class<Info> > ThisServerActor)
    00391  {
    00392      local int i;
    00393      local class<Mutator> M;
    00394
    00395      if (PI == None)
    00396          return 0;
    00397      PI.Clear();
    00398
    00399      if (ThisGameInfo == None)
    00400          return 1;
    00401
    00402      if (ThisAccessControl == None)
    00403          return 2;
    00404
    00405      if (ThisMutator.Length > 0)
    00406          for (i=0;i<ThisMutator.Length;i++)
    00407              if (ThisMutator[i] == None)
    00408                  return 3;
    00409
    00410      if (ThisServerActor.Length > 0)
    00411          for (i=0;i<ThisServerActor.Length;i++)
    00412              if (ThisServerActor[i] == None)
    00413                  return 4;
    00414
    00415      ThisGameInfo.static.FillPlayInfo(PI);
    00416      PI.PopClass();
    00417
    00418      if (ThisGameInfo.default.MutatorClass != "")
    00419      {
    00420          M = class<Mutator>(DynamicLoadObject(ThisGameInfo.default.MutatorClass,class'Class'));
    00421          if (M != None)
    00422              M.static.FillPlayInfo(PI);
    00423      }
    00424
    00425      ThisAccessControl.static.FillPlayInfo(PI);
    00426      PI.PopClass();
    00427
    00428      for (i = 0; i < ThisMutator.Length; i++)
    00429      {
    00430          ThisMutator[i].static.FillPlayInfo(PI);
    00431          PI.PopClass();
    00432      }
    00433
    00434      for (i = 0; i < ThisServerActor.Length; i++)
    00435      {
    00436          ThisServerActor[i].static.FillPlayInfo(PI);
    00437          PI.PopClass();
    00438      }
    00439
    00440      class'CommandLineParams'.static.FillPlayInfo(PI);
    00441      PI.PopClass();
    00442
    00443      return -1;
    00444  }
    00445
    00446  function ProfileConfigSet GetCurrentConfigSet()
    00447  {
    00448      local int i;
    00449
    00450      if (CurrentProfile == None)
    00451      {
    00452          i = LadderRules.FindActiveProfile();
    00453          if (i >= 0) CurrentProfile = LadderRules.LadderProfiles[i];
    00454      }
    00455
    00456      return CurrentProfile;
    00457  }
    00458
    00459  function int GetCurrentConfigIndex()
    00460  {
    00461      local int i;
    00462
    00463      if (CurrentProfile != None)
    00464          for (i = 0;i < LadderRules.LadderProfiles.Length;i++)
    00465              if (LadderRules.LadderProfiles[i] == CurrentProfile)
    00466                  return i;
    00467
    00468      return LadderRules.FindActiveProfile();
    00469  }
    00470
    00471  // Returns an array of class names for mutators that this profile will use in the game
    00472  function array<string> LoadActiveProfileMutators(optional string CurrentProfileItem)
    00473  {
    00474      return LadderRules.GetProfileMutators(CurrentProfileItem);
    00475  }
    00476
    00477  function array<string> LoadActiveProfileServerActors(optional string CurrentProfileItem)
    00478  {
    00479      return LadderRules.GetProfileServerActors(CurrentProfileItem);
    00480  }
    00481
    00482  // Returns an array of map names that in the maplist for this profile
    00483  function array<string> LoadActiveProfileMaps(optional string CurrentProfileItem)
    00484  {
    00485      return LadderRules.GetProfileServerActors(CurrentProfileItem);
    00486  }
    00487  /*
    00488  function CreateFullMutatorList(out StringArray Mutators, out StringArray GroupsOnly)
    00489  {
    00490      local StringArray Grouped;
    00491      local int i,j,z;
    00492      local string GrpName;
    00493      local string thisgroup, nextgroup;
    00494
    00495  // This class provides a specialized sorting function
    00496  // since mutators may be grouped - mutators in the same groups
    00497  // are not allowed to be selected togther
    00498
    00499      Grouped = new(None) class'SortedStringArray';
    00500
    00501  // Create array sorted on GroupName...this allows to flag
    00502  // the mutator for a different .inc file
    00503      for (i = 0; i < Mutators.Count(); i++)
    00504      {
    00505          j = int(Mutators.GetItem(i));
    00506
    00507  // If the mutator author forgot to configure a group name for the mutator
    00508          if (AllMutators[j].GroupName == "")
    00509              GrpName = "Z" $ string (z++);
    00510          else GrpName = AllMutators[j].GroupName;
    00511
    00512          Grouped.Add(string(j),GrpName $ "." $ AllMutators[j].FriendlyName);
    00513      }
    00514
    00515  // Move all grouped mutators to GroupsOnly StringArray for sorting by friendly name
    00516      for (i=0;i<Grouped.Count();i++)
    00517      {
    00518          thisgroup = AllMutators[int(Grouped.GetItem(i))].GroupName;
    00519          nextgroup = "";
    00520
    00521          if (thisgroup=="")
    00522              continue;
    00523          if (i+1<Grouped.Count())
    00524              nextgroup = AllMutators[int(Grouped.GetItem(i+1))].GroupName;
    00525
    00526          if (thisgroup ~= nextgroup)
    00527          {
    00528              j=i;
    00529              while(nextgroup~=thisgroup && j<Grouped.Count())
    00530              {
    00531                  GroupsOnly.MoveFromId(Grouped, Grouped.FindItemId(Grouped.GetItem(j)));
    00532                  thisgroup = nextgroup;
    00533                  if (j+1==Grouped.Count())
    00534                      nextgroup="";
    00535                  else nextgroup = AllMutators[int(Grouped.GetItem(j+1))].GroupName;
    00536              }
    00537              if (j<Grouped.Count())
    00538                  GroupsOnly.MoveFromId(Grouped,Grouped.FindItemId(Grouped.GetItem(j)));
    00539              i=-1;
    00540          }
    00541      }
    00542
    00543  // Move all non-grouped mutators back to Mutators array
    00544  // for re-sorting by Friendly Name
    00545      Mutators.Reset();
    00546      for (i=0;i<Grouped.Count();i++)
    00547      {
    00548          j=int(Grouped.GetItem(i));
    00549          Mutators.Add(string(j),AllMutators[j].FriendlyName);
    00550      }
    00551      Grouped.Reset();
    00552  }
    00553  */
    00554  //****************************************************************
    00555  //****************************************************************
    00556  // Helper functions
    00557  //
    00558  //****************************************************************
    00559  //**************************
    00560  // HTML Generation
    00561  //*************************
    00562
    00563  // Creates a listing of PlayInfo data
    00564  // Pass "defaults_row" in the 'IncludeFile' param to add the
    00565  // input form objects to the output
    00566
    00567  function string GeneratePlayInfoRows(WebRequest Req, WebResponse Res, string IncludeFile)
    00568  {
    00569      local int i,j,k,z;
    00570      local string    TempStr, Data, Op, SID,
    00571                      TempRow, HeadingRow, PlayInfoRows;
    00572
    00573      local Session       CurS;
    00574      local PlayInfo      TempPI;
    00575      local StringArray   Info, InfoC, InfoS, InfoT;
    00576
    00577      local array<string>         Options;
    00578      local class<Mutator>        TempMut;
    00579      local class<Info>           TempSA;
    00580      local class<GameInfo>       GIClass;
    00581      local class<AccessControl>  ACClass;
    00582      local array<class<Mutator> > MClass;
    00583      local array<class<Info> >   SAClass;
    00584
    00585      SID = Req.GetVariable("SessionID");
    00586      CurS = SMaster.GetSession(SID);
    00587
    00588      TempStr = CurS.getValue("GameType");
    00589      if (TempStr != "")
    00590          GIClass = class<GameInfo>(DynamicLoadObject(TempStr,class'Class'));
    00591      if (GIClass == None)
    00592      {
    00593          ShowMessage(Res,ErrorGameClassTitle,ErrorGameClassText);
    00594          return "";
    00595      }
    00596
    00597      TempStr = CurS.getValue("ACClass",Level.Game.AccessControlClass);
    00598      if (TempStr != "")
    00599          ACClass = class<AccessControl>(DynamicLoadObject(TempStr,class'Class'));
    00600      if (ACClass == None)
    00601      {
    00602          ShowMessage(Res,ErrorAccessControlTitle,ErrorAccessControlText);
    00603          return "";
    00604      }
    00605
    00606      for (i=0;i<CurS.GetMutatorLength();i++)
    00607      {
    00608          TempStr = CurS.getMutator(i);
    00609          if (TempStr != "")
    00610          {
    00611              TempMut = class<Mutator>(DynamicLoadObject(TempStr,class'Class'));
    00612              if (TempMut != None)
    00613                  MClass[MClass.Length] = TempMut;
    00614          }
    00615      }
    00616
    00617      for (i=0;i<CurS.getSALength();i++)
    00618      {
    00619          TempStr = CurS.getServerActor(i);
    00620          if (TempStr != "")
    00621          {
    00622              TempSA = class<Info>(DynamicLoadObject(TempStr,class'Class'));
    00623              if (TempSA != None)
    00624                  SAClass[SAClass.Length] = TempSA;
    00625          }
    00626      }
    00627
    00628      // Initialize and fill PlayInfo
    00629      TempPI = new(None) class'PlayInfo';
    00630      LoadThisPlayInfo(TempPI, GIClass, ACClass, MClass, SAClass);
    00631
    00632      for (i=0;i<TempPI.Settings.Length;i++)
    00633          if (CurS.HasData(TempPI.Settings[i].SettingName))
    00634              TempPI.StoreSetting(i, CurS.getValue(TempPI.Settings[i].SettingName,TempPI.Settings[i].Value));
    00635
    00636      InfoC = new(None) class'SortedStringArray'; // Checkboxes
    00637      InfoS = new(None) class'SortedStringArray'; // Selects
    00638      InfoT = new(None) class'SortedStringArray'; // Textboxes
    00639      Info  = new(None) class'SortedStringArray'; // Contains each unique ClassFrom value
    00640
    00641      // Want to allow admin to input values for each setting
    00642      if (IncludeFile ~= "defaults_row")
    00643      {
    00644          for (i=0;i<TempPI.Settings.Length;i++)
    00645          {
    00646              if (TempPI.Settings[i].RenderType~="Text")
    00647              {
    00648                  // Hack for MOTD sorting
    00649                  if (Left(TempPI.Settings[i].SettingName,Len(TempPI.Settings[i].SettingName) - 1) ~= "GameReplicationInfo.MOTDLine")
    00650                      InfoT.Add(string(i), TempPI.Settings[i].SettingName);
    00651                  else InfoT.Add(string(i),TempPI.Settings[i].DisplayName);
    00652              }
    00653
    00654              else if (TempPI.Settings[i].RenderType~="Check")
    00655                  InfoC.Add(string(i),TempPI.Settings[i].DisplayName);
    00656
    00657              else if (TempPI.Settings[i].RenderType~="Select")
    00658                  InfoS.Add(string(i),TempPI.Settings[i].DisplayName);
    00659
    00660              for (j=0;j<Info.Count();j++)
    00661                  if (Info.GetTag(j) ~= string(TempPI.Settings[i].ClassFrom))
    00662                      break;
    00663
    00664              if (j == Info.Count())
    00665                  Info.Add(string(i), string(TempPI.Settings[i].ClassFrom));
    00666          }
    00667
    00668          for (k=0;k<Info.Count();k++)
    00669          {
    00670              TempRow = ""; HeadingRow = "";
    00671              Res.Subst("RowContent", "<td class=ttext colspan=\"3\">"$Info.GetTag(k)$"</td>");
    00672              HeadingRow = WebInclude(RowLeft);
    00673
    00674              for (i=0;i<InfoC.Count();i++)
    00675              {
    00676                  TempStr = "";
    00677                  j=int(InfoC.GetItem(i));
    00678                  if (!SettingIsAllowed(TempPI.Settings[j].SecLevel) || (string(TempPI.Settings[j].ClassFrom)!=Info.GetTag(k)))
    00679                      continue;
    00680
    00681                  Res.Subst("Content", Checkbox(TempPI.Settings[j].SettingName, TempPI.Settings[j].Value ~= "True", TempPI.Settings[j].Data != ""));
    00682                  TempStr = WebInclude(CellLeft);
    00683
    00684                  Res.Subst("Content", "<span class=location title=\"Required Security Level\">"$TempPI.Settings[j].SecLevel$"</span>");
    00685                  TempStr += WebInclude(CellLeft);
    00686
    00687                  Res.Subst("Content", "<span class='location'>"$HtmlEncode(TempPI.Settings[j].DisplayName)$"</span>");
    00688                  Res.Subst("RowContent", WebInclude(CellLeft) $ TempStr);
    00689                  TempRow += WebInclude(RowLeft);
    00690              }
    00691
    00692              for (i=0;i<InfoT.Count();i++)
    00693              {
    00694                  TempStr = "";
    00695                  j = int(InfoT.GetItem(i));
    00696                  if (!SettingIsAllowed(TempPI.Settings[j].SecLevel) || (string(TempPI.Settings[j].ClassFrom)!=Info.GetTag(k)))
    00697                      continue;
    00698
    00699                  Data = "8";
    00700                  if (TempPI.Settings[j].Data != "")
    00701                  {
    00702                      Data = TempPI.Settings[j].Data;
    00703                      Divide(TempPI.Settings[j].Data, ";", Data, Op);
    00704                      TempPI.SplitStringToArray(Options, Op, ":");
    00705                  }
    00706
    00707                  Op = "";
    00708                  if (Options.Length > 1)
    00709                      Op = " ("$Options[0]$" - "$Options[1]$")";
    00710
    00711                  Res.Subst("Content", Textbox(TempPI.Settings[j].SettingName, Data, 3 * int(Data), TempPI.Settings[j].Value) $ Op);
    00712                  TempStr = WebInclude(CellLeft);
    00713
    00714                  Res.Subst("Content", "<span class=location title=\"Required Security Level\">"$TempPI.Settings[j].SecLevel$"</span>");
    00715                  TempStr += WebInclude(CellLeft);
    00716
    00717                  Res.Subst("Content", "<span class='location'>"$HtmlEncode(TempPI.Settings[j].DisplayName)$"</span>");
    00718                  Res.Subst("RowContent", WebInclude(CellLeft) $ TempStr);
    00719                  TempRow += WebInclude(RowLeft);
    00720              }
    00721
    00722              for (i=0;i<InfoS.Count();i++)
    00723              {
    00724                  Data = ""; TempStr = "";
    00725                  j=int(InfoS.GetItem(i));
    00726                  if (!SettingIsAllowed(TempPI.Settings[j].SecLevel) || (string(TempPI.Settings[j].ClassFrom)!=Info.GetTag(k)))
    00727                      continue;
    00728                  // Build a set of options from PID.Data
    00729                  TempPI.SplitStringToArray(Options, TempPI.Settings[j].Data, ";");
    00730                  for (z = 0; (z+1)<Options.Length; z += 2)
    00731                  {
    00732                      Data += ("<option value='"$Options[z]$"'");
    00733                      If (TempPI.Settings[j].Value == Options[z])
    00734                          Data @= "selected";
    00735                      Data += (">"$HtmlEncode(Options[z+1])$"</option>");
    00736                  }
    00737
    00738                  Res.Subst("Content", Select(TempPI.Settings[j].SettingName, Data));
    00739                  TempStr = WebInclude(CellLeft);
    00740
    00741                  Res.Subst("Content", "<span class=location title=\"Required Security Level\">"$TempPI.Settings[j].SecLevel$"</span>");
    00742                  TempStr += WebInclude(CellLeft);
    00743
    00744                  Res.Subst("Content", "<span class='location'>"$HtmlEncode(TempPI.Settings[j].DisplayName)$"</span>");
    00745                  Res.Subst("RowContent", WebInclude(CellLeft) $ TempStr);
    00746                  TempRow += WebInclude(RowLeft);
    00747              }
    00748
    00749              if (TempRow!="")
    00750                  PlayInfoRows += (HeadingRow$TempRow);
    00751          }
    00752      }
    00753      else    // Displaying values only
    00754      {
    00755          for (i=0;i<TempPI.Settings.Length;i++)
    00756          {
    00757              if (Left(TempPI.Settings[i].SettingName,Len(TempPI.Settings[i].SettingName) - 1) ~= "GameReplicationInfo.MOTDLine")
    00758                  InfoS.Add(string(i), TempPI.Settings[i].SettingName);
    00759              else InfoS.Add(string(i),TempPI.Settings[i].DisplayName);
    00760
    00761              for (j=0;j<Info.Count();j++)
    00762                  if (Info.GetTag(j) ~= string(TempPI.Settings[i].ClassFrom))
    00763                      break;
    00764              if (j == Info.Count())
    00765                  Info.Add(string(i), string(TempPI.Settings[i].ClassFrom));
    00766          }
    00767
    00768          for (k=0;k<Info.Count();k++)
    00769          {
    00770              TempRow = "";
    00771              HeadingRow = "<tr><td class=ttext colspan=\"2\">"$Info.GetTag(k)$"</td></tr>";
    00772              for (i=0;i<InfoS.Count();i++)
    00773              {
    00774                  j=int(InfoS.GetItem(i));
    00775                  Data = "";
    00776
    00777                  if (!SettingIsAllowed(TempPI.Settings[j].SecLevel) || (string(TempPI.Settings[j].ClassFrom)!=Info.GetTag(k)))
    00778                      continue;
    00779
    00780                  Res.Subst("SettingName", HtmlEncode(TempPI.Settings[j].DisplayName));
    00781
    00782                  if (TempPI.Settings[j].Value ~= "true")
    00783                      Data = "True";
    00784
    00785                  else if (TempPI.Settings[j].Value ~= "false")
    00786                      Data = "False";
    00787
    00788                  else
    00789                  {
    00790                      if (TempPI.Settings[j].RenderType ~= "Select")
    00791                      {
    00792                          class'wUtils103.wString'.static.Split2(TempPI.Settings[j].Data, ";", Options);
    00793                          for (z=0;(z+1)<Options.Length;z+=2)
    00794                          {
    00795                              if (TempPI.Settings[j].Value == Options[z])
    00796                              {
    00797                                  Data = Options[z+1];
    00798                                  break;
    00799                              }
    00800                          }
    00801                      }
    00802                      else Data = TempPI.Settings[j].Value;
    00803                  }
    00804
    00805                  Res.Subst("SettingData", HtmlEncode(Data));
    00806                  Res.Subst("Extra", "");
    00807                  TempRow += WebInclude(IncludeFile);
    00808              }
    00809
    00810              if (TempRow!="")
    00811                  PlayInfoRows += (HeadingRow$TempRow);
    00812          }
    00813      }
    00814      return PlayInfoRows;
    00815  }
    00816
    00817  // Creates the drop-down box containing profiles names
    00818  function String GenerateSwitchProfileOptions(optional string CurrentProfileItem)
    00819  {
    00820      local int i;
    00821      local string SelectedStr, OptionStr;
    00822
    00823      if (LadderRules.AllLadderProfiles.Count() == 0)
    00824          return "<option value=\"\">***"@NoneText@"***</option>";
    00825
    00826      for (i=0; i < LadderRules.AllLadderProfiles.Count(); i++)
    00827      {
    00828      // This item was the item passed in by CurrentProfileItem, so make it active
    00829          if (CurrentProfileItem ~= LadderRules.AllLadderProfiles.GetItem(i))
    00830              SelectedStr = " selected";
    00831          else SelectedStr = "";
    00832
    00833          OptionStr = OptionStr$"<option value=\""$LadderRules.AllLadderProfiles.GetItem(i)$"\""$SelectedStr$">"$LadderRules.AllLadderProfiles.GetTag(i)@"</option>";
    00834      }
    00835      return OptionStr;
    00836  }
    00837
    00838  function bool SettingIsAllowed(byte SettingSecLevel)
    00839  {
    00840      return SettingSecLevel <= CurAdmin.MaxSecLevel();
    00841  }
    00842
    00843  // Handles generation of the double map select boxes (Exclude & Include)
    00844  function String CreateMapListSelect(array<ProfileConfigSet.ProfileMap> AllPCSMaps, StringArray MapList, StringArray MovedMaps)
    00845  {
    00846      local int i,j;
    00847      local String ResponseStr, SelectedStr, Tmp;
    00848
    00849      if (MapList.Count() == 0)
    00850          return "<option value=\"\">***"@NoneText@"***</option>";
    00851
    00852      for (i = 0; i<MapList.Count(); i++)
    00853      {
    00854      // Index for map within AllPCSMaps
    00855          j = int(MapList.GetItem(i));
    00856
    00857          Tmp = AllPCSMaps[j].MapName;
    00858          SelectedStr = "";
    00859          if (MovedMaps != None && MovedMaps.FindItemId(string(j)) >= 0)
    00860              SelectedStr = " selected";
    00861          ResponseStr = ResponseStr$"<option value=\""$Tmp$"\""$SelectedStr$">"$Tmp$"</option>";
    00862      }
    00863
    00864      return ResponseStr;
    00865  }
    00866
    00867  //**********************
    00868  // Import / Export
    00869  //**********************
    00870
    00871  // Handles spacing for textboxes on export page
    00872  function int GetLongestURL()
    00873  {
    00874      local int i, Current, Largest;
    00875
    00876      for (i = 0; i < ExportMaster.Zips.Length; i++)
    00877      {
    00878          Current = Len(ExportMaster.Zips[i].ZipURL);
    00879          if (Current > Largest)
    00880              Largest = Current;
    00881      }
    00882
    00883      return Largest + 1;
    00884  }
    00885
    00886  // Handles filling in zip-location textboxes on export page
    00887  function string GetLocation(string Package)
    00888  {
    00889      local int i;
    00890
    00891      // Check if we're dealing with a map or a mutator
    00892      i = InStr(Package, ".");
    00893
    00894      // Dealing with a mutator - remove class name
    00895      if (i != -1)
    00896          Package = Left(Package, i);
    00897
    00898      return ExportMaster.FindZipLocation(Package);
    00899  }
    00900
    00901  // Handles saving zip file locations from export page
    00902  function SetLocation(string Package, string NewLocation)
    00903  {
    00904      local int i;
    00905
    00906      // Check if we're dealing with a map or a mutator
    00907      i = InStr(Package, ".");
    00908
    00909      // Dealing with a mutator - remove class name
    00910      if (i != -1)
    00911          Package = Left(Package, i);
    00912
    00913      if (NewLocation == "")
    00914          ExportMaster.DeleteZipLocation(Package);
    00915      else ExportMaster.AddZipLocation(Package, NewLocation);
    00916  }
    00917
    00918  // Utility function to remove strings from profile names before
    00919  // creating .txt for exported profile
    00920  function string RemoveStr(string Source,string mask)
    00921  {
    00922      local int i;
    00923      local string left,right;
    00924
    00925      i = InStr(Source,mask);
    00926      while (i != -1)
    00927      {
    00928          Divide(Source,mask,left,right);
    00929          Source = Left$Right;
    00930          i = InStr(Source,Mask);
    00931      }
    00932
    00933      return Source;
    00934  }
    00935
    00936  // Prevents entering a zip file location for any package
    00937  // that is already included with the game
    00938  function bool EpicPackage(string Package)
    00939  {
    00940      local int i;
    00941
    00942      // Check if we're dealing with a map or a mutator
    00943      i = InStr(Package, ".");
    00944
    00945      // Dealing with a mutator - remove class name
    00946      if (i != -1)
    00947          Package = Left(Package, i);
    00948
    00949      for (i = 0;i < EPICNUMBER; i++)
    00950          if (Package ~= EpicPackages[i])
    00951              return true;
    00952      return false;
    00953  }
    00954
    00955  function CheckSettingValue(string SettingData, out string NewValue)
    00956  {
    00957      local string sMaxLength, sMinMax, sMin, sMax;
    00958      local int iMaxLength, iMin, iMax, iValue;
    00959      local float fMin, fMax, fValue;
    00960      local bool bFloat;
    00961
    00962      if (SettingData == "")
    00963          return;
    00964
    00965  // This setting has no valid min/max (it is a password setting or something)
    00966      if (InStr(SettingData,";") < 0 )
    00967      {
    00968          // Allow only up to three times the configured max length
    00969          iMaxLength = 3 * int(SettingData);
    00970          if (Len(NewValue) > iMaxLength)
    00971              NewValue = Left(NewValue,iMaxLength);
    00972          return;
    00973      }
    00974
    00975      Divide(SettingData,";",sMaxLength,sMinMax); // Split the Max Length & MinMax Info
    00976      Divide(sMinMax,":",sMin,sMax);              // Split the Min & Max info for casting
    00977      iMaxLength = int(sMaxLength);
    00978      if ( InStr(sMin,".") >= 0 || InStr(sMax,".") >= 0)  // Are we dealing with floating point numbers?
    00979      {
    00980          bFloat = True;
    00981          fMin = float(sMin);
    00982          fMax = float(sMax);
    00983      }
    00984
    00985      else
    00986      {
    00987          iMin = int(sMin);
    00988          iMax = int(sMax);
    00989      }
    00990
    00991      // First check for length
    00992      if (Len(NewValue) > iMaxLength)
    00993          NewValue = Left(NewValue,iMaxLength);
    00994
    00995      if (bFloat)
    00996      {
    00997          fValue = float(NewValue);
    00998          fValue = FClamp(fValue,fMin,fMax);
    00999          NewValue = string(fValue);
    01000      }
    01001      else
    01002      {
    01003          iValue = int(NewValue);
    01004          iValue = Clamp(iValue,iMin,iMax);
    01005          NewValue = string(iValue);
    01006      }
    01007  }
    01008  //*****************************************************************************
    01009  //*****************************************************************************
    01010  // Query Methods
    01011  //
    01012  //
    01013
    01014  // Passes the SessionID variable to all pages in this query action
    01015  // if SessionID is not present in WebRequest, generates one
    01016  // (Helpful when dealing with frames)
    01017  function bool PreQuery(WebRequest Req, WebResponse Res)
    01018  {
    01019      local string SID;
    01020
    01021      SID = Req.GetVariable("SessionID");
    01022      if (SID == "")
    01023      {
    01024          SID = SMaster.getSession("xxxxx",true).GetHash();
    01025          Req.AddVariable("SessionID", SID);
    01026      }
    01027      Res.Subst("SessionID", SID);
    01028      return true;
    01029  }
    01030
    01031  function bool Query(WebRequest Request, WebResponse Response)
    01032  {
    01033      switch (Mid(Request.URI, 1))
    01034      {
    01035      case DefaultPage:       if (!MapIsChanging()) QueryLadderFrame(Request, Response);      return true;
    01036      case ProfileMenuURI:    if (!MapIsChanging()) QueryLadderMenu(Request, Response);       return true;
    01037      case ProfileViewURI:    if (!MapIsChanging()) QueryLadderView(Request, Response);       return true;
    01038      case ProfileEditURI:    if (!MapIsChanging()) QueryLadderEdit(Request, Response);       return true;
    01039      case ProfileSwitchURI:  if (!MapIsChanging()) QueryLadderSwitch(Request, Response);     return true;
    01040      case ProfileManageURI:  if (!MapIsChanging()) QueryLadderManage(Request, Response);     return true;
    01041
    01042  // Management subframes
    01043      case SubFrameURI:       if (!MapIsChanging()) QuerySubFrame(Request, Response);         return true;
    01044      case SubFrameMenuURI:   if (!MapIsChanging()) QuerySubMenu(Request, Response);          return true;
    01045      case SubGametypeURI:    if (!MapIsChanging()) QuerySubGameType(Request, Response);      return true;
    01046      case SubMapsURI:        if (!MapIsChanging()) QuerySubMaps(Request, Response);          return true;
    01047      case SubMutatorsURI:    if (!MapIsChanging()) QuerySubMutators(Request, Response);      return true;
    01048      case SubRulesURI:       if (!MapIsChanging()) QuerySubRules(Request, Response);         return true;
    01049      case SubReviewURI:      if (!MapIsChanging()) QuerySubReview(Request, Response);        return true;
    01050      case SubSavedURI:       if (!MapIsChanging()) QuerySubSaved(Request, Response);         return true;
    01051      case SubImportURI:      if (!MapIsChanging()) QuerySubImport(Request, Response);        return true;
    01052      case SubExportURI:      if (!MapIsChanging()) QuerySubExport(Request, Response);        return true;
    01053      }
    01054  // This query is looking for a page from another query handler
    01055  // or the map is changing
    01056      return false;
    01057  }
    01058
    01059  function QueryLadderFrame(WebRequest Req, WebResponse Res)
    01060  {
    01061      local String Page;
    01062      local string SID;
    01063
    01064  // if no page specified, use the default
    01065      Page = Req.GetVariable("Page", ProfileViewURI);
    01066      SID = Req.GetVariable("SessionID");
    01067
    01068  // Tell the menu page which page we're viewing (with the ?Page=),
    01069  // so that it can highlight the appropriate link
    01070      Res.Subst("IndexURI",ProfileMenuURI$"?Page="$Page$"?SessionID="$SID);
    01071
    01072  // Load the main page into the frameset
    01073      Res.Subst("MainURI", Page$"?SessionID="$SID);
    01074
    01075      ShowFrame(Res, DefaultPage);
    01076  }
    01077
    01078  function QuerySubFrame(WebRequest Req, WebResponse Res)
    01079  {
    01080      local string Page, SID, TempStr, Action;
    01081      local Session CurS;
    01082
    01083      SID = Req.GetVariable("SessionID");
    01084      CurS = SMaster.getSession(SID, true);
    01085
    01086      Action = Req.GetVariable("Actions","Add");
    01087
    01088      if (Action ~= "Modify")
    01089      {
    01090          TempStr = Req.GetVariable("ProfileNameSelect", "");
    01091          if (TempStr != "") CreateSessionInfo(TempStr,SID,True);
    01092      }
    01093
    01094      else if (Action ~= "Add")
    01095      {
    01096          TempStr = Req.GetVariable("TextInput");
    01097          if (TempStr != "") CurS.setValue("ProfileName",TempStr,True);
    01098      }
    01099
    01100  // if no page specified, use the default
    01101      Page = Req.GetVariable("Page", SubGameTypeURI);
    01102      CurS.setValue("CurrentPage", Page, True);
    01103
    01104  // Tell the SubMenu page which page we're viewing, so that it can highlight
    01105  // the appropriate link
    01106      Res.Subst("SubMenuURI", SubFrameMenuURI$"?SessionID="$SID);
    01107
    01108  // Load the main page into the frameset
    01109      Res.Subst("SubMainURI", Page$"?SessionID="$SID);
    01110      ShowFrame(Res, SubFrame);
    01111  }
    01112
    01113  function QueryLadderMenu(WebRequest Req, WebResponse Res)
    01114  {
    01115      local string SID;
    01116
    01117      SID = Req.GetVariable("SessionID");
    01118  /*
    01119  If ?SessionID= is appended to the link, PreQuery() will not generate
    01120  a new Session when this link is queried
    01121  */
    01122      // Set URIs
    01123      if (CanPerform("Lv"))
    01124          Res.Subst("ViewProfiles", "<a href=\""$ProfileViewURI$"\" target=\"main\">"$LinkViewProfile$"</a><br>");
    01125
    01126      if (CanPerform("Le"))
    01127          Res.Subst("EditProfiles", "<a href=\""$ProfileEditURI$"\" target=\"main\">"$LinkEditProfile$"</a><br>");
    01128
    01129      if (CanPerform("Ls"))
    01130          Res.Subst("SwitchProfiles", "<a href=\""$ProfileSwitchURI$"\" target=\"main\">"$LinkSwitchProfile$"</a><br>");
    01131
    01132      if (CanPerform("Lm"))
    01133          Res.Subst("ManageProfiles", "<a href=\""$ProfileManageURI$"\" target=\"main\">"$LinkManageProfile$"</a><br>");
    01134
    01135      ShowPage(Res, ProfileMenuURI);
    01136  }
    01137
    01138  function QuerySubMenu(WebRequest Req, WebResponse Res)
    01139  {
    01140  // Highlight the current page
    01141      local string Highlighted, Background, SID;
    01142      local string GameLink, MutatorLink, MapLink, RuleLink, ReviewLink;
    01143      local string GameSpan, MutatorSpan, MapSpan, RuleSpan, ReviewSpan;
    01144
    01145      local string Page;
    01146      local Session CurS;
    01147
    01148      if (CanPerform("Lm"))
    01149      {
    01150          Highlighted = "<span class=\"blue\">";
    01151          Background = "<span class=\"red\">";
    01152          SID = Req.GetVariable("SessionID");
    01153          CurS = SMaster.getSession(SID, true);
    01154
    01155          // We are managing an existing profile
    01156          if (CurS.HasData("ProfileIndex"))
    01157              Res.Subst("Section", LabelModifyProfile);
    01158
    01159          else Res.Subst("Section", LabelAddProfile);
    01160
    01161          Page = CurS.getValue("CurrentPage",SubGametypeURI);
    01162
    01163      // Including ?SessionID= in link prevents PreQuery() from generating a new Session
    01164          GameLink =      "<a href=\""$SubFrameURI$"?SessionID="$SID$"?Page="$SubGametypeURI$ "\" target=\"_parent\">";
    01165          MutatorLink =   "<a href=\""$SubFrameURI$"?SessionID="$SID$"?Page="$SubMutatorsURI$ "\" target=\"_parent\">";
    01166          MapLink =       "<a href=\""$SubFrameURI$"?SessionID="$SID$"?Page="$SubMapsURI$     "\" target=\"_parent\">";
    01167          RuleLink =      "<a href=\""$SubFrameURI$"?SessionID="$SID$"?Page="$SubRulesURI$    "\" target=\"_parent\">";
    01168          ReviewLink =    "<a href=\""$SubFrameURI$"?SessionID="$SID$"?Page="$SubReviewURI$   "\" target=\"_parent\">";
    01169
    01170      // Initially set all spans to the background color
    01171          GameSpan    = Background;
    01172          MutatorSpan = Background;
    01173          MapSpan     = Background;
    01174          RuleSpan    = Background;
    01175          ReviewSpan  = Background;
    01176
    01177          // Then set the appropriate span to the highlighted color
    01178          Res.Subst("SubTitle", CurS.GetValue("ProfileName"));
    01179          switch (Page)
    01180          {
    01181              case SubGametypeURI:
    01182                  Curs.SetValue("ButtonName",     ProfileButtonName[1],true);
    01183                  Curs.SetValue("ButtonValue",    ProfileButtonValue[1],true);
    01184
    01185                  Res.Subst("PageHelp", HelpGameType);
    01186                  GameSpan = Highlighted; break;
    01187
    01188              case SubMutatorsURI:
    01189                  Curs.SetValue("ButtonName",     ProfileButtonName[2],true);
    01190                  Curs.SetValue("ButtonValue",    ProfileButtonValue[2],true);
    01191
    01192                  Res.Subst("PageHelp", HelpMutators);
    01193                  MutatorSpan = Highlighted; break;
    01194
    01195              case SubMapsURI:
    01196                  Curs.SetValue("ButtonName",     ProfileButtonName[3],true);
    01197                  Curs.SetValue("ButtonValue",    ProfileButtonValue[3],true);
    01198
    01199                  Res.Subst("PageHelp", HelpMaps);
    01200                  Mapspan = Highlighted; break;
    01201
    01202              case SubRulesURI:
    01203                  Curs.SetValue("ButtonName",     ProfileButtonName[4],true);
    01204                  Curs.SetValue("ButtonValue",    ProfileButtonValue[4],true);
    01205
    01206                  Res.Subst("PageHelp", HelpPlayInfo);
    01207                  RuleSpan = Highlighted; break;
    01208
    01209              case SubReviewURI:
    01210                  Curs.SetValue("ButtonName",     ProfileButtonName[5],true);
    01211                  Curs.SetValue("ButtonValue",    ProfileButtonValue[5],true);
    01212
    01213                  Res.Subst("PageHelp", HelpReview);
    01214                  ReviewSpan = Highlighted; break;
    01215          }
    01216
    01217          GameLink    = GameLink      $ GameSpan      $ TableTitle[1]$"</span></a>";
    01218          MutatorLink = MutatorLink   $ MutatorSpan   $ TableTitle[2]$"</span></a>";
    01219          MapLink     = MapLink       $ MapSpan       $ TableTitle[3]$"</span></a>";
    01220          RuleLink    = RuleLink      $ RuleSpan      $ TableTitle[4]$"</span></a>";
    01221          ReviewLink  = ReviewLink    $ ReviewSpan    $ TableTitle[5]$"</span></a>";
    01222
    01223          Res.Subst("GameTypeLink",   GameLink);
    01224          Res.Subst("MutatorsLink",   MutatorLink);
    01225          Res.Subst("MapsLink",       MapLink);
    01226          Res.Subst("RulesLink",      RuleLink);
    01227          Res.Subst("ReviewLink",     ReviewLink);
    01228
    01229          ShowPage(Res, SubFrameMenu);
    01230      }
    01231
    01232      else AccessDenied(Res);
    01233  }
    01234
    01235  function QueryLadderView(WebRequest Req, WebResponse Res)
    01236  {
    01237      local int i,j;
    01238      local Session   CurS;
    01239      local string    SID,
    01240                      TempStr,
    01241                      ViewRows,
    01242                      NewProfile,
    01243                      NewGameType;
    01244
    01245      local StringArray           Mutators, GroupsOnly, ServerActors;
    01246      local class<GameInfo>       GIClass;
    01247      local class<AccessControl>  ACClass;
    01248      local class<Mutator>        TempMut;
    01249      local class<Info>           TempSA;
    01250
    01251
    01252      if (CanPerform("Lv"))
    01253      {
    01254          SID = Req.GetVariable("SessionID");
    01255          CurS = SMaster.getSession(SID,true);
    01256
    01257          if (CanPerform("Ls"))
    01258          {
    01259
    01260              if (Req.GetVariable("SetProfileName","")!="") // We would like to view a different profile
    01261                  TempStr = Req.GetVariable("ProfileNameSelect", "");
    01262
    01263              If (TempStr == "")  // Not selecting a new profile to view
    01264              {
    01265              // First, see if the current session is holding a profile
    01266                  NewProfile = CurS.getValue("ProfileIndex");
    01267                  if (NewProfile == "")
    01268                  {
    01269                  // See if a profile is currently loaded
    01270                      j = GetCurrentConfigIndex();
    01271                      if (j!=-1)      // Found an active profile - this profile should be selected
    01272                          NewProfile = string(j);
    01273                  }
    01274              }
    01275
    01276              if (TempStr!="")
    01277                  NewProfile = TempStr;
    01278
    01279              Res.Subst("ButtonName", "SetProfileName");
    01280              Res.Subst("ButtonValue", ButtonLoadProfile);
    01281              Res.Subst("PageCaption", "<select class=mini name='ProfileNameSelect'>"$GenerateSwitchProfileOptions(NewProfile)$"</select>");
    01282          }
    01283
    01284      // If admin doesn't have switch privileges, check for current profile
    01285          if (NewProfile == "")
    01286          {
    01287              NewProfile = CurS.getValue("ProfileIndex");
    01288              if (NewProfile == "")
    01289              {
    01290                  j = GetCurrentConfigIndex();
    01291                  if (j != -1)
    01292                      NewProfile = string(j);
    01293              }
    01294          }
    01295
    01296          if (NewProfile != "" && LadderRules.AllLadderProfiles.Count() > 0)
    01297          {
    01298              CurS.setValue("ProfileIndex", NewProfile, True);
    01299              CreateSessionInfo(NewProfile,SID);
    01300              NewGameType = CurS.getValue("GameType");
    01301
    01302              if (NewGameType != "")
    01303                  GIClass = class<GameInfo>(DynamicLoadObject(NewGameType,class'Class'));
    01304              if (GIClass==None)
    01305              {
    01306                  ShowMessage(Res,ErrorGameClassTitle,ErrorGameClassText);
    01307                  return;
    01308              }
    01309
    01310              TempStr = CurS.getValue("ACClass",Level.Game.AccessControlClass);
    01311              if (TempStr != "")
    01312                  ACClass = class<AccessControl>(DynamicLoadObject(TempStr,class'Class'));
    01313              if (ACClass == None)
    01314              {
    01315                  ShowMessage(Res,ErrorAccessControlTitle,ErrorAccessControlText);
    01316                  return;
    01317              }
    01318
    01319              Mutators = new(None) class'SortedStringArray';
    01320              GroupsOnly = new(None) class'SortedStringArray';
    01321              ServerActors = new(None) class'SortedStringArray';
    01322          // Mutator Section
    01323              for (i=0;i<CurS.getMutatorLength();i++)
    01324              {
    01325                  TempStr = CurS.getMutator(i);
    01326                  for (j=0;j<AllMutators.Length;j++)
    01327                  {
    01328                      if (TempStr ~= AllMutators[j].ClassName)
    01329                      {
    01330                          TempMut = class<Mutator>(DynamicLoadObject(TempStr,class'Class'));
    01331                          if (TempMut != None)
    01332                              Mutators.Add(string(j), AllMutators[j].FriendlyName);
    01333                      }
    01334                  }
    01335              }
    01336
    01337              for (i=0;i<CurS.getSALength();i++)
    01338              {
    01339                  TempStr = CurS.GetServerActor(i);
    01340                  for (j=0;j<ConfigM.ManagedActors.Length;j++)
    01341                  {
    01342                      if (TempStr ~= string(ConfigM.ManagedActors[j].SAClass))
    01343                      {
    01344                          TempSA = class<Info>(DynamicLoadObject(TempStr,class'Class'));
    01345                          if (TempSA != None)
    01346                              ServerActors.Add(string(j),ConfigM.ManagedActors[j].SAName);
    01347                      }
    01348                  }
    01349              }
    01350
    01351              Res.Subst("SectionName", TableTitle[2]);
    01352              Res.Subst("SpecialInstructions", "");
    01353              ViewRows = ViewRows$WebInclude(IncludeSection);
    01354
    01355              for (i = 0; i<ServerActors.Count(); i++)
    01356              {
    01357                  j = int(ServerActors.GetItem(i));
    01358                  Res.Subst("SettingName", ServerActors.GetTag(i));
    01359                  if (CurS.SARequired(string(ConfigM.ManagedActors[j].SAClass)))
    01360                      Res.Subst("SettingData", RequiredText);
    01361                  else Res.Subst("SettingData", "&nbsp;&nbsp;");
    01362                  ViewRows = ViewRows $ WebInclude(IncludeRows);
    01363              }
    01364              ViewRows = ViewRows $ "<tr><td colspan=\"2\">&nbsp;&nbsp;</td></tr>";
    01365              for (i = 0; i<Mutators.Count(); i++)
    01366              {
    01367                  j = int(Mutators.GetItem(i));
    01368                  Res.Subst("SettingName", AllMutators[j].FriendlyName);
    01369                  if (CurS.MutRequired(AllMutators[j].ClassName))
    01370                      Res.Subst("SettingData", RequiredText);
    01371                  else Res.Subst("SettingData", "&nbsp;&nbsp;");
    01372                  ViewRows = ViewRows$WebInclude(IncludeRows);
    01373              }
    01374
    01375              Res.Subst("SectionName", TableTitle[3]);
    01376              Res.Subst("SpecialInstructions", "");
    01377              ViewRows = ViewRows$WebInclude(IncludeSection);
    01378
    01379              Res.Subst("SettingName", LabelMaxMaps);
    01380              TempStr = CurS.getValue("MaxMaps");
    01381              if (TempStr == "0")
    01382                  TempStr = UnlimitedText;
    01383              Res.Subst("SettingData", TempStr);
    01384              Res.Subst("Extra", "<tr><td colspan=\"2\">&nbsp;&nbsp;</td></tr>");
    01385              ViewRows = ViewRows$WebInclude(IncludeRows);
    01386              for (i=0;i<CurS.getMapLength();i++)
    01387              {
    01388                  TempStr = CurS.getMap(i);
    01389                  Res.Subst("SettingName", TempStr);
    01390                  Res.Subst("Extra", "");
    01391                  if (CurS.MapRequired(TempStr))
    01392                      Res.Subst("SettingData", RequiredText);
    01393                  else Res.Subst("SettingData", "&nbsp;&nbsp");
    01394
    01395                  ViewRows = ViewRows$WebInclude(IncludeRows);
    01396              }
    01397
    01398              Res.Subst("SectionName", TableTitle[4]);
    01399              Res.Subst("SpecialInstructions", "&nbsp;&nbsp;");
    01400              ViewRows = ViewRows $ WebInclude(IncludeSection);
    01401              ViewRows = ViewRows $ "<tr><td colspan=\"2\">&nbsp;</td></tr>" $ GeneratePlayInfoRows(Req, Res, IncludeRows);
    01402          }
    01403
    01404      // We have no profile currently active
    01405          else
    01406          {
    01407              Res.Subst("SettingName", PageCaption[0]);
    01408              ViewRows = ViewRows $ WebInclude(IncludeRows);
    01409          }
    01410
    01411          TempStr = CurS.getValue("ProfileName", PageCaption[0]);
    01412          if (LadderRules.GetRemainingMatches() > 0 && TempStr == LadderRules.Profiles[GetCurrentConfigIndex()].ProfileName)
    01413              TempStr = TempStr @ LabelNumberMatchesLeft @ string(LadderRules.GetRemainingMatches());
    01414
    01415          Res.Subst("TableRows", ViewRows);
    01416          Res.Subst("LadderTable", WebInclude(IncludeCaptionButton)$WebInclude(IncludeTable));
    01417          Res.Subst("Section", LinkViewProfile);
    01418          Res.Subst("SubTitle", TempStr);
    01419          Res.Subst("PageHelp", HelpViewProfile);
    01420          Res.Subst("PostAction", ProfileViewURI$"?SessionID="$SID);
    01421
    01422          ShowPage(Res, MasterPage);
    01423      }
    01424
    01425      else AccessDenied(Res);
    01426  }
    01427
    01428  function QueryLadderEdit(WebRequest Req, WebResponse Res)
    01429  {
    01430      local Session CurS;
    01431      local bool  bAllMuts;
    01432      local int   i,j,k,z,
    01433                  id,
    01434                  Count,
    01435                  MoveCount;
    01436
    01437      local string    SID,
    01438                      EditRows,
    01439                      TempStr, Tmp, NewProfile, NewGameType,
    01440                      lastgroup, thisgroup, nextgroup, EmptyRow;
    01441
    01442      local ProfileConfigSet      TempPCS;
    01443      local array<string>         TempMutes;
    01444      local class<GameInfo>       GIClass;
    01445      local class<AccessControl>  ACClass;
    01446      local array<ProfileConfigSet.ProfileMap>        AllPCSMaps;
    01447      local array<ProfileConfigSet.ProfileMutator>    AllPCSMutators;
    01448      local array<ProfileConfigSet.ProfileSA>         AllPCSServerActors;
    01449      local StringArray
    01450                  Mutators, GroupsOnly, Required, ServerActors, ReqSA,
    01451                  RequiredMaps, IncludeMaps, ExcludeMaps, MovedMaps;
    01452
    01453      SID = Req.GetVariable("SessionID");
    01454      CurS = SMaster.getSession(SID,true);
    01455      if (CanPerform("Le"))
    01456      {
    01457          if (CanPerform("Ls"))
    01458          {
    01459              if (Req.GetVariable("SetProfileName","")!="") // We would like to view a different profile
    01460                  TempStr = Req.GetVariable("ProfileNameSelect", "");
    01461
    01462              If (TempStr == "")  // Not selecting a new profile to view
    01463              {
    01464              // First, see if the current session is holding a profile
    01465                  NewProfile = CurS.getValue("ProfileIndex");
    01466
    01467                  if (NewProfile == "")
    01468                  {
    01469                  // See if a profile is currently loaded
    01470                      j = GetCurrentConfigIndex();
    01471                      if (j!=-1)      // Found an active profile - this profile should be selected
    01472                          NewProfile = string(j);
    01473                  }
    01474
    01475              }
    01476
    01477              if (TempStr!="")
    01478                  NewProfile = TempStr;
    01479
    01480              Res.Subst("ButtonName", "SetProfileName");
    01481              Res.Subst("ButtonValue", ButtonLoadProfile);
    01482              Res.Subst("PageCaption", "<select class=mini name='ProfileNameSelect'>"$GenerateSwitchProfileOptions(NewProfile)$"</select>");
    01483          }
    01484          CurS.setValue("CurrentPage", ProfileEditURI, true);
    01485          CurS.setValue("ButtonName", "ApplyProfileChanges",true);
    01486          CurS.setValue("ButtonValue", ButtonApplyProfileChanges, true);
    01487
    01488  // If admin doesn't have switch privileges, check for current profile
    01489          if (NewProfile == "")
    01490          {
    01491              NewProfile = CurS.getValue("ProfileIndex");
    01492              if (NewProfile == "")
    01493              {
    01494                  j = GetCurrentConfigIndex();
    01495                  if (j != -1)
    01496                      NewProfile = string(j);
    01497              }
    01498          }
    01499
    01500          CurS.setValue("ProfileIndex", NewProfile, True);
    01501          if (NewProfile != "" && LadderRules.AllLadderProfiles.Count() > 0)
    01502          {
    01503              ProfileMaps.Reset();
    01504              Required = new(None)        class'SortedStringArray';
    01505              ReqSA   = new(None)         class'SortedStringArray';
    01506              Mutators = new(None)        class'SortedStringArray';
    01507              MovedMaps = new(None)       class'SortedStringArray';
    01508              GroupsOnly = new(None)      class'SortedStringArray';
    01509              ServerActors = new(None)    class'SortedStringArray';
    01510              IncludeMaps = new(None)     class'SortedStringArray';
    01511              ExcludeMaps = new(None)     class'SortedStringArray';
    01512              RequiredMaps = new(None)    class'SortedStringArray';
    01513
    01514              CreateSessionInfo(NewProfile,SID);
    01515              TempPCS = LadderRules.LadderProfiles[int(NewProfile)];
    01516              TempPCS.StartEdit();
    01517
    01518              NewGameType = CurS.getValue("GameType");
    01519              GIClass = class<GameInfo>(DynamicLoadObject(NewGameType,class'Class'));
    01520              if (GIClass==None)
    01521              {
    01522                  ShowMessage(Res,ErrorGameClassTitle,ErrorGameClassText);
    01523                  return;
    01524              }
    01525
    01526              TempStr = CurS.getValue("ACClass", Level.Game.AccessControlClass);
    01527              if (TempStr != "")
    01528                  ACClass = class<AccessControl>(DynamicLoadObject(TempStr,class'Class'));
    01529              AllPCSMutators = TempPCS.GetProfileMutators();
    01530              AllPCSMaps = TempPCS.GetProfileMaps();
    01531              AllPCSServerActors = TempPCS.GetProfileServerActors();
    01532
    01533      // Load Exclude Maps
    01534              for (i=0;i<AllPCSMaps.Length;i++)
    01535              {
    01536                  ProfileMaps.Add(string(i), AllPCSMaps[i].MapName);
    01537                  if (AllPCSMaps[i].bRequired)
    01538                  {
    01539                      RequiredMaps.Add(string(i),string(AllPCSMaps[i].MapListOrder));
    01540                      IncludeMaps.Add(string(i),string(AllPCSMaps[i].MapListOrder));
    01541                  }
    01542
    01543                  else ExcludeMaps.Add(string(i),string(AllPCSMaps[i].MapListOrder));
    01544              }
    01545
    01546              for (i=0;i<CurS.GetMapLength();i++)
    01547              {
    01548                  j = ExcludeMaps.FindItemId(ProfileMaps.GetItem(ProfileMaps.FindTagId(CurS.getMap(i))));
    01549                  if (j >= 0) IncludeMaps.MoveFromId(ExcludeMaps, j);
    01550              }
    01551
    01552              if (Req.GetVariable("ApplyProfileChanges","")!="")
    01553              {
    01554                  for (i=0;i<AllPCSMutators.Length;i++)
    01555                      for (j=0;j<AllMutators.Length;j++)
    01556                          if (AllPCSMutators[i].MutatorName ~= AllMutators[j].ClassName)
    01557                              Mutators.Add(string(j),AllPCSMutators[i].MutatorName);
    01558
    01559                  for (i=0;i<Mutators.Count();i++)
    01560                  {
    01561                      if ((Req.GetVariable(Mutators.GetTag(i),"")!="")||(Req.GetVariable(AllMutators[int(Mutators.GetItem(i))].GroupName)~=Mutators.GetTag(i)))
    01562                          TempPCS.AddMutator(Mutators.GetTag(i));
    01563                      else TempPCS.DelMutator(Mutators.GetTag(i));
    01564                  }
    01565
    01566                  for (i=0;i<AllPCSServerActors.Length;i++)
    01567                  {
    01568                      if (Req.GetVariable(AllPCSServerActors[i].ActorClass,"") != "")
    01569                          TempPCS.AddServerActor(AllPCSServerActors[i].ActorClass);
    01570                      else TempPCS.DelServerActor(AllPCSServerActors[i].ActorClass);
    01571                  }
    01572
    01573                  for (i=0;i<AllPCSMaps.Length;i++)
    01574                  {
    01575                      if (AllPCSMaps[i].bRequired) TempPCS.AddMap(AllPCSMaps[i].MapName,int(RequiredMaps.GetTag(RequiredMaps.FindItemId(string(i)))));
    01576                      else if (IncludeMaps.FindItemId(string(i)) >= 0) TempPCS.AddMap(AllPCSMaps[i].MapName,int(IncludeMaps.GetTag(IncludeMaps.FindItemId(string(i)))));
    01577                      else TempPCS.RemoveMap(AllPCSMaps[i].MapName);
    01578                  }
    01579
    01580                  CreateSessionInfo(NewProfile,SID,false,true);
    01581              }
    01582              else if (Req.GetVariable("AddMap", "") != "")
    01583              {
    01584                  Count = Req.GetVariableCount("ExcludeMapsSelect");
    01585                  for (i=0; i<Count; i++)
    01586                  {
    01587                      if (IncludeMaps.Count() >= TempPCS.MaxMaps && TempPCS.MaxMaps > 0)
    01588                          break;
    01589                      if (ExcludeMaps.Count() > 0)
    01590                      {
    01591                          id = IncludeMaps.MoveFromId(ExcludeMaps, ExcludeMaps.FindItemId(ProfileMaps.GetItem(ProfileMaps.FindTagId(Req.GetVariableNumber("ExcludeMapsSelect", i)))));
    01592                          if (id >= 0)
    01593                          {
    01594                              TempPCS.AddMap(AllPCSMaps[int(IncludeMaps.getItem(id))].MapName,int(IncludeMaps.getTag(id)));
    01595                              MovedMaps.CopyFromId(IncludeMaps, id);
    01596                          }
    01597                          else
    01598                              Log(ErrorExcludeMapNotFound@Req.GetVariableNumber("ExcludeMapsSelect", i),LOGNAME);
    01599                      }
    01600                  }
    01601                  for (i=0;i<IncludeMaps.Count();i++)
    01602                      TempPCS.AddMap(AllPCSMaps[int(IncludeMaps.getItem(i))].MapName,i);
    01603
    01604                  CreateSessionInfo(NewProfile,SID,false,true,True);
    01605              }
    01606
    01607              else if (Req.GetVariable("DelMap", "") != "" && Req.GetVariableCount("IncludeMapsSelect") > 0)
    01608              {
    01609                  Count = Req.GetVariableCount("IncludeMapsSelect");
    01610                  for (i=0; i<Count; i++)
    01611                  {
    01612                      if (RequiredMaps.FindItemId(ProfileMaps.GetItem(ProfileMaps.FindTagId(Req.GetVariableNumber("IncludeMapsSelect", i)))) < 0)
    01613                      {
    01614                          if (IncludeMaps.Count() > 0)
    01615                          {
    01616                              id = ExcludeMaps.MoveFromId(IncludeMaps, IncludeMaps.FindItemId(ProfileMaps.GetItem(ProfileMaps.FindTagId(Req.GetVariableNumber("IncludeMapsSelect", i)))));
    01617                              if (id >= 0)
    01618                              {
    01619                                  TempPCS.RemoveMap(AllPCSMaps[int(ExcludeMaps.GetItem(id))].MapName);
    01620                                  MovedMaps.CopyFromId(ExcludeMaps, id);
    01621                              }
    01622                              else
    01623                                  Log(ErrorIncludeMapNotFound@Req.GetVariableNumber("IncludeMapsSelect", i),LOGNAME);
    01624                          }
    01625                      }
    01626                  }
    01627                  CreateSessionInfo(NewProfile,SID,false,true,True);
    01628              }
    01629              else if (Req.GetVariable("AddAllMap", "") != "")
    01630              {
    01631                  while (ExcludeMaps.Count() > 0 && (IncludeMaps.Count() < TempPCS.MaxMaps || TempPCS.MaxMaps == 0) )
    01632                  {
    01633                      id = IncludeMaps.MoveFromId(ExcludeMaps, ExcludeMaps.Count()-1);
    01634                      if (id >= 0)
    01635                      {
    01636                          TempPCS.AddMap(AllPCSMaps[int(IncludeMaps.getItem(id))].MapName,int(IncludeMaps.getTag(id)));
    01637                          MovedMaps.CopyFromId(IncludeMaps, id);
    01638                      }
    01639                  }
    01640                  for (i=0;i<IncludeMaps.Count();i++)
    01641                      TempPCS.AddMap(AllPCSMaps[int(IncludeMaps.getItem(i))].MapName,i);
    01642                 CreateSessionInfo(NewProfile,SID,false,true,True);
    01643              }
    01644              else if (Req.GetVariable("DelAllMap", "") != "")
    01645              {
    01646                  i = IncludeMaps.Count();
    01647                  while (i > 0 && IncludeMaps.Count() > RequiredMaps.Count())
    01648                  {
    01649                      if (RequiredMaps.FindItemId(IncludeMaps.GetItem(i-1)) < 0)
    01650                      {
    01651                          id =  ExcludeMaps.MoveFromId(IncludeMaps, i-1);
    01652                          if (id >= 0)
    01653                          {
    01654                              TempPCS.RemoveMap(AllPCSMaps[int(ExcludeMaps.GetItem(id))].MapName);
    01655                              MovedMaps.CopyFromId(ExcludeMaps, id);
    01656                          }
    01657                      }
    01658                      i--;
    01659                  }
    01660                  CreateSessionInfo(NewProfile,SID,false,true,True);
    01661              }
    01662              else if (Req.GetVariable("MoveMap", "") != "")
    01663              {
    01664                  MoveCount = int(Abs(float(Req.GetVariable("MoveMapCount"))));
    01665                  if (MoveCount != 0)
    01666                  {
    01667                      Count = Req.GetVariableCount("IncludeMapsSelect");
    01668
    01669                      // 1) Create a sorted MovedMaps list
    01670                      for (i = 0; i<Count; i++)
    01671                          MovedMaps.CopyFromId(IncludeMaps, IncludeMaps.FindItemId(ProfileMaps.GetItem(ProfileMaps.FindTagId(Req.GetVariableNumber("IncludeMapsSelect", i)))));
    01672
    01673                      if (Req.GetVariable("MoveMap") ~= "Down")
    01674                      {
    01675                          // 2) Browse from Last to 0 until all maps are moved by count
    01676                          //    but stop moving them if hitting bottom
    01677                          for (i = IncludeMaps.Count()-1; i >= 0; i--)
    01678                              if (MovedMaps.FindItemId(IncludeMaps.GetItem(i)) >= 0)
    01679                                  IncludeMaps.ShiftStrict(i, MoveCount);
    01680                      }
    01681                      else
    01682                      {
    01683                          MoveCount = -MoveCount;
    01684                          for (i = 0; i<IncludeMaps.Count(); i++)
    01685                              if (MovedMaps.FindItemId(IncludeMaps.GetItem(i)) >= 0)
    01686                                  IncludeMaps.ShiftStrict(i, MoveCount);
    01687                      }
    01688                  }
    01689
    01690                  for (i=0;i<IncludeMaps.Count();i++)
    01691                      TempPCS.AddMap(AllPCSMaps[int(IncludeMaps.getItem(i))].MapName,i);
    01692
    01693                  CreateSessionInfo(NewProfile,SID,false,true,True);
    01694              }
    01695
    01696              if (TempPCS.CanEdit())
    01697                  TempPCS.StartEdit();
    01698  // Mutator Section
    01699              Mutators.Reset();
    01700      // Set active ServerActors
    01701              TempMutes = LoadActiveProfileServerActors(NewProfile);
    01702              TempStr = class'wUtils103.wArray'.static.Join(TempMutes,",");
    01703
    01704              bAllMuts = TempMutes.Length == ConfigM.ManagedActors.Length;
    01705
    01706              for (i=0;i<AllPCSServerActors.Length;i++)
    01707              {
    01708                  for (j = 0; j < ConfigM.ManagedActors.Length; j++)
    01709                  {
    01710                      if (AllPCSServerActors[i].ActorClass ~= string(ConfigM.ManagedActors[j].SAClass))
    01711                      {
    01712                          if (AllPCSServerActors[i].bRequired)
    01713                              ReqSA.Add(string(j), ConfigM.ManagedActors[j].SAName);
    01714                          else ServerActors.Add(string(j),ConfigM.ManagedActors[j].SAName);
    01715                          break;
    01716                      }
    01717                  }
    01718              }
    01719              TempMutes = LoadActiveProfileMutators(NewProfile);
    01720              TempStr = class'wUtils103.wArray'.static.Join(TempMutes,",");
    01721          // Set Available Mutators for this profile
    01722              bAllMuts = bAllMuts && AllPCSMutators.Length == AllMutators.Length;
    01723              for (i=0;i<AllPCSMutators.Length;i++)
    01724              {
    01725                  for (j=0;j<AllMutators.Length;j++)
    01726                  {
    01727                      if (AllMutators[j].ClassName ~= AllPCSMutators[i].MutatorName)
    01728                      {
    01729                          if (AllPCSMutators[i].bRequired)
    01730                              Required.Add(string(j),AllMutators[j].FriendlyName);
    01731                          else
    01732                          {
    01733                      // Don't add available mutator if it belongs in the same group as a required mutator
    01734                              for (k=0;k<Required.Count();k++)
    01735                                  if (AllMutators[int(Required.GetItem(k))].GroupName ~= AllMutators[j].GroupName)
    01736                                      break;
    01737                              if (k==Required.Count())
    01738                                  Mutators.Add(string(j),AllPCSMutators[i].MutatorName);
    01739                          }
    01740                          break;
    01741                      }
    01742                  }
    01743              }
    01744  // BEGIN OUTPUT ////////////////////////////////////////////
    01745  /*
    01746      TempMutes is an array of active mutators, including required ones
    01747      AllPCSMutators is a ProfileMutator array, which includes a required flag
    01748
    01749      Need to generate a regular mutator selection list, but list all required
    01750      first, followed by the list of all other mutators which are available
    01751  */
    01752  // MAPS
    01753              Res.Subst("SpanLength", "2");
    01754              Res.Subst("SpanContent", "&nbsp;&nbsp;");
    01755              EmptyRow = "<tr>" $ WebInclude(CellColSpan) $ "</tr>";
    01756
    01757              Res.Subst("SectionName", TableTitle[3]);
    01758              TempStr = string(TempPCS.GetMaxMaps());
    01759              if (TempStr == "0") TempStr = "Unlimited";
    01760              Res.Subst("SpecialInstructions", LabelMaxMaps$":"@TempStr);
    01761              EditRows += WebInclude(IncludeSection);
    01762
    01763              j = RequiredMaps.Count();
    01764              if (j > 0)
    01765              {
    01766                  EditRows = EditRows $ EmptyRow $ "<tr><td class=ttext>" $ RequiredText @ MapText $ "</td><td class=ttext>" $ FollowingMaps@AreAssignedText $ "</td></tr>";
    01767                  i=0;
    01768                  while (i<j)
    01769                  {
    01770                      Res.Subst("SettingName", AllPCSMaps[int(RequiredMaps.GetItem(i++))].MapName);
    01771                      Res.Subst("SettingData", StringIf(i < j, AllPCSMaps[int(RequiredMaps.GetItem(i++))].MapName, ""));
    01772
    01773                      Res.Subst("Extra", "");
    01774                      EditRows += WebInclude(IncludeRows);
    01775                  }
    01776              }
    01777
    01778              EditRows = EditRows $ EmptyRow $ "<tr><td class=ttext>" $ AvailableText@MapText $ "</td><td class=ttext>" $ LabelChangeMaplist $ "</td></tr>";
    01779
    01780              Res.Subst("ExcludeMapsOptions", CreateMapListSelect(AllPCSMaps, ExcludeMaps,MovedMaps));
    01781              Res.Subst("IncludeMapsOptions", CreateMapListSelect(AllPCSMaps, IncludeMaps,MovedMaps));
    01782              Res.Subst("SpanContent", WebInclude(IncludeMapSelect));
    01783              Res.Subst("RowContent", WebInclude(CellColSpan));
    01784              EditRows += WebInclude(RowLeft);
    01785
    01786  // MUTATORS
    01787              CreateFullMutatorList(Mutators,GroupsOnly);
    01788              Res.Subst("SectionName", TableTitle[2]);
    01789              Res.Subst("SpecialInstructions", "");
    01790              EditRows += WebInclude(IncludeSection);
    01791
    01792              if (ReqSA.Count() > 0 || Required.Count() > 0)
    01793                  EditRows = EditRows $ EmptyRow $ "<tr><td class=ttext>" $ RequiredText@MutatorText $ "</td><td class=ttext>" $ FollowingMutators@AreAssignedText $ "</td></tr>";
    01794  // Include ServerActors first
    01795              for (i=0;i<ReqSA.Count();i++)
    01796              {
    01797                  j = int(ReqSA.GetItem(i));
    01798                  Res.Subst("SettingName", ReqSA.GetTag(i));
    01799                  Res.Subst("SettingData", ConfigM.ManagedActors[j].SADescription);
    01800                  Res.Subst("Extra", "");
    01801
    01802                  EditRows += WebInclude(IncludeRows);
    01803              }
    01804
    01805              for (i=0;i<Required.Count();i++)
    01806              {
    01807                  j=int(Required.GetItem(i));
    01808                  Res.Subst("SettingName", AllMutators[j].FriendlyName);
    01809                  Res.Subst("SettingData", AllMutators[j].Description);
    01810                  Res.Subst("Extra", "");
    01811
    01812                  EditRows += WebInclude(IncludeRows);
    01813              }
    01814
    01815              EditRows = EditRows $ EmptyRow $ "<tr><td class=ttext>" $ AvailableText@MutatorText $ "</td><td class=ttext>" $ FollowingMutators@AreAvailableText $ "</td></tr>";
    01816              for (i=0;i<GroupsOnly.Count();i++)
    01817              {
    01818                  j=int(GroupsOnly.GetItem(i));
    01819                  if (AllMutators[j].GroupName=="")
    01820                      thisgroup="Z"$string(z++);
    01821                  else thisgroup = AllMutators[j].GroupName;
    01822                  if ( (i + 1) == GroupsOnly.Count())
    01823                      nextgroup = "";
    01824                  else
    01825                  {
    01826                  // Assign nextgroup to the next mutators group
    01827                      k = int(GroupsOnly.GetItem(i + 1));
    01828                      if (AllMutators[k].GroupName=="")
    01829                          nextgroup="Z"$string(z);
    01830                      else nextgroup = AllMutators[k].GroupName;
    01831                  }
    01832
    01833                  Res.Subst("GroupName", thisgroup);
    01834                  Res.Subst("MutatorClass", AllMutators[j].ClassName);
    01835                  Res.Subst("MutatorName", AllMutators[j].FriendlyName);
    01836                  Res.Subst("MutatorDesc", AllMutators[j].Description);
    01837
    01838                  if ((lastgroup != thisgroup) && (thisgroup == nextgroup)) // and the next mut is in the same group as this one
    01839                  {
    01840                      Res.Subst("Checked", " checked");
    01841                      EditRows += WebInclude("current_mutators_group");
    01842                  }
    01843
    01844                  Res.Subst("Checked", StringIf(CurS.HasMutator(AllMutators[j].ClassName), " checked", ""));
    01845                  EditRows += WebInclude("current_mutators_group_row");
    01846
    01847                  lastgroup=thisgroup;
    01848              }
    01849  // Add ServerActors first
    01850              for (i = 0; i < ServerActors.Count(); i++)
    01851              {
    01852                  TempStr = "";
    01853                  j = int(ServerActors.GetItem(i));
    01854
    01855                  Res.Subst("Content", Checkbox(string(ConfigM.ManagedActors[j].SAClass), CurS.HasServerActor(string(ConfigM.ManagedActors[j].SAClass))) $ "&nbsp;" $ ServerActors.GetTag(i));
    01856                  TempStr = WebInclude(NowrapLeft);
    01857                  Res.Subst("Content", ConfigM.ManagedActors[j].SADescription);
    01858                  Res.Subst("RowContent", TempStr $ WebInclude(CellLeft));
    01859                  EditRows += WebInclude(RowLeft);
    01860              }
    01861
    01862              for (i = 0; i<Mutators.Count(); i++)
    01863              {
    01864                  TempStr = "";
    01865                  j = int(Mutators.GetItem(i));
    01866
    01867                  Res.Subst("Content", Checkbox(AllMutators[j].ClassName,CurS.HasMutator(AllMutators[j].ClassName)) $ "&nbsp;" $ AllMutators[j].FriendlyName);
    01868                  TempStr += WebInclude(NowrapLeft);
    01869                  Res.Subst("Content", AllMutators[j].Description);
    01870                  Res.Subst("RowContent", TempStr $ WebInclude(CellLeft));
    01871                  EditRows += WebInclude(RowLeft);
    01872              }
    01873              TempPCS.EndEdit(False);
    01874          }
    01875      // We have no profile currently active
    01876          else
    01877          {
    01878              Res.Subst("SettingName", PageCaption[0]);
    01879              EditRows += WebInclude(IncludeRows);
    01880          }
    01881          Res.Subst("TableRows", EditRows);
    01882          TempStr = "";
    01883          TempStr = WebInclude(IncludeCaptionButton)$Tmp$WebInclude(IncludeTable);
    01884
    01885          if (NewProfile != "")
    01886          {
    01887              Res.Subst("ButtonName", curS.getValue("ButtonName","ApplyProfileChanges"));
    01888              Res.Subst("ButtonValue", ButtonApplyProfileChanges);
    01889              Res.Subst("PageCaption", "");
    01890              TempStr += WebInclude(IncludeCaptionButton);
    01891          }
    01892
    01893          Tmp = CurS.getValue("ProfileName",PageCaption[0]);
    01894          if (LadderRules.GetRemainingMatches() > 0 && Tmp == LadderRules.Profiles[GetCurrentConfigIndex()].ProfileName)
    01895              Tmp = Tmp @ LabelNumberMatchesLeft @ string(LadderRules.GetRemainingMatches());
    01896
    01897          Res.Subst("LadderTable",    TempStr);
    01898          Res.Subst("Section",        LinkEditProfile);
    01899          Res.Subst("SubTitle",       Tmp);
    01900          Res.Subst("PageHelp",       HelpEditProfile);
    01901          Res.Subst("PostAction",     ProfileEditURI$"?SessionID="$SID);
    01902          ShowPage(Res, MasterPage);
    01903      }
    01904
    01905      else AccessDenied(Res);
    01906  }
    01907
    01908  function QueryLadderSwitch(WebRequest Req, WebResponse Res)
    01909  {
    01910      local int       j, NumMatches;
    01911      local bool      bDelayChange, bSwitching;
    01912      local Session   CurS;
    01913      local string    SID,
    01914                      TempStr, Tmp,
    01915                      Checked;
    01916
    01917      SID = Req.GetVariable("SessionID");
    01918      CurS = SMaster.getSession(SID,true);
    01919
    01920      if (CanPerform("Ls"))
    01921      {
    01922          TempStr = Req.GetVariable("ProfileNameSelect", "");
    01923          Tmp = Req.GetVariable("SetNewProfile", "");
    01924          if (Tmp != "")
    01925          {
    01926              if (TempStr != "")
    01927              {
    01928                  NumMatches = int(Req.GetVariable("NumMatches", "0"));
    01929                  bDelayChange = Req.GetVariable("DelaySwitch","") != "";
    01930                  if (bDelayChange)
    01931                  {
    01932                      if (LadderRules.WaitApplyProfile(TempStr, NumMatches))
    01933                      {
    01934                          CurS.setValue("ProfileIndex", TempStr, True);
    01935                          bSwitching = True;
    01936                      }
    01937                  }
    01938                  else
    01939                  {
    01940                  // We would like to switch immediately
    01941                      LadderRules.ApplyProfile(TempStr, NumMatches);
    01942                      MapIsChanging();
    01943                      return;
    01944                  }
    01945              }
    01946              else StatusError(Res, ErrorNoProfilesExist);
    01947          }
    01948
    01949          else if (LadderRules.Profiles.Length > 0)
    01950          {
    01951              j = GetCurrentConfigIndex();
    01952              if (j >= 0) TempStr = string(j);
    01953          }
    01954
    01955          bDelayChange = Req.GetVariable("DelaySwitch","") != "" || LadderRules.bWaitingToSwitch;
    01956          if (bDelayChange)
    01957              Checked = " checked";
    01958          else Checked = "";
    01959
    01960          Res.Subst("ProfileSelect",      GenerateSwitchProfileOptions(TempStr));
    01961          Res.Subst("NumberGamesText",    LabelNumberGames);
    01962          Res.Subst("TextName",           "NumMatches");
    01963          Res.Subst("TextValue",          string(NumMatches));
    01964          Res.Subst("TextSize",           "3");
    01965          Res.Subst("TextLength",         "3");
    01966          Res.Subst("SwitchButtonName",   "SetNewProfile");
    01967          Res.Subst("SwitchButtonValue",  ButtonLoadProfile);
    01968          Res.Subst("DelayCheckName",     "DelaySwitch");
    01969          Res.Subst("Checked",            Checked);
    01970          Res.Subst("DelayCheckLabel",    LabelDelayProfileChange);
    01971
    01972          if (Tmp != "" && bSwitching)
    01973              StatusOK(Res, SuccessSwitchProfile);
    01974
    01975          Tmp = CurS.getValue("ProfileName", PageCaption[0]);
    01976          if (LadderRules.GetRemainingMatches() > 0 && Tmp == LadderRules.Profiles[GetCurrentConfigIndex()].ProfileName)
    01977              Tmp = Tmp @ LabelNumberMatchesLeft @ string(LadderRules.GetRemainingMatches());
    01978
    01979          Res.Subst("LadderTable",    WebInclude(IncludeSwitch));
    01980          Res.Subst("Section",        LinkSwitchProfile);
    01981          Res.Subst("SubTitle",       Tmp);
    01982          Res.Subst("PageHelp",       HelpSwitchProfile);
    01983          Res.Subst("PostAction",     ProfileSwitchURI$"?SessionID="$SID);
    01984
    01985          ShowPage(Res, MasterPage);
    01986      }
    01987      else AccessDenied(Res);
    01988  }
    01989
    01990  function QuerySubImport(WebRequest Req, WebResponse Res)
    01991  {
    01992      local string                    SID;
    01993      local Session                   CurS;
    01994      local ProfileConfigSet          TempPCS;
    01995
    01996      SID = Req.GetVariable("SessionID");
    01997      CurS = SMaster.getSession(SID,true);
    01998      if (CanPerform("Lm"))
    01999      {
    02000      // We've gotten our profile - want to integrate it into the server now
    02001          if (Req.GetVariable("ImportRemoteProfile","") != "")
    02002          {
    02003              TempPCS = CreateImportSessionInfo(CurS);
    02004              if (TempPCS == None)
    02005              {
    02006                  ShowMessage(Res, ImportProfileFailTitle, ImportProfileFailText);
    02007                  return;
    02008              }
    02009              ShowMessage(Res, SuccessImportProfileTitle, SuccessImportProfile);
    02010              return;
    02011          }
    02012      }
    02013
    02014      else AccessDenied(Res);
    02015  }
    02016
    02017  function RemoteImport(ProfileImporter ProfileConn)
    02018  {
    02019      local int i,j;
    02020      local Session   CurS;
    02021      local string    Tmp, TempStr,
    02022                      ImportRows,
    02023                      PackageLink,
    02024                      NewGameType, CustomGameLocation,
    02025                      NewAccessType, CustomAccessLocation,
    02026                      ImportProfileHTML,
    02027                      MapLocation, MutatorLocation, MutatorName;
    02028      local StringArray ImportMaps, ImportMutators;
    02029
    02030      local WebRequest        Req;
    02031      local WebResponse       Res;
    02032
    02033      Req = ProfileConn.QueryRequest;
    02034      Res = ProfileConn.QueryResponse;
    02035
    02036      if (Res == None)
    02037      {
    02038          ShowMessage(Res, ErrorText, ErrorTimeout);
    02039          return;
    02040      }
    02041
    02042      switch (ProfileConn.ImportResult)
    02043      {
    02044      case IMPORT_BadURL:         ShowMessage(Res,ErrorText,ErrorBadURL);         CleanupQuery(); return;
    02045      case IMPORT_ResolveError:   ShowMessage(Res,ErrorText,ErrorResolve);        CleanupQuery(); return;
    02046      case IMPORT_BindError:      ShowMessage(Res,ErrorText,ErrorBind);           CleanupQuery(); return;
    02047      case IMPORT_TimeOut:        ShowMessage(Res,ErrorText,ErrorTimeout);        CleanupQuery(); return;
    02048      case IMPORT_ServerError:    ShowMessage(Res,ErrorText,ErrorServer);         CleanupQuery(); return;
    02049      case IMPORT_BadRequest:     ShowMessage(Res,ErrorText,ErrorBadRequest);     CleanupQuery(); return;
    02050      case IMPORT_Unauthorized:   ShowMessage(Res,ErrorText,ErrorUnauthorized);   CleanupQuery(); return;
    02051      case IMPORT_Forbidden:      ShowMessage(Res,ErrorText,ErrorForbidden);      CleanupQuery(); return;
    02052      case IMPORT_NotFound:       ShowMessage(Res,ErrorText,ErrorNotFound);       CleanupQuery(); return;
    02053      case IMPORT_InvalidProfile: ShowMessage(Res,ErrorText,ErrorProfile);        CleanupQuery(); return;
    02054      }
    02055
    02056      CurS = ProfileConn.ImportS;
    02057      ImportMaps = new(None) class'SortedStringArray';
    02058      ImportMutators = new(None) class'SortedStringArray';
    02059
    02060  // General Profile Info
    02061      Res.Subst("SectionName", LabelGeneralProfile);
    02062      Res.Subst("SpecialInstructions", "");
    02063      ImportRows += WebInclude(IncludeSection);
    02064
    02065      Res.Subst("SettingName", LabelProfileName);
    02066      Res.Subst("SettingData", CurS.getValue("ProfileName"));
    02067      Res.Subst("Extra","");
    02068      ImportRows += WebInclude(IncludeRows);
    02069
    02070  // Profile Gametype Class
    02071      NewGameType = CurS.getValue("GameType");
    02072      CustomGameLocation = CurS.getValue("CustomGameLoc");
    02073
    02074      if (CustomGameLocation != "")
    02075          PackageLink = "<a href=\""$CustomGameLocation$"\" target=\"_blank\">"$CurS.getValue("GameName")$"</a>";
    02076      else PackageLink = CurS.getValue("GameName");
    02077
    02078      Res.Subst("SettingName", LabelGameType);
    02079      Res.Subst("SettingData", PackageLink);
    02080      Res.Subst("Extra","");
    02081      ImportRows += WebInclude(IncludeRows);
    02082
    02083  // Profile access control class
    02084      NewAccessType = CurS.getValue("ACClass");
    02085      CustomAccessLocation = CurS.getValue("CustomACLoc");
    02086
    02087      if (CustomAccessLocation != "")
    02088          PackageLink = "<a href=\""$CustomAccessLocation$"\" target=\"_blank\">"$NewAccessType$"</a>";
    02089      else PackageLink = NewAccessType;
    02090
    02091      Res.Subst("SettingName", LabelAccessControl);
    02092      Res.Subst("SettingData", PackageLink);
    02093      Res.Subst("Extra","");
    02094      ImportRows += WebInclude(IncludeRows);
    02095
    02096  // Map Information
    02097
    02098      Res.Subst("SectionName", TableTitle[3]);
    02099      Res.Subst("SpecialInstructions", "");
    02100      ImportRows += WebInclude(IncludeSection);
    02101
    02102      for (i = 0; i < CurS.getMapLength(); i++)
    02103          ImportMaps.Add(string(i), string(CurS.MapOrder(i)));
    02104
    02105      for (i = 0; i < ImportMaps.Count(); i++)
    02106      {
    02107          TempStr = CurS.getMap( int(ImportMaps.getItem(i)) );
    02108          MapLocation = ProfileConn.FindRemoteZipLocation(TempStr,ProfileConn.ProfileServerAddress $ ProfileConn.RemoteProfilePath);
    02109          if (MapLocation != "") PackageLink = "<a href=\""$MapLocation$"\" target=\"_blank\">"$TempStr$"</a>";
    02110          else PackageLink = TempStr;
    02111
    02112          if (CurS.MapRequired( TempStr ))
    02113              TempStr = "<font color=\"red\">"$RequiredText$"</font>";
    02114          else TempStr = AvailableText;
    02115
    02116          Res.Subst("SettingName", TempStr);
    02117          Res.Subst("SettingData", PackageLink);
    02118          Res.Subst("Extra", "");
    02119          ImportRows = ImportRows $ WebInclude(IncludeRows);
    02120      }
    02121
    02122  // Mutator Information
    02123      Res.Subst("SectionName", TableTitle[2]);
    02124      Res.Subst("SpecialInstructions", "");
    02125      ImportRows += WebInclude(IncludeSection);
    02126
    02127      for (i = 0; i < CurS.getMutatorLength(); i++)
    02128          ImportMutators.Add(string(i), CurS.getMutator(i));
    02129
    02130      for (i = 0; i < ImportMutators.Count(); i++)
    02131      {
    02132          TempStr = CurS.getMutator( int(ImportMutators.getItem(i)) );
    02133          for (j=0;j<CurS.getDataLength();j++)
    02134          {
    02135              CurS.getIDValue(j,MutatorName,Tmp);
    02136              if (Tmp ~= TempStr) break;
    02137          }
    02138
    02139          MutatorLocation = ProfileConn.FindRemoteZipLocation(TempStr,ProfileConn.ProfileServerAddress $ ProfileConn.RemoteProfilePath);
    02140          PackageLink = StringIf(MutatorLocation != "", "<a href=\""$MutatorLocation$"\" target=\"_blank\">"$MutatorName$"</a>", MutatorName);
    02141          TempStr = Stringif(CurS.MutRequired(TempStr), "<font color=\"red\">"$RequiredText$"</font>", AvailableText);
    02142
    02143          Res.Subst("SettingName", TempStr);
    02144          Res.Subst("SettingData", PackageLink);
    02145          Res.Subst("Extra", "");
    02146          ImportRows += WebInclude(IncludeRows);
    02147      }
    02148
    02149  // PlayInfo Information
    02150      Res.Subst("SectionName", TableTitle[4]);
    02151      Res.Subst("SpecialInstructions", "");
    02152      ImportRows += WebInclude(IncludeSection);
    02153      ImportRows = ImportRows $"<tr><td colspan=\"2\">&nbsp;</td></tr>"$ GeneratePlayInfoRows(Req,Res,IncludeRows);
    02154
    02155  // Build Subst's
    02156      Res.Subst("ButtonName", "ImportRemoteProfile");
    02157      Res.Subst("ButtonValue", ButtonApplyImportProfile);
    02158      Res.Subst("PageCaption", LabelApplyImportProfile);
    02159      ImportProfileHTML = WebInclude(IncludeCaptionButton);
    02160
    02161      Res.Subst("TableRows", ImportRows);
    02162      Res.Subst("LadderTable", WebInclude(IncludeTable) $ ImportProfileHTML);
    02163
    02164      Tmp = CurS.getValue("ProfileName", PageCaption[0]);
    02165      if (LadderRules.GetRemainingMatches() > 0 && Tmp == LadderRules.Profiles[GetCurrentConfigIndex()].ProfileName)
    02166          Tmp = Tmp @ LabelNumberMatchesLeft @ string(LadderRules.GetRemainingMatches());
    02167
    02168      Res.Subst("Section", LinkImportProfile);
    02169      Res.Subst("SubTitle", Tmp);
    02170      Res.Subst("PageHelp", HelpImportProfile);
    02171      Res.Subst("PostAction", SubImportURI$"?SessionID="$CurS.getHash());
    02172      ShowPage(Res, MasterPage);
    02173      CleanupQuery();
    02174  }
    02175
    02176  function QuerySubExport(WebRequest Req, WebResponse Res)
    02177  {
    02178      local int i,j;
    02179      local PlayInfo  TempPI;
    02180      local FileLog   EProfile;
    02181      local Session   CurS;
    02182      local string    SID, Logname,
    02183                      TempStr, Tmp,
    02184                      dataname, datavalue,
    02185                      ProfileIndex, NewGameType,
    02186                      ExportRows, Location;
    02187
    02188      local class<GameInfo>       GIClass;
    02189      local class<AccessControl>  ACClass;
    02190      local class<Mutator>        TempMut;
    02191      local array<class<Mutator> > MClass;
    02192      local class<Info>           TempSA;
    02193      local array<class<Info> >   SAClass;
    02194      local StringArray Mutators,GroupsOnly;
    02195
    02196
    02197      if (CanPerform("Lm"))
    02198      {
    02199          SID = Req.GetVariable("SessionID");
    02200          CurS = SMaster.getSession(SID,true);
    02201          ProfileIndex = Req.GetVariable("ProfileNameSelect", CurS.getValue("ProfileIndex"));
    02202
    02203          CreateSessionInfo(ProfileIndex,SID,True);
    02204          Logname = CurS.getValue("Logname",Req.GetVariable("TextInput"));
    02205          if (Logname == "")
    02206              Logname = CurS.getValue("ProfileName");
    02207
    02208          CurS.setValue("Logname",Logname,True);
    02209          for (i=0;i<CurS.getMutatorLength();i++)
    02210          {
    02211              TempStr = CurS.getMutator(i);
    02212              if (EpicPackage(TempStr))
    02213                  continue;
    02214              if (Req.GetVariable("Save"$TempStr,"") != "")
    02215                  SetLocation(TempStr,Req.GetVariable(TempStr));
    02216          }
    02217
    02218          for (i=0;i<CurS.getMapLength();i++)
    02219          {
    02220              TempStr = CurS.getMap(i);
    02221              if (EpicPackage(TempStr))
    02222                  continue;
    02223              if (Req.GetVariable("Save"$TempStr,"") != "")
    02224                  SetLocation(TempStr,Req.GetVariable(TempStr));
    02225          }
    02226
    02227          NewGameType = CurS.getValue("GameType");
    02228          if (NewGameType != "")
    02229              GIClass = class<GameInfo>(DynamicLoadObject(NewGameType,class'Class'));
    02230          if (GIClass==None)
    02231          {
    02232              ShowMessage(Res,ErrorGameClassTitle,ErrorGameClassText);
    02233              return;
    02234          }
    02235
    02236          TempStr = CurS.getValue("ACClass", Level.Game.AccessControlClass);
    02237          if (TempStr != "")
    02238              ACClass = class<AccessControl>(DynamicLoadObject(TempStr,class'Class'));
    02239          if (ACClass == None)
    02240          {
    02241              ShowMessage(Res,ErrorAccessControlTitle,ErrorAccessControlText);
    02242              return;
    02243          }
    02244
    02245          if (Req.GetVariable("Export","")!="")
    02246          {
    02247          // Write file locations to .ini
    02248              EProfile = Level.Spawn(class'FileLog');
    02249              if (EProfile == None)
    02250              {
    02251                  ShowMessage(Res, ErrorText, ErrorExportingProfile);
    02252                  return;
    02253              }
    02254
    02255              EProfile.OpenLog(RemoveStr(CurS.getValue("Logname")," "));
    02256              EProfile.Logf("Profile:"$CurS.getValue("ProfileName")$Chr(21)$CurS.getValue("GameType")$Chr(21)$CurS.getValue("MaxMaps")$Chr(21)$GIClass.default.GameName$Chr(21)$string(ACClass));
    02257
    02258              for (i=0;i<CurS.getMapLength();i++)
    02259              {
    02260                  TempStr = CurS.getMap(i);
    02261
    02262                  if (Req.GetVariable(TempStr,"") != "")
    02263                      Location = Chr(21) $ Req.GetVariable(TempStr);
    02264                  else Location = "";
    02265
    02266                  EProfile.Logf("Map:"$TempStr$Chr(21)$CurS.MapOrder(i)$Chr(21)$CurS.MapRequired(TempStr)$Location);
    02267              }
    02268
    02269              for (i=0;i<CurS.getSALength();i++)
    02270              {
    02271                  TempStr = CurS.getServerActor(i);
    02272                  for (j=0;j<ConfigM.ManagedActors.Length;j++)
    02273                      if (string(ConfigM.ManagedActors[j].SAClass) ~= TempStr)
    02274                          DataName = ConfigM.ManagedActors[j].SAName;
    02275
    02276                  if (Req.GetVariable(TempStr,"") != "")
    02277                      Location = Chr(21) $ Req.GetVariable(TempStr);
    02278                  else Location = "";
    02279
    02280                  EProfile.Logf("Mutator:"$DataName$Chr(21)$TempStr$Chr(21)$CurS.SARequired(TempStr)$Location);
    02281              }
    02282
    02283              for (i=0;i<CurS.getMutatorLength();i++)
    02284              {
    02285                  TempStr = CurS.getMutator(i);
    02286                  for (j=0;j<AllMutators.Length;j++)
    02287                      if (AllMutators[j].ClassName == TempStr)
    02288                          DataName = AllMutators[j].FriendlyName;
    02289
    02290                  if (Req.GetVariable(TempStr,"") != "")
    02291                      Location = Chr(21) $ Req.GetVariable(TempStr);
    02292                  else Location = "";
    02293
    02294                  EProfile.Logf("Mutator:"$DataName$Chr(21)$TempStr$Chr(21)$CurS.MutRequired(TempStr)$Location);
    02295              }
    02296
    02297              i=0;
    02298              j=0;
    02299              while (i<CurS.getDataLength())
    02300              {
    02301                  CurS.getIdValue(i,dataname,datavalue);
    02302                  if (InStr(dataname,".") != -1)
    02303                      EProfile.Logf("Data:"$DataName$Chr(21)$DataValue);
    02304                  i++;
    02305              }
    02306              EProfile.Destroy();
    02307              ShowMessage(Res, SuccessText, SuccessExportProfile$RemoveStr(LogName," ")$".txt");
    02308              return;
    02309          }
    02310
    02311
    02312      // Mutator Section
    02313          Mutators = new(None) class'SortedStringArray';
    02314          GroupsOnly = new(None) class'SortedStringArray';
    02315          for (i=0;i<CurS.getMutatorLength();i++)
    02316          {
    02317              TempStr = CurS.getMutator(i);
    02318              for (j=0;j<AllMutators.Length;j++)
    02319                  if (TempStr ~= AllMutators[j].ClassName)
    02320                      Mutators.Add(string(j), AllMutators[j].FriendlyName);
    02321              TempMut = class<Mutator>(DynamicLoadObject(TempStr,class'Class'));
    02322              if (TempMut != None)
    02323                  MClass[MClass.Length] = TempMut;
    02324          }
    02325
    02326          Res.Subst("SectionName", TableTitle[2]);
    02327          Res.Subst("SpecialInstructions", "");
    02328          ExportRows += WebInclude(IncludeSection);
    02329
    02330          for (i = 0; i<Mutators.Count(); i++)
    02331          {
    02332              j = int(Mutators.GetItem(i));
    02333
    02334              Res.Subst("SettingName", AllMutators[j].FriendlyName);
    02335              if (EpicPackage(AllMutators[j].ClassName))
    02336                  Res.Subst("SettingData", "");
    02337              else Res.Subst("SettingData", Textbox(AllMutators[j].ClassName,Min(Max(GetLongestURL(),16),64),128,GetLocation(AllMutators[j].ClassName)) $ "&nbsp;&nbsp;" $ SubmitButton("Save"$AllMutators[j].ClassName,ProfileButtonName[0]));
    02338
    02339              Res.Subst("Extra", "");
    02340              ExportRows += WebInclude(IncludeRows);
    02341          }
    02342
    02343          for (i=0;i<CurS.getSALength();i++)
    02344          {
    02345              TempStr = CurS.getServerActor(i);
    02346              if (TempStr != "")
    02347              {
    02348                  TempSA = class<Info>(DynamicLoadObject(TempStr,class'class'));
    02349                  if (TempSA != None)
    02350                      SAClass[SAClass.Length] = TempSA;
    02351              }
    02352          }
    02353
    02354          TempPI = new(None) class'PlayInfo';
    02355          LoadThisPlayInfo(TempPI, GIClass, ACClass, MClass, SAClass);
    02356
    02357          Res.Subst("SectionName", TableTitle[3]);
    02358          Res.Subst("SpecialInstructions", "");
    02359          ExportRows += WebInclude(IncludeSection);
    02360
    02361          Res.Subst("SettingName", LabelMaxMaps);
    02362          TempStr = CurS.getValue("MaxMaps");
    02363          if (TempStr == "0")
    02364              TempStr = UnlimitedText;
    02365          Res.Subst("SettingData", TempStr);
    02366          Res.Subst("Extra", "<tr><td colspan=\"2\">&nbsp;&nbsp;</td></tr>");
    02367          ExportRows += WebInclude(IncludeRows);
    02368
    02369  // Map Section
    02370          for (i=0;i<CurS.getMapLength();i++)
    02371          {
    02372              TempStr = CurS.getMap(i);
    02373              Res.Subst("SettingName", TempStr);
    02374              Res.Subst("Extra", "");
    02375              if (EpicPackage(TempStr))
    02376                  Res.Subst("SettingData", "");
    02377              else Res.Subst("SettingData", Textbox(TempStr,Min(Max(GetLongestURL(),16),64),128,GetLocation(TempStr)) $ "&nbsp;&nbsp;" $ SubmitButton("Save"$TempStr,ProfileButtonName[0]));
    02378
    02379              ExportRows += WebInclude(IncludeRows);
    02380          }
    02381
    02382  // PlayInfo section
    02383          Res.Subst("SectionName", TableTitle[4]);
    02384          Res.Subst("SpecialInstructions", "&nbsp;&nbsp;");
    02385          ExportRows += WebInclude(IncludeSection);
    02386          ExportRows += ("<tr><td colspan=\"2\">&nbsp;</td></tr>" $ GeneratePlayInfoRows(Req, Res, IncludeRows));
    02387          ExportRows += ("<tr><td colspan=\"2\">&nbsp;</td></tr><tr><td colspan=\"2\">"$LabelApplyExportProfile$"</td></tr><tr><td colspan=\"2\">"$SubmitButton("Export",ButtonApplyExportProfile)$"</td></tr>");
    02388
    02389          Res.Subst("TableRows", ExportRows);
    02390          Res.Subst("LadderTable", WebInclude(IncludeTable));
    02391
    02392          Tmp = CurS.getValue("ProfileName", PageCaption[0]);
    02393          if (LadderRules.GetRemainingMatches() > 0 && Tmp == LadderRules.Profiles[GetCurrentConfigIndex()].ProfileName)
    02394              Tmp = Tmp @ LabelNumberMatchesLeft @ string(LadderRules.GetRemainingMatches());
    02395
    02396          Res.Subst("Section", LinkExportProfile);
    02397          Res.Subst("PageHelp", HelpExportProfile);
    02398          Res.Subst("SubTitle", Tmp);
    02399          Res.Subst("PostAction", SubExportURI$"?SessionID="$SID);
    02400          ShowPage(Res, MasterPage);
    02401      }
    02402
    02403      else AccessDenied(Res);
    02404  }
    02405
    02406  //****************************************************************
    02407  //****************************************************************
    02408  // Query subpages for Add & Manage Modules
    02409  //
    02410  //
    02411
    02412  // Page 0
    02413  function QueryLadderManage(WebRequest Req, WebResponse Res)
    02414  {
    02415      local string    HeaderRows, ManagementRows,
    02416                      TempStr, Tmp, SID;
    02417      local bool      bAdd, bModify, bCopy, bDelete, bImport, bExport;
    02418      local Session   CurS;
    02419      local ProfileImporter ProfileConn;
    02420
    02421      if (CanPerform("Lm"))
    02422      {
    02423          SID = Req.GetVariable("SessionID");
    02424          CurS = SMaster.getSession(SID, True);
    02425
    02426          // Submit button was pressed
    02427          if (Req.GetVariable(ProfileButtonName[0], "") != "")
    02428          {
    02429              switch (Req.GetVariable("Actions",""))
    02430              {
    02431                  case "Add":
    02432                      bAdd = True;
    02433                      QuerySubFrame(Req, Res);
    02434                      break;
    02435
    02436                  case "Modify":
    02437                      bModify = True;
    02438                      TempStr = Req.GetVariable("ProfileNameSelect");
    02439                      if (TempStr == "")
    02440                      {
    02441                          StatusError(Res, ErrorNoProfilesExist);
    02442                          break;
    02443                      }
    02444                      QuerySubFrame(Req, Res);
    02445                      return;
    02446
    02447                  case "Copy":
    02448                      bCopy = True;
    02449                      Tmp = Req.GetVariable("ProfileNameSelect");
    02450                      if (Tmp == "")
    02451                          StatusError(Res, ErrorNoProfilesExist);
    02452
    02453                      TempStr = Req.GetVariable("TextInput");
    02454                      if (TempStr == "")
    02455                      {
    02456                          StatusError(Res, ErrorCopyNoName);
    02457                          break;
    02458                      }
    02459
    02460                      if (LadderRules.CopyProfile(int(Tmp),TempStr))
    02461                          StatusOK(Res,SuccessCopyProfile);
    02462                      else StatusError(Res, ErrorCopyFrom);
    02463                      break;
    02464
    02465                  case "Delete":
    02466                      bDelete = True;
    02467                      TempStr = Req.GetVariable("ProfileNameSelect");
    02468                      if (TempStr != "")
    02469                      {
    02470                          if (LadderRules.RemoveProfile(int(TempStr)))
    02471                              StatusOK(Res, SuccessDeleteProfile);
    02472                          else StatusError(Res, ErrorDeletingProfile);
    02473                      }
    02474                      else StatusError(Res, ErrorNoProfilesExist);
    02475                      break;
    02476
    02477                  case "Import":
    02478                      bImport = True;
    02479                      TempStr = Req.GetVariable("TextInput","");
    02480                      if (!(Left(TempStr,7) ~= "http://"))
    02481                      {
    02482                          StatusError(Res, ErrorBadURL);
    02483                          break;
    02484                      }
    02485
    02486                  // Spawn class to handle network interaction to receive remote profile
    02487                      ProfileConn = Level.Spawn(Class'ProfileImporter');
    02488                      If (ProfileConn == None)
    02489                      {
    02490                          ShowMessage(Res, ErrorText, ImportClassSpawnError);
    02491                          return;
    02492                      }
    02493
    02494                  // Assign local connection objects to importer class
    02495                      ProfileConn.QueryPage = Self;
    02496                      ProfileConn.QueryRequest = Req;
    02497                      ProfileConn.QueryResponse = Res;
    02498
    02499                  // Setting bDelayCleanup prevents the connection from being closed
    02500                  // when QueryProfileImport() returns to Query()
    02501                  // Set this prior to initializing connection, to ensure correct behavior
    02502                      Res.Connection.bDelayCleanup = True;
    02503
    02504                  // Initialize connection to foreign host, pass Importer class a Session
    02505                  // object to allow it to build a profile config set.
    02506                      ProfileConn.Connect(TempStr, CurS);
    02507                      return;
    02508
    02509                  case "Export":
    02510                      bExport = True;
    02511                      TempStr = Req.GetVariable("ProfileNameSelect", "");
    02512                      if (TempStr == "")
    02513                      {
    02514                          StatusError(Res, ErrorNoProfilesExist);
    02515                          break;
    02516                      }
    02517                      QuerySubExport(Req,Res);
    02518                      return;
    02519
    02520                  default:
    02521                      bModify = True;
    02522              }
    02523          }
    02524
    02525      // Output code -
    02526      // TODO: move to .inc file
    02527          HeaderRows = "<tr><td nowrap>"$LabelChooseAction$"</td><td nowrap>"$LabelInputDescription$"</td></tr>";
    02528          ManagementRows += ("<tr><td nowrap>"$RadioButton("Actions", "Add", bAdd)$LabelAddProfile$"<br>");
    02529          ManagementRows += (RadioButton("Actions", "Modify", bModify)$LabelModifyProfile$"</td>");
    02530          ManagementRows += ("<td><select class=mini name='ProfileNameSelect'>"$GenerateSwitchProfileOptions(TempStr)$"</select>&nbsp;"$LabelSelectActions$"</td></tr>");
    02531          ManagementRows += ("<tr><td nowrap>"$RadioButton("Actions", "Copy", bCopy)$LabelCopyProfile$"<br>");
    02532          ManagementRows += (RadioButton("Actions", "Delete", bDelete)$LabelDeleteProfile$"</td>");
    02533          ManagementRows += ("<td nowrap>"$Textbox("TextInput",64,128)$"&nbsp;"$LabelTextboxActions$"</td></tr>");
    02534          ManagementRows += ("<tr><td nowrap>"$RadioButton("Actions", "Import", bImport)$LabelImportProfile$"<br>");
    02535          ManagementRows += (RadioButton("Actions", "Export", bExport)$LabelExportProfile$"</td>");
    02536          ManagementRows += ("<td>"$SubmitButton(ProfileButtonName[0],ProfileButtonValue[0])$"</td></tr>");
    02537
    02538          Res.Subst("TableTitle", TableTitle[0]);
    02539          Res.Subst("HeaderRow", HeaderRows);
    02540          Res.Subst("TableRows",ManagementRows);
    02541
    02542          Tmp = CurS.getValue("ProfileName", PageCaption[0]);
    02543          if (LadderRules.GetRemainingMatches() > 0 && Tmp == LadderRules.Profiles[GetCurrentConfigIndex()].ProfileName)
    02544              Tmp @= (LabelNumberMatchesLeft @ string(LadderRules.GetRemainingMatches()));
    02545
    02546          Res.Subst("Section", LabelManagement);
    02547          Res.Subst("PageHelp", HelpManageProfile);
    02548          Res.Subst("SubTitle", Tmp);
    02549          Res.Subst("LadderTable", WebInclude(IncludeTable));
    02550          Res.Subst("PostAction", ProfileManageURI);
    02551          ShowPage(Res, MasterPage);
    02552      }
    02553
    02554      else AccessDenied(Res);
    02555  }
    02556
    02557  // Page 1
    02558  function QuerySubGameType(WebRequest Req, WebResponse Res)
    02559  {
    02560      local int i;
    02561      local string DataName, DataValue, SID, NewName, OldName;
    02562      local string GameTypeRows, OldGameType, CommandLineRows;
    02563      local string GameTypeTable, CommandLineTable, ApplyTable;
    02564      local Session CurS;
    02565      local LadderProfiles LadderMaster;
    02566
    02567
    02568      if (CanPerform("Lm"))
    02569      {
    02570          SID = Req.GetVariable("SessionID");
    02571          CurS = SMaster.getSession(SID, true);
    02572
    02573          if (Req.GetVariable(CurS.getValue("ButtonName",""),"")!="")
    02574          {
    02575              NewName = Req.GetVariable("NewProfile",DefaultProfileName);
    02576              OldName = CurS.getValue("ProfileName");
    02577              if ((OldName != "" && !(OldName ~= NewName)) || OldName == "")
    02578              {
    02579                  for (i=0;i<LadderRules.Profiles.Length;i++)
    02580                  {
    02581                      if (NewName ~= LadderRules.Profiles[i].ProfileName)
    02582                      {
    02583                          StatusError(Res, ErrorSameProfileName);
    02584                          NewName = DefaultProfileName;
    02585                          break;
    02586                      }
    02587                  }
    02588              }
    02589              CurS.setValue("ProfileName", NewName, true);
    02590              CurS.setValue("GameType", Req.GetVariable("NewGameType"), True, OldGameType);
    02591              if (!(OldGameType ~= CurS.getValue("GameType")))
    02592              {
    02593                  CurS.ClearMaps();
    02594              // Reset all stored PlayInfo information
    02595                  for (i=0;i<CurS.getDataLength();i++)
    02596                  {
    02597                      CurS.getIDValue(i,DataName,DataValue);
    02598                      if (InStr(DataName, ".") != -1)
    02599                      {
    02600                          CurS.delValue(DataName);
    02601                          i--;
    02602                      }
    02603                  }
    02604              }
    02605          }
    02606
    02607          Res.Subst("NewProfileName", CurS.getValue("ProfileName", DefaultProfileName));
    02608          GameTypeRows = WebInclude(IncludeProfileName);
    02609
    02610          for (i=0;i<AGameType.Count();i++)
    02611          {
    02612              Res.Subst("GameTypeClass",  AGameType.GetItem(i));
    02613              Res.Subst("GameTypeName",   AGameType.GetTag(i));
    02614              Res.Subst("Selected",       StringIf(CurS.getValue("GameType") ~= AGameType.GetItem(i), " checked", ""));
    02615              GameTypeRows += WebInclude(IncludeGameType);
    02616          }
    02617
    02618      // Fill in caption table values
    02619          Res.Subst("PageCaption",    CurS.getValue("PageCaption", PageCaption[1]));
    02620          Res.Subst("ButtonName",     CurS.getValue("ButtonName", ProfileButtonName[1]));
    02621          Res.Subst("ButtonValue",    CurS.getValue("ButtonValue", ProfileButtonValue[1]));
    02622
    02623          Res.Subst("TableRows",      GameTypeRows);
    02624          Res.Subst("LadderTable",    WebInclude(IncludeTable)$WebInclude(IncludeCaptionButton));
    02625          Res.Subst("PostAction",     CurS.GetValue("CurrentPage"));
    02626          ShowPage(Res, SubFrameContent);
    02627      }
    02628
    02629      else AccessDenied(Res);
    02630  }
    02631
    02632  // Page 2
    02633  function QuerySubMutators(WebRequest Req, WebResponse Res)
    02634  {
    02635      local int i,j;
    02636      local bool      bAllMuts,
    02637                      bClearMuts,
    02638                      bChecked;
    02639      local string    MutatorRows,
    02640                      SID, TempStr;
    02641
    02642      local Session CurS;
    02643      local StringArray Mutators, ServerActors;
    02644      local class<Mutator> MutClass;
    02645
    02646
    02647      if (CanPerform("Lm"))
    02648      {
    02649          SID = Req.GetVariable("SessionID");
    02650          CurS = SMaster.getSession(SID, true);
    02651
    02652          if (Req.GetVariable(CurS.getValue("ButtonName",""),"")!="")
    02653          {
    02654              bAllMuts = Req.GetVariable("AllowAllMutators")!="";
    02655              bClearMuts = Req.GetVariable("ClearAllMutators")!="";
    02656  //          CurS.ClearMutators();
    02657
    02658              for (i=0;i<ConfigM.ManagedActors.Length;i++)
    02659              {
    02660                  TempStr = string(ConfigM.ManagedActors[i].SAClass);
    02661                  if (bAllMuts || (!bClearMuts && Req.GetVariable(TempStr,"") != ""))
    02662                      CurS.setServerActor(TempStr, True, CurS.SARequired(TempStr));
    02663                  else CurS.delServerActor(TempStr);
    02664              }
    02665
    02666              for (i=0;i<AllMutators.Length;i++)
    02667              {
    02668                  if (bAllMuts || (!bClearMuts && (Req.GetVariable(AllMutators[i].ClassName,"")!="" || Req.GetVariable(AllMutators[i].GroupName)~=AllMutators[i].ClassName)))
    02669                      CurS.setMutator(AllMutators[i].ClassName,true,CurS.MutRequired(AllMutators[i].ClassName));
    02670                  else if (Req.GetVariable(AllMutators[i].GroupName) ~= "None")
    02671                      CurS.setMutator(AllMutators[i].GroupName,true);
    02672                  else
    02673                  {
    02674                      CurS.delMutator(AllMutators[i].ClassName);
    02675                      CurS.delMutator(AllMutators[i].GroupName);
    02676                  }
    02677              }
    02678          }
    02679
    02680          Mutators = new(None) class'SortedStringArray';
    02681          ServerActors = new(None) class'SortedStringArray';
    02682  //      GroupsOnly = new(None) class'SortedStringArray';
    02683          for (i = 0; i<AllMutators.Length; i++)
    02684          {
    02685              MutClass = class<Mutator>(DynamicLoadObject(AllMutators[i].ClassName, class'Class'));
    02686              if (MutClass != None)
    02687                  Mutators.Add(string(i),AllMutators[i].FriendlyName);
    02688          }
    02689
    02690          for (i=0;i<ConfigM.ManagedActors.Length;i++)
    02691              if (ConfigM.ManagedActors[i].SAClass != None)
    02692                  ServerActors.Add(string(i),ConfigM.ManagedActors[i].SAName);
    02693
    02694  // Uncomment this to allow mutators to be grouped according to MutatorGroup
    02695  /*
    02696          CreateFullMutatorList(Mutators,GroupsOnly);
    02697
    02698          for (i=0;i<CurS.GetMutatorLength();i++)
    02699          {
    02700              k = 0-1;
    02701              for (j=0;j<AllMutators.Length;j++)
    02702                  if (CurS.GetMutator(i) ~= AllMutators[j].ClassName)
    02703                      break;
    02704              if (j<AllMutators.Length) k = GroupsOnly.FindItemId(string(j));
    02705              if (k >= 0)
    02706              {
    02707                  for (z=0;z<TempA.Length;z++)
    02708                  {
    02709                      if (TempA[z] ~= AllMutators[j].GroupName)
    02710                      {
    02711                          bAllMuts = True;
    02712                          break;
    02713                      }
    02714                  }
    02715
    02716                  if (!bAllMuts) TempA[TempA.Length] = AllMutators[j].GroupName;
    02717              }
    02718              if (bAllMuts)
    02719                  break;
    02720          }
    02721
    02722          lastgroup = "";
    02723          thisgroup = "";
    02724          nextgroup = "";
    02725          MutatorRows="";
    02726
    02727          for (i=0;i<GroupsOnly.Count();i++)
    02728          {
    02729              j=int(GroupsOnly.GetItem(i));
    02730              if (AllMutators[j].GroupName=="")
    02731                  thisgroup="Z"$string(z++);
    02732              else thisgroup = AllMutators[j].GroupName;
    02733              if ( (i + 1) == GroupsOnly.Count())
    02734                  nextgroup = "";
    02735              else
    02736              {
    02737              // Assign nextgroup to the next mutators group
    02738                  k = int(GroupsOnly.GetItem(i + 1));
    02739                  if (AllMutators[k].GroupName=="")
    02740                      nextgroup="Z"$string(z);
    02741                  else nextgroup = AllMutators[k].GroupName;
    02742              }
    02743
    02744              Res.Subst("GroupName", thisgroup);
    02745              Res.Subst("MutatorClass", AllMutators[j].ClassName);
    02746              Res.Subst("MutatorName", AllMutators[j].FriendlyName);
    02747              Res.Subst("MutatorDesc", AllMutators[j].Description);
    02748
    02749              if ((lastgroup != thisgroup) && (thisgroup == nextgroup)) // and the next mut is in the same group as this one
    02750              {
    02751                  if (bAllMuts||CurS.HasMutator(thisgroup)) Res.Subst("Checked", "checked");
    02752                  MutatorRows = MutatorRows$WebInclude("current_mutators_group");
    02753              }
    02754              else
    02755              {
    02756                  if (CurS.HasMutator(AllMutators[j].ClassName) && !bAllMuts) Res.Subst("Checked", "checked"); else Res.Subst("Checked", "");
    02757                  MutatorRows = MutatorRows$WebInclude("current_mutators_group_row");
    02758              }
    02759
    02760              lastgroup=thisgroup;
    02761          }
    02762  */
    02763          bAllMuts = True;
    02764          for (i = 0; i<ServerActors.Count(); i++)
    02765          {
    02766              TempStr = ""; bChecked = False;
    02767              j = int(ServerActors.GetItem(i));
    02768
    02769              if (CurS.HasServerActor(string(ConfigM.ManagedActors[j].SAClass)))
    02770                  bChecked = True;
    02771              else if (bAllMuts) bAllMuts = False;
    02772
    02773              Res.Subst("Content", Checkbox(string(ConfigM.ManagedActors[j].SAClass),bChecked) $ "&nbsp;" $ ServerActors.GetTag(i));
    02774              TempStr = WebInclude(NowrapLeft);
    02775              Res.Subst("Content", ConfigM.ManagedActors[j].SADescription);
    02776              Res.Subst("RowContent", TempStr $ WebInclude(CellLeft));
    02777
    02778              MutatorRows += WebInclude(RowLeft);
    02779          }
    02780
    02781          for (i = 0; i<Mutators.Count(); i++)
    02782          {
    02783              TempStr = ""; bChecked = False;
    02784              j = int(Mutators.GetItem(i));
    02785
    02786              if (CurS.HasMutator(AllMutators[j].ClassName))
    02787                  bChecked = True;
    02788              else if (bAllMuts) bAllMuts = False;
    02789
    02790              Res.Subst("Content", CheckBox(AllMutators[j].ClassName, bChecked) $ "&nbsp;" $ AllMutators[j].FriendlyName);
    02791              TempStr = WebInclude(NowrapLeft);
    02792              Res.Subst("Content", AllMutators[j].Description);
    02793              Res.Subst("RowContent", TempStr $ WebInclude(CellLeft));
    02794
    02795              MutatorRows += WebInclude(RowLeft);
    02796          }
    02797
    02798          if (bAllMuts)
    02799              Res.Subst("Content", Checkbox("ClearAllMutators", False)@LabelUncheckAllMutator);
    02800          else
    02801              Res.Subst("Content", Checkbox("AllowAllMutators", False)@LabelCheckAllMutator);
    02802          Res.Subst("SpanLength", "2");
    02803          Res.Subst("SpanContent", "&nbsp;&nbsp;");
    02804          Res.Subst("RowContent", WebInclude(CellColSpan));
    02805          MutatorRows += WebInclude(RowLeft);
    02806
    02807          Res.Subst("RowContent", WebInclude(CellLeft));
    02808          MutatorRows += WebInclude(RowLeft);
    02809
    02810          Res.Subst("TableRows", MutatorRows);
    02811      // Fill in caption table values
    02812          Res.Subst("PageCaption",    CurS.getValue("PageCaption", PageCaption[2]));
    02813          Res.Subst("ButtonName",     CurS.getValue("ButtonName", ProfileButtonName[2]));
    02814          Res.Subst("ButtonValue",    CurS.getValue("ButtonValue", ProfileButtonValue[2]));
    02815
    02816          Res.Subst("LadderTable",    WebInclude(IncludeTable)$WebInclude(IncludeCaptionButton));
    02817          Res.Subst("PostAction",     CurS.GetValue("CurrentPage"));
    02818          ShowPage(Res, SubFrameContent);
    02819      }
    02820
    02821      else AccessDenied(Res);
    02822  }
    02823
    02824  // Page3
    02825  function QuerySubMaps(WebRequest Req, WebResponse Res)
    02826  {
    02827      local int i;
    02828      local string    SID,
    02829                      MapRows,
    02830                      TempStr, Temp,
    02831                      CheckString;
    02832      local bool      bAllMaps,
    02833                      bClearMaps,
    02834                      bChecked;
    02835
    02836      local Session CurS;
    02837      local StringArray SortedMaps;
    02838      local array<string> TempMaps;
    02839      local class<GameInfo> GIClass;
    02840
    02841
    02842      if (CanPerform("Lm"))
    02843      {
    02844          SID = Req.GetVariable("SessionID");
    02845          CurS = SMaster.getSession(SID);
    02846
    02847          TempStr = CurS.getValue("GameType");
    02848          if (TempStr != "")
    02849              GIClass = class<GameInfo>(DynamicLoadObject(TempStr,class'Class'));
    02850          if (GIClass == None)
    02851          {
    02852              ShowFramedMessage(Res,ErrorGameClassText,True);
    02853              return;
    02854          }
    02855          // Build a string array of maps valid for this gametype.
    02856          GIClass.static.LoadMapList(GIClass.default.MapPrefix, TempMaps);
    02857
    02858          if (Req.GetVariable(CurS.getValue("ButtonName",""),"")!="")
    02859          {
    02860              bAllMaps = Req.GetVariable("AllowAllMaps","")!="";
    02861              bClearMaps = Req.GetVariable("ClearAllMaps","")!="";
    02862
    02863              for (i=0;i<TempMaps.Length;i++)
    02864                  if (bAllMaps || (!bClearMaps && Req.GetVariable(TempMaps[i])!=""))
    02865                      CurS.setMap(TempMaps[i],0,True,CurS.MapRequired(TempMaps[i]));
    02866                  else CurS.delMap(TempMaps[i]);
    02867          }
    02868          // Add the map name array to a sorted string array for sorting
    02869          SortedMaps = new(None) class'SortedStringArray';
    02870          for(i=0;i<TempMaps.Length;i++)
    02871              SortedMaps.Add(string(i),TempMaps[i]);
    02872
    02873          bAllMaps = True;
    02874          // Now build the map rows
    02875          for (i=0;i<SortedMaps.Count();i++)
    02876          {
    02877              Temp = ""; bChecked = False;
    02878              TempStr = SortedMaps.GetTag(i);
    02879              if (CurS.HasMap(TempStr))
    02880                  bChecked = True;
    02881              else if (bAllMaps) bAllMaps = False;
    02882
    02883              Res.Subst("Content", Checkbox(TempStr, bChecked) $ "&nbsp;" $ TempStr);
    02884              Res.Subst("RowContent", WebInclude(CellLeft));
    02885          // Build string for javascript function
    02886              if (CheckString!="")
    02887                  CheckString += "','";
    02888              CheckString += TempStr;
    02889
    02890              MapRows += WebInclude(RowLeft);
    02891          }
    02892
    02893      // Fill Javascript substs
    02894          Res.Subst("JavaScripts","<script language=\"JavaScript\" type=\"text/JavaScript\">function MM_findObj(n,d){var p,i,x;if(!d)d=document;if((p=n.indexOf(\"?\"))>0&&parent.frames.length){d=parent.frames[n.substring(p+1)].document;n=n.substring(0,p);}if(!(x=d[n])&&d.all)x=d.all[n];for(i=0;!x&&i<d.forms.length;i++)x=d.forms[i][n];for(i=0;!x&&d.layers&&i<d.layers.length;i++)x=MM_findObj(n,d.layers[i].document);if(!x&&d.getElementById)x=d.getElementById(n);return x;}function CheckMaps(){var maps=CheckMaps.arguments;var MapChecked=false;for(var i=0;i<maps.length;i++){var myObj=MM_findObj(maps[i]);if(myObj.checked==true){MapChecked=true}}if(MapChecked==false){alert('You must check at least one map to continue!')}document.MM_returnValue=(MapChecked);}</script>");
    02895          Res.Subst("JCheck"," onClick=\"CheckMaps('AllowAllMaps','"$CheckString$"');return document.MM_returnValue\"");
    02896          Res.Subst("Checked","");
    02897
    02898          if (bAllMaps)
    02899              Res.Subst("Content", Checkbox("ClearAllMaps", False) @ LabelUncheckAllMap);
    02900          else Res.Subst("Content", Checkbox("AllowAllMaps", False) @ LabelCheckAllMap);
    02901
    02902          Res.Subst("SpanLength", "2");
    02903          Res.Subst("SpanContent", "&nbsp;&nbsp;");
    02904          Res.Subst("RowContent", WebInclude(CellColSpan));
    02905          MapRows += WebInclude(RowLeft);
    02906
    02907          Res.Subst("RowContent", WebInclude(CellLeft));
    02908          MapRows += WebInclude(RowLeft);
    02909
    02910          // Set ladder_caption_table subst's
    02911          Res.Subst("PageCaption",    CurS.getValue("PageCaption",PageCaption[3]));
    02912          Res.Subst("ButtonName",     CurS.getValue("ButtonName", ProfileButtonName[3]));
    02913          Res.Subst("ButtonValue",    CurS.getValue("ButtonValue", ProfileButtonValue[3]));
    02914
    02915          Res.Subst("TableRows", MapRows);
    02916
    02917          Res.Subst("LadderTable",    WebInclude(IncludeTable)$WebInclude(IncludeCaptionButton));
    02918          Res.Subst("PostAction",     CurS.getValue("CurrentPage"));
    02919          ShowPage(Res, SubFrameContent);
    02920      }
    02921
    02922      else AccessDenied(Res);
    02923  }
    02924
    02925  // Page 4
    02926  function QuerySubRules(WebRequest Req, WebResponse Res)
    02927  {
    02928      local int i;
    02929      local string    TempStr,
    02930                      SID;
    02931      local Session   CurS;
    02932      local PlayInfo  TempPI;
    02933      local class<Mutator>        TempClass;
    02934      local class<GameInfo>       GIClass;
    02935      local class<AccessControl>  ACClass;
    02936      local array<class<Mutator> > MClass;
    02937      local class<Info>           TempSA;
    02938      local array<class<Info> >   SAClass;
    02939
    02940      if (CanPerform("Lm"))
    02941      {
    02942          SID = Req.GetVariable("SessionID");
    02943          CurS = SMaster.GetSession(SID);
    02944
    02945          TempStr = CurS.getValue("GameType");
    02946          if (TempStr != "")
    02947              GIClass = class<GameInfo>(DynamicLoadObject(TempStr,class'Class'));
    02948          if (GIClass == None)
    02949          {
    02950              ShowFramedMessage(Res,ErrorGameClassText,True);
    02951              return;
    02952          }
    02953
    02954          TempStr = CurS.getValue("ACClass", Level.Game.AccessControlClass);
    02955          if (TempStr != "")
    02956              ACClass = class<AccessControl>(DynamicLoadObject(TempStr,class'Class'));
    02957          if (ACClass == None)
    02958          {
    02959              ShowFramedMessage(Res,ErrorAccessControlText,True);
    02960              return;
    02961          }
    02962
    02963          if (Req.GetVariable(CurS.getValue("ButtonName",""),"")!="")
    02964          {
    02965              for (i=0;i<CurS.GetMutatorLength();i++)
    02966              {
    02967                  TempStr = CurS.getMutator(i);
    02968                  if (TempStr != "")
    02969                  {
    02970                      TempClass = class<Mutator>(DynamicLoadObject(TempStr,class'Class'));
    02971                      if (TempClass != None)
    02972                          MClass[MClass.Length] = TempClass;
    02973                  }
    02974              }
    02975
    02976              TempPI = new(None) class'PlayInfo';
    02977              for (i=0;i<CurS.getSALength(); i++)
    02978              {
    02979                  TempStr = CurS.getServerActor(i);
    02980                  if (TempStr != "")
    02981                  {
    02982                      TempSA = class<Info>(DynamicLoadObject(TempStr,class'Class'));
    02983                      if (TempSA != None)
    02984                          SAClass[SAClass.Length] = TempSA;
    02985                  }
    02986              }
    02987
    02988              LoadThisPlayInfo(TempPI, GIClass, ACClass, MClass, SAClass);
    02989              for (i=0;i<TempPI.Settings.Length;i++)
    02990              {
    02991                  if (!SettingIsAllowed(TempPI.Settings[i].SecLevel)) continue;
    02992                  TempStr = Req.GetVariable(TempPI.Settings[i].SettingName,TempPI.Settings[i].Value);
    02993
    02994                  if (TempPI.Settings[i].RenderType == "Text")
    02995                      CheckSettingValue(TempPI.Settings[i].Data, TempStr);
    02996
    02997                  CurS.setValue(TempPI.Settings[i].SettingName,TempStr,true);
    02998              }
    02999          }
    03000
    03001          Res.Subst("TableRows",      GeneratePlayInfoRows(Req, Res, "defaults_row"));
    03002
    03003          // Set ladder_caption_table subst's
    03004          Res.Subst("PageCaption",    CurS.getValue("PageCaption",PageCaption[4]));
    03005          Res.Subst("ButtonName",     CurS.getValue("ButtonName", ProfileButtonName[4]));
    03006          Res.Subst("ButtonValue",    CurS.getValue("ButtonValue", ProfileButtonValue[4]));
    03007
    03008          Res.Subst("LadderTable",    WebInclude(IncludeTable)$WebInclude(IncludeCaptionButton));
    03009          Res.Subst("PostAction",     CurS.getValue("CurrentPage"));
    03010          ShowPage(Res, SubFrameContent);
    03011      }
    03012
    03013      else AccessDenied(Res);
    03014  }
    03015
    03016  // Page 5
    03017  function QuerySubReview(WebRequest Req, WebResponse Res)
    03018  {
    03019      local int i,j,k,z;
    03020      local string    SID,
    03021                      TempStr, TempSA,
    03022                      ReviewRows,
    03023                      thisgroup, lastgroup, nextgroup;
    03024
    03025      local Session CurS;
    03026      local StringArray Mutators, GroupsOnly;
    03027      local class<Mutator>        TempClass;
    03028      local class<Info>           TempSAClass;
    03029      local class<GameInfo>       GIClass;
    03030      local class<AccessControl>  ACClass;
    03031      local array<class<Mutator> > MClass;
    03032
    03033      if (CanPerform("Lm"))
    03034      {
    03035          SID = Req.GetVariable("SessionID");
    03036          CurS = SMaster.getSession(SID);
    03037
    03038          TempStr = CurS.getValue("GameType");
    03039          if (TempStr != "")
    03040              GIClass = class<GameInfo>(DynamicLoadObject(TempStr,class'Class'));
    03041          if (GIClass == None)
    03042          {
    03043              ShowFramedMessage(Res,ErrorGameClassText,True);
    03044              return;
    03045          }
    03046
    03047          TempStr = CurS.getValue("ACClass",Level.Game.AccessControlClass);
    03048          if (TempStr != "")
    03049              ACClass = class<AccessControl>(DynamicLoadObject(TempStr,class'Class'));
    03050          if (ACClass == None)
    03051          {
    03052              ShowFramedMessage(Res,ErrorAccessControlText,True);
    03053              return;
    03054          }
    03055
    03056          Mutators = new(None) class'SortedStringArray';
    03057          GroupsOnly = new(None) class'SortedStringArray';
    03058          for (i = 0; i<AllMutators.Length; i++)
    03059          {
    03060              if (CurS.HasMutator(AllMutators[i].ClassName)||CurS.HasMutator(AllMutators[i].GroupName))
    03061              {
    03062                  TempClass = class<Mutator>(DynamicLoadObject(AllMutators[i].ClassName, class'Class'));
    03063                  if (TempClass != None)
    03064                  {
    03065                      MClass[MClass.Length] = TempClass;
    03066                      Mutators.Add(string(i),AllMutators[i].FriendlyName);
    03067                  }
    03068              }
    03069          }
    03070
    03071          CreateFullMutatorList(Mutators,GroupsOnly);
    03072          lastgroup = ""; thisgroup = ""; nextgroup = "";
    03073
    03074          Res.Subst("SectionName", TableTitle[2]);
    03075          Res.Subst("SpecialInstructions", LabelRequiredMutators);
    03076          ReviewRows += WebInclude(IncludeSection);
    03077
    03078          for (i=0;i<GroupsOnly.Count();i++)
    03079          {
    03080              j=int(GroupsOnly.GetItem(i));
    03081
    03082              if (AllMutators[j].GroupName=="")
    03083                  thisgroup="Z"$string(z++);
    03084              else thisgroup = AllMutators[j].GroupName;
    03085
    03086              if ( (i + 1) == GroupsOnly.Count())
    03087                  nextgroup = "";
    03088              else
    03089              {
    03090              // Assign nextgroup to the next mutators group
    03091                  k = int(GroupsOnly.GetItem(i + 1));
    03092                  if (AllMutators[k].GroupName=="")
    03093                      nextgroup="Z"$string(z);
    03094                  else nextgroup = AllMutators[k].GroupName;
    03095              }
    03096
    03097              Res.Subst("GroupName", thisgroup);
    03098              Res.Subst("MutatorClass", AllMutators[j].ClassName);
    03099              Res.Subst("MutatorName", AllMutators[j].FriendlyName);
    03100              Res.Subst("MutatorDesc", AllMutators[j].Description);
    03101
    03102              if ((lastgroup != thisgroup) && (thisgroup == nextgroup)) // and the next mut is in the same group as this one
    03103              {
    03104                  Res.Subst("Checked", " checked");
    03105                  ReviewRows += WebInclude("current_mutators_group");
    03106              }
    03107
    03108              Res.Subst("Checked", StringIf(CurS.MutRequired(AllMutators[j].ClassName), " checked", ""));
    03109              ReviewRows += WebInclude("current_mutators_group_row");
    03110
    03111              lastgroup=thisgroup;
    03112          }
    03113
    03114          for (i = 0; i<Mutators.Count(); i++)
    03115          {
    03116              TempStr = "";
    03117              j = int(Mutators.GetItem(i));
    03118
    03119              Res.Subst("Content", CheckBox(AllMutators[j].ClassName, CurS.MutRequired(AllMutators[j].ClassName)) $ "&nbsp;" $ AllMutators[j].FriendlyName);
    03120              TempStr = WebInclude(NowrapLeft);
    03121              Res.Subst("Content", AllMutators[j].Description);
    03122              Res.Subst("RowContent", TempStr $ WebInclude(CellLeft));
    03123
    03124              ReviewRows += WebInclude(RowLeft);
    03125          }
    03126
    03127          Mutators.Reset();
    03128          for (i = 0; i < ConfigM.ManagedActors.Length; i++)
    03129          {
    03130              TempSA = string(ConfigM.ManagedActors[i].SAClass);
    03131              if (CurS.HasServerActor(TempSA))
    03132              {
    03133                  TempSAClass = class<Info>(DynamicLoadObject(TempSA,class'Class'));
    03134                  if (TempSAClass != None)
    03135                      Mutators.Add(string(i),ConfigM.ManagedActors[i].SAName);
    03136              }
    03137          }
    03138          lastgroup = "";
    03139          Res.Subst("SpanLength", "2");
    03140          Res.Subst("SpanContent", "&nbsp;&nbsp;");
    03141          Res.Subst("RowContent", WebInclude(CellColSpan));
    03142          lastgroup = WebInclude(RowLeft);
    03143          ReviewRows += lastgroup;
    03144
    03145          for (i=0;i<Mutators.Count();i++)
    03146          {
    03147              TempStr = "";
    03148              j = int(Mutators.GetItem(i));
    03149
    03150              Res.Subst("Content", Checkbox(string(ConfigM.ManagedActors[j].SAClass), CurS.SARequired(string(ConfigM.ManagedActors[j].SAClass))) $ "&nbsp;" $ Mutators.GetTag(i));
    03151              TempStr = WebInclude(NowrapLeft);
    03152              Res.Subst("Content", ConfigM.ManagedActors[j].SADescription);
    03153              Res.Subst("RowContent", TempStr $ WebInclude(CellLeft));
    03154              ReviewRows += WebInclude(RowLeft);
    03155          }
    03156
    03157          Res.Subst("SectionName", TableTitle[3]);
    03158          Res.Subst("SpecialInstructions", LabelRequiredMaps);
    03159          ReviewRows += WebInclude(IncludeSection);
    03160
    03161          Res.Subst("SettingName", LabelMaxMaps);
    03162          Res.Subst("SettingData", Textbox("MaxMaps", 3, 3, CurS.getValue("MaxMaps","3")));
    03163          Res.Subst("Extra", lastgroup);
    03164          ReviewRows += WebInclude(IncludeRows);
    03165          for (i=0;i<CurS.GetMapLength();i++)
    03166          {
    03167              Res.Subst("SettingName", CurS.getMap(i));
    03168              Res.Subst("Extra", "");
    03169              Res.Subst("SettingData", Checkbox(CurS.getMap(i), CurS.MapRequired(CurS.getMap(i))));
    03170
    03171              ReviewRows += WebInclude(IncludeRows);
    03172          }
    03173
    03174          Res.Subst("SectionName", TableTitle[4]);
    03175          Res.Subst("SpecialInstructions", LabelPlayInfo);
    03176          Res.Subst("Extra", lastgroup);
    03177          ReviewRows += WebInclude(IncludeSection);
    03178
    03179          ReviewRows += (lastgroup $ GeneratePlayInfoRows(Req, Res, IncludeRows));
    03180          Res.Subst("TableRows", ReviewRows);
    03181
    03182      // Set ladder_caption_table subst's
    03183          Res.Subst("PageCaption",    CurS.getValue("PageCaption",PageCaption[5]));
    03184          Res.Subst("ButtonName",     CurS.getValue("ButtonName", ProfileButtonName[5]));
    03185          Res.Subst("ButtonValue",    CurS.getValue("ButtonValue", ProfileButtonValue[5]));
    03186
    03187          Res.Subst("LadderTable",    WebInclude(IncludeTable)$WebInclude(IncludeCaptionButton));
    03188          Res.Subst("PostAction",     SubSavedURI$"?SessionID="$SID);
    03189          Res.Subst("NewTarget",      " target=\"_parent\"");
    03190          ShowPage(Res, SubFrameContent);
    03191      }
    03192
    03193      else AccessDenied(Res);
    03194  }
    03195
    03196  // Page 6
    03197  function QuerySubSaved(WebRequest Req, WebResponse Res)
    03198  {
    03199      local int i,k, x;
    03200      local string    SID,
    03201                      tmp, tmp1,
    03202                      TempStr;
    03203      local Session               CurS;
    03204      local PlayInfo              TempPI;
    03205      local ProfileConfigSet      TempPCS;
    03206      local array<string>         TempArr;
    03207      local array<class<Mutator> > MClass;
    03208      local array<class<Info> >   SAClass;
    03209
    03210      local class<Mutator>        MutClass;
    03211      local class<GameInfo>       GIClass;
    03212      local class<AccessControl>  ACClass;
    03213      local class<Info>           TempSA;
    03214
    03215
    03216      SID = Req.GetVariable("SessionID");
    03217      CurS = SMaster.getSession(SID);
    03218      if (CanPerform("Lm"))
    03219      {
    03220          TempStr = CurS.getValue("GameType");
    03221          if (TempStr != "")
    03222              GIClass = class<GameInfo>(DynamicLoadObject(TempStr,class'Class'));
    03223          if (GIClass == None)
    03224          {
    03225              ShowFramedMessage(Res,ErrorGameClassText,True);
    03226              return;
    03227          }
    03228
    03229          TempStr = CurS.getValue("ACClass",Level.Game.AccessControlClass);
    03230          if (TempStr != "")
    03231              ACClass = class<AccessControl>(DynamicLoadObject(TempStr,class'Class'));
    03232          if (ACClass == None)
    03233          {
    03234              ShowFramedMessage(Res,ErrorAccessControlText,True);
    03235              return;
    03236          }
    03237          TempPI = new(None) class'PlayInfo';
    03238
    03239          // We are managing an existing profile
    03240          if (CurS.hasData("ProfileIndex"))
    03241          {
    03242              k = int(CurS.getValue("ProfileIndex"));
    03243              TempPCS = LadderRules.LadderProfiles[k];
    03244              if (LadderRules.Profiles[k].ProfileName != CurS.getValue("ProfileName"))
    03245              {
    03246                  LadderRules.Profiles[k].ProfileName = CurS.getValue("ProfileName");
    03247                  LadderRules.AllLadderProfiles.Remove(LadderRules.AllLadderProfiles.FindItemId(string(k)));
    03248                  LadderRules.AllLadderProfiles.Add(string(k),LadderRules.Profiles[k].ProfileName);
    03249                  LadderRules.SaveConfig();
    03250              }
    03251
    03252              if (TempPCS.StartEdit())
    03253              {
    03254                  TempPCS.SetGameType(CurS.getValue("GameType"));
    03255                  TempPCS.EndEdit(False);
    03256              }
    03257          }
    03258
    03259          else TempPCS = LadderRules.AddProfile(CurS.getValue("ProfileName"), CurS.getValue("GameType"));
    03260
    03261          if (TempPCS.StartEdit())
    03262          {
    03263              for (i=0;i<AllMutators.Length;i++)
    03264              {
    03265                  MutClass = class<Mutator>(DynamicLoadObject(AllMutators[i].ClassName,class'Class'));
    03266                  if (MutClass != None)
    03267                  {
    03268                      if ((Req.GetVariable(AllMutators[i].ClassName,"")!="")||(Req.GetVariable(AllMutators[i].GroupName,"")~=AllMutators[i].ClassName))
    03269                          CurS.setMutator(AllMutators[i].ClassName,true,true);
    03270                      else CurS.setMutator(AllMutators[i].ClassName,false);
    03271
    03272                      if (CurS.HasMutator(AllMutators[i].ClassName))
    03273                      {
    03274                          MClass[MClass.Length] = MutClass;
    03275                          TempPCS.AddProfileMutator(AllMutators[i].ClassName,CurS.MutRequired(AllMutators[i].ClassName));
    03276                      }
    03277                      else TempPCS.DelProfileMutator(AllMutators[i].ClassName);
    03278                  }
    03279              }
    03280
    03281              for (i=0;i<ConfigM.ManagedActors.Length;i++)
    03282              {
    03283                  TempSA = ConfigM.ManagedActors[i].SAClass;
    03284                  if (TempSA != None)
    03285                  {
    03286                      TempStr = string(ConfigM.ManagedActors[i].SAClass);
    03287                      if (Req.GetVariable(TempStr,"") != "")
    03288                          CurS.setServerActor(TempStr, True, True);
    03289                      else CurS.setServerActor(TempStr, False);
    03290
    03291                      if (CurS.HasServerActor(TempStr))
    03292                      {
    03293                          SAClass[SAClass.Length] = TempSA;
    03294                          TempPCS.AddProfileServerActor(TempStr,CurS.SARequired(TempStr));
    03295                      }
    03296                      else TempPCS.DelProfileServerActor(TempStr);
    03297                  }
    03298              }
    03299
    03300              x = LoadThisPlayInfo(TempPI, GIClass, ACClass, MClass, SAClass);
    03301              if (x >= 0)
    03302              {
    03303                  ShowFramedMessage(Res, ErrorLoadingPlayInfoText[x],True);
    03304                  return;
    03305              }
    03306              CurS.setValue("MaxMaps",Req.GetVariable("MaxMaps"),true);
    03307              TempPCS.MaxMaps = int(CurS.getValue("MaxMaps"));
    03308
    03309              GIClass.static.LoadMapList(GIClass.default.MapPrefix, TempArr);
    03310              for (i=0;i<TempArr.Length;i++)
    03311              {
    03312                  if (Req.GetVariable(TempArr[i],"")!="")
    03313                      CurS.setMap(TempArr[i],0,true,true);
    03314                  else CurS.setMap(TempArr[i],0,false,false);
    03315
    03316                  if (CurS.HasMap(TempArr[i]))
    03317                      TempPCS.AddProfileMap(TempArr[i], CurS.MapRequired(TempArr[i]));
    03318                  else TempPCS.DelProfileMap(TempArr[i]);
    03319              }
    03320
    03321              for (i=0;i<TempPI.Settings.Length;i++)
    03322              {
    03323                  if (TempPI.Settings[i].SecLevel > CurAdmin.MaxSecLevel()) continue;
    03324                  tmp = ""; tmp1="";
    03325                  if (CurS.getIdValue(i,tmp,tmp1) == -1)
    03326                      break;
    03327                  if (!TempPCS.SetProfileNamedParam(TempPI.Settings[i].SettingName, CurS.getValue(TempPI.Settings[i].SettingName,TempPI.Settings[i].Value)))
    03328                      TempPCS.SetProfileParam(TempPCS.Count(),TempPI.Settings[i].SettingName,CurS.getValue(TempPI.Settings[i].SettingName,TempPI.Settings[i].Value));
    03329              }
    03330
    03331              TempPCS.EndEdit(true);
    03332          }
    03333
    03334          else
    03335          {
    03336              StatusError(Res,ErrorSavingProfile);
    03337              QuerySubReview(Req, Res);
    03338              return;
    03339          }
    03340          Tmp = CurS.getValue("ProfileName", PageCaption[0]);
    03341          if (LadderRules.GetRemainingMatches() > 0 && Tmp == LadderRules.Profiles[GetCurrentConfigIndex()].ProfileName)
    03342              Tmp = Tmp @ LabelNumberMatchesLeft @ string(LadderRules.GetRemainingMatches());
    03343          Res.Subst("SubTitle", Tmp);
    03344          ShowMessage(Res, TableTitle[6], PageCaption[6]);
    03345          return;
    03346      }
    03347
    03348      else AccessDenied(Res);
    03349  }
    03350
    03351  defaultproperties
    03352  {
    03353       EpicPackages(0)="BR-Anubis"
    03354       EpicPackages(1)="BR-Bifrost"
    03355       EpicPackages(2)="BR-Disclosure"
    03356       EpicPackages(3)="BR-IceFields"
    03357       EpicPackages(4)="BR-Skyline"
    03358       EpicPackages(5)="BR-Slaughterhouse"
    03359       EpicPackages(6)="BR-TwinTombs"
    03360       EpicPackages(7)="CTF-Chrome"
    03361       EpicPackages(8)="CTF-Citadel"
    03362       EpicPackages(9)="CTF-December"
    03363       EpicPackages(10)="CTF-Face3"
    03364       EpicPackages(11)="CTF-Geothermal"
    03365       EpicPackages(12)="CTF-Lostfaith"
    03366       EpicPackages(13)="CTF-Magma"
    03367       EpicPackages(14)="CTF-Maul"
    03368       EpicPackages(15)="CTF-Orbital2"
    03369       EpicPackages(16)="DM-Antalus"
    03370       EpicPackages(17)="DM-Asbestos"
    03371       EpicPackages(18)="DM-Compressed"
    03372       EpicPackages(19)="DM-Curse3"
    03373       EpicPackages(20)="DM-Flux2"
    03374       EpicPackages(21)="DM-Gael"
    03375       EpicPackages(22)="DM-Inferno"
    03376       EpicPackages(23)="DM-Insidious"
    03377       EpicPackages(24)="DM-Leviathan"
    03378       EpicPackages(25)="DM-Oceanic"
    03379       EpicPackages(26)="DM-Phobos2"
    03380       EpicPackages(27)="DM-Plunge"
    03381       EpicPackages(28)="DM-Serpentine"
    03382       EpicPackages(29)="DM-TokaraForest"
    03383       EpicPackages(30)="DM-TrainingDay"
    03384       EpicPackages(31)="DOM-Core"
    03385       EpicPackages(32)="DOM-OutRigger"
    03386       EpicPackages(33)="DOM-Ruination"
    03387       EpicPackages(34)="DOM-ScorchedEarth"
    03388       EpicPackages(35)="DOM-SepukkuGorge"
    03389       EpicPackages(36)="DOM-Suntemple"
    03390       EpicPackages(37)="Entry"
    03391       EpicPackages(38)="NvidiaLogo"
    03392       EpicPackages(39)="TUT-BR"
    03393       EpicPackages(40)="TUT-CTF"
    03394       EpicPackages(41)="TUT-DM"
    03395       EpicPackages(42)="TUT-DOM"
    03396       EpicPackages(43)="UT2-intro"
    03397       EpicPackages(44)="VehicleDemo"
    03398       EpicPackages(45)="endgame"
    03399       EpicPackages(46)="Core"
    03400       EpicPackages(47)="Editor"
    03401       EpicPackages(48)="Engine"
    03402       EpicPackages(49)="Fire"
    03403       EpicPackages(50)="GamePlay"
    03404       EpicPackages(51)="IpDrv"
    03405       EpicPackages(52)="UWeb"
    03406       EpicPackages(53)="UnrealEd"
    03407       EpicPackages(54)="UnrealGame"
    03408       EpicPackages(55)="Vehicles"
    03409       EpicPackages(56)="XAdmin"
    03410       EpicPackages(57)="XEffects"
    03411       EpicPackages(58)="XGame"
    03412       EpicPackages(59)="XGame_rc"
    03413       EpicPackages(60)="XInterface"
    03414       EpicPackages(61)="XPickups"
    03415       EpicPackages(62)="XPickups_rc"
    03416       EpicPackages(63)="XWeapons"
    03417       EpicPackages(64)="XWeapons_rc"
    03418       EpicPackages(65)="XWebAdmin"
    03419       EpicPackages(66)="BR-DE-ElecFields"
    03420       EpicPackages(67)="CTF-DE-ElecFields"
    03421       EpicPackages(68)="CTF-DE-LavaGiant2"
    03422       EpicPackages(69)="DM-DE-Grendelkeep"
    03423       EpicPackages(70)="DM-DE-Ironic"
    03424       EpicPackages(71)="DM-DE-Osiris2"
    03425       EpicPackages(72)="BR-Canyon"
    03426       EpicPackages(73)="CTF-Avaris"
    03427       EpicPackages(74)="DM-1on1-Crash"
    03428       EpicPackages(75)="DM-1on1-Mixer"
    03429       EpicPackages(76)="DM-Icetomb"
    03430       EpicPackages(77)="DM-Injector"
    03431       EpicPackages(78)="DM-IronDeity"
    03432       EpicPackages(79)="DM-Rustatorium"
    03433       EpicPackages(80)="DOM-Junkyard"
    03434       EpicPackages(81)="SkaarjPack"
    03435       EpicPackages(82)="SkaarjPack_rc"
    03436       EpicPackages(83)="BonusPack"
    03437       EpicPackages(84)="OGGPlayer"
    03438       MasterPage="ladder"
    03439       SubFrame="ladder_frame"
    03440       SubFrameMenu="ladder_frame1"
    03441       SubFrameContent="ladder_frame2"
    03442       IncludeTable="ladder_table"
    03443       IncludeSection="ladder_section"
    03444       IncludeRows="ladder_rows"
    03445       IncludeCaptionButton="ladder_caption"
    03446       IncludeMapSelect="ladder_mapselect"
    03447       IncludeProfileName="ladder_name"
    03448       IncludeGameType="ladder_gametype"
    03449       IncludeCheckBox="ladder_checkrow"
    03450       IncludeSwitch="ladder_switch"
    03451       ProfileViewURI="ladder_view"
    03452       ProfileEditURI="ladder_edit"
    03453       ProfileMenuURI="ladder_menu"
    03454       ProfileSwitchURI="ladder_switch"
    03455       ProfileManageURI="ladder_manage"
    03456       SubFrameURI="profile_management"
    03457       SubFrameMenuURI="management_menu"
    03458       SubMapsURI="ladder_maps"
    03459       SubSavedURI="ladder_save"
    03460       SubRulesURI="ladder_rules"
    03461       SubReviewURI="ladder_review"
    03462       SubGametypeURI="management_game_type"
    03463       SubMutatorsURI="ladder_mutators"
    03464       SubImportURI="profile_import"
    03465       SubExportURI="profile_export"
    03466       LinkEditProfile="Edit Profiles"
    03467       LinkViewProfile="View Profiles"
    03468       LinkSwitchProfile="Switch Profiles"
    03469       LinkManageProfile="Manage Profiles"
    03470       LinkImportProfile="Import Profile"
    03471       LinkExportProfile="Export Profile"
    03472       TableTitle(0)="Profile Management Portal"
    03473       TableTitle(1)="Profile GameType"
    03474       TableTitle(2)="Profile Mutators"
    03475       TableTitle(3)="Profile Maps"
    03476       TableTitle(4)="Profile Settings"
    03477       TableTitle(5)="Review Profile"
    03478       TableTitle(6)="Profile Saved"
    03479       PageCaption(0)="No Profile Loaded"
    03480       PageCaption(1)="Select the gametype that will be associated with this profile."
    03481       PageCaption(2)="Select the mutators that will be available in this profile."
    03482       PageCaption(3)="Select the maps that will be available in this profile."
    03483       PageCaption(4)="Select the settings that will be associated with this profile."
    03484       PageCaption(5)="Review all settings for accuracy before saving to file."
    03485       PageCaption(6)="Settings were saved successfully!"
    03486       ProfileButtonName(0)="Save Location"
    03487       ProfileButtonName(1)="GameType"
    03488       ProfileButtonName(2)="Mutators"
    03489       ProfileButtonName(3)="Maps"
    03490       ProfileButtonName(4)="Rules"
    03491       ProfileButtonName(5)="Review"
    03492       ProfileButtonName(6)="Saved"
    03493       ProfileButtonValue(0)="Proceed"
    03494       ProfileButtonValue(1)="Set GameType"
    03495       ProfileButtonValue(2)="Set Mutators"
    03496       ProfileButtonValue(3)="Set Maps"
    03497       ProfileButtonValue(4)="Set Rules"
    03498       ProfileButtonValue(5)="Save Profile"
    03499       ProfileButtonValue(6)="Profile Saved"
    03500       MapText="Maps"
    03501       ErrorText="Error"
    03502       MutatorText="Mutators"
    03503       RequiredText="Required"
    03504       AvailableText="Available"
    03505       UnlimitedText="Unlimited"
    03506       FollowingMaps="The following maps"
    03507       AreAssignedText="are assigned to this profile and cannot be removed."
    03508       AreAvailableText="may be added to this profile."
    03509       FollowingMutators="The following mutators"
    03510       CommandLineOptionsTitle="Command Line Options"
    03511       ButtonLoadProfile="Load Profile"
    03512       ButtonDeleteProfile="Delete Profile"
    03513       ButtonPreviewProfile="Load Profile"
    03514       ButtonApplyImportProfile="Import Profile"
    03515       ButtonApplyExportProfile="Export Profile"
    03516       ButtonApplyProfileChanges="Apply Profile Changes"
    03517       LabelCopyProfile="Copy Profile"
    03518       LabelDeleteProfile="Delete Profile"
    03519       LabelImportProfile="Import Profile"
    03520       LabelExportProfile="Export Profile"
    03521       LabelAddProfile="Add Profile"
    03522       LabelSelectActions="(Copy, Modify, Delete, Export)"
    03523       LabelTextboxActions="(Add, Copy, Import)"
    03524       LabelPlayInfo="Profile Game Parameters"
    03525       LabelGeneralProfile="General Profile Information"
    03526       LabelGameType="Profile Game Type"
    03527       LabelProfileName="Profile Name"
    03528       LabelAccessControl="Profile Access Control"
    03529       LabelChooseAction="Choose action to perform:"
    03530       LabelManagement="Profile Management"
    03531       LabelInputDescription="Actions which require input from this field are listed on the right."
    03532       LabelMaxMaps="Maximum maps allowed in this profile's maplist"
    03533       LabelNumberGames="Number of matches (0 = unlimited)"
    03534       LabelCheckAllMap="Select all maps"
    03535       LabelRequiredMaps="Check each map that will be required (non-removable) for this profile."
    03536       LabelUncheckAllMap="Deselect all maps"
    03537       LabelChangeMaplist="Changes to the maplist are saved immediately."
    03538       LabelCheckAllMutator="Select all mutators"
    03539       LabelRequiredMutators="Check each mutator that will be required (non-removable) for this profile."
    03540       LabelNumberMatchesLeft="Matches Remaining:"
    03541       LabelUncheckAllMutator="Deselect all mutators"
    03542       LabelDelayProfileChange="Check to delay applying profile until end of current match."
    03543       LabelApplyImportProfile="Click Apply Import to make this profile available in your server's list of profiles."
    03544       LabelApplyExportProfile="Click Apply Export to save this profile to a .txt file."
    03545       LabelModifyProfile="Modify Profile"
    03546       SuccessText="Success"
    03547       SuccessDeleteProfile="Profile successfully deleted!  It will no longer appear in your list of available profiles."
    03548       SuccessExportProfile="Profile exported successfully!  Exported profile has been saved to the server's System folder as "
    03549       SuccessImportProfile="Profile imported successfully! The remote profile will now appear in your list of available profiles."
    03550       SuccessImportProfileTitle="Import Successful!"
    03551       SuccessCopyProfile="Profile copied successfully! Copied profile will now be available in your list of available profiles."
    03552       SuccessSwitchProfile="Profile successfully applied! Changes take effect at the end of the current match."
    03553       ErrorLoadingPlayInfoText(0)="Error while loading playinfo.  LoadThisPlayInfo() received bad playinfo object!"
    03554       ErrorLoadingPlayInfoText(1)="Error while loading playinfo.  LoadThisPlayInfo() could not load incoming game class!"
    03555       ErrorLoadingPlayInfoText(2)="Error while loading playinfo.  LoadThisPlayInfo() could not load associated access control!"
    03556       ErrorLoadingPlayInfoText(3)="Error while loading playinfo.  LoadThisPlayInfo() had exception while loading mutators!"
    03557       ErrorLoadingPlayInfoText(4)="Error while loading playinfo.  LoadThisPlayInfo() had exception while loading server actors!"
    03558       ErrorGameClassText="No gametype was selected, or the files required by this gametype do not exist on this server."
    03559       ErrorGameClassTitle="Invalid GameType"
    03560       ErrorAccessControlText="Exception while loading access control.  Please double check the AccessControlClass= line of the [Engine.GameInfo] section of your server's .ini file."
    03561       ErrorAccessControlTitle="Invalid Access Control"
    03562       ErrorSameProfileName="Another profile already exists with that name. Please select a different name!"
    03563       ErrorRemoteMutator="Error loading mutator from remote profile. Could not find mutator package:"
    03564       ErrorRemoteServerActor="Error loading ServerActor from remote profile.  Could not find ServerActor package:"
    03565       ErrorSavingProfile="Exception while saving new profile! Please resubmit save request."
    03566       ErrorDeletingProfile="Error deleting profile!  Please check server log for details."
    03567       ErrorExportingProfile="Error exporting profile! Export class could not be spawned!"
    03568       ErrorNoProfilesExist="No profiles exist! Could not perform selected action!"
    03569       ErrorCopyFrom="Error copying profile.  No Profile Found!"
    03570       ErrorCopyNoName="You must specify a unique name for the new profile!"
    03571       ErrorExcludeMapNotFound="Error! Exclude map not found:"
    03572       ErrorIncludeMapNotFound="Error! Include map not found:"
    03573       ErrorReplacingWebConnection="Exception replacing WebServer.AcceptClass! (Very bad) Please send an email to Evolution containing your server's ini and log files."
    03574       ImportClassSpawnError="Exception occured spawning connection class.  Please try again!"
    03575       ImportProfileFailText="Error while importing profile.  Please ensure you have all the files necessary to load this remote profile."
    03576       ImportProfileFailTitle="Import Failed!"
    03577       ErrorBind="Failed to bind port! Please try again!"
    03578       ErrorBadURL="URL must start with 'http://' !"
    03579       ErrorServer="Unspecified error while importing profile!"
    03580       ErrorResolve="URL could not be resolved!"
    03581       ErrorProfile="Attempted to import a file that does not contain a profile!"
    03582       ErrorTimeout="Timed out while waiting for response from foreign host!"
    03583       ErrorNotFound="Profile does not exist on remote server!"
    03584       ErrorForbidden="Remote profile could not be imported: Forbidden"
    03585       ErrorBadRequest="Request could not be processed by remote server!"
    03586       ErrorUnauthorized="Remote profile could not be imported: Unauthorized"
    03587       DefaultPage="ladder_main"
    03588       Title="Ladder"
    03589  }

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