| 1 | #!/usr/bin/python2.5 |
|---|
| 2 | |
|---|
| 3 | libdir = '/home/joerg/opencoin' |
|---|
| 4 | datadir = '/home/joerg/opencoin/webwallet/data' |
|---|
| 5 | |
|---|
| 6 | ################################## |
|---|
| 7 | |
|---|
| 8 | import sys, os |
|---|
| 9 | sys.path.append(libdir) |
|---|
| 10 | import cgitb; cgitb.enable() |
|---|
| 11 | import cgi |
|---|
| 12 | import oc2 |
|---|
| 13 | from oc2 import storage as oc2storage |
|---|
| 14 | from oc2 import wallet, transports |
|---|
| 15 | |
|---|
| 16 | #for key,value in os.environ.items(): |
|---|
| 17 | # print '%s: %s<br>\n' % (key,value) |
|---|
| 18 | #print str(username) |
|---|
| 19 | |
|---|
| 20 | class CGIWallet: |
|---|
| 21 | |
|---|
| 22 | def __init__(self,storage): |
|---|
| 23 | self.storage = storage |
|---|
| 24 | self.wallet = wallet.Wallet(storage) |
|---|
| 25 | self.output = [] |
|---|
| 26 | self.mimetype = 'text/html' |
|---|
| 27 | |
|---|
| 28 | def out(self,text): |
|---|
| 29 | if type(text) != type(''): |
|---|
| 30 | text = str(text) |
|---|
| 31 | self.output.append(text) |
|---|
| 32 | |
|---|
| 33 | def printout(self): |
|---|
| 34 | print """Content-type:%s""" % self.mimetype |
|---|
| 35 | print "\r" |
|---|
| 36 | if self.mimetype == 'text/html': |
|---|
| 37 | print '<html><body>' |
|---|
| 38 | #print '<small><a href="%s?action=logout">Logout</a></small>' % (baseurl) |
|---|
| 39 | print '<br/>\n'.join(self.output) |
|---|
| 40 | print '</body></html>' |
|---|
| 41 | else: |
|---|
| 42 | print '\n'.join(self.output) |
|---|
| 43 | |
|---|
| 44 | def getCurrency(self,currencyId): |
|---|
| 45 | return dict(self.getCurrencies())[currencyId] |
|---|
| 46 | |
|---|
| 47 | def getCurrencies(self): |
|---|
| 48 | return [(cdd.currencyId,(cdd,amount)) for cdd,amount in self.wallet.listCurrencies()] |
|---|
| 49 | |
|---|
| 50 | def dispatchRequest(self): |
|---|
| 51 | self.env = os.environ |
|---|
| 52 | self.action = action = self.form.getfirst('action','') |
|---|
| 53 | self.method = method = self.env['REQUEST_METHOD'].lower() |
|---|
| 54 | |
|---|
| 55 | postmapping = dict(addcurrency = self.addCurrency, |
|---|
| 56 | mint = self.mintCoins, |
|---|
| 57 | redeem = self.redeemCoins, |
|---|
| 58 | delcurrency = self.delCurrency, |
|---|
| 59 | spend = self.spendCoins, |
|---|
| 60 | login = self.displayMain) |
|---|
| 61 | |
|---|
| 62 | getmapping = dict(addcurrency = self.displayAddCurrency, |
|---|
| 63 | mint = self.displayMint, |
|---|
| 64 | redeem = self.displayRedeem, |
|---|
| 65 | spend = self.displaySpend, |
|---|
| 66 | delcurrency = self.displayDelCurrency, |
|---|
| 67 | freshenup = self.freshenUp) |
|---|
| 68 | |
|---|
| 69 | if method == 'post': |
|---|
| 70 | if postmapping.has_key(action): |
|---|
| 71 | postmapping[action]() |
|---|
| 72 | else: |
|---|
| 73 | self.receiveCoins() |
|---|
| 74 | |
|---|
| 75 | elif method == 'get': |
|---|
| 76 | if getmapping.has_key(action): |
|---|
| 77 | getmapping[action]() |
|---|
| 78 | else: |
|---|
| 79 | self.displayMain() |
|---|
| 80 | |
|---|
| 81 | |
|---|
| 82 | ################################ main ################################################ |
|---|
| 83 | |
|---|
| 84 | |
|---|
| 85 | def displayMain(self): |
|---|
| 86 | tmp = [(cdd.currencyId,cdd,amount) for cdd,amount in self.wallet.listCurrencies()] |
|---|
| 87 | tmp.sort() |
|---|
| 88 | currencies = [(t[1],t[2]) for t in tmp] |
|---|
| 89 | items = [] |
|---|
| 90 | for cdd,amount in currencies: |
|---|
| 91 | entry = """ |
|---|
| 92 | <p><b>%(amount)s</b> %(cid)ss<br/> |
|---|
| 93 | <a href='%(baseurl)s?action=spend¤cyId=%(cid)s'>Pay</a> |
|---|
| 94 | <a href='%(baseurl)s?action=freshenup¤cyId=%(cid)s'>Get change</a> |
|---|
| 95 | <a href='%(baseurl)s?action=mint¤cyId=%(cid)s'>Withdraw</a> |
|---|
| 96 | <a href='%(baseurl)s?action=redeem¤cyId=%(cid)s'>Exchange back</a> |
|---|
| 97 | <a href='%(baseurl)s?action=delcurrency¤cyId=%(cid)s'>Remove</a> |
|---|
| 98 | </p> |
|---|
| 99 | """ % dict(amount=amount, |
|---|
| 100 | isl=cdd.issuerServiceLocation, |
|---|
| 101 | cid=cdd.currencyId, |
|---|
| 102 | baseurl=baseurl) |
|---|
| 103 | items.append(entry) |
|---|
| 104 | items = '\n'.join(items) |
|---|
| 105 | html = """ |
|---|
| 106 | <h2>Wallet content</h2> |
|---|
| 107 | %s |
|---|
| 108 | ----<br/> |
|---|
| 109 | <a href='%s?action=addcurrency'>Add a currency</a> |
|---|
| 110 | """ % (items,baseurl) |
|---|
| 111 | self.out(html) |
|---|
| 112 | |
|---|
| 113 | ############################### add a currency #################################### |
|---|
| 114 | |
|---|
| 115 | |
|---|
| 116 | def addCurrency(self): |
|---|
| 117 | url = self.form.getfirst('url','') |
|---|
| 118 | if url: |
|---|
| 119 | transport = transports.HTTPTransport(url) |
|---|
| 120 | self.wallet.addCurrency(transport) |
|---|
| 121 | self.storage.save() |
|---|
| 122 | self.displayMain() |
|---|
| 123 | |
|---|
| 124 | def displayAddCurrency(self): |
|---|
| 125 | html=""" |
|---|
| 126 | <h2>Add a currency</h2> |
|---|
| 127 | <form action='%s' method='post'> |
|---|
| 128 | The url of the issuer:<br> |
|---|
| 129 | <input type='text' name='url' value='http://baach.de:9090' /><br> |
|---|
| 130 | <input type='submit' /> |
|---|
| 131 | <input type='hidden' name='action' value='addcurrency'/> |
|---|
| 132 | </form> |
|---|
| 133 | """ % baseurl |
|---|
| 134 | self.out(html) |
|---|
| 135 | |
|---|
| 136 | |
|---|
| 137 | |
|---|
| 138 | ############################### delete a currency #################################### |
|---|
| 139 | |
|---|
| 140 | def displayDelCurrency(self): |
|---|
| 141 | currencyId = self.form.getfirst('currencyId','') |
|---|
| 142 | cdd,amount = self.getCurrency(currencyId) |
|---|
| 143 | html=""" |
|---|
| 144 | <h2>Remove %s</h2> |
|---|
| 145 | <form action='%s' method='post'> |
|---|
| 146 | <p>Really really delete %s with %s coins - there is no way to recover</p> |
|---|
| 147 | <p><input type='submit' value='Remove %ss'/> |
|---|
| 148 | or |
|---|
| 149 | |
|---|
| 150 | <a href='%s'>go back to main screen</a> |
|---|
| 151 | </p> |
|---|
| 152 | <input type='hidden' name='action' value='delcurrency'/> |
|---|
| 153 | <input type='hidden' name='currencyId' value='%s'/> |
|---|
| 154 | </form> |
|---|
| 155 | """ % (currencyId,baseurl,currencyId,amount,currencyId,baseurl,currencyId) |
|---|
| 156 | self.out(html) |
|---|
| 157 | |
|---|
| 158 | def delCurrency(self): |
|---|
| 159 | id = self.form.getfirst('currencyId','') |
|---|
| 160 | self.wallet.deleteCurrency(id) |
|---|
| 161 | self.storage.save() |
|---|
| 162 | self.displayMain() |
|---|
| 163 | |
|---|
| 164 | |
|---|
| 165 | ############################### minting #################################### |
|---|
| 166 | |
|---|
| 167 | def mintCoins(self): |
|---|
| 168 | amount = int(self.form.getfirst('amount',1)) |
|---|
| 169 | reference = self.form.getfirst('reference') |
|---|
| 170 | cdd,wehave = self.getCurrency(self.form.getfirst('currencyId')) |
|---|
| 171 | transport = transports.HTTPTransport(cdd.issuerServiceLocation) |
|---|
| 172 | self.wallet.mintCoins(transport,amount,reference) |
|---|
| 173 | self.storage.save() |
|---|
| 174 | self.displayMain() |
|---|
| 175 | |
|---|
| 176 | |
|---|
| 177 | def displayMint(self): |
|---|
| 178 | currencyId = self.form.getfirst('currencyId','coin') |
|---|
| 179 | html=""" |
|---|
| 180 | <h2>Get new coins</h2> |
|---|
| 181 | <form action='%s' method='post'> |
|---|
| 182 | How many <b>%ss</b><br> |
|---|
| 183 | <input type='number' name='amount' value='1' /><br> |
|---|
| 184 | Optional message<br> |
|---|
| 185 | <input type='text' name='reference' value='secret' /><br> |
|---|
| 186 | <input type='submit' /> |
|---|
| 187 | <input type='hidden' name='action' value='mint'/> |
|---|
| 188 | <input type='hidden' name='currencyId' value='%s'/> |
|---|
| 189 | </form> |
|---|
| 190 | """ % (baseurl,currencyId,currencyId) |
|---|
| 191 | self.out(html) |
|---|
| 192 | |
|---|
| 193 | ############################### redeem #################################### |
|---|
| 194 | |
|---|
| 195 | def redeemCoins(self): |
|---|
| 196 | amount = int(self.form.getfirst('amount',1)) |
|---|
| 197 | reference = self.form.getfirst('reference') |
|---|
| 198 | cdd,wehave = self.getCurrency(self.form.getfirst('currencyId')) |
|---|
| 199 | transport = transports.HTTPTransport(cdd.issuerServiceLocation) |
|---|
| 200 | self.wallet.redeemCoins(transport,amount,reference) |
|---|
| 201 | self.storage.save() |
|---|
| 202 | self.displayMain() |
|---|
| 203 | |
|---|
| 204 | |
|---|
| 205 | def displayRedeem(self): |
|---|
| 206 | currencyId = self.form.getfirst('currencyId','coin') |
|---|
| 207 | html=""" |
|---|
| 208 | <h2>Redeem coins</h2> |
|---|
| 209 | <form action='%s' method='post'> |
|---|
| 210 | How many <b>%ss</b><br> |
|---|
| 211 | <input type='number' name='amount' value='1' /><br> |
|---|
| 212 | Optional message<br> |
|---|
| 213 | <input type='text' name='reference' value='secret' /><br> |
|---|
| 214 | <input type='submit' /> |
|---|
| 215 | <input type='hidden' name='action' value='redeem'/> |
|---|
| 216 | <input type='hidden' name='currencyId' value='%s'/> |
|---|
| 217 | </form> |
|---|
| 218 | |
|---|
| 219 | """ % (baseurl,currencyId,currencyId) |
|---|
| 220 | self.out(html) |
|---|
| 221 | |
|---|
| 222 | ############################### spend #################################### |
|---|
| 223 | |
|---|
| 224 | def spendCoins(self): |
|---|
| 225 | amount = int(self.form.getfirst('amount',1)) |
|---|
| 226 | reference = self.form.getfirst('reference') |
|---|
| 227 | url = self.form.getfirst('url') |
|---|
| 228 | if not url.startswith('http://'): |
|---|
| 229 | url = 'http://%s' % url |
|---|
| 230 | cid = self.form.getfirst('currencyId') |
|---|
| 231 | transport = transports.HTTPTransport(url) |
|---|
| 232 | self.wallet.spendCoins(transport,cid,amount,reference) |
|---|
| 233 | self.storage.save() |
|---|
| 234 | self.displayMain() |
|---|
| 235 | |
|---|
| 236 | |
|---|
| 237 | def displaySpend(self): |
|---|
| 238 | currencyId = self.form.getfirst('currencyId','coin') |
|---|
| 239 | html=""" |
|---|
| 240 | <h2>Pay someone</h2> |
|---|
| 241 | <form action='%s' method='post'> |
|---|
| 242 | Recipient<br/> |
|---|
| 243 | <input type='text' name='url' value='http://baach.de/cgi-local/wallet.cgi/' /><br> |
|---|
| 244 | How many <b>%ss</b><br> |
|---|
| 245 | <input type='number' name='amount' value='1' /><br> |
|---|
| 246 | Optional message<br> |
|---|
| 247 | <input type='text' name='reference' value='secret' /><br> |
|---|
| 248 | Please make sure the other side is ready to accept!<br> |
|---|
| 249 | <input type='submit' /> |
|---|
| 250 | <input type='hidden' name='action' value='spend'/> |
|---|
| 251 | <input type='hidden' name='currencyId' value='%s'/> |
|---|
| 252 | </form> |
|---|
| 253 | """ % (baseurl,currencyId,currencyId) |
|---|
| 254 | self.out(html) |
|---|
| 255 | |
|---|
| 256 | ############################### freshenUp #################################### |
|---|
| 257 | |
|---|
| 258 | def freshenUp(self): |
|---|
| 259 | cdd,wehave = self.getCurrency(self.form.getfirst('currencyId')) |
|---|
| 260 | transport = transports.HTTPTransport(cdd.issuerServiceLocation) |
|---|
| 261 | self.wallet.freshenUp(transport,cdd) |
|---|
| 262 | self.storage.save() |
|---|
| 263 | self.displayMain() |
|---|
| 264 | |
|---|
| 265 | |
|---|
| 266 | ############################### freshenUp #################################### |
|---|
| 267 | |
|---|
| 268 | def receiveCoins(self): |
|---|
| 269 | message = transports.createMessage(self.form.list[0].name) |
|---|
| 270 | |
|---|
| 271 | if message.header == 'SumAnnounce': |
|---|
| 272 | answer = self.wallet.listenSum(message) |
|---|
| 273 | if message.header == 'SpendRequest': |
|---|
| 274 | cdd,wehave = self.getCurrency(message.coins[0].currencyId) |
|---|
| 275 | transport = transports.HTTPTransport(cdd.issuerServiceLocation) |
|---|
| 276 | answer = self.wallet.listenSpend(transport,message) |
|---|
| 277 | self.storage.save() |
|---|
| 278 | self.mimetype='text/plain' |
|---|
| 279 | self.out(answer.toString(True)) |
|---|
| 280 | |
|---|
| 281 | form = cgi.FieldStorage(keep_blank_values=1) |
|---|
| 282 | |
|---|
| 283 | baseserver = "http://%s:%s" % (os.environ['SERVER_NAME'],os.environ['SERVER_PORT']) |
|---|
| 284 | username = os.environ.get('PATH_INFO','') |
|---|
| 285 | baseurl = os.environ['SCRIPT_NAME']+username |
|---|
| 286 | |
|---|
| 287 | def die(string): |
|---|
| 288 | print 'Content-type:text/plain\r\n' |
|---|
| 289 | print string |
|---|
| 290 | sys.exit(0) |
|---|
| 291 | |
|---|
| 292 | if username == '/' or not username: |
|---|
| 293 | die('username required, no direct access allowed. Try %s%s/YOURNAME' % (baseserver,baseurl)) |
|---|
| 294 | username = username[1:] |
|---|
| 295 | if username.startswith('.') or '/' in username: |
|---|
| 296 | die('hacking in, ey') |
|---|
| 297 | |
|---|
| 298 | if 0: |
|---|
| 299 | password = None |
|---|
| 300 | |
|---|
| 301 | if form.has_key('password'): |
|---|
| 302 | password = form.getfirst('password') |
|---|
| 303 | print "Set-Cookie:%s=%s" % (username,password) |
|---|
| 304 | elif form.getfirst('action','') == 'logout': |
|---|
| 305 | print "Set-Cookie:%s=%s" % (username,'') |
|---|
| 306 | elif os.environ.has_key('HTTP_COOKIE'): |
|---|
| 307 | for cookie in [c.strip() for c in os.environ['HTTP_COOKIE'].split(';')]: |
|---|
| 308 | if not cookie: |
|---|
| 309 | continue |
|---|
| 310 | (key, value ) = cookie.split('='); |
|---|
| 311 | if key == username: |
|---|
| 312 | password = value |
|---|
| 313 | |
|---|
| 314 | |
|---|
| 315 | filepath = datadir+'/%s.bin' % username |
|---|
| 316 | storage = oc2storage.CryptedStorage() |
|---|
| 317 | storage.setPassword(password) |
|---|
| 318 | storage.setFilename(filepath) |
|---|
| 319 | message = '' |
|---|
| 320 | if password and not os.path.exists(filepath): |
|---|
| 321 | storage.save() |
|---|
| 322 | elif form.getfirst('action','') not in ['logout','']: |
|---|
| 323 | try: |
|---|
| 324 | storage.restore() |
|---|
| 325 | storage.save() |
|---|
| 326 | except: |
|---|
| 327 | print "Set-Cookie:%s=%s" % (username,'') |
|---|
| 328 | password = None |
|---|
| 329 | message = 'Wrong password<br>' |
|---|
| 330 | |
|---|
| 331 | if not password: |
|---|
| 332 | print """Content-type:text/html |
|---|
| 333 | |
|---|
| 334 | <html><body> |
|---|
| 335 | <form action='%s' method='post'> |
|---|
| 336 | %s |
|---|
| 337 | Enter your password: <input type='password' name='password'> <input type='submit'> |
|---|
| 338 | <input type='hidden' name='action' value='login' /> |
|---|
| 339 | </form> |
|---|
| 340 | </body></html> |
|---|
| 341 | """ % (baseurl,message) |
|---|
| 342 | sys.exit(0) |
|---|
| 343 | filepath = datadir+'/%s.bin' % username |
|---|
| 344 | storage = oc2storage.Storage() |
|---|
| 345 | storage.setFilename(filepath) |
|---|
| 346 | storage.restore() |
|---|
| 347 | w = CGIWallet(storage) |
|---|
| 348 | w.form = form |
|---|
| 349 | w.dispatchRequest() |
|---|
| 350 | w.printout() |
|---|
| 351 | |
|---|
| 352 | |
|---|
| 353 | |
|---|
| 354 | #for key,value in os.environ.items(): |
|---|
| 355 | # print '%s: %s<br>\n' % (key,value) |
|---|
| 356 | #print str(username) |
|---|