-
-
Save tang9ian/6200275 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!--- | |
Parts of this are based on Tim Dawe's | |
http://amazonsig.riaforge.org | |
and | |
Joe Danziger's Amazon S3 REST Wrapper | |
http://amazons3.riaforge.org/ | |
Written by Patrick Liess | |
Twitter: @smrchy | |
http://www.tcs.de | |
---> | |
<cfcomponent> | |
<cffunction name="init" output="false" hint="Returns an instance of the CFC initialized."> | |
<cfargument name="awsAccessKeyId" type="string" required="true" /> | |
<cfargument name="secretAccessKey" type="string" required="true" /> | |
<cfscript> | |
This.awsAccessKeyId = Arguments.awsAccessKeyId; | |
This.secretAccessKey = Arguments.secretAccessKey; | |
This.SQSVersion = "2009-02-01"; | |
This.SQSserviceUrl = "http://queue.amazonaws.com/"; | |
This.CFVersion = "2010-11-01"; | |
return This; | |
</cfscript> | |
</cffunction> | |
<!--- CloudFront ---> | |
<cffunction name="CFInvalidation" output="false" returntype="any"> | |
<cfargument name="distributionid" type="string" required="yes"> | |
<cfargument name="patharray" type="array" required="yes"> | |
<cfset var i = 0> | |
<cfset var dateTimeString = GetHTTPTimeString(Now())> | |
<cfset var cs = "#dateTimeString#"> | |
<cfset var signature = createSignature(cs)> | |
<cfset var thexml = '<InvalidationBatch>'> | |
<cfloop index="i" array="#Arguments.patharray#"> | |
<cfset thexml = thexml & '<Path>#i#</Path>'> | |
</cfloop> | |
<cfset thexml = thexml & '<CallerReference>#CreateUUID()#</CallerReference></InvalidationBatch>'> | |
<cfhttp method="POST" url="https://cloudfront.amazonaws.com/#This.CFVersion#/distribution/#Arguments.distributionid#/invalidation"> | |
<cfhttpparam type="header" name="Date" value="#dateTimeString#"> | |
<cfhttpparam type="header" name="Content-Type" value="text/xml"> | |
<cfhttpparam type="header" name="Authorization" value="AWS #This.awsAccessKeyId#:#signature#"> | |
<cfhttpparam type="body" value="#thexml#"> | |
</cfhttp> | |
<cfreturn cfhttp> | |
</cffunction> | |
<!--- S3 ---> | |
<cffunction name="S3createSignedURL" output="false" returntype="string"> | |
<cfargument name="bucketName" type="string" required="yes"> | |
<cfargument name="fileKey" type="string" required="yes"> | |
<cfargument name="minutesValid" type="string" required="false" default="60"> | |
<cfargument name="secure" type="boolean" required="false" default="false"> | |
<cfscript> | |
var epochTime = DateDiff("s", DateConvert("utc2Local", "January 1 1970 00:00"), now()) + (arguments.minutesValid * 60); | |
// Create a canonical string to send | |
var cs = "GET\n\n\n#epochTime#\n/#arguments.bucketName#/#arguments.fileKey#"; | |
// Create a proper signature | |
var signature = createSignature(cs); | |
// Create the timed link for the image | |
var protocol = 'http://'; | |
if (arguments.secure) { | |
protocol = 'https://'; | |
} | |
var timedAmazonLink = protocol & arguments.bucketName&'.s3.amazonaws.com/' & arguments.fileKey & '?AWSAccessKeyId=' & URLEncodedFormat(This.awsAccessKeyId) & '&Expires=' & epochTime & '&Signature=' & URLEncodedFormat(signature); | |
return timedAmazonLink; | |
</cfscript> | |
</cffunction> | |
<cffunction name="S3deleteObject" output="false" returntype="struct"> | |
<cfargument name="bucketName" type="string" required="yes"> | |
<cfargument name="fileKey" type="string" required="yes"> | |
<cfset var dateTimeString = GetHTTPTimeString(Now())> | |
<cfset var cs = "DELETE\n\n\n#dateTimeString#\n/#arguments.bucketName#/#arguments.fileKey#"> | |
<cfset var signature = createSignature(cs)> | |
<cfhttp method="DELETE" url="http://s3.amazonaws.com/#arguments.bucketName#/#arguments.fileKey#"> | |
<cfhttpparam type="header" name="Date" value="#dateTimeString#"> | |
<cfhttpparam type="header" name="Authorization" value="AWS #This.awsAccessKeyId#:#signature#"> | |
</cfhttp> | |
<!--- We return the full struct so we can check the cfhttp.statuscode for errors ---> | |
<cfreturn cfhttp> | |
</cffunction> | |
<cffunction name="S3putObject" access="public" output="false" returntype="string"> | |
<cfargument name="bucketName" type="string" required="yes"> | |
<cfargument name="filekey" type="string" required="yes"> | |
<cfargument name="filebinary" type="binary" required="yes"> | |
<cfargument name="contentType" type="string" required="yes"> | |
<cfargument name="ACL" type="string" required="no" default="public-read"> | |
<cfargument name="HTTPtimeout" type="numeric" required="no" default="300"> | |
<cfargument name="cacheControl" type="boolean" required="no" default="true"> | |
<cfargument name="cacheDays" type="numeric" required="no" default="300"> | |
<cfset var dateTimeString = GetHTTPTimeString(Now())> | |
<cfset var cacheSeconds = Arguments.cacheDays * 86400> | |
<cfset var cs = "PUT\n\n#arguments.contentType#\n#dateTimeString#\nx-amz-acl:#arguments.ACL#\n/#arguments.bucketName#/#arguments.filekey#"> | |
<!--- Never allow cacheControl for secure images ---> | |
<cfif arguments.ACL NEQ "public-read"> | |
<cfset arguments.cacheControl = false> | |
</cfif> | |
<cfset var signature = createSignature(cs)> | |
<!--- Send the file to amazon. The "x-amz-acl" controls the access properties of the file ---> | |
<cfhttp method="PUT" url="http://s3.amazonaws.com/#arguments.bucketName#/#arguments.fileKey#" timeout="#arguments.HTTPtimeout#"> | |
<cfhttpparam type="header" name="Authorization" value="AWS #This.awsAccessKeyId#:#signature#"> | |
<cfhttpparam type="header" name="Content-Type" value="#arguments.contentType#"> | |
<cfhttpparam type="header" name="Date" value="#dateTimeString#"> | |
<cfhttpparam type="header" name="x-amz-acl" value="#arguments.ACL#"> | |
<cfhttpparam type="body" value="#Arguments.filebinary#"> | |
<cfif arguments.cacheControl> | |
<cfhttpparam type="header" name="Cache-Control" value="max-age=#cacheSeconds#"> | |
</cfif> | |
</cfhttp> | |
<cfreturn cfhttp.FileContent> | |
</cffunction> | |
<!--- SQS ---> | |
<cffunction name="SQSgetQueueAttributes" output="false" returntype="string"> | |
<cfargument name="queue" type="string" required="true"/> | |
<cfargument name="name" type="string" required="true"/> | |
<cfset var requrl= This.SQSserviceUrl & Arguments.queue & | |
"?Action=GetQueueAttributes" & | |
"&AttributeName=" & Arguments.name & | |
"&Version=" & This.SQSVersion> | |
<cfset requrl = signRequest(requrl,"GET")> | |
<cfhttp method="GET" url="#requrl#" charset="UTF-8"></cfhttp> | |
<cfreturn cfhttp.FileContent> | |
</cffunction> | |
<cffunction name="SQSdeleteMessage" output="false" returntype="struct"> | |
<cfargument name="queue" type="string" required="true"/> | |
<cfargument name="receipthandle" type="string" required="true"/> | |
<cfset var requrl= This.SQSserviceUrl & Arguments.queue & | |
"?Action=DeleteMessage" & | |
"&ReceiptHandle=" & URLEncodedFormat(Arguments.receipthandle,"utf-8") & | |
"&Version=" & This.SQSVersion> | |
<cfset requrl = signRequest(requrl,"GET")> | |
<cfhttp method="GET" url="#requrl#" charset="UTF-8"></cfhttp> | |
<!--- We return the full struct so we can check the cfhttp.statuscode for errors ---> | |
<cfreturn cfhttp> | |
</cffunction> | |
<cffunction name="SQSreceiveMessage" output="false" returntype="string"> | |
<cfargument name="queue" type="string" required="true"/> | |
<cfargument name="amount" type="numeric" required="true"/> | |
<cfset var requrl= This.SQSserviceUrl & Arguments.queue & | |
"?Action=ReceiveMessage" & | |
"&AttributeName=None" & | |
"&MaxNumberOfMessages=" & Arguments.amount & | |
"&Version=" & This.SQSVersion> | |
<cfset requrl = signRequest(requrl,"GET")> | |
<cfhttp method="GET" url="#requrl#" charset="UTF-8"></cfhttp> | |
<cfreturn cfhttp.FileContent> | |
</cffunction> | |
<cffunction name="SQSsendMessage" output="false" returntype="string"> | |
<cfargument name="queue" type="string" required="true"/> | |
<cfargument name="msg" type="string" required="true"/> | |
<cfset var requrl= This.SQSserviceUrl & Arguments.queue & | |
"?Action=SendMessage" & | |
"&MessageBody=" & URLEncodedFormat(Arguments.msg,"utf-8") & | |
"&Version=" & This.SQSVersion> | |
<cfset requrl = signRequest(requrl,"GET")> | |
<cfhttp method="GET" url="#requrl#" charset="UTF-8"></cfhttp> | |
<cfreturn cfhttp.FileContent> | |
</cffunction> | |
<cffunction name="SQSsetQueueAttributes" output="false" returntype="string"> | |
<cfargument name="queue" type="string" required="true"/> | |
<cfargument name="name" type="string" required="true"/> | |
<cfargument name="value" type="string" required="true"/> | |
<cfset var requrl= This.SQSserviceUrl & Arguments.queue & | |
"?Action=SetQueueAttributes" & | |
"&Attribute.Name=" & Arguments.name & | |
"&Attribute.Value=" & Arguments.value & | |
"&Version=" & This.SQSVersion> | |
<cfset requrl = signRequest(requrl,"GET")> | |
<cfhttp method="GET" url="#requrl#" charset="UTF-8"></cfhttp> | |
<cfreturn cfhttp.FileContent> | |
</cffunction> | |
<!---- Util functions ---> | |
<cffunction name="signRequest" returntype="string" output="false"> | |
<cfargument name="request" required="yes" type="string"> | |
<cfargument name="method" required="no" default="GET" type="string"> | |
<cfscript> | |
var lc = structnew(); | |
// Extract the URL part of the request and strip the protocol | |
lc.requesturl = listfirst(arguments.request, "?"); | |
lc.requesturl = replacenocase(lc.requesturl, "http://", ""); | |
// Split into host and path | |
lc.host = listfirst(lc.requesturl, "/"); | |
lc.path = right(lc.requesturl, len(lc.requesturl) - len(lc.host)); | |
// Process the query string parameters into a structure | |
lc.querystring = listlast(arguments.request, "?"); | |
lc.strParams = structnew(); | |
</cfscript> | |
<cfloop list="#lc.querystring#" index="i" delimiters="&"> | |
<cfset lc.strParams[listfirst(i, "=")] = urldecode(listlast(i, "="))> | |
</cfloop> | |
<cfscript> | |
// Add the timestamp | |
if (not StructKeyExists(lc.strParams, "Timestamp")) { | |
lc.utcdate = dateconvert("local2Utc", now()); | |
lc.strParams["Timestamp"] = dateformat(lc.utcdate, 'yyyy-mm-dd') & "T" & timeformat(lc.utcdate, 'HH:mm:ss') & "Z"; | |
} | |
// Add the standard parameters | |
lc.strParams["AWSAccessKeyId"] = This.awsAccessKeyId; | |
lc.strParams["SignatureVersion"] = 2; | |
lc.strParams["SignatureMethod"] = "HmacSHA1"; | |
// Sort the parameters | |
lc.keys = listsort(structkeylist(lc.strParams), "text"); | |
// Generate a new query string including timestamp, with parameters in the correct order, encoding as we go | |
lc.qs = ""; | |
</cfscript> | |
<cfloop list="#lc.keys#" index="i"> | |
<cfset lc.qs = lc.qs & rfc3986EncodedFormat(i) & "=" & rfc3986EncodedFormat(lc.strParams[i]) & "&"> | |
</cfloop> | |
<cfscript> | |
// Strip off the last & | |
lc.qs = left(lc.qs, len(lc.qs)-1); | |
// Build the string to sign | |
lc.stringToSign = arguments.method & chr(10); | |
lc.stringToSign = lc.stringToSign & lc.host & chr(10); | |
lc.stringToSign = lc.stringToSign & lc.path & chr(10); | |
lc.stringToSign = lc.stringToSign & lc.qs; | |
lc.signature = HMAC_SHA1(lc.stringToSign); | |
// Return the new request URL | |
return "http://" & lc.host & lc.path & "?" & lc.qs & "&Signature=" & urlencodedformat(tobase64(lc.signature)); | |
</cfscript> | |
</cffunction> | |
<cffunction name="HMAC_SHA1" returntype="binary" access="private" output="false"> | |
<cfargument name="signMessage" type="string" required="true" /> | |
<cfscript> | |
var jMsg = JavaCast("string",arguments.signMessage).getBytes("iso-8859-1"); | |
var jKey = JavaCast("string",This.secretAccessKey).getBytes("iso-8859-1"); | |
var key = createObject("java","javax.crypto.spec.SecretKeySpec"); | |
var mac = createObject("java","javax.crypto.Mac"); | |
key = key.init(jKey,"HmacSHA1"); | |
mac = mac.getInstance(key.getAlgorithm()); | |
mac.init(key); | |
mac.update(jMsg); | |
return mac.doFinal(); | |
</cfscript> | |
</cffunction> | |
<cffunction name="createSignature" returntype="string" access="public" output="false"> | |
<cfargument name="stringIn" type="string" required="true" /> | |
<cfset var fixedData = replace(arguments.stringIn,"\n","#chr(10)#","all")> | |
<cfset var digest = HMAC_SHA1(fixedData)> | |
<cfset var signature = ToBase64("#digest#")> | |
<cfreturn signature> | |
</cffunction> | |
<cffunction name="rfc3986EncodedFormat" returntype="string" output="false"> | |
<cfargument name="text" required="yes" type="string"> | |
<cfset var lc = structnew()> | |
<cfset lc.objNet = createObject("java","java.net.URLEncoder")> | |
<cfset lc.encodedText = lc.objNet.encode(arguments.text, 'utf-8').replace("+", "%20").replace("*", "%2A").replace("%7E", "~")> | |
<cfreturn lc.encodedText> | |
</cffunction> | |
</cfcomponent> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment