Fixing crappy code in coke handler, debug in others
[tpg/opendispense2.git] / src / server / server.c
index 0b9005d..315b129 100644 (file)
@@ -59,13 +59,16 @@ void        Server_Cmd_ENUMITEMS(tClient *Client, char *Args);
 void   Server_Cmd_ITEMINFO(tClient *Client, char *Args);
 void   Server_Cmd_DISPENSE(tClient *Client, char *Args);
 void   Server_Cmd_GIVE(tClient *Client, char *Args);
+void   Server_Cmd_DONATE(tClient *Client, char *Args);
 void   Server_Cmd_ADD(tClient *Client, char *Args);
+void   Server_Cmd_SET(tClient *Client, char *Args);
 void   Server_Cmd_ENUMUSERS(tClient *Client, char *Args);
 void   Server_Cmd_USERINFO(tClient *Client, char *Args);
 void   _SendUserInfo(tClient *Client, int UserID);
 void   Server_Cmd_USERADD(tClient *Client, char *Args);
 void   Server_Cmd_USERFLAGS(tClient *Client, char *Args);
 // --- Helpers ---
+void   Debug(tClient *Client, const char *Format, ...);
  int   Server_int_ParseFlags(tClient *Client, const char *Str, int *Mask, int *Value);
  int   sendf(int Socket, const char *Format, ...);
 
@@ -83,7 +86,9 @@ const struct sClientCommand {
        {"ITEM_INFO", Server_Cmd_ITEMINFO},
        {"DISPENSE", Server_Cmd_DISPENSE},
        {"GIVE", Server_Cmd_GIVE},
+       {"DONATE", Server_Cmd_DONATE},
        {"ADD", Server_Cmd_ADD},
+       {"SET", Server_Cmd_SET},
        {"ENUM_USERS", Server_Cmd_ENUMUSERS},
        {"USER_INFO", Server_Cmd_USERINFO},
        {"USER_ADD", Server_Cmd_USERADD},
@@ -141,12 +146,14 @@ void Server_Start(void)
                uint    len = sizeof(client_addr);
                 int    bTrusted = 0;
                
+               // Accept a connection
                client_socket = accept(giServer_Socket, (struct sockaddr *) &client_addr, &len);
                if(client_socket < 0) {
                        fprintf(stderr, "ERROR: Unable to accept client connection\n");
                        return ;
                }
                
+               // Debug: Print the connection string
                if(giDebugLevel >= 2) {
                        char    ipstr[INET_ADDRSTRLEN];
                        inet_ntop(AF_INET, &client_addr.sin_addr, ipstr, INET_ADDRSTRLEN);
@@ -154,6 +161,10 @@ void Server_Start(void)
                                ipstr, ntohs(client_addr.sin_port));
                }
                
+               // Doesn't matter what, localhost is trusted
+               if( ntohl( client_addr.sin_addr.s_addr ) == 0x7F000001 )
+                       bTrusted = 1;
+               
                // Trusted Connections
                if( ntohs(client_addr.sin_port) < 1024 )
                {
@@ -162,6 +173,7 @@ void Server_Start(void)
                        {
                        case 0x7F000001:        // 127.0.0.1    localhost
                        //case 0x825E0D00:      // 130.95.13.0
+                       case 0x825E0D07:        // 130.95.13.7  motsugo
                        case 0x825E0D12:        // 130.95.13.18 mussel
                        case 0x825E0D17:        // 130.95.13.23 martello
                                bTrusted = 1;
@@ -203,6 +215,7 @@ void Server_HandleClient(int Socket, int bTrusted)
        clientInfo.Socket = Socket;
        clientInfo.ID = giServer_NextClientID ++;
        clientInfo.bIsTrusted = bTrusted;
+       clientInfo.EffectiveUID = -1;
        
        // Read from client
        /*
@@ -329,7 +342,7 @@ void Server_Cmd_USER(tClient *Client, char *Args)
        
        // Debug!
        if( giDebugLevel )
-               printf("Client %i authenticating as '%s'\n", Client->ID, Args);
+               Debug(Client, "Authenticating as '%s'", Args);
        
        // Save username
        if(Client->Username)
@@ -390,7 +403,7 @@ void Server_Cmd_AUTOAUTH(tClient *Client, char *Args)
        // Check if trusted
        if( !Client->bIsTrusted ) {
                if(giDebugLevel)
-                       printf("Client %i: Untrusted client attempting to AUTOAUTH\n", Client->ID);
+                       Debug(Client, "Untrusted client attempting to AUTOAUTH");
                sendf(Client->Socket, "401 Untrusted\n");
                return ;
        }
@@ -399,7 +412,7 @@ void Server_Cmd_AUTOAUTH(tClient *Client, char *Args)
        Client->UID = Bank_GetAcctByName( Args );       
        if( Client->UID < 0 ) {
                if(giDebugLevel)
-                       printf("Client %i: Unknown user '%s'\n", Client->ID, Args);
+                       Debug(Client, "Unknown user '%s'", Args);
                sendf(Client->Socket, "401 Auth Failure\n");
                return ;
        }
@@ -410,9 +423,11 @@ void Server_Cmd_AUTOAUTH(tClient *Client, char *Args)
                sendf(Client->Socket, "401 Auth Failure\n");
                return ;
        }
+
+       Client->bIsAuthed = 1;
        
        if(giDebugLevel)
-               printf("Client %i: Authenticated as '%s' (%i)\n", Client->ID, Args, Client->UID);
+               Debug(Client, "Auto authenticated as '%s' (%i)", Args, Client->UID);
        
        sendf(Client->Socket, "200 Auth OK\n");
 }
@@ -434,7 +449,7 @@ void Server_Cmd_SETEUSER(tClient *Client, char *Args)
        }
 
        // Check user permissions
-       if( !(Bank_GetFlags(Client->UID) & USER_FLAG_COKE) ) {
+       if( !(Bank_GetFlags(Client->UID) & (USER_FLAG_COKE|USER_FLAG_ADMIN)) ) {
                sendf(Client->Socket, "403 Not in coke\n");
                return ;
        }
@@ -728,7 +743,7 @@ void Server_Cmd_ADD(tClient *Client, char *Args)
        reason ++;
 
        // Check user permissions
-       if( !(Bank_GetFlags(Client->UID) & USER_FLAG_COKE)  ) {
+       if( !(Bank_GetFlags(Client->UID) & (USER_FLAG_COKE|USER_FLAG_ADMIN))  ) {
                sendf(Client->Socket, "403 Not in coke\n");
                return ;
        }
@@ -768,39 +783,205 @@ void Server_Cmd_ADD(tClient *Client, char *Args)
        }
 }
 
+void Server_Cmd_SET(tClient *Client, char *Args)
+{
+       char    *user, *ammount, *reason;
+        int    uid, iAmmount;
+       
+       if( !Client->bIsAuthed ) {
+               sendf(Client->Socket, "401 Not Authenticated\n");
+               return ;
+       }
+
+       user = Args;
+
+       ammount = strchr(Args, ' ');
+       if( !ammount ) {
+               sendf(Client->Socket, "407 Invalid Argument, expected 3 parameters, 1 encountered\n");
+               return ;
+       }
+       *ammount = '\0';
+       ammount ++;
+
+       reason = strchr(ammount, ' ');
+       if( !reason ) {
+               sendf(Client->Socket, "407 Invalid Argument, expected 3 parameters, 2 encountered\n");
+               return ;
+       }
+       *reason = '\0';
+       reason ++;
+
+       // Check user permissions
+       if( !(Bank_GetFlags(Client->UID) & USER_FLAG_ADMIN)  ) {
+               sendf(Client->Socket, "403 Not an admin\n");
+               return ;
+       }
+
+       // Get recipient
+       uid = Bank_GetAcctByName(user);
+       if( uid == -1 ) {
+               sendf(Client->Socket, "404 Invalid user\n");
+               return ;
+       }
+       
+       // You can't alter an internal account
+       if( Bank_GetFlags(uid) & USER_FLAG_INTERNAL ) {
+               sendf(Client->Socket, "404 Invalid user\n");
+               return ;
+       }
+
+       // Parse ammount
+       iAmmount = atoi(ammount);
+       if( iAmmount == 0 && ammount[0] != '0' ) {
+               sendf(Client->Socket, "407 Invalid Argument\n");
+               return ;
+       }
+
+       // Do give
+       switch( DispenseSet(Client->UID, uid, iAmmount, reason) )
+       {
+       case 0:
+               sendf(Client->Socket, "200 Add OK\n");
+               return ;
+       case 2:
+               sendf(Client->Socket, "402 Poor Guy\n");
+               return ;
+       default:
+               sendf(Client->Socket, "500 Unknown error\n");
+               return ;
+       }
+}
+
 void Server_Cmd_ENUMUSERS(tClient *Client, char *Args)
 {
         int    i, numRet = 0;
-        int    maxBal = INT_MAX, minBal = INT_MIN;
        tAcctIterator   *it;
+        int    maxBal = INT_MAX, minBal = INT_MIN;
+        int    flagMask = 0, flagVal = 0;
         int    sort = BANK_ITFLAG_SORT_NAME;
+       time_t  lastSeenAfter=0, lastSeenBefore=0;
+       
+        int    flags;  // Iterator flags
+        int    balValue;       // Balance value for iterator
+       time_t  timeValue;      // Time value for iterator
        
        // Parse arguments
        if( Args && strlen(Args) )
        {
-               char    *min = Args, *max;
-               
-               max = strchr(Args, ' ');
-               if( max ) {
-                       *max = '\0';
-                       max ++;
-               }
-               
-               // If <minBal> != "-"
-               if( strcmp(min, "-") != 0 )
-                       minBal = atoi(min);
-               // If <maxBal> != "-"
-               if( max && strcmp(max, "-") != 0 )
-                       maxBal = atoi(max);
+               char    *space = Args, *type, *val;
+               do
+               {
+                       type = space;
+                       // Get next space
+                       space = strchr(space, ' ');
+                       if(space)       *space = '\0';
+                       
+                       // Get type
+                       val = strchr(type, ':');
+                       if( val ) {
+                               *val = '\0';
+                               val ++;
+                               
+                               // Types
+                               // - Minium Balance
+                               if( strcmp(type, "min_balance") == 0 ) {
+                                       minBal = atoi(val);
+                               }
+                               // - Maximum Balance
+                               else if( strcmp(type, "max_balance") == 0 ) {
+                                       maxBal = atoi(val);
+                               }
+                               // - Flags
+                               else if( strcmp(type, "flags") == 0 ) {
+                                       if( Server_int_ParseFlags(Client, val, &flagMask, &flagVal) )
+                                               return ;
+                               }
+                               // - Last seen before timestamp
+                               else if( strcmp(type, "last_seen_before") == 0 ) {
+                                       lastSeenAfter = atoll(val);
+                               }
+                               // - Last seen after timestamp
+                               else if( strcmp(type, "last_seen_after") == 0 ) {
+                                       lastSeenAfter = atoll(val);
+                               }
+                               // - Sorting 
+                               else if( strcmp(type, "sort") == 0 ) {
+                                       char    *dash = strchr(val, '-');
+                                       if( dash ) {
+                                               *dash = '\0';
+                                               dash ++;
+                                       }
+                                       if( strcmp(val, "name") == 0 ) {
+                                               sort = BANK_ITFLAG_SORT_NAME;
+                                       }
+                                       else if( strcmp(val, "balance") == 0 ) {
+                                               sort = BANK_ITFLAG_SORT_BAL;
+                                       }
+                                       else if( strcmp(val, "lastseen") == 0 ) {
+                                               sort = BANK_ITFLAG_SORT_LASTSEEN;
+                                       }
+                                       else {
+                                               sendf(Client->Socket, "407 Unknown sort field ('%s')\n", val);
+                                               return ;
+                                       }
+                                       // Handle sort direction
+                                       if( dash ) {
+                                               if( strcmp(dash, "desc") == 0 ) {
+                                                       sort |= BANK_ITFLAG_REVSORT;
+                                               }
+                                               else {
+                                                       sendf(Client->Socket, "407 Unknown sort direction '%s'\n", dash);
+                                                       return ;
+                                               }
+                                               dash[-1] = '-';
+                                       }
+                               }
+                               else {
+                                       sendf(Client->Socket, "407 Unknown argument to ENUM_USERS '%s:%s'\n", type, val);
+                                       return ;
+                               }
+                               
+                               val[-1] = ':';
+                       }
+                       else {
+                               sendf(Client->Socket, "407 Unknown argument to ENUM_USERS '%s'\n", type);
+                               return ;
+                       }
+                       
+                       // Eat whitespace
+                       if( space ) {
+                               *space = ' ';   // Repair (to be nice)
+                               space ++;
+                               while(*space == ' ')    space ++;
+                       }
+               }       while(space);
        }
        
        // Create iterator
-       if( maxBal != INT_MAX )
-               it = Bank_Iterator(0, 0, sort|BANK_ITFLAG_MAXBALANCE, maxBal, 0);
-       else if( minBal != INT_MIN )
-               it = Bank_Iterator(0, 0, sort|BANK_ITFLAG_MINBALANCE, minBal, 0);
-       else
-               it = Bank_Iterator(0, 0, sort, 0, 0);
+       if( maxBal != INT_MAX ) {
+               flags = sort|BANK_ITFLAG_MAXBALANCE;
+               balValue = maxBal;
+       }
+       else if( minBal != INT_MIN ) {
+               flags = sort|BANK_ITFLAG_MINBALANCE;
+               balValue = minBal;
+       }
+       else {
+               flags = sort;
+               balValue = 0;
+       }
+       if( lastSeenBefore ) {
+               timeValue = lastSeenBefore;
+               flags |= BANK_ITFLAG_SEENBEFORE;
+       }
+       else if( lastSeenAfter ) {
+               timeValue = lastSeenAfter;
+               flags |= BANK_ITFLAG_SEENAFTER;
+       }
+       else {
+               timeValue = 0;
+       }
+       it = Bank_Iterator(flagMask, flagVal, flags, balValue, timeValue);
        
        // Get return number
        while( (i = Bank_IteratorNext(it)) != -1 )
@@ -822,12 +1003,7 @@ void Server_Cmd_ENUMUSERS(tClient *Client, char *Args)
        
        
        // Create iterator
-       if( maxBal != INT_MAX )
-               it = Bank_Iterator(0, 0, sort|BANK_ITFLAG_MAXBALANCE, maxBal, 0);
-       else if( minBal != INT_MIN )
-               it = Bank_Iterator(0, 0, sort|BANK_ITFLAG_MINBALANCE, minBal, 0);
-       else
-               it = Bank_Iterator(0, 0, sort, 0, 0);
+       it = Bank_Iterator(flagMask, flagVal, flags, balValue, timeValue);
        
        while( (i = Bank_IteratorNext(it)) != -1 )
        {
@@ -855,10 +1031,14 @@ void Server_Cmd_USERINFO(tClient *Client, char *Args)
        space = strchr(user, ' ');
        if(space)       *space = '\0';
        
+       if( giDebugLevel )      Debug(Client, "User Info '%s'", user);
+       
        // Get recipient
        uid = Bank_GetAcctByName(user);
+       
+       if( giDebugLevel >= 2 ) Debug(Client, "uid = %i", uid);
        if( uid == -1 ) {
-               sendf(Client->Socket, "404 Invalid user");
+               sendf(Client->Socket, "404 Invalid user\n");
                return ;
        }
        
@@ -921,6 +1101,12 @@ void Server_Cmd_USERADD(tClient *Client, char *Args)
                return ;
        }
        
+       {
+               char    *thisName = Bank_GetAcctName(Client->UID);
+               Log_Info("Account '%s' created by '%s'", username, thisName);
+               free(thisName);
+       }
+       
        sendf(Client->Socket, "200 User Added\n");
 }
 
@@ -972,6 +1158,17 @@ void Server_Cmd_USERFLAGS(tClient *Client, char *Args)
 }
 
 // --- INTERNAL HELPERS ---
+void Debug(tClient *Client, const char *Format, ...)
+{
+       va_list args;
+       //printf("%010i [%i] ", (int)time(NULL), Client->ID);
+       printf("[%i] ", Client->ID);
+       va_start(args, Format);
+       vprintf(Format, args);
+       va_end(args);
+       printf("\n");
+}
+
 int sendf(int Socket, const char *Format, ...)
 {
        va_list args;

UCC git Repository :: git.ucc.asn.au