ARGS="--itemsfile items.cfg -p 11020"
ARGS=$ARGS" --cokeport /dev/ttyUSB0"
+if [ "x$2" != "x" ]; then
+ _cokebank=$1
+else
+ _cokebank="sqlite"
+fi
+
+rm cokebank.so
+rm cokebank.db
+
+ln -s cokebank_$_cokebank.so cokebank.so
+ln -s cokebank_$_cokebank.db cokebank.db
+
if [ "x$1" = "xdbg" ]; then
LD_LIBRARY_PATH=. gdb --args ./dispsrv $ARGS
else
general they will be limited to the standard alpha-numeric set
=== User Auth ===
+--- Untrusted Users ---
c USER <username>\n
-s 100 SALT <string>\n or 100 User Set\n (If no salt used)
+s 202 SALT <string>\n or 100 User Set\n (If no salt used)
c PASS <hash>\n (Hex-Encoded SHA-1 Hash of <username><salt><password>)
s 200 Auth OK\n or 401 Auth Failure\n
User is now authenticated
s 200 Auth OK\n or 404 Bad Username\n or 401 Untrusted\n
--- Alternate Method (MIFARE Authentication)
c MIFARE <card_id_hex>\n
-s 200 Auth OK as <username>\n or 404 Bad Card ID\n or 401 Untrusted\n
+s 200 Auth OK as <username>\n or 401 Untrusted\n or 404 Bad Card ID\n
--- Set effective user (User in `dispense -u`) ---
c SETEUSER <username>\n
=== Commands ===
--- Dispense an item ---
c DISPENSE <item_id>\n
-s 200 Dispense OK\n or 402 Poor You\n or 500 Dispense Error\n or 406 Bad Item\n
+s 200 Dispense OK\n or 402 Poor You\n or 406 Bad Item\n or 500 Dispense Error\n
--- Give to another user ---
c GIVE <user> <ammount> <reason>\n
s 200 Give OK\n or 402 Poor You\n or 404 Bad User\n
+--- Donate to the club ---
+c DONATE <ammount> <reason>\n
+s 200 Give OK\n or 402 Poor You\n
--- Alter balance ---
c ADD <user> <ammount> <reason>\n
s 200 Add OK\n or 402 No balance\n or 403 Not Coke\n or 404 Bad User\n
s 202 Item <item_id> <price> <description>\n
--- Get Users' Balances ---
- <max balance> and <min balance> can be '-' to indicate "none"
-c ENUM_USERS[ <min balance> [<max balance>]]\n
+c ENUM_USERS[ min:<balance>][ max:<balance>][ flags:<flagset>][ lastseen:<unix_timestamp>][ sort:<field>[-desc]]\n
s 201 Users <count>\n
s 202 User <username> <balance> <flags>\n
...
s 200 List End\n
+<balance> Integer balance value (in cents)
+<flagset> Flag values (same format as USER_FLAGS)
+<unix_timestamp> Number of seconds since 1/Jan/1970
+<field> Sort field (name,balance,lastseen)
--- Get a User's Balance ---
c USER_INFO\n
s 202 User <username> <balance> <flags>\n
s 200 User Added\n or 403 Not Wheel\n or 404 User Exists\n
--- Set user flags ---
<flags> is a comma-separated list of flag values (optionally preceded by
- - to remove the flag) Valid values are: user,coke,wheel,meta,disabled,door
+ - to remove the flag) Valid values are: user,coke,admin,internal,disabled,door
c USER_FLAGS <username> <flags>\n
s 200 User Updated\n or 403 Not Wheel\n or 404 Bad User\n or 407 Unknown Flags\n
--- Add MIFARE ID ---
.PHONY: all clean
all:
- @make -C cokebank all
+ @make -C cokebank_sqlite all
+ @make -C cokebank_basic all
@make -C server all
@make -C client all
clean:
- @make -C cokebank clean
+ @make -C cokebank_sqlite clean
+ @make -C cokebank_basic clean
@make -C server clean
@make -C client clean
+++ /dev/null
-cokebank_basic
\ No newline at end of file
#define COKEBANK_SALES_ACCT ">sales" //!< Sales made into
#define COKEBANK_DEBT_ACCT ">liability" //!< Credit taken out of
+#define COKEBANK_FREE_ACCT ">freeitems" //!< ODay drink costs taken out of
/**
* \brief Account iterator opaque structure
*/
enum eCokebank_Flags {
USER_FLAG_COKE = 0x01, //!< User is a coke member (can do coke accounting)
- USER_FLAG_WHEEL = 0x02, //!< User is a wheel member (can create, delete and lock accounts)
+ USER_FLAG_ADMIN = 0x02, //!< User is a administrator (can create, delete and lock accounts)
USER_FLAG_DOORGROUP = 0x04, //!< User is in the door group (can open the clubroom door)
USER_FLAG_INTERNAL = 0x40, //!< Account is internal (cannot be authenticated, no lower balance limit)
USER_FLAG_DISABLED = 0x80 //!< Account is disabled (no transactions allowed)
-BIN := ../../cokebank.so
+BIN := ../../cokebank_basic.so
OBJ := main.o
CPPFLAGS :=
// root
if( gaBank_Users[ID].UnixID == 0 ) {
- gaBank_Users[ID].Flags |= USER_FLAG_WHEEL|USER_FLAG_COKE;
+ gaBank_Users[ID].Flags |= USER_FLAG_ADMIN|USER_FLAG_COKE;
}
#if USE_UNIX_GROUPS
}
}
+ #if 0
// Check for additions to the "wheel" group
grp = getgrnam("wheel");
if( grp ) {
for( i = 0; grp->gr_mem[i]; i ++ )
{
if( strcmp(grp->gr_mem[i], pwd->pw_name) == 0 ) {
- gaBank_Users[ID].Flags |= USER_FLAG_WHEEL;
+ gaBank_Users[ID].Flags |= USER_FLAG_ADMIN;
break ;
}
}
}
+ #endif
}
#endif
return INT_MIN;
// Wheel is allowed to go to -$100
- if( (flags & USER_FLAG_WHEEL) )
+ if( (flags & USER_FLAG_ADMIN) )
return -10000;
// Coke is allowed to go to -$20
gaBank_Users[giBank_NumUsers].Flags = USER_FLAG_INTERNAL;
}
else if( strcmp(Username, "root") == 0 ) {
- gaBank_Users[giBank_NumUsers].Flags = USER_FLAG_WHEEL|USER_FLAG_COKE;
+ gaBank_Users[giBank_NumUsers].Flags = USER_FLAG_ADMIN|USER_FLAG_COKE;
}
// Increment count
#include "../cokebank.h"
#include <sqlite3.h>
-const char * const csBank_CreateAccountQry = "CREATE TABLE IF NOT EXISTS accounts ("
+const char * const csBank_DatabaseSetup =
+"CREATE TABLE IF NOT EXISTS accounts ("
" acct_id INTEGER PRIMARY KEY NOT NULL,"
" acct_balance INTEGER NOT NULL DEFAULT 0,"
+" acct_last_seen DATETIME NOT NULL DEFAULT (datetime('now')),"
" acct_name STRING UNIQUE,"
" acct_uid INTEGER UNIQUE DEFAULT NULL,"
-" acct_pin INTEGER CHECK (acct_pin > 0 AND acct_pin < 10000) DEFAULT NULL,"
+" acct_pin INTEGER DEFAULT NULL," //" acct_pin INTEGER CHECK (acct_pin > 0 AND acct_pin < 10000) DEFAULT NULL,"
" acct_is_disabled BOOLEAN NOT NULL DEFAULT false,"
" acct_is_coke BOOLEAN NOT NULL DEFAULT false,"
-" acct_is_wheel BOOLEAN NOT NULL DEFAULT false,"
+" acct_is_admin BOOLEAN NOT NULL DEFAULT false,"
" acct_is_door BOOLEAN NOT NULL DEFAULT false,"
" acct_is_internal BOOLEAN NOT NULL DEFAULT false"
-")";
-const char * const csBank_CreateCardsQry = "CREATE TABLE IF NOT EXISTS cards ("
+");"
+"CREATE TABLE IF NOT EXISTS cards ("
" acct_id INTEGER NOT NULL,"
" card_name STRING NOT NULL UNIQUE,"
" FOREIGN KEY (acct_id) REFERENCES accounts (acct_id) ON DELETE CASCADE"
// Deletion of the account frees the card ^ ^ ^
-")";
+");"
+"INSERT INTO accounts (acct_name,acct_is_admin,acct_uid) VALUES ('root',1,0);"
+"INSERT INTO accounts (acct_name,acct_is_internal,acct_uid) VALUES ('"COKEBANK_SALES_ACCT"',1,-1);"
+"INSERT INTO accounts (acct_name,acct_is_internal,acct_uid) VALUES ('"COKEBANK_DEBT_ACCT"',1,-2);"
+"INSERT INTO accounts (acct_name,acct_is_internal,acct_uid) VALUES ('"COKEBANK_FREE_ACCT"',1,-3);"
+;
// === TYPES ===
struct sAcctIterator // Unused really, just used as a void type
// === PROTOYPES ===
int Bank_Initialise(const char *Argument);
int Bank_Transfer(int SourceAcct, int DestAcct, int Ammount, const char *Reason);
- int Bank_GetUserFlags(int AcctID);
- int Bank_SetUserFlags(int AcctID, int Mask, int Value);
+ int Bank_GetFlags(int AcctID);
+ int Bank_SetFlags(int AcctID, int Mask, int Value);
int Bank_GetBalance(int AcctID);
char *Bank_GetAcctName(int AcctID);
sqlite3_stmt *Bank_int_MakeStatemnt(sqlite3 *Database, const char *Query);
{
// NOP
}
- else if( rv == SQLITE_NOTFOUND )
+ else if( rv == SQLITE_NOTFOUND || rv == SQLITE_ERROR )
{
sqlite3_free(errmsg);
// Create tables
- // - Accounts
- rv = sqlite3_exec(gBank_Database, csBank_CreateAccountQry, NULL, NULL, &errmsg);
+ rv = sqlite3_exec(gBank_Database, csBank_DatabaseSetup, NULL, NULL, &errmsg);
if( rv != SQLITE_OK ) {
- fprintf(stderr, "SQLite Error: %s\n", errmsg);
- sqlite3_free(errmsg);
- return 1;
- }
- // - Mifare relation
- rv = sqlite3_exec(gBank_Database, csBank_CreateCardsQry, NULL, NULL, &errmsg);
- if( rv != SQLITE_OK ) {
- fprintf(stderr, "SQLite Error: %s\n", errmsg);
+ fprintf(stderr, "Bank_Initialise - SQLite Error: %s\n", errmsg);
sqlite3_free(errmsg);
return 1;
}
else
{
// Unknown error
- fprintf(stderr, "SQLite Error: %s\n", errmsg);
+ fprintf(stderr, "Bank_Initialise - SQLite Error: %s (rv = %i)\n", errmsg, rv);
sqlite3_free(errmsg);
return 1;
}
sqlite3_exec(gBank_Database, "BEGIN TRANSACTION", NULL, NULL, NULL);
// Take from the source
- query = mkstr("UPDATE accounts SET acct_balance=acct_balance-%i WHERE acct_id=%i", Ammount, SourceUser);
+ query = mkstr("UPDATE accounts SET acct_balance=acct_balance-%i,acct_last_seen=datetime('now') WHERE acct_id=%i", Ammount, SourceUser);
+ printf("query = \"%s\"\n", query);
rv = sqlite3_exec(gBank_Database, query, NULL, NULL, &errmsg);
free(query);
if( rv != SQLITE_OK )
{
- fprintf(stderr, "SQLite Error: %s\n", errmsg);
+ fprintf(stderr, "Bank_Transfer - SQLite Error: %s\n", errmsg);
sqlite3_free(errmsg);
sqlite3_exec(gBank_Database, "ROLLBACK", NULL, NULL, NULL);
return 1;
}
// Give to the destination
- query = mkstr("UPDATE accounts SET acct_balance=acct_balance+%i WHERE acct_id=%i", Ammount, DestUser);
+ query = mkstr("UPDATE accounts SET acct_balance=acct_balance+%i,acct_last_seen=datetime('now') WHERE acct_id=%i", Ammount, DestUser);
+ printf("query = \"%s\"\n", query);
rv = sqlite3_exec(gBank_Database, query, NULL, NULL, &errmsg);
free(query);
if( rv != SQLITE_OK )
{
- fprintf(stderr, "SQLite Error: %s\n", errmsg);
+ fprintf(stderr, "Bank_Transfer - SQLite Error: %s\n", errmsg);
sqlite3_free(errmsg);
sqlite3_exec(gBank_Database, "ROLLBACK", NULL, NULL, NULL);
return 1;
/*
* Get user flags
*/
-int Bank_GetUserFlags(int UserID)
+int Bank_GetFlags(int UserID)
{
sqlite3_stmt *statement;
char *query;
// - Coke
if( sqlite3_column_int(statement, 1) ) ret |= USER_FLAG_COKE;
// - Wheel
- if( sqlite3_column_int(statement, 2) ) ret |= USER_FLAG_WHEEL;
+ if( sqlite3_column_int(statement, 2) ) ret |= USER_FLAG_ADMIN;
// - Door
if( sqlite3_column_int(statement, 3) ) ret |= USER_FLAG_DOORGROUP;
// - Internal
- if( sqlite3_column_int(statement, 3) ) ret |= USER_FLAG_INTERNAL;
+ if( sqlite3_column_int(statement, 4) ) ret |= USER_FLAG_INTERNAL;
// Destroy and return
sqlite3_finalize(statement);
/*
* Set user flags
*/
-int Bank_SetUserFlags(int UserID, int Mask, int Value)
+int Bank_SetFlags(int UserID, int Mask, int Value)
{
char *query;
int rv;
#define MAP_FLAG(name, flag) (Mask&(flag)?(Value&(flag)?","name"=1":","name"=0"):"")
query = mkstr(
- "UDPATE accounts WHERE acct_id=%i SET acct_id=acct_id%s%s%s%s%s",
- UserID,
+ "UPDATE accounts SET acct_id=acct_id%s%s%s%s%s WHERE acct_id=%i",// LIMIT 1",
MAP_FLAG("acct_is_coke", USER_FLAG_COKE),
- MAP_FLAG("acct_is_wheel", USER_FLAG_WHEEL),
+ MAP_FLAG("acct_is_admin", USER_FLAG_ADMIN),
MAP_FLAG("acct_is_door", USER_FLAG_DOORGROUP),
MAP_FLAG("acct_is_internal", USER_FLAG_INTERNAL),
- MAP_FLAG("acct_is_disabled", USER_FLAG_DISABLED)
+ MAP_FLAG("acct_is_disabled", USER_FLAG_DISABLED),
+ UserID
);
#undef MAP_FLAG
// Execute Query
rv = sqlite3_exec(gBank_Database, query, NULL, NULL, &errmsg);
- free(query);
if( rv != SQLITE_OK )
{
- fprintf(stderr, "SQLite Error: %s\n", errmsg);
+ fprintf(stderr, "Bank_SetUserFlags - SQLite Error: %s\n", errmsg);
+ fprintf(stderr, "query = '%s'\n", query);
+ free(query);
sqlite3_free(errmsg);
return -1;
}
+ free(query);
return 0;
}
if( !statement ) return -1;
ret = sqlite3_column_int(statement, 0);
+ if( ret == 0 ) return -1;
sqlite3_finalize(statement);
return ret;
rv = sqlite3_exec(gBank_Database, query, NULL, NULL, &errmsg);
if( rv != SQLITE_OK )
{
- fprintf(stderr, "SQLite Error: '%s'\n", errmsg);
+ fprintf(stderr, "Bank_CreateAcct - SQLite Error: '%s'\n", errmsg);
fprintf(stderr, "Query = '%s'\n", query);
sqlite3_free(errmsg);
free(query);
sqlite3_stmt *ret;
if( Flags & BANK_ITFLAG_MINBALANCE )
- balanceClause = "acct_balance>=";
+ balanceClause = " AND acct_balance>=";
else if( Flags & BANK_ITFLAG_MAXBALANCE )
- balanceClause = "acct_balance<=";
+ balanceClause = " AND acct_balance<=";
else {
- balanceClause = "1!=";
+ balanceClause = " AND 1!=";
MinMaxBalance = 0;
}
if( Flags & BANK_ITFLAG_SEENAFTER )
- lastSeenClause = "acct_last_seen>=";
+ lastSeenClause = " AND acct_last_seen>=";
else if( Flags & BANK_ITFLAG_SEENBEFORE )
- lastSeenClause = "acct_last_seen<=";
+ lastSeenClause = " AND acct_last_seen<=";
else {
- lastSeenClause = "datetime(0,'unixepoch')!=";
+ lastSeenClause = " AND datetime(-1,'unixepoch')!=";
}
switch( Flags & BANK_ITFLAG_SORTMASK )
"%s%s" // Sort and direction
,
MAP_FLAG("acct_is_coke", USER_FLAG_COKE),
- MAP_FLAG("acct_is_wheel", USER_FLAG_WHEEL),
+ MAP_FLAG("acct_is_admin", USER_FLAG_ADMIN),
MAP_FLAG("acct_is_door", USER_FLAG_DOORGROUP),
MAP_FLAG("acct_is_internal", USER_FLAG_INTERNAL),
MAP_FLAG("acct_is_disabled", USER_FLAG_DISABLED),
lastSeenClause, LastSeen,
orderClause, revSort
);
+ //printf("query = \"%s\"\n", query);
#undef MAP_FLAG
ret = Bank_int_MakeStatemnt(gBank_Database, query);
if( rv == SQLITE_DONE ) return -1;
if( rv != SQLITE_ROW ) {
- fprintf(stderr, "SQLite Error: %s\n", sqlite3_errmsg(gBank_Database));
+ fprintf(stderr, "Bank_IteratorNext - SQLite Error: %s\n", sqlite3_errmsg(gBank_Database));
return -1;
}
}
if( rv != SQLITE_OK )
{
- fprintf(stderr, "SQLite Error: '%s'\n", errmsg);
+ fprintf(stderr, "Bank_AddAcctCard - SQLite Error: '%s'\n", errmsg);
fprintf(stderr, "Query = '%s'\n", query);
sqlite3_free(errmsg);
free(query);
// --- Dispense ---
extern int DispenseItem(int ActualUser, int User, tItem *Item);
extern int DispenseGive(int ActualUser, int SrcUser, int DestUser, int Ammount, const char *ReasonGiven);
-extern int DispenseAdd(int User, int ByUser, int Ammount, const char *ReasonGiven);
+extern int DispenseAdd(int ActualUser, int User, int Ammount, const char *ReasonGiven);
+extern int DispenseDonate(int ActualUser, int User, int Ammount, const char *ReasonGiven);
// --- Logging ---
extern void Log_Error(const char *Format, ...);
*/
#include "common.h"
#include <stdlib.h>
+#include <limits.h>
+
+ int _GetMinBalance(int Account);
+ int _Transfer(int Source, int Destination, int Ammount, const char *Reason);
// === CODE ===
/**
// Subtract the balance
reason = mkstr("Dispense - %s:%i %s", handler->Name, Item->ID, Item->Name);
if( !reason ) reason = Item->Name; // TODO: Should I instead return an error?
- ret = Bank_Transfer( User, Bank_GetAcctByName(COKEBANK_SALES_ACCT), Item->Price, reason);
+ ret = _Transfer( User, Bank_GetAcctByName(COKEBANK_SALES_ACCT), Item->Price, reason);
free(reason);
if(ret) return 2; // 2: No balance
if(ret) {
Log_Error("Dispense failed after deducting cost (%s dispensing %s - %ic)",
username, Item->Name, Item->Price);
- Bank_Transfer( Bank_GetAcctByName(COKEBANK_SALES_ACCT), User, Item->Price, "rollback" );
+ _Transfer( Bank_GetAcctByName(COKEBANK_SALES_ACCT), User, Item->Price, "rollback" );
free( username );
return -1; // 1: Unkown Error again
}
actualUsername = Bank_GetAcctName(ActualUser);
// And log that it happened
- Log_Info("dispense '%s' (%s:%i) for %s by %s [cost %i, balance %i cents]",
+ Log_Info("dispense '%s' (%s:%i) for %s by %s [cost %i, balance %i]",
Item->Name, handler->Name, Item->ID,
username, actualUsername, Item->Price, Bank_GetBalance(User)
);
if( Ammount < 0 ) return 1; // Um... negative give? Not on my watch!
- ret = Bank_Transfer( SrcUser, DestUser, Ammount, ReasonGiven );
+ ret = _Transfer( SrcUser, DestUser, Ammount, ReasonGiven );
if(ret) return 2; // No Balance
+ actualUsername = Bank_GetAcctName(ActualUser);
srcName = Bank_GetAcctName(SrcUser);
dstName = Bank_GetAcctName(DestUser);
- actualUsername = Bank_GetAcctName(ActualUser);
- Log_Info("give %i to %s from %s by %s (%s) [balances %i, %i]",
- Ammount, dstName, srcName, actualUsername, ReasonGiven,
- Bank_GetBalance(SrcUser), Bank_GetBalance(DestUser)
+ Log_Info("give %i to %s from %s by %s [balances %i, %i] - %s",
+ Ammount, dstName, srcName, actualUsername,
+ Bank_GetBalance(SrcUser), Bank_GetBalance(DestUser),
+ ReasonGiven
);
free(srcName);
/**
* \brief Add money to an account
*/
-int DispenseAdd(int User, int ByUser, int Ammount, const char *ReasonGiven)
+int DispenseAdd(int ActualUser, int User, int Ammount, const char *ReasonGiven)
{
int ret;
char *dstName, *byName;
- ret = Bank_Transfer( Bank_GetAcctByName(COKEBANK_DEBT_ACCT), User, Ammount, ReasonGiven );
+ ret = _Transfer( Bank_GetAcctByName(COKEBANK_DEBT_ACCT), User, Ammount, ReasonGiven );
if(ret) return 2;
- byName = Bank_GetAcctName(ByUser);
+ byName = Bank_GetAcctName(ActualUser);
dstName = Bank_GetAcctName(User);
- Log_Info("add %i to %s by %s (%s) [balance %i]",
- Ammount, dstName, byName, ReasonGiven, Bank_GetBalance(User)
+ Log_Info("add %i to %s by %s [balance %i] - %s",
+ Ammount, dstName, byName, Bank_GetBalance(User), ReasonGiven
);
free(byName);
return 0;
}
+
+/**
+ * \brief Donate money to the club
+ */
+int DispenseDonate(int ActualUser, int User, int Ammount, const char *ReasonGiven)
+{
+ int ret;
+ char *srcName, *byName;
+
+ if( Ammount < 0 ) return 2;
+
+ ret = _Transfer( User, Bank_GetAcctByName(COKEBANK_DEBT_ACCT), Ammount, ReasonGiven );
+ if(ret) return 2;
+
+ byName = Bank_GetAcctName(ActualUser);
+ srcName = Bank_GetAcctName(User);
+
+ Log_Info("donate %i from %s by %s [balance %i] - %s",
+ Ammount, srcName, byName, Bank_GetBalance(User), ReasonGiven
+ );
+
+ free(byName);
+ free(srcName);
+
+ return 0;
+}
+
+// --- Internal Functions ---
+int _GetMinBalance(int Account)
+{
+ int flags = Bank_GetFlags(Account);
+
+ // - Internal accounts have no lower bound
+ if( flags & USER_FLAG_INTERNAL ) return INT_MIN;
+
+ // Admin to -$10
+ if( flags & USER_FLAG_ADMIN ) return -1000;
+
+ // Coke to -$10
+ if( flags & USER_FLAG_COKE ) return -500;
+
+ // Anyone else, non-negative
+ return 0;
+}
+
+int _Transfer(int Source, int Destination, int Ammount, const char *Reason)
+{
+ if( Ammount < 0 )
+ {
+ if( Bank_GetBalance(Source) + Ammount < _GetMinBalance(Source) )
+ return 1;
+ }
+ else
+ {
+ if( Bank_GetBalance(Destination) - Ammount < _GetMinBalance(Destination) )
+ return 1;
+ }
+
+ return Bank_Transfer(Source, Destination, Ammount, Reason);
+}
void Server_Cmd_USERADD(tClient *Client, char *Args);
void Server_Cmd_USERFLAGS(tClient *Client, char *Args);
// --- Helpers ---
+ int Server_int_ParseFlags(tClient *Client, const char *Str, int *Mask, int *Value);
int sendf(int Socket, const char *Format, ...);
// === CONSTANTS ===
}
}
+void Server_Cmd_DONATE(tClient *Client, char *Args)
+{
+ char *ammount, *reason;
+ int iAmmount;
+ int thisUid;
+
+ if( !Client->bIsAuthed ) {
+ sendf(Client->Socket, "401 Not Authenticated\n");
+ return ;
+ }
+
+ ammount = Args;
+
+ // Get the start of the reason
+ reason = strchr(Args, ' ');
+ if( !ammount ) {
+ sendf(Client->Socket, "407 Invalid Argument, expected 2 parameters, 1 encountered\n");
+ return ;
+ }
+ *reason = '\0';
+ reason ++;
+
+ // Check the end of the reason
+ if( strchr(reason, ' ') ) {
+ sendf(Client->Socket, "407 Invalid Argument, expected 2 parameters, more encountered\n");
+ return ;
+ }
+
+ // Parse ammount
+ iAmmount = atoi(ammount);
+ if( iAmmount <= 0 ) {
+ sendf(Client->Socket, "407 Invalid Argument, ammount must be > zero\n");
+ return ;
+ }
+
+ // Handle effective users
+ if( Client->EffectiveUID != -1 ) {
+ thisUid = Client->EffectiveUID;
+ }
+ else {
+ thisUid = Client->UID;
+ }
+
+ // Do give
+ switch( DispenseDonate(Client->UID, thisUid, iAmmount, reason) )
+ {
+ case 0:
+ sendf(Client->Socket, "200 Give OK\n");
+ return ;
+ case 2:
+ sendf(Client->Socket, "402 Poor You\n");
+ return ;
+ default:
+ sendf(Client->Socket, "500 Unknown error\n");
+ return ;
+ }
+}
+
void Server_Cmd_ADD(tClient *Client, char *Args)
{
char *user, *ammount, *reason;
}
// Do give
- switch( DispenseAdd(uid, Client->UID, iAmmount, reason) )
+ switch( DispenseAdd(Client->UID, uid, iAmmount, reason) )
{
case 0:
sendf(Client->Socket, "200 Add OK\n");
type = "internal";
}
else if( flags & USER_FLAG_COKE ) {
- if( flags & USER_FLAG_WHEEL )
- type = "coke,wheel";
+ if( flags & USER_FLAG_ADMIN )
+ type = "coke,admin";
else
type = "coke";
}
- else if( flags & USER_FLAG_WHEEL ) {
- type = "wheel";
+ else if( flags & USER_FLAG_ADMIN ) {
+ type = "admin";
}
else {
type = "user";
char *username, *space;
// Check permissions
- if( !(Bank_GetFlags(Client->UID) & USER_FLAG_WHEEL) ) {
- sendf(Client->Socket, "403 Not Wheel\n");
+ if( !(Bank_GetFlags(Client->UID) & USER_FLAG_ADMIN) ) {
+ sendf(Client->Socket, "403 Not a coke admin\n");
return ;
}
int uid;
// Check permissions
- if( !(Bank_GetFlags(Client->UID) & USER_FLAG_WHEEL) ) {
- sendf(Client->Socket, "403 Not Wheel\n");
+ if( !(Bank_GetFlags(Client->UID) & USER_FLAG_ADMIN) ) {
+ sendf(Client->Socket, "403 Not a coke admin\n");
return ;
}
}
// Parse flags
- do {
- int bRemove = 0;
- int i;
- struct {
- const char *Name;
- int Mask;
- int Value;
- } cFLAGS[] = {
- {"disabled", USER_FLAG_DISABLED, USER_FLAG_DISABLED}
- ,{"door", USER_FLAG_DOORGROUP, USER_FLAG_DOORGROUP}
- ,{"coke", USER_FLAG_COKE, USER_FLAG_COKE}
- ,{"wheel", USER_FLAG_WHEEL, USER_FLAG_WHEEL}
- // ,{"internal", USER_FLAG_INTERNAL, USER_FLAG_INTERNAL}
- };
- const int ciNumFlags = sizeof(cFLAGS)/sizeof(cFLAGS[0]);
-
- while( *flags == ' ' ) flags ++; // Eat whitespace
- space = strchr(flags, ','); // Find the end of the flag
- if(space) *space = '\0';
-
- // Check for inversion/removal
- if( *flags == '!' || *flags == '-' ) {
- bRemove = 1;
- flags ++;
- }
- else if( *flags == '+' ) {
- flags ++;
- }
-
- // Check flag values
- for( i = 0; i < ciNumFlags; i ++ )
- {
- if( strcmp(flags, cFLAGS[i].Name) == 0 ) {
- mask |= cFLAGS[i].Mask;
- value &= ~cFLAGS[i].Mask;
- if( !bRemove )
- value |= cFLAGS[i].Value;
- break;
- }
- }
-
- // Error check
- if( i == ciNumFlags ) {
- sendf(Client->Socket, "407 Unknown flag value '%s'\n", flags);
- return ;
- }
-
- flags = space + 1;
- } while(space);
+ if( Server_int_ParseFlags(Client, flags, &mask, &value) )
+ return ;
// Apply flags
Bank_SetFlags(uid, mask, value);
return send(Socket, buf, len, 0);
}
}
+
+int Server_int_ParseFlags(tClient *Client, const char *Str, int *Mask, int *Value)
+{
+ struct {
+ const char *Name;
+ int Mask;
+ int Value;
+ } cFLAGS[] = {
+ {"disabled", USER_FLAG_DISABLED, USER_FLAG_DISABLED}
+ ,{"door", USER_FLAG_DOORGROUP, USER_FLAG_DOORGROUP}
+ ,{"coke", USER_FLAG_COKE, USER_FLAG_COKE}
+ ,{"admin", USER_FLAG_ADMIN, USER_FLAG_ADMIN}
+ ,{"internal", USER_FLAG_INTERNAL, USER_FLAG_INTERNAL}
+ };
+ const int ciNumFlags = sizeof(cFLAGS)/sizeof(cFLAGS[0]);
+
+ char *space;
+
+ *Mask = 0;
+ *Value = 0;
+
+ do {
+ int bRemove = 0;
+ int i;
+ int len;
+
+ while( *Str == ' ' ) Str ++; // Eat whitespace
+ space = strchr(Str, ','); // Find the end of the flag
+ if(space)
+ len = space - Str;
+ else
+ len = strlen(Str);
+
+ // Check for inversion/removal
+ if( *Str == '!' || *Str == '-' ) {
+ bRemove = 1;
+ Str ++;
+ }
+ else if( *Str == '+' ) {
+ Str ++;
+ }
+
+ // Check flag values
+ for( i = 0; i < ciNumFlags; i ++ )
+ {
+ if( strncmp(Str, cFLAGS[i].Name, len) == 0 ) {
+ *Mask |= cFLAGS[i].Mask;
+ *Value &= ~cFLAGS[i].Mask;
+ if( !bRemove )
+ *Value |= cFLAGS[i].Value;
+ break;
+ }
+ }
+
+ // Error check
+ if( i == ciNumFlags ) {
+ char val[len+1];
+ strncpy(val, Str, len+1);
+ sendf(Client->Socket, "407 Unknown flag value '%s'\n", val);
+ return -1;
+ }
+
+ Str = space + 1;
+ } while(space);
+
+ return 0;
+}