diff --git a/src/client/main.c b/src/client/main.c
index 598e747e65c57683430a488548d8cb244bd411f2..4072bd0e37c38c245c4913eba7f8d4b0e991efb7 100644
--- a/src/client/main.c
+++ b/src/client/main.c
@@ -115,62 +115,91 @@ char	*gsUserName;	//!< User that dispense will happen as
 char	*gsUserFlags;	//!< User's flag set
  int	giUserBalance=-1;	//!< User balance (set by Authenticate)
  int	giDispenseCount = 1;	//!< Number of dispenses to do
+char	*gsTextArgs[MAX_TXT_ARGS];
+ int	giTextArgc;
 
 // === CODE ===
 void ShowUsage(void)
 {
-	printf(
-		"Usage:\n"
-		"  == Everyone ==\n"
-		"    dispense\n"
-		"        Show interactive list\n"
-		"    dispense <name>|<index>|<itemid>\n"
-		"        Dispense named item (<name> matches if it is a unique prefix)\n"
-		"    dispense give <user> <ammount> \"<reason>\"\n"
-		"        Give money to another user\n"
-		"    dispense donate <ammount> \"<reason>\"\n"
-		"        Donate to the club\n"
-		"    dispense iteminfo <itemid>\n"
-		"        Get the name and price for an item\n"
-		"  == Coke members == \n"
-		"    dispense acct [<user>]\n"
-		"        Show user balances\n"
-		"    dispense acct <user> [+-]<ammount> \"<reason>\"\n"
-		"        Alter a account value\n"
-		"    dispense refund <user> <itemid> [<price>]\n"
-		"        Refund an item to a user (with optional price override)\n"
-		"    dispense slot <itemid> <price> <name>\n"
-		"        Rename/Re-price a slot\n"
-		"  == Dispense administrators ==\n"
-		"    dispense acct <user> =<ammount> \"<reason>\"\n"
-		"        Set an account balance\n"
-		"    dispense user add <user>\n"
-		"        Create new account\n"
-		"    dispense user type <user> <flags>\n"
-		"        Alter a user's flags\n"
-		"        <flags> is a comma-separated list of user, coke, admin, internal or disabled\n"
-		"        Flags are removed by preceding the name with '-' or '!'\n"
-		"\n"
-		"General Options:\n"
-		"    -c <count>\n"
-		"        Dispense multiple times\n"
-		"    -u <username>\n"
-		"        Set a different user (Coke members only)\n"
-		"    -h / -?\n"
-		"        Show help text\n"
-		"    -G\n"
-		"        Use alternate GUI\n"
-		"    -n\n"
-		"        Dry run - Do not actually do dispenses\n"
-		"    -m <min balance>\n"
-		"    -M <max balance>\n"
-		"        Set the Maximum/Minimum balances shown in `dispense acct`\n"
-		"Definitions:\n"
-		"    <itemid>\n"
-		"        Item ID of the form <type>:<num> where <type> is a non-empty string of alpha-numeric characters, and <num> is a non-negative integer\n"
-//		"    <user>\n"
-//		"        Account name\n"
-		);
+	printf(	"Usage:\n" );
+	if( giTextArgc == 0 )
+		printf(
+			"  == Everyone ==\n"
+			"    dispense\n"
+			"        Show interactive list\n"
+			"    dispense <name>|<index>|<itemid>\n"
+			"        Dispense named item (<name> matches if it is a unique prefix)\n"
+			);
+	if( giTextArgc == 0 || strcmp(gsTextArgs[0], "give") == 0 )
+		printf(
+			"    dispense give <user> <ammount> \"<reason>\"\n"
+			"        Give money to another user\n"
+			);
+	
+	if( giTextArgc == 0 || strcmp(gsTextArgs[0], "donate") == 0 )
+		printf(
+			"    dispense donate <ammount> \"<reason>\"\n"
+			"        Donate to the club\n"
+			);
+	if( giTextArgc == 0 || strcmp(gsTextArgs[0], "iteminfo") == 0 )
+		printf(
+			"    dispense iteminfo <itemid>\n"
+			"        Get the name and price for an item\n"
+			);
+	if( giTextArgc == 0 )
+		printf("  == Coke members == \n");
+	if( giTextArgc == 0 || strcmp(gsTextArgs[0], "acct") == 0 )
+		printf(
+			"    dispense acct [<user>]\n"
+			"        Show user balances\n"
+			"    dispense acct <user> [+-]<ammount> \"<reason>\"\n"
+			"        Alter a account value\n"
+			"    dispense acct <user> =<ammount> \"<reason>\"\n"
+			"        Set an account balance\n"
+			);
+	if( giTextArgc == 0 || strcmp(gsTextArgs[0], "refund") == 0 )
+		printf(
+			"    dispense refund <user> <itemid> [<price>]\n"
+			"        Refund an item to a user (with optional price override)\n"
+			);
+	if( giTextArgc == 0 || strcmp(gsTextArgs[0], "slot") == 0 )
+		printf(
+			"    dispense slot <itemid> <price> <name>\n"
+			"        Rename/Re-price a slot\n"
+			);
+	if( giTextArgc == 0 )
+		printf("  == Dispense administrators ==\n");
+	if( giTextArgc == 0 || strcmp(gsTextArgs[0], "user") == 0 )
+		printf(
+			"    dispense user add <user>\n"
+			"        Create new account\n"
+			"    dispense user type <user> <flags>\n"
+			"        Alter a user's flags\n"
+			"        <flags> is a comma-separated list of user, coke, admin, internal or disabled\n"
+			"        Flags are removed by preceding the name with '-' or '!'\n"
+			);
+	if( giTextArgc == 0 )
+		printf(	"\n"
+			"General Options:\n"
+			"    -c <count>\n"
+			"        Dispense multiple times\n"
+			"    -u <username>\n"
+			"        Set a different user (Coke members only)\n"
+			"    -h / -?\n"
+			"        Show help text\n"
+			"    -G\n"
+			"        Use simple textual interface (instead of ncurses)\n"
+			"    -n\n"
+			"        Dry run - Do not actually do dispenses\n"
+			"    -m <min balance>\n"
+			"    -M <max balance>\n"
+			"        Set the Maximum/Minimum balances shown in `dispense acct`\n"
+			"Definitions:\n"
+			"    <itemid>\n"
+			"        Item ID of the form <type>:<num> where <type> is a non-empty string of alpha-numeric characters, and <num> is a non-negative integer\n"
+//			"    <user>\n"
+//			"        Account name\n"
+			);
 }
 
 int main(int argc, char *argv[])
@@ -178,10 +207,8 @@ int main(int argc, char *argv[])
 	 int	sock;
 	 int	i, ret = 0;
 	char	buffer[BUFSIZ];
-	char	*text_args[MAX_TXT_ARGS];	// Non-flag arguments
-	 int	text_argc = 0;
 	
-	text_args[0] = "";
+	gsTextArgs[0] = "";
 
 	// -- Create regular expressions
 	// > Code Type Count ...
@@ -268,13 +295,13 @@ int main(int argc, char *argv[])
 			
 			// Set slot name/price
 			case 's':
-				if( text_argc != 0 ) {
+				if( giTextArgc != 0 ) {
 					fprintf(stderr, "%s: -s must appear before other arguments\n", argv[0]);
 					ShowUsage();
 					return RV_ARGUMENTS;
 				}
-				text_args[0] = "slot";	// HACK!!
-				text_argc ++;
+				gsTextArgs[0] = "slot";	// HACK!!
+				giTextArgc ++;
 				break;
 			
 			case 'G':	// Don't use GUI
@@ -300,54 +327,54 @@ int main(int argc, char *argv[])
 			default:
 				// The first argument is not allowed to begin with 'i'
 				// (catches most bad flags)
-				if( text_argc == 0 ) {
+				if( giTextArgc == 0 ) {
 					fprintf(stderr, "%s: Unknown switch '%s'\n", argv[0], argv[i]);
 					ShowUsage();
 					return RV_ARGUMENTS;
 				}
-				if( text_argc + 1 ==  MAX_TXT_ARGS )
+				if( giTextArgc + 1 ==  MAX_TXT_ARGS )
 				{
 					fprintf(stderr, "ERROR: Too many arguments\n");
 					return RV_ARGUMENTS;
 				}
-				text_args[text_argc++] = argv[i];
+				gsTextArgs[giTextArgc++] = argv[i];
 				break;
 			}
 
 			continue;
 		}
 
-		if( text_argc + 1 == MAX_TXT_ARGS )
+		if( giTextArgc + 1 == MAX_TXT_ARGS )
 		{
 			fprintf(stderr, "ERROR: Too many arguments\n");
 			return RV_ARGUMENTS;
 		}
 	
-		text_args[text_argc++] = argv[i];
+		gsTextArgs[giTextArgc++] = argv[i];
 	
 	}
 
 	//
 	// `dispense acct`
 	// - 
-	if( strcmp(text_args[0], "acct") == 0 )
+	if( strcmp(gsTextArgs[0], "acct") == 0 )
 	{
 		// Connect to server
 		sock = OpenConnection(gsDispenseServer, giDispensePort);
 		if( sock < 0 )	return RV_SOCKET_ERROR;
 		// List accounts?
-		if( text_argc == 1 ) {
+		if( giTextArgc == 1 ) {
 			ret = Dispense_EnumUsers(sock);
 			close(sock);
 			return ret;
 		}
 			
-		// text_args[1]: Username
+		// gsTextArgs[1]: Username
 		
 		// Alter account?
-		if( text_argc != 2 )
+		if( giTextArgc != 2 )
 		{
-			if( text_argc != 4 ) {
+			if( giTextArgc != 4 ) {
 				fprintf(stderr, "`dispense acct` requires a reason\n");
 				ShowUsage();
 				return RV_ARGUMENTS;
@@ -357,28 +384,28 @@ int main(int argc, char *argv[])
 			ret = Authenticate(sock);
 			if(ret)	return ret;
 			
-			// text_args[1]: Username
-			// text_args[2]: Ammount
-			// text_args[3]: Reason
+			// gsTextArgs[1]: Username
+			// gsTextArgs[2]: Ammount
+			// gsTextArgs[3]: Reason
 			
-			if( text_args[2][0] == '=' ) {
+			if( gsTextArgs[2][0] == '=' ) {
 				// Set balance
-				if( text_args[2][1] != '0' && atoi(text_args[2]+1) == 0 ) {
+				if( gsTextArgs[2][1] != '0' && atoi(gsTextArgs[2]+1) == 0 ) {
 					fprintf(stderr, "Error: Invalid balance to be set\n");
 					exit(1);
 				}
 				
-				ret = Dispense_SetBalance(sock, text_args[1], atoi(text_args[2]+1), text_args[3]);
+				ret = Dispense_SetBalance(sock, gsTextArgs[1], atoi(gsTextArgs[2]+1), gsTextArgs[3]);
 			}
 			else {
 				// Alter balance
-				ret = Dispense_AlterBalance(sock, text_args[1], atoi(text_args[2]), text_args[3]);
+				ret = Dispense_AlterBalance(sock, gsTextArgs[1], atoi(gsTextArgs[2]), gsTextArgs[3]);
 			}
 		}
 		// TODO: Preserve ret if non-zero
 		
 		// Show user information
-		ret = Dispense_ShowUser(sock, text_args[1]);
+		ret = Dispense_ShowUser(sock, gsTextArgs[1]);
 		
 		close(sock);
 		return ret;
@@ -386,17 +413,17 @@ int main(int argc, char *argv[])
 	//
 	// `dispense give`
 	// - "Here, have some money."
-	else if( strcmp(text_args[0], "give") == 0 )
+	else if( strcmp(gsTextArgs[0], "give") == 0 )
 	{
-		if( text_argc != 4 ) {
+		if( giTextArgc != 4 ) {
 			fprintf(stderr, "`dispense give` takes three arguments\n");
 			ShowUsage();
 			return RV_ARGUMENTS;
 		}
 		
-		// text_args[1]: Destination
-		// text_args[2]: Ammount
-		// text_args[3]: Reason
+		// gsTextArgs[1]: Destination
+		// gsTextArgs[2]: Ammount
+		// gsTextArgs[3]: Reason
 		
 		// Connect to server
 		sock = OpenConnection(gsDispenseServer, giDispensePort);
@@ -406,7 +433,7 @@ int main(int argc, char *argv[])
 		ret = Authenticate(sock);
 		if(ret)	return ret;
 		
-		ret = Dispense_Give(sock, text_args[1], atoi(text_args[2]), text_args[3]);
+		ret = Dispense_Give(sock, gsTextArgs[1], atoi(gsTextArgs[2]), gsTextArgs[3]);
 
 		close(sock);
 	
@@ -415,10 +442,10 @@ int main(int argc, char *argv[])
 	// 
 	// `dispense user`
 	// - User administration (Admin Only)
-	if( strcmp(text_args[0], "user") == 0 )
+	if( strcmp(gsTextArgs[0], "user") == 0 )
 	{
 		// Check argument count
-		if( text_argc == 1 ) {
+		if( giTextArgc == 1 ) {
 			fprintf(stderr, "Error: `dispense user` requires arguments\n");
 			ShowUsage();
 			return RV_ARGUMENTS;
@@ -433,26 +460,26 @@ int main(int argc, char *argv[])
 		if(ret)	return ret;
 		
 		// Add new user?
-		if( strcmp(text_args[1], "add") == 0 )
+		if( strcmp(gsTextArgs[1], "add") == 0 )
 		{
-			if( text_argc != 3 ) {
+			if( giTextArgc != 3 ) {
 				fprintf(stderr, "Error: `dispense user add` requires an argument\n");
 				ShowUsage();
 				return RV_ARGUMENTS;
 			}
 			
-			ret = Dispense_AddUser(sock, text_args[2]);
+			ret = Dispense_AddUser(sock, gsTextArgs[2]);
 		}
 		// Update a user
-		else if( strcmp(text_args[1], "type") == 0 || strcmp(text_args[1], "flags") == 0 )
+		else if( strcmp(gsTextArgs[1], "type") == 0 || strcmp(gsTextArgs[1], "flags") == 0 )
 		{
-			if( text_argc != 4 ) {
-				fprintf(stderr, "Error: `dispense user flags` requires two arguments\n");
+			if( giTextArgc != 4 ) {
+				fprintf(stderr, "Error: `dispense user type` requires two arguments\n");
 				ShowUsage();
 				return RV_ARGUMENTS;
 			}
 			
-			ret = Dispense_SetUserType(sock, text_args[2], text_args[3]);
+			ret = Dispense_SetUserType(sock, gsTextArgs[2], gsTextArgs[3]);
 		}
 		else
 		{
@@ -464,10 +491,10 @@ int main(int argc, char *argv[])
 		return ret;
 	}
 	// Donation!
-	else if( strcmp(text_args[0], "donate") == 0 )
+	else if( strcmp(gsTextArgs[0], "donate") == 0 )
 	{
 		// Check argument count
-		if( text_argc != 3 ) {
+		if( giTextArgc != 3 ) {
 			fprintf(stderr, "Error: `dispense donate` requires two arguments\n");
 			ShowUsage();
 			return RV_ARGUMENTS;
@@ -482,18 +509,18 @@ int main(int argc, char *argv[])
 		if(ret)	return ret;
 		
 		// Do donation
-		ret = Dispense_Donate(sock, atoi(text_args[1]), text_args[2]);
+		ret = Dispense_Donate(sock, atoi(gsTextArgs[1]), gsTextArgs[2]);
 				
 		close(sock);
 
 		return ret;
 	}
 	// Refund an item
-	else if( strcmp(text_args[0], "refund") == 0 )
+	else if( strcmp(gsTextArgs[0], "refund") == 0 )
 	{
 		 int	 price = 0;
 		// Check argument count
-		if( text_argc != 3 && text_argc != 4 ) {
+		if( giTextArgc != 3 && giTextArgc != 4 ) {
 			fprintf(stderr, "Error: `dispense refund` takes 2 or 3 arguments\n");
 			ShowUsage();
 			return RV_ARGUMENTS;
@@ -507,8 +534,8 @@ int main(int argc, char *argv[])
 		ret = Authenticate(sock);
 		if(ret)	return ret;
 
-		if( text_argc == 4 ) {
-			price = atoi(text_args[3]);
+		if( giTextArgc == 4 ) {
+			price = atoi(gsTextArgs[3]);
 			if( price <= 0 ) {
 				fprintf(stderr, "Error: Override price is invalid (should be > 0)\n");
 				return RV_ARGUMENTS;
@@ -516,32 +543,32 @@ int main(int argc, char *argv[])
 		}
 
 		// Username, Item, cost
-		ret = Dispense_Refund(sock, text_args[1], text_args[2], price);
+		ret = Dispense_Refund(sock, gsTextArgs[1], gsTextArgs[2], price);
 
 		// TODO: More
 		close(sock);
 		return RV_UNKNOWN_ERROR;
 	}
 	// Query an item price
-	else if( strcmp(text_args[0], "iteminfo") == 0 )
+	else if( strcmp(gsTextArgs[0], "iteminfo") == 0 )
 	{
 		regmatch_t matches[3];
 		char	*type;
 		 int	id;
 		// Check argument count
-		if( text_argc != 2 ) {
+		if( giTextArgc != 2 ) {
 			fprintf(stderr, "Error: `dispense iteminfo` requires an argument\n");
 			ShowUsage();
 			return RV_ARGUMENTS;
 		}
 		// Parse item ID
-		if( RunRegex(&gUserItemIdentRegex, text_args[1], 3, matches, NULL) != 0 ) {
+		if( RunRegex(&gUserItemIdentRegex, gsTextArgs[1], 3, matches, NULL) != 0 ) {
 			fprintf(stderr, "Error: Invalid item ID passed (<type>:<id> expected)\n");
 			return RV_ARGUMENTS;
 		}
-		type = text_args[1] + matches[1].rm_so;
-		text_args[1][ matches[1].rm_eo ] = '\0';
-		id = atoi( text_args[1] + matches[2].rm_so );
+		type = gsTextArgs[1] + matches[1].rm_so;
+		gsTextArgs[1][ matches[1].rm_eo ] = '\0';
+		id = atoi( gsTextArgs[1] + matches[2].rm_so );
 
 		sock = OpenConnection(gsDispenseServer, giDispensePort);
 		if( sock < 0 )	return RV_SOCKET_ERROR;
@@ -551,37 +578,37 @@ int main(int argc, char *argv[])
 		return ret;
 	}
 	// Set slot
-	else if( strcmp(text_args[0], "slot") == 0 )
+	else if( strcmp(gsTextArgs[0], "slot") == 0 )
 	{
 		regmatch_t matches[3];
 		char	*item_type, *newname;
 		 int	item_id, price;
 		
 		// Check arguments
-		if( text_argc != 4 ) {
+		if( giTextArgc != 4 ) {
 			fprintf(stderr, "Error: `dispense slot` takes three arguments\n");
 			ShowUsage();
 			return RV_ARGUMENTS;
 		}
 		
 		// Parse arguments
-		if( RunRegex(&gUserItemIdentRegex, text_args[1], 3, matches, NULL) != 0 ) {
+		if( RunRegex(&gUserItemIdentRegex, gsTextArgs[1], 3, matches, NULL) != 0 ) {
 			fprintf(stderr, "Error: Invalid item ID passed (<type>:<id> expected)\n");
 			return RV_ARGUMENTS;
 		}
-		item_type = text_args[1] + matches[1].rm_so;
-		text_args[1][ matches[1].rm_eo ] = '\0';
-		item_id = atoi( text_args[1] + matches[2].rm_so );
+		item_type = gsTextArgs[1] + matches[1].rm_so;
+		gsTextArgs[1][ matches[1].rm_eo ] = '\0';
+		item_id = atoi( gsTextArgs[1] + matches[2].rm_so );
 
 		// - Price
-		price = atoi( text_args[2] );
-		if( price <= 0 && text_args[2][0] != '0' ) {
+		price = atoi( gsTextArgs[2] );
+		if( price <= 0 && gsTextArgs[2][0] != '0' ) {
 			fprintf(stderr, "Error: Invalid price passed (must be >= 0)\n");
 			return RV_ARGUMENTS;
 		}
 		
 		// - New name
-		newname = text_args[3];
+		newname = gsTextArgs[3];
 		// -- Sanity
 		{
 			char *pos;
@@ -608,7 +635,7 @@ int main(int argc, char *argv[])
 	// Item name / pattern
 	else
 	{
-		gsItemPattern = text_args[0];
+		gsItemPattern = gsTextArgs[0];
 	}
 	
 	// Connect to server
@@ -783,6 +810,8 @@ int main(int argc, char *argv[])
 		close(sock);
 	}
 
+	Dispense_ShowUser(sock, gsUserName);
+
 	return ret;
 }
 
@@ -2161,8 +2190,8 @@ char *ReadLine(int Socket)
 	
 	#if DEBUG_TRACE_SERVER
 	printf("ReadLine: ");
-	#endif
 	fflush(stdout);
+	#endif
 	
 	ret[0] = '\0';
 	
diff --git a/src/cokebank.h b/src/cokebank.h
index 2057a5d41d9fd9e8804ade0a67e6ca6f2a6f3b41..45d1304529e3216947419f4a4d2f11d8fcab0afb 100644
--- a/src/cokebank.h
+++ b/src/cokebank.h
@@ -20,6 +20,7 @@
 #define COKEBANK_SALES_PREFIX	">sales:"	//!< Sales made into
 #define COKEBANK_DEBT_ACCT	">liability"	//!< Credit taken out of
 #define COKEBANK_FREE_ACCT	">freeitems"	//!< ODay drink costs taken out of
+#define COKEBANK_DONATE_ACCT	">donations"	//!< Donations go here
 
 /**
  * \brief Account iterator opaque structure
diff --git a/src/server/dispense.c b/src/server/dispense.c
index 706167098eec493fe2c7f5bd5be44c166d950a12..8375ab672345876808046895c5286b2680ecfe1d 100644
--- a/src/server/dispense.c
+++ b/src/server/dispense.c
@@ -237,7 +237,7 @@ int DispenseDonate(int ActualUser, int User, int Ammount, const char *ReasonGive
 	
 	if( Ammount < 0 )	return 2;
 	
-	ret = _Transfer( User, Bank_GetAcctByName(COKEBANK_DEBT_ACCT,1), Ammount, ReasonGiven );
+	ret = _Transfer( User, Bank_GetAcctByName(COKEBANK_DONATE_ACCT,1), Ammount, ReasonGiven );
 	if(ret)	return 2;
 	
 	byName = Bank_GetAcctName(ActualUser);
diff --git a/src/server/server.c b/src/server/server.c
index 4dec980a580f81cef3fe7b7eed5ca1a145959e92..1f813d4c577d87f0ccb0e61d24d7b664069aab8e 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -148,7 +148,7 @@ void Server_Start(void)
 		return ;
 	}
 
-	// 
+	// Fork into background
 	if( gbServer_RunInBackground )
 	{
 		int newin, newout, newerr;
@@ -353,9 +353,7 @@ void Server_ParseClientCommand(tClient *Client, char *CommandString)
 	if( Server_int_ParseArgs(1, CommandString, &command, &args, NULL) )
 	{
 		if( command == NULL )	return ;
-//		printf("command=%s, args=%s\n", command, args);
 		// Is this an error? (just ignore for now)
-		//args = "";
 	}
 	
 	
@@ -535,6 +533,12 @@ void Server_Cmd_SETEUSER(tClient *Client, char *Args)
 		sendf(Client->Socket, "407 SETEUSER expects an argument\n");
 		return ;
 	}
+	
+	// Check authentication
+	if( !Client->bIsAuthed ) {
+		sendf(Client->Socket, "401 Not Authenticated\n");
+		return ;
+	}
 
 	// Check user permissions
 	userFlags = Bank_GetFlags(Client->UID);
@@ -788,6 +792,7 @@ void Server_Cmd_GIVE(tClient *Client, char *Args)
 		sendf(Client->Socket, "407 GIVE takes only 3 arguments\n");
 		return ;
 	}
+	
 	// Check for authed
 	if( !Client->bIsAuthed ) {
 		sendf(Client->Socket, "401 Not Authenticated\n");
@@ -1235,6 +1240,12 @@ void Server_Cmd_USERADD(tClient *Client, char *Args)
 		return ;
 	}
 	
+	// Check authentication
+	if( !Client->bIsAuthed ) {
+		sendf(Client->Socket, "401 Not Authenticated\n");
+		return ;
+	}
+	
 	// Check permissions
 	if( !(Bank_GetFlags(Client->UID) & USER_FLAG_ADMIN) ) {
 		sendf(Client->Socket, "403 Not a coke admin\n");
@@ -1258,13 +1269,22 @@ void Server_Cmd_USERADD(tClient *Client, char *Args)
 
 void Server_Cmd_USERFLAGS(tClient *Client, char *Args)
 {
-	char	*username, *flags;
+	char	*username, *flags, *reason=NULL;
 	 int	mask=0, value=0;
 	 int	uid;
 	
 	// Parse arguments
-	if( Server_int_ParseArgs(0, Args, &username, &flags, NULL) ) {
-		sendf(Client->Socket, "407 USER_FLAGS takes 2 arguments\n");
+	if( Server_int_ParseArgs(1, Args, &username, &flags, &reason, NULL) ) {
+		if( !flags ) {
+			sendf(Client->Socket, "407 USER_FLAGS takes at least 2 arguments\n");
+			return ;
+		}
+		reason = "";
+	}
+	
+	// Check authentication
+	if( !Client->bIsAuthed ) {
+		sendf(Client->Socket, "401 Not Authenticated\n");
 		return ;
 	}
 	
@@ -1291,6 +1311,10 @@ void Server_Cmd_USERFLAGS(tClient *Client, char *Args)
 	
 	// Apply flags
 	Bank_SetFlags(uid, mask, value);
+
+	// Log the change
+	Log_Info("Updated '%s' with flag set '%s' - Reason: %s",
+		username, flags, reason);
 	
 	// Return OK
 	sendf(Client->Socket, "200 User Updated\n");