Line ending normalization to CRLF (Windows)

This commit is contained in:
Lucas Nicodemus 2013-08-22 21:17:32 -06:00
parent f82bff1b17
commit 9470e20423
16 changed files with 1859 additions and 1854 deletions

5
.gitattributes vendored Normal file
View file

@ -0,0 +1,5 @@
* text=auto
*.cs text eol=crlf
*.sln text eol=crlf
*.csproj text eol=crlf
*.vsmdi text eol=crlf

View file

@ -244,8 +244,8 @@ namespace TShockAPI
add(Permissions.savessi, SaveSSI, "savessi"); add(Permissions.savessi, SaveSSI, "savessi");
add(Permissions.savessi, OverrideSSI, "overridessi", "ossi"); add(Permissions.savessi, OverrideSSI, "overridessi", "ossi");
add(Permissions.xmas, ForceXmas, "forcexmas"); add(Permissions.xmas, ForceXmas, "forcexmas");
add(Permissions.settempgroup, TempGroup, "tempgroup"); add(Permissions.settempgroup, TempGroup, "tempgroup");
add(null, Aliases, "aliases"); add(null, Aliases, "aliases");
add(Rests.RestPermissions.restmanage, ManageRest, "rest"); add(Rests.RestPermissions.restmanage, ManageRest, "rest");
//add(null, TestCallbackCommand, "test"); //add(null, TestCallbackCommand, "test");
@ -1284,11 +1284,11 @@ namespace TShockAPI
private static void Broadcast(CommandArgs args) private static void Broadcast(CommandArgs args)
{ {
string message = string.Join(" ", args.Parameters); string message = string.Join(" ", args.Parameters);
TShock.Utils.Broadcast( TShock.Utils.Broadcast(
"(Server Broadcast) " + message, "(Server Broadcast) " + message,
Convert.ToByte(TShock.Config.BroadcastRGB[0]), Convert.ToByte(TShock.Config.BroadcastRGB[1]), Convert.ToByte(TShock.Config.BroadcastRGB[0]), Convert.ToByte(TShock.Config.BroadcastRGB[1]),
Convert.ToByte(TShock.Config.BroadcastRGB[2])); Convert.ToByte(TShock.Config.BroadcastRGB[2]));
} }
@ -1318,7 +1318,7 @@ namespace TShockAPI
} }
else else
{ {
string reason = ((args.Parameters.Count > 0) ? "Server shutting down: " + String.Join(" ", args.Parameters) : "Server shutting down!"); string reason = ((args.Parameters.Count > 0) ? "Server shutting down: " + String.Join(" ", args.Parameters) : "Server shutting down!");
TShock.Utils.RestartServer(true, reason); TShock.Utils.RestartServer(true, reason);
} }
} }
@ -1340,57 +1340,57 @@ namespace TShockAPI
args.Player.SendInfoMessage("Starting plugin update process:"); args.Player.SendInfoMessage("Starting plugin update process:");
args.Player.SendInfoMessage("This may take a while, do not turn off the server!"); args.Player.SendInfoMessage("This may take a while, do not turn off the server!");
new PluginUpdaterThread(args.Player); new PluginUpdaterThread(args.Player);
} }
private static void ManageRest(CommandArgs args)
{
string subCommand = "help";
if (args.Parameters.Count > 0)
subCommand = args.Parameters[0];
switch(subCommand.ToLower()) private static void ManageRest(CommandArgs args)
{ {
case "listusers": string subCommand = "help";
{ if (args.Parameters.Count > 0)
int pageNumber; subCommand = args.Parameters[0];
if (!PaginationTools.TryParsePageNumber(args.Parameters, 1, args.Player, out pageNumber))
return; switch(subCommand.ToLower())
{
Dictionary<string,int> restUsersTokens = new Dictionary<string,int>(); case "listusers":
foreach (Rests.SecureRest.TokenData tokenData in TShock.RestApi.Tokens.Values) {
{ int pageNumber;
if (restUsersTokens.ContainsKey(tokenData.Username)) if (!PaginationTools.TryParsePageNumber(args.Parameters, 1, args.Player, out pageNumber))
restUsersTokens[tokenData.Username]++; return;
else
restUsersTokens.Add(tokenData.Username, 1); Dictionary<string,int> restUsersTokens = new Dictionary<string,int>();
} foreach (Rests.SecureRest.TokenData tokenData in TShock.RestApi.Tokens.Values)
{
List<string> restUsers = new List<string>( if (restUsersTokens.ContainsKey(tokenData.Username))
restUsersTokens.Select(ut => string.Format("{0} ({1} tokens)", ut.Key, ut.Value))); restUsersTokens[tokenData.Username]++;
else
PaginationTools.SendPage( restUsersTokens.Add(tokenData.Username, 1);
args.Player, pageNumber, PaginationTools.BuildLinesFromTerms(restUsers), new PaginationTools.Settings { }
NothingToDisplayString = "There are currently no active REST users.",
HeaderFormat = "Active REST Users ({0}/{1}):", List<string> restUsers = new List<string>(
FooterFormat = "Type /rest listusers {0} for more." restUsersTokens.Select(ut => string.Format("{0} ({1} tokens)", ut.Key, ut.Value)));
}
); PaginationTools.SendPage(
args.Player, pageNumber, PaginationTools.BuildLinesFromTerms(restUsers), new PaginationTools.Settings {
break; NothingToDisplayString = "There are currently no active REST users.",
} HeaderFormat = "Active REST Users ({0}/{1}):",
case "destroytokens": FooterFormat = "Type /rest listusers {0} for more."
{ }
TShock.RestApi.Tokens.Clear(); );
args.Player.SendSuccessMessage("All REST tokens have been destroyed.");
break; break;
} }
default: case "destroytokens":
{ {
args.Player.SendInfoMessage("Available REST Sub-Commands:"); TShock.RestApi.Tokens.Clear();
args.Player.SendMessage("listusers - Lists all REST users and their current active tokens.", Color.White); args.Player.SendSuccessMessage("All REST tokens have been destroyed.");
args.Player.SendMessage("destroytokens - Destroys all current REST tokens.", Color.White); break;
break; }
} default:
{
args.Player.SendInfoMessage("Available REST Sub-Commands:");
args.Player.SendMessage("listusers - Lists all REST users and their current active tokens.", Color.White);
args.Player.SendMessage("destroytokens - Destroys all current REST tokens.", Color.White);
break;
}
} }
} }
@ -2044,8 +2044,8 @@ namespace TShockAPI
} }
} }
#endregion #endregion
return; return;
case "parent": case "parent":
#region Parent #region Parent
{ {
@ -2053,45 +2053,45 @@ namespace TShockAPI
{ {
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /group parent <group name> [new parent group name]"); args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /group parent <group name> [new parent group name]");
return; return;
} }
string groupName = args.Parameters[1]; string groupName = args.Parameters[1];
Group group = TShock.Groups.GetGroupByName(groupName); Group group = TShock.Groups.GetGroupByName(groupName);
if (group == null) if (group == null)
{ {
args.Player.SendErrorMessage("No such group \"{0}\".", groupName); args.Player.SendErrorMessage("No such group \"{0}\".", groupName);
return; return;
} }
if (args.Parameters.Count > 2) if (args.Parameters.Count > 2)
{ {
string newParentGroupName = string.Join(" ", args.Parameters.Skip(2)); string newParentGroupName = string.Join(" ", args.Parameters.Skip(2));
if (!string.IsNullOrWhiteSpace(newParentGroupName) && !TShock.Groups.GroupExists(newParentGroupName)) if (!string.IsNullOrWhiteSpace(newParentGroupName) && !TShock.Groups.GroupExists(newParentGroupName))
{ {
args.Player.SendErrorMessage("No such group \"{0}\".", newParentGroupName); args.Player.SendErrorMessage("No such group \"{0}\".", newParentGroupName);
return; return;
} }
try try
{ {
TShock.Groups.UpdateGroup(groupName, newParentGroupName, group.Permissions, group.ChatColor); TShock.Groups.UpdateGroup(groupName, newParentGroupName, group.Permissions, group.ChatColor);
if (!string.IsNullOrWhiteSpace(newParentGroupName)) if (!string.IsNullOrWhiteSpace(newParentGroupName))
args.Player.SendSuccessMessage("Parent of group \"{0}\" set to \"{1}\".", groupName, newParentGroupName); args.Player.SendSuccessMessage("Parent of group \"{0}\" set to \"{1}\".", groupName, newParentGroupName);
else else
args.Player.SendSuccessMessage("Removed parent of group \"{0}\".", groupName); args.Player.SendSuccessMessage("Removed parent of group \"{0}\".", groupName);
} }
catch (GroupManagerException ex) catch (GroupManagerException ex)
{ {
args.Player.SendErrorMessage(ex.Message); args.Player.SendErrorMessage(ex.Message);
} }
} }
else else
{ {
if (group.Parent != null) if (group.Parent != null)
args.Player.SendSuccessMessage("Parent of \"{0}\" is \"{1}\".", group.Name, group.Parent.Name); args.Player.SendSuccessMessage("Parent of \"{0}\" is \"{1}\".", group.Name, group.Parent.Name);
else else
args.Player.SendSuccessMessage("Group \"{0}\" has no parent.", group.Name); args.Player.SendSuccessMessage("Group \"{0}\" has no parent.", group.Name);
} }
} }
#endregion #endregion
@ -2202,7 +2202,7 @@ namespace TShockAPI
}); });
} }
#endregion #endregion
return; return;
case "help": case "help":
args.Player.SendInfoMessage("Syntax: /group <command> [arguments]"); args.Player.SendInfoMessage("Syntax: /group <command> [arguments]");
args.Player.SendInfoMessage("Commands: add, addperm, parent, del, delperm, list, listperm"); args.Player.SendInfoMessage("Commands: add, addperm, parent, del, delperm, list, listperm");
@ -2413,7 +2413,7 @@ namespace TShockAPI
private static void Reload(CommandArgs args) private static void Reload(CommandArgs args)
{ {
TShock.Utils.Reload(args.Player); TShock.Utils.Reload(args.Player);
args.Player.SendSuccessMessage( args.Player.SendSuccessMessage(
"Configuration, permissions, and regions reload complete. Some changes may require a server restart."); "Configuration, permissions, and regions reload complete. Some changes may require a server restart.");
@ -3457,8 +3457,8 @@ namespace TShockAPI
args.Player.SendSuccessMessage("Annoying " + ply.Name + " for " + annoy + " seconds."); args.Player.SendSuccessMessage("Annoying " + ply.Name + " for " + annoy + " seconds.");
(new Thread(ply.Whoopie)).Start(annoy); (new Thread(ply.Whoopie)).Start(annoy);
} }
} }
private static void Aliases(CommandArgs args) private static void Aliases(CommandArgs args)
{ {
if (args.Parameters.Count < 1) if (args.Parameters.Count < 1)
@ -3466,31 +3466,31 @@ namespace TShockAPI
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /aliases <command or alias>"); args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /aliases <command or alias>");
return; return;
} }
string givenCommandName = string.Join(" ", args.Parameters); string givenCommandName = string.Join(" ", args.Parameters);
if (string.IsNullOrWhiteSpace(givenCommandName)) { if (string.IsNullOrWhiteSpace(givenCommandName)) {
args.Player.SendErrorMessage("Please enter a proper command name or alias."); args.Player.SendErrorMessage("Please enter a proper command name or alias.");
return; return;
} }
string commandName; string commandName;
if (givenCommandName[0] == '/') if (givenCommandName[0] == '/')
commandName = givenCommandName.Substring(1); commandName = givenCommandName.Substring(1);
else else
commandName = givenCommandName; commandName = givenCommandName;
bool didMatch = false; bool didMatch = false;
foreach (Command matchingCommand in ChatCommands.Where(cmd => cmd.Names.IndexOf(commandName) != -1)) { foreach (Command matchingCommand in ChatCommands.Where(cmd => cmd.Names.IndexOf(commandName) != -1)) {
if (matchingCommand.Names.Count > 1) if (matchingCommand.Names.Count > 1)
args.Player.SendInfoMessage( args.Player.SendInfoMessage(
"Aliases of /{0}: /{1}", matchingCommand.Name, string.Join(", /", matchingCommand.Names.Skip(1))); "Aliases of /{0}: /{1}", matchingCommand.Name, string.Join(", /", matchingCommand.Names.Skip(1)));
else else
args.Player.SendInfoMessage("/{0} defines no aliases.", matchingCommand.Name); args.Player.SendInfoMessage("/{0} defines no aliases.", matchingCommand.Name);
didMatch = true; didMatch = true;
} }
if (!didMatch) if (!didMatch)
args.Player.SendErrorMessage("No command or command alias matching \"{0}\" found.", givenCommandName); args.Player.SendErrorMessage("No command or command alias matching \"{0}\" found.", givenCommandName);
} }

View file

@ -251,9 +251,9 @@ namespace TShockAPI
[Description("The path of the directory where logs should be written into.")] public string LogPath = "tshock"; [Description("The path of the directory where logs should be written into.")] public string LogPath = "tshock";
[Description("Prevents players from placing tiles with an invalid style.")] public bool PreventInvalidPlaceStyle = true; [Description("Prevents players from placing tiles with an invalid style.")] public bool PreventInvalidPlaceStyle = true;
[Description("#.#.#. = Red/Blue/Green - RGB Colors for broadcasts. Max value: 255.")] public float[] BroadcastRGB = [Description("#.#.#. = Red/Blue/Green - RGB Colors for broadcasts. Max value: 255.")] public float[] BroadcastRGB =
{127,255,212}; {127,255,212};
// TODO: Get rid of this when the old REST permission model is removed. // TODO: Get rid of this when the old REST permission model is removed.

View file

@ -18,8 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using MySql.Data.MySqlClient; using MySql.Data.MySqlClient;
@ -166,7 +166,7 @@ namespace TShockAPI.DB
/// <param name="permissions">permissions</param> /// <param name="permissions">permissions</param>
/// <param name="chatcolor">chatcolor</param> /// <param name="chatcolor">chatcolor</param>
public void UpdateGroup(string name, string parentname, string permissions, string chatcolor) public void UpdateGroup(string name, string parentname, string permissions, string chatcolor)
{ {
Group group = GetGroupByName(name); Group group = GetGroupByName(name);
if (group == null) if (group == null)
throw new GroupNotExistException(name); throw new GroupNotExistException(name);
@ -176,22 +176,22 @@ namespace TShockAPI.DB
{ {
parent = GetGroupByName(parentname); parent = GetGroupByName(parentname);
if (parent == null || parent == group) if (parent == null || parent == group)
throw new GroupManagerException("Invalid parent \"{0}\" for group \"{1}\".".SFormat(parentname, name)); throw new GroupManagerException("Invalid parent \"{0}\" for group \"{1}\".".SFormat(parentname, name));
// Check if the new parent would cause loops. // Check if the new parent would cause loops.
List<Group> groupChain = new List<Group> { group, parent }; List<Group> groupChain = new List<Group> { group, parent };
Group checkingGroup = parent.Parent; Group checkingGroup = parent.Parent;
while (checkingGroup != null) while (checkingGroup != null)
{ {
if (groupChain.Contains(checkingGroup)) if (groupChain.Contains(checkingGroup))
throw new GroupManagerException( throw new GroupManagerException(
string.Format("Invalid parent \"{0}\" for group \"{1}\" would cause loops in the parent chain.", parentname, name)); string.Format("Invalid parent \"{0}\" for group \"{1}\" would cause loops in the parent chain.", parentname, name));
groupChain.Add(checkingGroup); groupChain.Add(checkingGroup);
checkingGroup = checkingGroup.Parent; checkingGroup = checkingGroup.Parent;
} }
} }
// Ensure any group validation is also persisted to the DB. // Ensure any group validation is also persisted to the DB.
var newGroup = new Group(name, parent, chatcolor, permissions); var newGroup = new Group(name, parent, chatcolor, permissions);
string query = "UPDATE GroupList SET Parent=@0, Commands=@1, ChatColor=@2 WHERE GroupName=@3"; string query = "UPDATE GroupList SET Parent=@0, Commands=@1, ChatColor=@2 WHERE GroupName=@3";
@ -265,107 +265,107 @@ namespace TShockAPI.DB
} }
public void LoadPermisions() public void LoadPermisions()
{ {
try try
{ {
List<Group> newGroups = new List<Group>(groups.Count); List<Group> newGroups = new List<Group>(groups.Count);
Dictionary<string,string> newGroupParents = new Dictionary<string, string>(groups.Count); Dictionary<string,string> newGroupParents = new Dictionary<string, string>(groups.Count);
using (var reader = database.QueryReader("SELECT * FROM GroupList")) using (var reader = database.QueryReader("SELECT * FROM GroupList"))
{ {
while (reader.Read()) while (reader.Read())
{ {
string groupName = reader.Get<string>("GroupName"); string groupName = reader.Get<string>("GroupName");
if (groupName == "superadmin") if (groupName == "superadmin")
{ {
Log.ConsoleInfo("WARNING: Group \"superadmin\" is defined in the database even though it's a reserved group name."); Log.ConsoleInfo("WARNING: Group \"superadmin\" is defined in the database even though it's a reserved group name.");
continue; continue;
} }
newGroups.Add(new Group(groupName, null, reader.Get<string>("ChatColor"), reader.Get<string>("Commands")) { newGroups.Add(new Group(groupName, null, reader.Get<string>("ChatColor"), reader.Get<string>("Commands")) {
Prefix = reader.Get<string>("Prefix"), Prefix = reader.Get<string>("Prefix"),
Suffix = reader.Get<string>("Suffix"), Suffix = reader.Get<string>("Suffix"),
}); });
try try
{ {
newGroupParents.Add(groupName, reader.Get<string>("Parent")); newGroupParents.Add(groupName, reader.Get<string>("Parent"));
} }
catch (ArgumentException) catch (ArgumentException)
{ {
// Just in case somebody messed with the unique primary key. // Just in case somebody messed with the unique primary key.
Log.ConsoleError("ERROR: Group name \"{0}\" occurs more than once. Keeping current group settings."); Log.ConsoleError("ERROR: Group name \"{0}\" occurs more than once. Keeping current group settings.");
return; return;
} }
} }
} }
try try
{ {
// Get rid of deleted groups. // Get rid of deleted groups.
for (int i = 0; i < groups.Count; i++) for (int i = 0; i < groups.Count; i++)
if (newGroups.All(g => g.Name != groups[i].Name)) if (newGroups.All(g => g.Name != groups[i].Name))
groups.RemoveAt(i--); groups.RemoveAt(i--);
// Apply changed group settings while keeping the current instances and add new groups. // Apply changed group settings while keeping the current instances and add new groups.
foreach (Group newGroup in newGroups) foreach (Group newGroup in newGroups)
{ {
Group currentGroup = groups.FirstOrDefault(g => g.Name == newGroup.Name); Group currentGroup = groups.FirstOrDefault(g => g.Name == newGroup.Name);
if (currentGroup != null) if (currentGroup != null)
newGroup.AssignTo(currentGroup); newGroup.AssignTo(currentGroup);
else else
groups.Add(newGroup); groups.Add(newGroup);
} }
// Resolve parent groups. // Resolve parent groups.
Debug.Assert(newGroups.Count == newGroupParents.Count); Debug.Assert(newGroups.Count == newGroupParents.Count);
for (int i = 0; i < groups.Count; i++) for (int i = 0; i < groups.Count; i++)
{ {
Group group = groups[i]; Group group = groups[i];
string parentGroupName; string parentGroupName;
if (!newGroupParents.TryGetValue(group.Name, out parentGroupName) || string.IsNullOrEmpty(parentGroupName)) if (!newGroupParents.TryGetValue(group.Name, out parentGroupName) || string.IsNullOrEmpty(parentGroupName))
continue; continue;
group.Parent = groups.FirstOrDefault(g => g.Name == parentGroupName); group.Parent = groups.FirstOrDefault(g => g.Name == parentGroupName);
if (group.Parent == null) if (group.Parent == null)
{ {
Log.ConsoleError( Log.ConsoleError(
"ERROR: Group \"{0}\" is referencing non existent parent group \"{1}\", parent reference was removed.", "ERROR: Group \"{0}\" is referencing non existent parent group \"{1}\", parent reference was removed.",
group.Name, parentGroupName); group.Name, parentGroupName);
} }
else else
{ {
if (group.Parent == group) if (group.Parent == group)
Log.ConsoleInfo( Log.ConsoleInfo(
"WARNING: Group \"{0}\" is referencing itself as parent group, parent reference was removed.", group.Name); "WARNING: Group \"{0}\" is referencing itself as parent group, parent reference was removed.", group.Name);
List<Group> groupChain = new List<Group> { group }; List<Group> groupChain = new List<Group> { group };
Group checkingGroup = group; Group checkingGroup = group;
while (checkingGroup.Parent != null) while (checkingGroup.Parent != null)
{ {
if (groupChain.Contains(checkingGroup.Parent)) if (groupChain.Contains(checkingGroup.Parent))
{ {
Log.ConsoleError( Log.ConsoleError(
"ERROR: Group \"{0}\" is referencing parent group \"{1}\" which is already part of the parent chain. Parent reference removed.", "ERROR: Group \"{0}\" is referencing parent group \"{1}\" which is already part of the parent chain. Parent reference removed.",
checkingGroup.Name, checkingGroup.Parent.Name); checkingGroup.Name, checkingGroup.Parent.Name);
checkingGroup.Parent = null; checkingGroup.Parent = null;
break; break;
} }
groupChain.Add(checkingGroup); groupChain.Add(checkingGroup);
checkingGroup = checkingGroup.Parent; checkingGroup = checkingGroup.Parent;
} }
} }
} }
} }
finally finally
{ {
if (!groups.Any(g => g is SuperAdminGroup)) if (!groups.Any(g => g is SuperAdminGroup))
groups.Add(new SuperAdminGroup()); groups.Add(new SuperAdminGroup());
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.ConsoleError("Error on reloading groups: " + ex); Log.ConsoleError("Error on reloading groups: " + ex);
} }
} }
} }

View file

@ -394,10 +394,10 @@ namespace TShockAPI.DB
mergedIDs = reader.Get<string>("UserIds"); mergedIDs = reader.Get<string>("UserIds");
} }
string userIdToAdd = Convert.ToString(TShock.Users.GetUserID(userName)); string userIdToAdd = Convert.ToString(TShock.Users.GetUserID(userName));
string[] ids = mergedIDs.Split(','); string[] ids = mergedIDs.Split(',');
// Is the user already allowed to the region? // Is the user already allowed to the region?
if (ids.Contains(userIdToAdd)) if (ids.Contains(userIdToAdd))
return true; return true;
if (string.IsNullOrEmpty(mergedIDs)) if (string.IsNullOrEmpty(mergedIDs))
@ -484,9 +484,9 @@ namespace TShockAPI.DB
mergedGroups = reader.Get<string>("Groups"); mergedGroups = reader.Get<string>("Groups");
} }
string[] groups = mergedGroups.Split(','); string[] groups = mergedGroups.Split(',');
// Is the group already allowed to the region? // Is the group already allowed to the region?
if (groups.Contains(groupName)) if (groups.Contains(groupName))
return true; return true;
if (mergedGroups != "") if (mergedGroups != "")

View file

@ -270,26 +270,26 @@ namespace TShockAPI
return; return;
} }
permissions.Remove(permission); permissions.Remove(permission);
} }
/// <summary> /// <summary>
/// Assigns all fields of this instance to another. /// Assigns all fields of this instance to another.
/// </summary> /// </summary>
/// <param name="otherGroup">The other instance.</param> /// <param name="otherGroup">The other instance.</param>
public void AssignTo(Group otherGroup) public void AssignTo(Group otherGroup)
{ {
otherGroup.Name = Name; otherGroup.Name = Name;
otherGroup.Parent = Parent; otherGroup.Parent = Parent;
otherGroup.Prefix = Prefix; otherGroup.Prefix = Prefix;
otherGroup.Suffix = Suffix; otherGroup.Suffix = Suffix;
otherGroup.R = R; otherGroup.R = R;
otherGroup.G = G; otherGroup.G = G;
otherGroup.B = B; otherGroup.B = B;
otherGroup.Permissions = Permissions; otherGroup.Permissions = Permissions;
} }
public override string ToString() { public override string ToString() {
return this.Name; return this.Name;
} }
} }

View file

@ -70,12 +70,12 @@ namespace TShockAPI
public static void Data(String message) public static void Data(String message)
{ {
Write(message, LogLevel.Data); Write(message, LogLevel.Data);
} }
/// <summary> /// <summary>
/// Writes data to the log file. /// Writes data to the log file.
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
public static void Data(String format, params String[] args) public static void Data(String format, params String[] args)
{ {
@ -89,12 +89,12 @@ namespace TShockAPI
public static void Error(String message) public static void Error(String message)
{ {
Write(message, LogLevel.Error); Write(message, LogLevel.Error);
} }
/// <summary> /// <summary>
/// Writes an error to the log file. /// Writes an error to the log file.
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
public static void Error(String format, params String[] args) public static void Error(String format, params String[] args)
{ {
@ -111,12 +111,12 @@ namespace TShockAPI
Console.WriteLine(message); Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Write(message, LogLevel.Error); Write(message, LogLevel.Error);
} }
/// <summary> /// <summary>
/// Writes an error to the log file. /// Writes an error to the log file.
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
public static void ConsoleError(String format, params String[] args) public static void ConsoleError(String format, params String[] args)
{ {
@ -130,12 +130,12 @@ namespace TShockAPI
public static void Warn(String message) public static void Warn(String message)
{ {
Write(message, LogLevel.Warning); Write(message, LogLevel.Warning);
} }
/// <summary> /// <summary>
/// Writes a warning to the log file. /// Writes a warning to the log file.
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
public static void Warn(String format, params String[] args) public static void Warn(String format, params String[] args)
{ {
@ -149,12 +149,12 @@ namespace TShockAPI
public static void Info(String message) public static void Info(String message)
{ {
Write(message, LogLevel.Info); Write(message, LogLevel.Info);
} }
/// <summary> /// <summary>
/// Writes an informative string to the log file. /// Writes an informative string to the log file.
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
public static void Info(String format, params String[] args) public static void Info(String format, params String[] args)
{ {
@ -171,12 +171,12 @@ namespace TShockAPI
Console.WriteLine(message); Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Write(message, LogLevel.Info); Write(message, LogLevel.Info);
} }
/// <summary> /// <summary>
/// Writes an informative string to the log file. Also outputs to the console. /// Writes an informative string to the log file. Also outputs to the console.
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
public static void ConsoleInfo(String format, params String[] args) public static void ConsoleInfo(String format, params String[] args)
{ {
@ -190,12 +190,12 @@ namespace TShockAPI
public static void Debug(String message) public static void Debug(String message)
{ {
Write(message, LogLevel.Debug); Write(message, LogLevel.Debug);
} }
/// <summary> /// <summary>
/// Writes a debug string to the log file. /// Writes a debug string to the log file.
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
public static void Debug(String format, params String[] args) public static void Debug(String format, params String[] args)
{ {

View file

@ -174,8 +174,8 @@ namespace TShockAPI
[Description("User can elevate other users' groups temporarily.")] public static readonly string settempgroup; [Description("User can elevate other users' groups temporarily.")] public static readonly string settempgroup;
[Description("User can download updates to plugins that are currently running.")] public static readonly string updateplugins; [Description("User can download updates to plugins that are currently running.")] public static readonly string updateplugins;
static Permissions() static Permissions()
{ {
foreach (var field in typeof (Permissions).GetFields()) foreach (var field in typeof (Permissions).GetFields())

View file

@ -36,13 +36,13 @@ namespace Rests
/// <param name="parameters">Parameters in the url</param> /// <param name="parameters">Parameters in the url</param>
/// <param name="verbs">{x} in urltemplate</param> /// <param name="verbs">{x} in urltemplate</param>
/// <returns>Response object or null to not handle request</returns> /// <returns>Response object or null to not handle request</returns>
public delegate object RestCommandD(RestVerbs verbs, IParameterCollection parameters); public delegate object RestCommandD(RestVerbs verbs, IParameterCollection parameters);
/// <summary> /// <summary>
/// Secure Rest command delegate including token data. /// Secure Rest command delegate including token data.
/// </summary> /// </summary>
/// <param name="parameters">Parameters in the url</param> /// <param name="parameters">Parameters in the url</param>
/// <param name="verbs">{x} in urltemplate</param> /// <param name="verbs">{x} in urltemplate</param>
/// <param name="tokenData">The data of stored for the provided token.</param> /// <param name="tokenData">The data of stored for the provided token.</param>
/// <returns>Response object or null to not handle request</returns> /// <returns>Response object or null to not handle request</returns>
public delegate object SecureRestCommandD(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData); public delegate object SecureRestCommandD(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData);
@ -189,32 +189,32 @@ namespace Rests
protected virtual object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms) protected virtual object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
{ {
object result = cmd.Execute(verbs, parms); object result = cmd.Execute(verbs, parms);
if (cmd.DoLog) if (cmd.DoLog)
Log.ConsoleInfo("Anonymous requested REST endpoint: " + BuildRequestUri(cmd, verbs, parms, false)); Log.ConsoleInfo("Anonymous requested REST endpoint: " + BuildRequestUri(cmd, verbs, parms, false));
return result; return result;
} }
protected virtual string BuildRequestUri( protected virtual string BuildRequestUri(
RestCommand cmd, RestVerbs verbs, IParameterCollection parms, bool includeToken = true RestCommand cmd, RestVerbs verbs, IParameterCollection parms, bool includeToken = true
) { ) {
StringBuilder requestBuilder = new StringBuilder(cmd.UriTemplate); StringBuilder requestBuilder = new StringBuilder(cmd.UriTemplate);
char separator = '?'; char separator = '?';
foreach (IParameter paramImpl in parms) foreach (IParameter paramImpl in parms)
{ {
Parameter param = (paramImpl as Parameter); Parameter param = (paramImpl as Parameter);
if (param == null || (!includeToken && param.Name.Equals("token", StringComparison.InvariantCultureIgnoreCase))) if (param == null || (!includeToken && param.Name.Equals("token", StringComparison.InvariantCultureIgnoreCase)))
continue; continue;
requestBuilder.Append(separator); requestBuilder.Append(separator);
requestBuilder.Append(param.Name); requestBuilder.Append(param.Name);
requestBuilder.Append('='); requestBuilder.Append('=');
requestBuilder.Append(param.Value); requestBuilder.Append(param.Value);
separator = '&'; separator = '&';
} }
return requestBuilder.ToString(); return requestBuilder.ToString();
} }
#region Dispose #region Dispose

View file

@ -16,9 +16,9 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using HttpServer; using HttpServer;
namespace Rests namespace Rests
{ {
public class RestCommand public class RestCommand
@ -27,10 +27,10 @@ namespace Rests
public string UriTemplate { get; protected set; } public string UriTemplate { get; protected set; }
public string UriVerbMatch { get; protected set; } public string UriVerbMatch { get; protected set; }
public string[] UriVerbs { get; protected set; } public string[] UriVerbs { get; protected set; }
public virtual bool RequiresToken { get { return false; } } public virtual bool RequiresToken { get { return false; } }
public bool DoLog { get; set; } public bool DoLog { get; set; }
private RestCommandD callback; private RestCommandD callback;
/// <summary> /// <summary>
/// ///
@ -45,7 +45,7 @@ namespace Rests
UriVerbMatch = string.Format("^{0}$", string.Join("([^/]*)", Regex.Split(uritemplate, "\\{[^\\{\\}]*\\}"))); UriVerbMatch = string.Format("^{0}$", string.Join("([^/]*)", Regex.Split(uritemplate, "\\{[^\\{\\}]*\\}")));
var matches = Regex.Matches(uritemplate, "\\{([^\\{\\}]*)\\}"); var matches = Regex.Matches(uritemplate, "\\{([^\\{\\}]*)\\}");
UriVerbs = (from Match match in matches select match.Groups[1].Value).ToArray(); UriVerbs = (from Match match in matches select match.Groups[1].Value).ToArray();
this.callback = callback; this.callback = callback;
DoLog = true; DoLog = true;
} }
@ -62,44 +62,44 @@ namespace Rests
public bool HasVerbs public bool HasVerbs
{ {
get { return UriVerbs.Length > 0; } get { return UriVerbs.Length > 0; }
}
public virtual object Execute(RestVerbs verbs, IParameterCollection parameters)
{
return callback(verbs, parameters);
} }
}
public virtual object Execute(RestVerbs verbs, IParameterCollection parameters)
public class SecureRestCommand: RestCommand {
{ return callback(verbs, parameters);
public override bool RequiresToken { get { return true; } } }
public string[] Permissions { get; set; } }
private SecureRestCommandD callback; public class SecureRestCommand: RestCommand
{
public SecureRestCommand(string name, string uritemplate, SecureRestCommandD callback, params string[] permissions) public override bool RequiresToken { get { return true; } }
public string[] Permissions { get; set; }
private SecureRestCommandD callback;
public SecureRestCommand(string name, string uritemplate, SecureRestCommandD callback, params string[] permissions)
: base(name, uritemplate, null) : base(name, uritemplate, null)
{ {
this.callback = callback; this.callback = callback;
Permissions = permissions; Permissions = permissions;
} }
public SecureRestCommand(string uritemplate, SecureRestCommandD callback, params string[] permissions) public SecureRestCommand(string uritemplate, SecureRestCommandD callback, params string[] permissions)
: this(string.Empty, uritemplate, callback, permissions) : this(string.Empty, uritemplate, callback, permissions)
{ {
} }
public override object Execute(RestVerbs verbs, IParameterCollection parameters) public override object Execute(RestVerbs verbs, IParameterCollection parameters)
{ {
return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." }; return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." };
} }
public object Execute(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData) public object Execute(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
{ {
if (tokenData.Equals(SecureRest.TokenData.None)) if (tokenData.Equals(SecureRest.TokenData.None))
return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." }; return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." };
return callback(verbs, parameters, tokenData); return callback(verbs, parameters, tokenData);
} }
} }
} }

View file

@ -17,8 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using HttpServer; using HttpServer;
using Rests; using Rests;
@ -38,27 +38,27 @@ namespace TShockAPI
public void RegisterRestfulCommands() public void RegisterRestfulCommands()
{ {
// Server Commands // Server Commands
if (TShock.Config.EnableTokenEndpointAuthentication) if (TShock.Config.EnableTokenEndpointAuthentication)
{ {
Rest.Register(new SecureRestCommand("/v2/server/status", ServerStatusV2)); Rest.Register(new SecureRestCommand("/v2/server/status", ServerStatusV2));
Rest.Register(new SecureRestCommand("/status", ServerStatus)); Rest.Register(new SecureRestCommand("/status", ServerStatus));
Rest.Register(new SecureRestCommand("/v3/server/motd", ServerMotd)); Rest.Register(new SecureRestCommand("/v3/server/motd", ServerMotd));
Rest.Register(new SecureRestCommand("/v3/server/rules", ServerRules)); Rest.Register(new SecureRestCommand("/v3/server/rules", ServerRules));
} }
else else
{ {
Rest.Register(new RestCommand("/v2/server/status", (a, b) => this.ServerStatusV2(a, b, SecureRest.TokenData.None))); Rest.Register(new RestCommand("/v2/server/status", (a, b) => this.ServerStatusV2(a, b, SecureRest.TokenData.None)));
Rest.Register(new RestCommand("/status", (a, b) => this.ServerStatusV2(a, b, SecureRest.TokenData.None))); Rest.Register(new RestCommand("/status", (a, b) => this.ServerStatusV2(a, b, SecureRest.TokenData.None)));
Rest.Register(new RestCommand("/v3/server/motd", (a, b) => this.ServerMotd(a, b, SecureRest.TokenData.None))); Rest.Register(new RestCommand("/v3/server/motd", (a, b) => this.ServerMotd(a, b, SecureRest.TokenData.None)));
Rest.Register(new RestCommand("/v3/server/rules", (a, b) => this.ServerRules(a, b, SecureRest.TokenData.None))); Rest.Register(new RestCommand("/v3/server/rules", (a, b) => this.ServerRules(a, b, SecureRest.TokenData.None)));
} }
Rest.Register(new SecureRestCommand("/v2/server/broadcast", ServerBroadcast)); Rest.Register(new SecureRestCommand("/v2/server/broadcast", ServerBroadcast));
Rest.Register(new SecureRestCommand("/v3/server/reload", ServerReload, RestPermissions.restcfg)); Rest.Register(new SecureRestCommand("/v3/server/reload", ServerReload, RestPermissions.restcfg));
Rest.Register(new SecureRestCommand("/v2/server/off", ServerOff, RestPermissions.restmaintenance)); Rest.Register(new SecureRestCommand("/v2/server/off", ServerOff, RestPermissions.restmaintenance));
Rest.Register(new SecureRestCommand("/v3/server/restart", ServerRestart, RestPermissions.restmaintenance)); Rest.Register(new SecureRestCommand("/v3/server/restart", ServerRestart, RestPermissions.restmaintenance));
Rest.Register(new SecureRestCommand("/v2/server/rawcmd", ServerCommand, RestPermissions.restrawcommand)); Rest.Register(new SecureRestCommand("/v2/server/rawcmd", ServerCommand, RestPermissions.restrawcommand));
Rest.Register(new SecureRestCommand("/v3/server/rawcmd", ServerCommandV3, RestPermissions.restrawcommand)); Rest.Register(new SecureRestCommand("/v3/server/rawcmd", ServerCommandV3, RestPermissions.restrawcommand));
Rest.Register(new SecureRestCommand("/tokentest", ServerTokenTest)); Rest.Register(new SecureRestCommand("/tokentest", ServerTokenTest));
@ -107,35 +107,35 @@ namespace TShockAPI
private object ServerCommand(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData) private object ServerCommand(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
{ {
if (string.IsNullOrWhiteSpace(parameters["cmd"])) if (string.IsNullOrWhiteSpace(parameters["cmd"]))
return RestMissingParam("cmd"); return RestMissingParam("cmd");
Group restPlayerGroup; Group restPlayerGroup;
// TODO: Get rid of this when the old REST permission model is removed. // TODO: Get rid of this when the old REST permission model is removed.
if (TShock.Config.RestUseNewPermissionModel) if (TShock.Config.RestUseNewPermissionModel)
restPlayerGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName); restPlayerGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
else else
restPlayerGroup = new SuperAdminGroup(); restPlayerGroup = new SuperAdminGroup();
TSRestPlayer tr = new TSRestPlayer(tokenData.Username, restPlayerGroup); TSRestPlayer tr = new TSRestPlayer(tokenData.Username, restPlayerGroup);
Commands.HandleCommand(tr, parameters["cmd"]); Commands.HandleCommand(tr, parameters["cmd"]);
return RestResponse(string.Join("\n", tr.GetCommandOutput())); return RestResponse(string.Join("\n", tr.GetCommandOutput()));
} }
private object ServerCommandV3(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData) private object ServerCommandV3(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
{ {
if (string.IsNullOrWhiteSpace(parameters["cmd"])) if (string.IsNullOrWhiteSpace(parameters["cmd"]))
return RestMissingParam("cmd"); return RestMissingParam("cmd");
Group restPlayerGroup; Group restPlayerGroup;
// TODO: Get rid of this when the old REST permission model is removed. // TODO: Get rid of this when the old REST permission model is removed.
if (TShock.Config.RestUseNewPermissionModel) if (TShock.Config.RestUseNewPermissionModel)
restPlayerGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName); restPlayerGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
else else
restPlayerGroup = new SuperAdminGroup(); restPlayerGroup = new SuperAdminGroup();
TSRestPlayer tr = new TSRestPlayer(tokenData.Username, restPlayerGroup); TSRestPlayer tr = new TSRestPlayer(tokenData.Username, restPlayerGroup);
Commands.HandleCommand(tr, parameters["cmd"]); Commands.HandleCommand(tr, parameters["cmd"]);
return new RestObject() return new RestObject()
{ {
{"response", tr.GetCommandOutput()} {"response", tr.GetCommandOutput()}
}; };
@ -151,8 +151,8 @@ namespace TShockAPI
TShock.Utils.StopServer(!GetBool(parameters["nosave"], false), reason); TShock.Utils.StopServer(!GetBool(parameters["nosave"], false), reason);
return RestResponse("The server is shutting down"); return RestResponse("The server is shutting down");
} }
private object ServerRestart(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData) private object ServerRestart(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
{ {
if (!GetBool(parameters["confirm"], false)) if (!GetBool(parameters["confirm"], false))
@ -163,10 +163,10 @@ namespace TShockAPI
TShock.Utils.RestartServer(!GetBool(parameters["nosave"], false), reason); TShock.Utils.RestartServer(!GetBool(parameters["nosave"], false), reason);
return RestResponse("The server is shutting down and will attempt to restart"); return RestResponse("The server is shutting down and will attempt to restart");
} }
private object ServerReload(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData) private object ServerReload(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
{ {
TShock.Utils.Reload(new TSRestPlayer(tokenData.Username, TShock.Groups.GetGroupByName(tokenData.UserGroupName))); TShock.Utils.Reload(new TSRestPlayer(tokenData.Username, TShock.Groups.GetGroupByName(tokenData.UserGroupName)));
return RestResponse("Configuration, permissions, and regions reload complete. Some changes may require a server restart."); return RestResponse("Configuration, permissions, and regions reload complete. Some changes may require a server restart.");
@ -179,29 +179,29 @@ namespace TShockAPI
return RestMissingParam("msg"); return RestMissingParam("msg");
TShock.Utils.Broadcast(msg); TShock.Utils.Broadcast(msg);
return RestResponse("The message was broadcasted successfully"); return RestResponse("The message was broadcasted successfully");
} }
private object ServerMotd(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData) private object ServerMotd(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
{ {
string motdFilePath = Path.Combine(TShock.SavePath, "motd.txt"); string motdFilePath = Path.Combine(TShock.SavePath, "motd.txt");
if (!File.Exists(motdFilePath)) if (!File.Exists(motdFilePath))
return this.RestError("The motd.txt was not found.", "500"); return this.RestError("The motd.txt was not found.", "500");
return new RestObject() return new RestObject()
{ {
{"motd", File.ReadAllLines(motdFilePath)} {"motd", File.ReadAllLines(motdFilePath)}
}; };
} }
private object ServerRules(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
{
string rulesFilePath = Path.Combine(TShock.SavePath, "rules.txt");
if (!File.Exists(rulesFilePath))
return this.RestError("The rules.txt was not found.", "500");
return new RestObject() private object ServerRules(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
{ {
{"rules", File.ReadAllLines(rulesFilePath)} string rulesFilePath = Path.Combine(TShock.SavePath, "rules.txt");
if (!File.Exists(rulesFilePath))
return this.RestError("The rules.txt was not found.", "500");
return new RestObject()
{
{"rules", File.ReadAllLines(rulesFilePath)}
}; };
} }
@ -225,8 +225,8 @@ namespace TShockAPI
{"port", TShock.Config.ServerPort}, {"port", TShock.Config.ServerPort},
{"playercount", Main.player.Where(p => null != p && p.active).Count()}, {"playercount", Main.player.Where(p => null != p && p.active).Count()},
{"maxplayers", TShock.Config.MaxSlots}, {"maxplayers", TShock.Config.MaxSlots},
{"world", Main.worldName}, {"world", Main.worldName},
{"uptime", (DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime).ToString(@"d'.'hh':'mm':'ss")}, {"uptime", (DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime).ToString(@"d'.'hh':'mm':'ss")},
{"serverpassword", !string.IsNullOrEmpty(TShock.Config.ServerPassword)} {"serverpassword", !string.IsNullOrEmpty(TShock.Config.ServerPassword)}
}; };
@ -256,7 +256,7 @@ namespace TShockAPI
rules.Add("HardcoreOnly", TShock.Config.HardcoreOnly); rules.Add("HardcoreOnly", TShock.Config.HardcoreOnly);
rules.Add("PvPMode", TShock.Config.PvPMode); rules.Add("PvPMode", TShock.Config.PvPMode);
rules.Add("SpawnProtection", TShock.Config.SpawnProtection); rules.Add("SpawnProtection", TShock.Config.SpawnProtection);
rules.Add("SpawnProtectionRadius", TShock.Config.SpawnProtectionRadius); rules.Add("SpawnProtectionRadius", TShock.Config.SpawnProtectionRadius);
rules.Add("ServerSideInventory", TShock.Config.ServerSideInventory); rules.Add("ServerSideInventory", TShock.Config.ServerSideInventory);
ret.Add("rules", rules); ret.Add("rules", rules);
@ -265,10 +265,10 @@ namespace TShockAPI
} }
private object ServerTokenTest(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData) private object ServerTokenTest(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
{ {
return new RestObject() return new RestObject()
{ {
{"response", "Token is valid and was passed through correctly."}, {"response", "Token is valid and was passed through correctly."},
{"associateduser", tokenData.Username} {"associateduser", tokenData.Username}
}; };
} }

View file

@ -14,80 +14,80 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
namespace Rests namespace Rests
{ {
public static class RestPermissions public static class RestPermissions
{ {
[Description("User can create REST tokens.")] [Description("User can create REST tokens.")]
public static readonly string restapi; public static readonly string restapi;
[Description("User or REST user can destroy all REST tokens.")] [Description("User or REST user can destroy all REST tokens.")]
public static readonly string restmanage; public static readonly string restmanage;
[Description("REST user can turn off / restart the server.")] [Description("REST user can turn off / restart the server.")]
public static readonly string restmaintenance; public static readonly string restmaintenance;
[Description("REST user can reload configurations, save the world and set auto save settings.")] [Description("REST user can reload configurations, save the world and set auto save settings.")]
public static readonly string restcfg; public static readonly string restcfg;
[Description("REST user can list and get detailed information about users.")] [Description("REST user can list and get detailed information about users.")]
public static readonly string restviewusers; public static readonly string restviewusers;
[Description("REST user can alter users.")] [Description("REST user can alter users.")]
public static readonly string restmanageusers; public static readonly string restmanageusers;
[Description("REST user can list and get detailed information about bans.")] [Description("REST user can list and get detailed information about bans.")]
public static readonly string restviewbans; public static readonly string restviewbans;
[Description("REST user can alter bans.")] [Description("REST user can alter bans.")]
public static readonly string restmanagebans; public static readonly string restmanagebans;
[Description("REST user can list and get detailed information about groups.")] [Description("REST user can list and get detailed information about groups.")]
public static readonly string restviewgroups; public static readonly string restviewgroups;
[Description("REST user can alter groups.")] [Description("REST user can alter groups.")]
public static readonly string restmanagegroups; public static readonly string restmanagegroups;
[Description("REST user can get user information.")] [Description("REST user can get user information.")]
public static readonly string restuserinfo; public static readonly string restuserinfo;
[Description("REST user can kick players.")] [Description("REST user can kick players.")]
public static readonly string restkick; public static readonly string restkick;
[Description("REST user can ban players.")] [Description("REST user can ban players.")]
public static readonly string restban; public static readonly string restban;
[Description("REST user can mute and unmute players.")] [Description("REST user can mute and unmute players.")]
public static readonly string restmute; public static readonly string restmute;
[Description("REST user can kill players.")] [Description("REST user can kill players.")]
public static readonly string restkill; public static readonly string restkill;
[Description("REST user can drop meteors or change bloodmoon.")] [Description("REST user can drop meteors or change bloodmoon.")]
public static readonly string restcauseevents; public static readonly string restcauseevents;
[Description("REST user can butcher npcs.")] [Description("REST user can butcher npcs.")]
public static readonly string restbutcher; public static readonly string restbutcher;
[Description("REST user can run raw TShock commands (the raw command permissions are also checked though).")] [Description("REST user can run raw TShock commands (the raw command permissions are also checked though).")]
public static readonly string restrawcommand; public static readonly string restrawcommand;
static RestPermissions() static RestPermissions()
{ {
foreach (var field in typeof (RestPermissions).GetFields()) foreach (var field in typeof (RestPermissions).GetFields())
{ {
field.SetValue(null, field.Name); field.SetValue(null, field.Name);
} }
} }
} }
} }

View file

@ -18,35 +18,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text; using System.Text;
using HttpServer; using HttpServer;
using TShockAPI; using TShockAPI;
using TShockAPI.DB; using TShockAPI.DB;
namespace Rests namespace Rests
{ {
public class SecureRest : Rest public class SecureRest : Rest
{ {
public struct TokenData public struct TokenData
{ {
public static readonly TokenData None = default(TokenData); public static readonly TokenData None = default(TokenData);
public string Username { get; set; } public string Username { get; set; }
public string UserGroupName { get; set; } public string UserGroupName { get; set; }
} }
public Dictionary<string,TokenData> Tokens { get; protected set; } public Dictionary<string,TokenData> Tokens { get; protected set; }
public SecureRest(IPAddress ip, int port) public SecureRest(IPAddress ip, int port)
: base(ip, port) : base(ip, port)
{ {
Tokens = new Dictionary<string, TokenData>(); Tokens = new Dictionary<string, TokenData>();
Register(new RestCommand("/token/create/{username}/{password}", NewToken) { DoLog = false }); Register(new RestCommand("/token/create/{username}/{password}", NewToken) { DoLog = false });
Register(new RestCommand("/v2/token/create/{password}", NewTokenV2) { DoLog = false }); Register(new RestCommand("/v2/token/create/{password}", NewTokenV2) { DoLog = false });
Register(new SecureRestCommand("/token/destroy/{token}", DestroyToken)); Register(new SecureRestCommand("/token/destroy/{token}", DestroyToken));
Register(new SecureRestCommand("/v3/token/destroy/all", DestroyAllTokens, RestPermissions.restmanage)); Register(new SecureRestCommand("/v3/token/destroy/all", DestroyAllTokens, RestPermissions.restmanage));
foreach (KeyValuePair<string, TokenData> t in TShockAPI.TShock.RESTStartupTokens) foreach (KeyValuePair<string, TokenData> t in TShockAPI.TShock.RESTStartupTokens)
{ {
@ -55,7 +55,7 @@ namespace Rests
// TODO: Get rid of this when the old REST permission model is removed. // TODO: Get rid of this when the old REST permission model is removed.
if (!TShock.Config.RestUseNewPermissionModel) if (!TShock.Config.RestUseNewPermissionModel)
{ {
string warningMessage = string.Concat( string warningMessage = string.Concat(
"You're using the old REST permission model which is highly vulnerable in matter of security. ", "You're using the old REST permission model which is highly vulnerable in matter of security. ",
"The old model will be removed with the next maintenance release of TShock. In order to switch to the new model, ", "The old model will be removed with the next maintenance release of TShock. In order to switch to the new model, ",
@ -64,16 +64,16 @@ namespace Rests
Log.Warn(warningMessage); Log.Warn(warningMessage);
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(warningMessage); Console.WriteLine(warningMessage);
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
} }
else else
{ {
string warningMessage = string.Concat( string warningMessage = string.Concat(
"You're using the new more secure REST permission model which can lead to compatibility problems ", "You're using the new more secure REST permission model which can lead to compatibility problems ",
"with existing REST services. If compatibility problems occur, you can switch back to the unsecure permission ", "with existing REST services. If compatibility problems occur, you can switch back to the unsecure permission ",
"model by changing the config setting \"RestUseNewPermissionModel\" to false, which is not recommended." "model by changing the config setting \"RestUseNewPermissionModel\" to false, which is not recommended."
); );
Log.ConsoleInfo(warningMessage); Log.ConsoleInfo(warningMessage);
} }
} }
@ -91,11 +91,11 @@ namespace Rests
} }
return new RestObject() return new RestObject()
{ Response = "Requested token was successfully destroyed." }; { Response = "Requested token was successfully destroyed." };
} }
private object DestroyAllTokens(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData) private object DestroyAllTokens(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
{ {
Tokens.Clear(); Tokens.Clear();
return new RestObject() return new RestObject()
{ Response = "All tokens were successfully destroyed." }; { Response = "All tokens were successfully destroyed." };
@ -114,13 +114,13 @@ namespace Rests
var user = verbs["username"]; var user = verbs["username"];
var pass = verbs["password"]; var pass = verbs["password"];
RestObject response = this.NewTokenInternal(user, pass); RestObject response = this.NewTokenInternal(user, pass);
response["deprecated"] = "This endpoint is depracted and will be removed in the future."; response["deprecated"] = "This endpoint is depracted and will be removed in the future.";
return response; return response;
} }
private RestObject NewTokenInternal(string username, string password) private RestObject NewTokenInternal(string username, string password)
{ {
User userAccount = TShock.Users.GetUserByName(username); User userAccount = TShock.Users.GetUserByName(username);
if (userAccount == null || !string.IsNullOrWhiteSpace(userAccount.Address)) if (userAccount == null || !string.IsNullOrWhiteSpace(userAccount.Address))
return new RestObject("401") return new RestObject("401")
@ -129,12 +129,12 @@ namespace Rests
if (!TShock.Utils.HashPassword(password).Equals(userAccount.Password, StringComparison.InvariantCultureIgnoreCase)) if (!TShock.Utils.HashPassword(password).Equals(userAccount.Password, StringComparison.InvariantCultureIgnoreCase))
return new RestObject("401") return new RestObject("401")
{ Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." }; { Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." };
Group userGroup = TShock.Utils.GetGroup(userAccount.Group); Group userGroup = TShock.Utils.GetGroup(userAccount.Group);
if (!userGroup.HasPermission(RestPermissions.restapi) && userAccount.Group != "superadmin") if (!userGroup.HasPermission(RestPermissions.restapi) && userAccount.Group != "superadmin")
return new RestObject("403") return new RestObject("403")
{ Error = "Although your account was successfully found and identified, your account lacks the permission required to use the API. (restapi)" }; { Error = "Although your account was successfully found and identified, your account lacks the permission required to use the API. (restapi)" };
string tokenHash; string tokenHash;
var rand = new Random(); var rand = new Random();
var randbytes = new byte[32]; var randbytes = new byte[32];
@ -145,53 +145,53 @@ namespace Rests
} while (Tokens.ContainsKey(tokenHash)); } while (Tokens.ContainsKey(tokenHash));
Tokens.Add(tokenHash, new TokenData { Username = userAccount.Name, UserGroupName = userGroup.Name }); Tokens.Add(tokenHash, new TokenData { Username = userAccount.Name, UserGroupName = userGroup.Name });
RestObject response = new RestObject() { Response = "Successful login" }; RestObject response = new RestObject() { Response = "Successful login" };
response["token"] = tokenHash; response["token"] = tokenHash;
return response; return response;
} }
protected override object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms) protected override object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
{ {
if (!cmd.RequiresToken) if (!cmd.RequiresToken)
return base.ExecuteCommand(cmd, verbs, parms); return base.ExecuteCommand(cmd, verbs, parms);
var token = parms["token"]; var token = parms["token"];
if (token == null) if (token == null)
return new RestObject("401") return new RestObject("401")
{ Error = "Not authorized. The specified API endpoint requires a token." }; { Error = "Not authorized. The specified API endpoint requires a token." };
SecureRestCommand secureCmd = (SecureRestCommand)cmd; SecureRestCommand secureCmd = (SecureRestCommand)cmd;
TokenData tokenData; TokenData tokenData;
if (!Tokens.TryGetValue(token, out tokenData)) if (!Tokens.TryGetValue(token, out tokenData))
return new RestObject("403") return new RestObject("403")
{ Error = "Not authorized. The specified API endpoint requires a token, but the provided token was not valid." }; { Error = "Not authorized. The specified API endpoint requires a token, but the provided token was not valid." };
// TODO: Get rid of this when the old REST permission model is removed. // TODO: Get rid of this when the old REST permission model is removed.
if (TShock.Config.RestUseNewPermissionModel) { if (TShock.Config.RestUseNewPermissionModel) {
Group userGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName); Group userGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
if (userGroup == null) if (userGroup == null)
{ {
Tokens.Remove(token); Tokens.Remove(token);
return new RestObject("403") return new RestObject("403")
{ Error = "Not authorized. The provided token became invalid due to group changes, please create a new token." }; { Error = "Not authorized. The provided token became invalid due to group changes, please create a new token." };
} }
if (secureCmd.Permissions.Length > 0 && secureCmd.Permissions.All(perm => !userGroup.HasPermission(perm))) if (secureCmd.Permissions.Length > 0 && secureCmd.Permissions.All(perm => !userGroup.HasPermission(perm)))
{ {
return new RestObject("403") return new RestObject("403")
{ Error = string.Format("Not authorized. User \"{0}\" has no access to use the specified API endpoint.", tokenData.Username) }; { Error = string.Format("Not authorized. User \"{0}\" has no access to use the specified API endpoint.", tokenData.Username) };
} }
} }
object result = secureCmd.Execute(verbs, parms, tokenData); object result = secureCmd.Execute(verbs, parms, tokenData);
if (cmd.DoLog) if (cmd.DoLog)
TShock.Utils.SendLogs(string.Format( TShock.Utils.SendLogs(string.Format(
"\"{0}\" requested REST endpoint: {1}", tokenData.Username, this.BuildRequestUri(cmd, verbs, parms, false)), "\"{0}\" requested REST endpoint: {1}", tokenData.Username, this.BuildRequestUri(cmd, verbs, parms, false)),
Color.PaleVioletRed); Color.PaleVioletRed);
return result; return result;
} }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -1,205 +1,205 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{49606449-072B-4CF5-8088-AA49DA586694}</ProjectGuid> <ProjectGuid>{49606449-072B-4CF5-8088-AA49DA586694}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TShockAPI</RootNamespace> <RootNamespace>TShockAPI</RootNamespace>
<AssemblyName>TShockAPI</AssemblyName> <AssemblyName>TShockAPI</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<IsWebBootstrapper>false</IsWebBootstrapper> <IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl> <PublishUrl>publish\</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Disk</InstallFrom> <InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled> <UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode> <UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval> <UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits> <UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically> <UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired> <UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions> <MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion> <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust> <UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled> <BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\TShockAPI.XML</DocumentationFile> <DocumentationFile>bin\Debug\TShockAPI.XML</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;COMPAT_SIGS</DefineConstants> <DefineConstants>TRACE;COMPAT_SIGS</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\TShockAPI.XML</DocumentationFile> <DocumentationFile>bin\Release\TShockAPI.XML</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="HttpServer"> <Reference Include="HttpServer">
<HintPath>..\HttpBins\HttpServer.dll</HintPath> <HintPath>..\HttpBins\HttpServer.dll</HintPath>
</Reference> </Reference>
<Reference Include="Mono.Data.Sqlite"> <Reference Include="Mono.Data.Sqlite">
<HintPath>..\SqlBins\Mono.Data.Sqlite.dll</HintPath> <HintPath>..\SqlBins\Mono.Data.Sqlite.dll</HintPath>
</Reference> </Reference>
<Reference Include="MySql.Data, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL"> <Reference Include="MySql.Data, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\SqlBins\MySql.Data.dll</HintPath> <HintPath>..\SqlBins\MySql.Data.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="MySql.Web, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL"> <Reference Include="MySql.Web, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\SqlBins\MySql.Web.dll</HintPath> <HintPath>..\SqlBins\MySql.Web.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json"> <Reference Include="Newtonsoft.Json">
<HintPath>.\Newtonsoft.Json.dll</HintPath> <HintPath>.\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="TerrariaServer"> <Reference Include="TerrariaServer">
<HintPath>..\TerrariaServerBins\TerrariaServer.exe</HintPath> <HintPath>..\TerrariaServerBins\TerrariaServer.exe</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BackupManager.cs" /> <Compile Include="BackupManager.cs" />
<Compile Include="DB\RegionManager.cs" /> <Compile Include="DB\RegionManager.cs" />
<Compile Include="Hooks\GeneralHooks.cs" /> <Compile Include="Hooks\GeneralHooks.cs" />
<Compile Include="Hooks\PlayerHooks.cs" /> <Compile Include="Hooks\PlayerHooks.cs" />
<Compile Include="PaginationTools.cs" /> <Compile Include="PaginationTools.cs" />
<Compile Include="PluginUpdater\PluginUpdaterThread.cs" /> <Compile Include="PluginUpdater\PluginUpdaterThread.cs" />
<Compile Include="PluginUpdater\PluginVersionCheck.cs" /> <Compile Include="PluginUpdater\PluginVersionCheck.cs" />
<Compile Include="PluginUpdater\VersionInfo.cs" /> <Compile Include="PluginUpdater\VersionInfo.cs" />
<Compile Include="Rest\RestPermissions.cs" /> <Compile Include="Rest\RestPermissions.cs" />
<Compile Include="SaveManager.cs" /> <Compile Include="SaveManager.cs" />
<Compile Include="DB\BanManager.cs" /> <Compile Include="DB\BanManager.cs" />
<Compile Include="DB\InventoryManager.cs" /> <Compile Include="DB\InventoryManager.cs" />
<Compile Include="DB\IQueryBuilder.cs" /> <Compile Include="DB\IQueryBuilder.cs" />
<Compile Include="DB\ItemManager.cs" /> <Compile Include="DB\ItemManager.cs" />
<Compile Include="DB\SqlColumn.cs" /> <Compile Include="DB\SqlColumn.cs" />
<Compile Include="DB\SqlTable.cs" /> <Compile Include="DB\SqlTable.cs" />
<Compile Include="DB\SqlValue.cs" /> <Compile Include="DB\SqlValue.cs" />
<Compile Include="Extensions\DbExt.cs" /> <Compile Include="Extensions\DbExt.cs" />
<Compile Include="DB\GroupManager.cs" /> <Compile Include="DB\GroupManager.cs" />
<Compile Include="DB\UserManager.cs" /> <Compile Include="DB\UserManager.cs" />
<Compile Include="Extensions\RandomExt.cs" /> <Compile Include="Extensions\RandomExt.cs" />
<Compile Include="Extensions\StringExt.cs" /> <Compile Include="Extensions\StringExt.cs" />
<Compile Include="GeoIPCountry.cs" /> <Compile Include="GeoIPCountry.cs" />
<Compile Include="HandlerList.cs" /> <Compile Include="HandlerList.cs" />
<Compile Include="IPackable.cs" /> <Compile Include="IPackable.cs" />
<Compile Include="Commands.cs" /> <Compile Include="Commands.cs" />
<Compile Include="ConfigFile.cs" /> <Compile Include="ConfigFile.cs" />
<Compile Include="FileTools.cs" /> <Compile Include="FileTools.cs" />
<Compile Include="GetDataHandlers.cs" /> <Compile Include="GetDataHandlers.cs" />
<Compile Include="Group.cs" /> <Compile Include="Group.cs" />
<Compile Include="Extensions\LinqExt.cs" /> <Compile Include="Extensions\LinqExt.cs" />
<Compile Include="Log.cs" /> <Compile Include="Log.cs" />
<Compile Include="Net\BaseMsg.cs" /> <Compile Include="Net\BaseMsg.cs" />
<Compile Include="Net\DisconnectMsg.cs" /> <Compile Include="Net\DisconnectMsg.cs" />
<Compile Include="Net\NetTile.cs" /> <Compile Include="Net\NetTile.cs" />
<Compile Include="Net\ProjectileRemoveMsg.cs" /> <Compile Include="Net\ProjectileRemoveMsg.cs" />
<Compile Include="Net\SpawnMsg.cs" /> <Compile Include="Net\SpawnMsg.cs" />
<Compile Include="Net\WorldInfoMsg.cs" /> <Compile Include="Net\WorldInfoMsg.cs" />
<Compile Include="PacketBufferer.cs" /> <Compile Include="PacketBufferer.cs" />
<Compile Include="Permissions.cs" /> <Compile Include="Permissions.cs" />
<Compile Include="RconHandler.cs" /> <Compile Include="RconHandler.cs" />
<Compile Include="DB\RememberedPosManager.cs" /> <Compile Include="DB\RememberedPosManager.cs" />
<Compile Include="Resources.Designer.cs"> <Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="Rest\Rest.cs" /> <Compile Include="Rest\Rest.cs" />
<Compile Include="Rest\RestCommand.cs" /> <Compile Include="Rest\RestCommand.cs" />
<Compile Include="Rest\RestManager.cs" /> <Compile Include="Rest\RestManager.cs" />
<Compile Include="Rest\RestObject.cs" /> <Compile Include="Rest\RestObject.cs" />
<Compile Include="Rest\RestVerbs.cs" /> <Compile Include="Rest\RestVerbs.cs" />
<Compile Include="Rest\SecureRest.cs" /> <Compile Include="Rest\SecureRest.cs" />
<Compile Include="StatTracker.cs" /> <Compile Include="StatTracker.cs" />
<Compile Include="Utils.cs" /> <Compile Include="Utils.cs" />
<Compile Include="TShock.cs" /> <Compile Include="TShock.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TSPlayer.cs" /> <Compile Include="TSPlayer.cs" />
<Compile Include="UpdateManager.cs" /> <Compile Include="UpdateManager.cs" />
<Compile Include="DB\WarpsManager.cs" /> <Compile Include="DB\WarpsManager.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="config\groups.txt" /> <None Include="config\groups.txt" />
<None Include="TShockAPI.licenseheader" /> <None Include="TShockAPI.licenseheader" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="config\users.txt" /> <None Include="config\users.txt" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Resources.resx"> <EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0"> <BootstrapperPackage Include=".NETFramework,Version=v4.0">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName> <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5"> <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install> <Install>false</Install>
</BootstrapperPackage> </BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName> <ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install> <Install>false</Install>
</BootstrapperPackage> </BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName> <ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="config\itembans.txt" /> <Content Include="config\itembans.txt" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PreBuildEvent> <PreBuildEvent>
</PreBuildEvent> </PreBuildEvent>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PostBuildEvent>"$(ProjectDir)postbuild.bat"</PostBuildEvent> <PostBuildEvent>"$(ProjectDir)postbuild.bat"</PostBuildEvent>
</PropertyGroup> </PropertyGroup>
<ProjectExtensions> <ProjectExtensions>
<VisualStudio> <VisualStudio>
<UserProperties BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_StartDate="2011/6/17" BuildVersion_IncrementBeforeBuild="False" /> <UserProperties BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_StartDate="2011/6/17" BuildVersion_IncrementBeforeBuild="False" />
</VisualStudio> </VisualStudio>
</ProjectExtensions> </ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
</Target> </Target>
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>

View file

@ -22,8 +22,8 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using TShockAPI.DB; using TShockAPI.DB;
using Terraria; using Terraria;
namespace TShockAPI namespace TShockAPI
@ -221,7 +221,7 @@ namespace TShockAPI
/// Sends message to all players with 'logs' permission. /// Sends message to all players with 'logs' permission.
/// </summary> /// </summary>
/// <param name="log">Message to send</param> /// <param name="log">Message to send</param>
/// <param name="color">Color of the message</param> /// <param name="color">Color of the message</param>
/// <param name="excludedPlayer">The player to not send the message to.</param> /// <param name="excludedPlayer">The player to not send the message to.</param>
public void SendLogs(string log, Color color, TSPlayer excludedPlayer = null) public void SendLogs(string log, Color color, TSPlayer excludedPlayer = null)
{ {
@ -229,7 +229,7 @@ namespace TShockAPI
TSPlayer.Server.SendMessage(log, color); TSPlayer.Server.SendMessage(log, color);
foreach (TSPlayer player in TShock.Players) foreach (TSPlayer player in TShock.Players)
{ {
if (player != null && player != excludedPlayer && player.Active && player.Group.HasPermission(Permissions.logs) && if (player != null && player != excludedPlayer && player.Active && player.Group.HasPermission(Permissions.logs) &&
player.DisplayLogs && TShock.Config.DisableSpewLogs == false) player.DisplayLogs && TShock.Config.DisableSpewLogs == false)
player.SendMessage(log, color); player.SendMessage(log, color);
} }
@ -560,10 +560,10 @@ namespace TShockAPI
// Disconnect after kick as that signifies server is exiting and could cause a race // Disconnect after kick as that signifies server is exiting and could cause a race
Netplay.disconnect = true; Netplay.disconnect = true;
} }
/// <summary> /// <summary>
/// Stops the server after kicking all players with a reason message, and optionally saving the world then attempts to /// Stops the server after kicking all players with a reason message, and optionally saving the world then attempts to
/// restart it. /// restart it.
/// </summary> /// </summary>
/// <param name="save">bool perform a world save before stop (default: true)</param> /// <param name="save">bool perform a world save before stop (default: true)</param>
@ -573,23 +573,23 @@ namespace TShockAPI
if (TShock.Config.ServerSideInventory) if (TShock.Config.ServerSideInventory)
foreach (TSPlayer player in TShock.Players) foreach (TSPlayer player in TShock.Players)
if (player != null && player.IsLoggedIn && !player.IgnoreActionsForClearingTrashCan) if (player != null && player.IsLoggedIn && !player.IgnoreActionsForClearingTrashCan)
TShock.InventoryDB.InsertPlayerData(player); TShock.InventoryDB.InsertPlayerData(player);
StopServer(true, reason); StopServer(true, reason);
System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
Environment.Exit(0); Environment.Exit(0);
} }
/// <summary> /// <summary>
/// Reloads all configuration settings, groups, regions and raises the reload event. /// Reloads all configuration settings, groups, regions and raises the reload event.
/// </summary> /// </summary>
public void Reload(TSPlayer player) public void Reload(TSPlayer player)
{ {
FileTools.SetupConfig(); FileTools.SetupConfig();
TShock.HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs()); TShock.HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs());
TShock.Groups.LoadPermisions(); TShock.Groups.LoadPermisions();
TShock.Regions.ReloadAllRegions(); TShock.Regions.ReloadAllRegions();
Hooks.GeneralHooks.OnReloadEvent(player); Hooks.GeneralHooks.OnReloadEvent(player);
} }
#if COMPAT_SIGS #if COMPAT_SIGS
@ -879,19 +879,19 @@ namespace TShockAPI
/// </summary> /// </summary>
/// <param name="regionArea">The region's area to enumerate through.</param> /// <param name="regionArea">The region's area to enumerate through.</param>
/// <returns>The enumerated boundary points.</returns> /// <returns>The enumerated boundary points.</returns>
public IEnumerable<Point> EnumerateRegionBoundaries(Rectangle regionArea) public IEnumerable<Point> EnumerateRegionBoundaries(Rectangle regionArea)
{ {
for (int x = 0; x < regionArea.Width + 1; x++) for (int x = 0; x < regionArea.Width + 1; x++)
{ {
yield return new Point(regionArea.Left + x, regionArea.Top); yield return new Point(regionArea.Left + x, regionArea.Top);
yield return new Point(regionArea.Left + x, regionArea.Bottom); yield return new Point(regionArea.Left + x, regionArea.Bottom);
} }
for (int y = 1; y < regionArea.Height; y++) for (int y = 1; y < regionArea.Height; y++)
{ {
yield return new Point(regionArea.Left, regionArea.Top + y); yield return new Point(regionArea.Left, regionArea.Top + y);
yield return new Point(regionArea.Right, regionArea.Top + y); yield return new Point(regionArea.Right, regionArea.Top + y);
} }
} }
} }
} }