From: John Hodge Date: Mon, 21 Mar 2011 00:33:26 +0000 (+0800) Subject: Fixing bugs and slight cleanup X-Git-Url: https://git.ucc.asn.au/?p=tpg%2Fopendispense2.git;a=commitdiff_plain;h=399c1a3a2a1eb9c81ec0f7bdfb1512bdd2e41c6a Fixing bugs and slight cleanup - Fixed issue with the USER_FLAGS and USER_ADD not checking authentication > They were relying on Bank_GetFlags, which returns -1 on error - Changed 'donate' to its own destination account - Updated client's --help output to show help for the current command > E.g. `dispense user --help` will give help for th euser family of commands --- diff --git a/src/client/main.c b/src/client/main.c index 598e747..4072bd0 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 ||\n" - " Dispense named item ( matches if it is a unique prefix)\n" - " dispense give \"\"\n" - " Give money to another user\n" - " dispense donate \"\"\n" - " Donate to the club\n" - " dispense iteminfo \n" - " Get the name and price for an item\n" - " == Coke members == \n" - " dispense acct []\n" - " Show user balances\n" - " dispense acct [+-] \"\"\n" - " Alter a account value\n" - " dispense refund []\n" - " Refund an item to a user (with optional price override)\n" - " dispense slot \n" - " Rename/Re-price a slot\n" - " == Dispense administrators ==\n" - " dispense acct = \"\"\n" - " Set an account balance\n" - " dispense user add \n" - " Create new account\n" - " dispense user type \n" - " Alter a user's flags\n" - " 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 \n" - " Dispense multiple times\n" - " -u \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 \n" - " -M \n" - " Set the Maximum/Minimum balances shown in `dispense acct`\n" - "Definitions:\n" - " \n" - " Item ID of the form : where is a non-empty string of alpha-numeric characters, and is a non-negative integer\n" -// " \n" -// " Account name\n" - ); + printf( "Usage:\n" ); + if( giTextArgc == 0 ) + printf( + " == Everyone ==\n" + " dispense\n" + " Show interactive list\n" + " dispense ||\n" + " Dispense named item ( matches if it is a unique prefix)\n" + ); + if( giTextArgc == 0 || strcmp(gsTextArgs[0], "give") == 0 ) + printf( + " dispense give \"\"\n" + " Give money to another user\n" + ); + + if( giTextArgc == 0 || strcmp(gsTextArgs[0], "donate") == 0 ) + printf( + " dispense donate \"\"\n" + " Donate to the club\n" + ); + if( giTextArgc == 0 || strcmp(gsTextArgs[0], "iteminfo") == 0 ) + printf( + " dispense iteminfo \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 []\n" + " Show user balances\n" + " dispense acct [+-] \"\"\n" + " Alter a account value\n" + " dispense acct = \"\"\n" + " Set an account balance\n" + ); + if( giTextArgc == 0 || strcmp(gsTextArgs[0], "refund") == 0 ) + printf( + " dispense refund []\n" + " Refund an item to a user (with optional price override)\n" + ); + if( giTextArgc == 0 || strcmp(gsTextArgs[0], "slot") == 0 ) + printf( + " dispense slot \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 \n" + " Create new account\n" + " dispense user type \n" + " Alter a user's flags\n" + " 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 \n" + " Dispense multiple times\n" + " -u \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 \n" + " -M \n" + " Set the Maximum/Minimum balances shown in `dispense acct`\n" + "Definitions:\n" + " \n" + " Item ID of the form : where is a non-empty string of alpha-numeric characters, and is a non-negative integer\n" +// " \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 (: 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 (: 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 2057a5d..45d1304 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 7061670..8375ab6 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 4dec980..1f813d4 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");