Details

    • Type: Bug
    • Status: Resolved (View Workflow)
    • Priority: Critical
    • Resolution: Done
    • Affects Version/s: 3.1
    • Fix Version/s: 3.1
    • Labels:

      Description

      When using CFHTTP and the Body field to PUT binary data to Amazon S3, the data becomes corrupted.

      PUTs of plain text data using the same CFML code work fine.

      The following code produces this file:
      http://blambertbackups.s3.amazonaws.com/put_object

      <cffunction name="HMAC_SHA1" returntype="binary" access="private" output="false" hint="NSA SHA-1 Algorithm">
      <cfargument name="signKey" type="string" required="true" />
      <cfargument name="signMessage" type="string" required="true" />

      <cfset var jMsg = JavaCast("string",arguments.signMessage).getBytes("UTF-8") />
      <cfset var jKey = JavaCast("string",arguments.signKey).getBytes("UTF-8") />
      <cfset var key = createObject("java","javax.crypto.spec.SecretKeySpec") />
      <cfset var mac = createObject("java","javax.crypto.Mac") />

      <cfset key = key.init(jKey,"HmacSHA1") />
      <cfset mac = mac.getInstance(key.getAlgorithm()) />
      <cfset mac.init(key) />
      <cfset mac.update(jMsg) />

      <cfreturn mac.doFinal() />
      </cffunction>

      <cffunction name="createSignature" returntype="string" access="public" output="false">
      <cfargument name="stringIn" type="string" required="true" />

      <!--- Replace "\n" with "chr(10) to get a correct digest --->
      <cfset var fixedData = replace(arguments.stringIn,"\n","#chr(10)#","all")>
      <!--- Calculate the hash of the information --->
      <cfset var digest = HMAC_SHA1(variables.secretAccessKey,fixedData)>
      <!--- fix the returned data to be a proper signature --->
      <cfset var signature = ToBase64("#digest#")>

      <cfreturn signature>
      </cffunction>

      <cfhttp url="http://blambertbackups.s3.amazonaws.com/orig_object.jpg" method="GET" timeout="10"></cfhttp>

      <cfset variables.accessKeyId = "XXXXXX">
      <cfset variables.secretAccessKey = "XXXXXX">
      <cfset arguments.bucketName="XXXXXX">

      <cfset arguments.fileUpload=cfhttp.fileContent>
      <cfset arguments.contentType=cfhttp.mimeType>
      <cfset arguments.fileKey="put_object">
      <cfset arguments.contentEncoding="ISO-8859-1">
      <cfset arguments.HTTPtimeout="300">

      <cfset dateTimeString = GetHTTPTimeString(DateAdd("h", 0, Now()))>
      <cfset cs = "PUT\n\n#arguments.contentType#,#arguments.contentEncoding#\n#dateTimeString#\nx-amz-acl:public-read\n/#arguments.bucketName#/#arguments.fileKey#">

      <!--- Create a proper signature --->
      <cfset 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#" charset="#arguments.contentEncoding#" timeout="#arguments.HTTPtimeout#">
      <cfhttpparam type="header" name="Authorization" value="AWS #variables.accessKeyId#:#signature#">
      <cfhttpparam type="header" name="Content-Type" value="#arguments.contentType#">
      <cfhttpparam type="header" name="Content-Type" value="#arguments.contentEncoding#">
      <cfhttpparam type="header" name="Content-Length" value="#Len(arguments.fileUpload)#">
      <cfhttpparam type="header" name="Date" value="#dateTimeString#">
      <cfhttpparam type="header" name="x-amz-acl" value="public-read">
      <cfhttpparam type="body" value="#arguments.fileUpload#">
      </cfhttp>

        Gliffy Diagrams

          Attachments

            Activity

              People

              • Assignee:
                micstriit Michael Offner
                Reporter:
                blambert Bradley Lambert
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: