#!/usr/bin/python

# (c) 2008 Maciej Ceglowski <maciej@ceglowski.com>
# This is free (GPL) software

import sys
import hmac
import sha
import base64
from datetime import datetime
from urllib import urlencode
from google.appengine.api.urlfetch import * 

BASE_SQS_URL =   "http://queue.amazonaws.com/"

class SQSUrlBuilder:
    """
    Generates appropriately-signed query URLs for use with Amazon's 
    SQS service
    """
    def __init__(self,key_id,access_key):
        """
        constructor requires an amazon key ID and secret access key.  See
        SQS documentation for details
        """
        self.key_id     = key_id
        self.access_key = access_key
        
    def listQueues(self):
        args = { "Action" : "ListQueues" }
        return self._buildURL(args)
        
    def createQueue(self,name,timeout=30):
        args = { "Action" : "CreateQueue", 
                 "QueueName" : name,
                 "DefaultVisibilityTimeout" : str(timeout) }
        return self._buildURL(args)
    
    def deleteQueue(self,name):
        args = { "Action" : "DeleteQueue" }
        return self._buildURL(args,name)
        
    
    def deleteMessage(self,queue,receiptHandle):
        args = { "Action" : "DeleteMessage",
                "ReceiptHandle" : receiptHandle }
        return self._buildURL(args,queue)
        
    def sendMessage(self,queue,message):
        args = { "Action" : "SendMessage", 
                 "MessageBody" : message }
        return self._buildURL(args,queue)
        
    def receiveMessage(self,queue):
        args = { "Action" : "ReceiveMessage" }
        return self._buildURL(args,queue)    
       
    def _addBoilerplate(self,args):
        bplate = { "AWSAccessKeyId" : self.key_id,
             "Version" : "2008-01-01",
             "SignatureVersion" : "1",
             "Timestamp" : datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
             }
        for k,v in bplate.iteritems():
            args[k] = v
        return self._sign(args,self.access_key)
    
    def _sign(self,params,cryptokey):
        """
        AWS signature protocol: sort headers in alphabetical order by name,
        concatenate header names and values, sign everything using SHA1 HMAC
        and set a header called Signature with the base64-encoded value
        """
        # case-insensitive sort
        headers = [(x.lower(), x) for x in params.keys()]
        headers.sort()
        keylist = [x[1] for x in headers]
        string = ''
        for key in keylist:
            string += key + params[key]
        digest = hmac.new(cryptokey, string, sha.sha)
        params['Signature'] = base64.b64encode(digest.digest())
        return params
    
    def _buildURL(self,args,queueName = ''):
        args = self._addBoilerplate(args)
        url = BASE_SQS_URL + queueName + "?" + urlencode(args)
        return url
    

   