Hacked to stop root dispenses
[tpg/opendispense2.git] / src / server / dispense.c
1 /**
2  */
3 #include "common.h"
4 #include <stdlib.h>
5 #include <limits.h>
6
7  int    _GetMinBalance(int Account);
8  int    _CanTransfer(int Source, int Destination, int Ammount);
9  int    _Transfer(int Source, int Destination, int Ammount, const char *Reason);
10
11 // === CODE ===
12 /**
13  * \brief Dispense an item for a user
14  * 
15  * The core of the dispense system, I kinda like it :)
16  */
17 int DispenseItem(int ActualUser, int User, tItem *Item)
18 {
19          int    ret, salesAcct;
20         tHandler        *handler;
21         char    *username, *actualUsername;
22         
23         salesAcct = Bank_GetAcctByName(COKEBANK_SALES_ACCT);
24
25         // Check if the user can afford it
26         if( Item->Price && !_CanTransfer(User, salesAcct, Item->Price) )
27         {
28                 return 2;       // 2: No balance
29         }
30         
31         handler = Item->Handler;
32         
33         // Check if the dispense is possible
34         if( handler->CanDispense ) {
35                 ret = handler->CanDispense( User, Item->ID );
36                 if(ret) return 1;       // 1: Unable to dispense
37         }
38         
39         // Get username for debugging
40         username = Bank_GetAcctName(User);
41         
42         // Actually do the dispense
43         if( handler->DoDispense ) {
44                 ret = handler->DoDispense( User, Item->ID );
45                 if(ret) {
46                         Log_Error("Dispense failed (%s dispensing '%s' - %ic)",
47                                 username, Item->Name, Item->Price);
48                         free( username );
49                         return -1;      // 1: Unknown Error again
50                 }
51         }
52         
53         // Take away money
54         if( Item->Price )
55         {
56                 char    *reason;
57                 reason = mkstr("Dispense - %s:%i %s", handler->Name, Item->ID, Item->Name);
58                 _Transfer( User, salesAcct, Item->Price, reason );
59                 free(reason);
60         }
61         
62         actualUsername = Bank_GetAcctName(ActualUser);
63         
64         // And log that it happened
65         Log_Info("dispense '%s' (%s:%i) for %s by %s [cost %i, balance %i]",
66                 Item->Name, handler->Name, Item->ID,
67                 username, actualUsername, Item->Price, Bank_GetBalance(User)
68                 );
69         
70         free( username );
71         free( actualUsername );
72         return 0;       // 0: EOK
73 }
74
75 /**
76  * \brief Give money from one user to another
77  */
78 int DispenseGive(int ActualUser, int SrcUser, int DestUser, int Ammount, const char *ReasonGiven)
79 {
80          int    ret;
81         char    *actualUsername;
82         char    *srcName, *dstName;
83         
84         if( Ammount < 0 )       return 1;       // Um... negative give? Not on my watch!
85         
86         ret = _Transfer( SrcUser, DestUser, Ammount, ReasonGiven );
87         if(ret) return 2;       // No Balance
88         
89         
90         actualUsername = Bank_GetAcctName(ActualUser);
91         srcName = Bank_GetAcctName(SrcUser);
92         dstName = Bank_GetAcctName(DestUser);
93         
94         Log_Info("give %i to %s from %s by %s [balances %i, %i] - %s",
95                 Ammount, dstName, srcName, actualUsername,
96                 Bank_GetBalance(SrcUser), Bank_GetBalance(DestUser),
97                 ReasonGiven
98                 );
99         
100         free(srcName);
101         free(dstName);
102         free(actualUsername);
103         
104         return 0;
105 }
106
107 /**
108  * \brief Add money to an account
109  */
110 int DispenseAdd(int ActualUser, int User, int Ammount, const char *ReasonGiven)
111 {
112          int    ret;
113         char    *dstName, *byName;
114         
115         ret = _Transfer( Bank_GetAcctByName(COKEBANK_DEBT_ACCT), User, Ammount, ReasonGiven );
116         if(ret) return 2;
117         
118         byName = Bank_GetAcctName(ActualUser);
119         dstName = Bank_GetAcctName(User);
120         
121         Log_Info("add %i to %s by %s [balance %i] - %s",
122                 Ammount, dstName, byName, Bank_GetBalance(User), ReasonGiven
123                 );
124         
125         free(byName);
126         free(dstName);
127         
128         return 0;
129 }
130
131 int DispenseSet(int ActualUser, int User, int Balance, const char *ReasonGiven)
132 {
133          int    curBal = Bank_GetBalance(User);
134         char    *byName, *dstName;
135         
136         _Transfer( Bank_GetAcctByName(COKEBANK_DEBT_ACCT), User, Balance-curBal, ReasonGiven );
137         
138         byName = Bank_GetAcctName(ActualUser);
139         dstName = Bank_GetAcctName(User);
140         
141         Log_Info("set balance of %s to %i by %s [balance %i] - %s",
142                 dstName, Balance, byName, Bank_GetBalance(User), ReasonGiven
143                 );
144         
145         free(byName);
146         free(dstName);
147         
148         return 0;
149 }
150
151 /**
152  * \brief Donate money to the club
153  */
154 int DispenseDonate(int ActualUser, int User, int Ammount, const char *ReasonGiven)
155 {
156          int    ret;
157         char    *srcName, *byName;
158         
159         if( Ammount < 0 )       return 2;
160         
161         ret = _Transfer( User, Bank_GetAcctByName(COKEBANK_DEBT_ACCT), Ammount, ReasonGiven );
162         if(ret) return 2;
163         
164         byName = Bank_GetAcctName(ActualUser);
165         srcName = Bank_GetAcctName(User);
166         
167         Log_Info("donate %i from %s by %s [balance %i] - %s",
168                 Ammount, srcName, byName, Bank_GetBalance(User), ReasonGiven
169                 );
170         
171         free(byName);
172         free(srcName);
173         
174         return 0;
175 }
176
177 // --- Internal Functions ---
178 int _GetMinBalance(int Account)
179 {
180          int    flags = Bank_GetFlags(Account);
181         
182         // Evil little piece of HACK:
183         // root's balance cannot be changed by any of the above functions
184         // - Stops dispenses as root by returning insufficent balance.
185         {
186                 char    *username = Bank_GetAcctName(Account);
187                 if( strcmp(username, "root") == 0 )
188                 {
189                         free(username);
190                         return INT_MAX;
191                 }
192                 free(username);
193         }
194         
195         // - Internal accounts have no lower bound
196         if( flags & USER_FLAG_INTERNAL )        return INT_MIN;
197         
198         // Admin to -$10
199         if( flags & USER_FLAG_ADMIN )   return -1000;
200         
201         // Coke to -$5
202         if( flags & USER_FLAG_COKE )    return -500;
203         
204         // Anyone else, non-negative
205         return 0;
206 }
207
208 /**
209  * \brief Check if a transfer is possible
210  */
211 int _CanTransfer(int Source, int Destination, int Ammount)
212 {
213         if( Ammount > 0 )
214         {
215                 if( Bank_GetBalance(Source) + Ammount < _GetMinBalance(Source) )
216                         return 0;
217         }
218         else
219         {
220                 if( Bank_GetBalance(Destination) - Ammount < _GetMinBalance(Destination) )
221                         return 0;
222         }
223         return 1;
224 }
225
226 int _Transfer(int Source, int Destination, int Ammount, const char *Reason)
227 {
228         if( !_CanTransfer(Source, Destination, Ammount) )
229                 return 1;
230         return Bank_Transfer(Source, Destination, Ammount, Reason);
231 }

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