Base64 decoding error in coldfusion - coldfusion

I'm trying to decode a base64 string with #ToString( ToBinary( stringToDecode ) )# and coldfusion gives an error saying the parameter must be a base-64 encoded string. The string comes from a third party, and is supposed to be a pdf file. Here is a part of it:
JVBERi0xLjUKJeLjz9MKMSAwIG9iago8PC9UeXBlL1hPYmplY3QvUmVzb3VyY2VzPDw+Pi9TdWJ0 eXBlL0Zvcm0vQkJveFswIDAgMTUuNDQgMTUuNDZdL01hdHJpeCBbMSAwIDAgMSAwIDBdL0xlbmd0 aCAyMi9Gb3JtVHlwZSAxL0ZpbHRlci9GbGF0ZURlY29kZT4+c3RyZWFtCk9lHxbaEDXZpIO1A/Gj mGuxQdW3qkgKZW5kc3RyZWFtCmVuZG9iagoyIDAgb2JqCjw8L1R5cGUvWE9iamVjdC9SZXNvdXJj ZXM8PD4+L1N1YnR5cGUvRm9ybS9CQm94WzAgMCAxNS40NCAxNS4xOV0vTWF0cml4IFsxIDAgMCAx IDAgMF0vTGVuZ3RoIDIyL0Zvcm1UeXBlIDEvRmlsdGVyL0ZsYXRlRGVjb2RlPj5zdHJlYW0KtDN8 NkUKYx04Gj8V9LfOboGvN9VRIgplbmRzdHJlYW0KZW5kb2JqCjMgMCBvYmoKPDwvVHlwZS9YT2Jq ZWN0L1Jlc291cmNlczw8Pj4vU3VidHlwZS9Gb3JtL0JCb3hbMCAwIDE1LjQ0IDE1LjcyXS9NYXRy aXggWzEgMCAwIDEgMCAwXS9MZW5ndGggMjIvRm9ybVR5cGUgMS9GaWx0ZXIvRmxhdGVEZWNvZGU+
What I had thought was the spaces were a problem, but I did a replace to replace all " " with "" and they are still in there. Is there something else I should be doing?

In my testing I can take a local pdf and convert it to a string to mimic the string you are getting from the API. I can then take it and convert it back to a PDF.
When I use the string you put above I cannot get it to work. Not sure if something is list from you pasting it here or not.
Here is my code, maybe you can alter it to use the string right from the api.
<cffile action="readbinary" file="#expandPath('./test.pdf')#" variable="thefile"/>
<cfset the_string = toString(theFile)/>
<cfscript>
patrick_string = ToBase64("JVBERi0xLjUKJeLjz9MKMSAwIG9iago8PC9UeXBlL1hPYmplY3QvUmVzb3VyY2VzPDw+Pi9TdWJ0 eXBlL0Zvcm0vQkJveFswIDAgMTUuNDQgMTUuNDZdL01hdHJpeCBbMSAwIDAgMSAwIDBdL0xlbmd0 aCAyMi9Gb3JtVHlwZSAxL0ZpbHRlci9GbGF0ZURlY29kZT4+c3RyZWFtCk9lHxbaEDXZpIO1A/Gj mGuxQdW3qkgKZW5kc3RyZWFtCmVuZG9iagoyIDAgb2JqCjw8L1R5cGUvWE9iamVjdC9SZXNvdXJj ZXM8PD4+L1N1YnR5cGUvRm9ybS9CQm94WzAgMCAxNS40NCAxNS4xOV0vTWF0cml4IFsxIDAgMCAx IDAgMF0vTGVuZ3RoIDIyL0Zvcm1UeXBlIDEvRmlsdGVyL0ZsYXRlRGVjb2RlPj5zdHJlYW0KtDN8 NkUKYx04Gj8V9LfOboGvN9VRIgplbmRzdHJlYW0KZW5kb2JqCjMgMCBvYmoKPDwvVHlwZS9YT2Jq ZWN0L1Jlc291cmNlczw8Pj4vU3VidHlwZS9Gb3JtL0JCb3hbMCAwIDE1LjQ0IDE1LjcyXS9NYXRy aXggWzEgMCAwIDEgMCAwXS9MZW5ndGggMjIvRm9ybVR5cGUgMS9GaWx0ZXIvRmxhdGVEZWNvZGU+");
string2 = toBinary(ToBase64(the_string));
binencode=BinaryEncode(string2, "Base64");
</cfscript>
<cffile action="write" file="#expandPath('./randy.pdf')#" output="#thefile#" addnewline="No" />
click
Updated Code:
<cffile action="readbinary" file="#expandPath('./test.pdf')#" variable="thefile"/>
<cfset the_string = toBase64(theFile)/>
<cfscript>
string2 = toBinary(the_string);
</cfscript>
<cffile action="write" file="#expandPath('./randy.pdf')#" output="#string2#" addnewline="No" />
click

Here's an updated cfscript way of doing it in case anyone is interested:
<cfscript>
// read the binary file and save it as a variable
myPdf = fileReadBinary( expandPath( "/test.pdf" ) );
// encode as base64
myPdf = toBase64( myPdf );
// output the base64 version to the browser
writedump( myPdf );
// convert back to binary
myPdf = toBinary( myPdf );
// write to a new PDF file
fileWrite( expandPath( "/new.pdf" ), myPdf );
</cfscript>

Related

Coldfusion 2018 No SOF segment Multi-Page TIFF Error

I have a new CF18 server and I'm getting some errors reading and converting some old images that were readable on my previous CF11 server. FYI GetReadableImageFormats results in "BMP,GIF,JPEG,JPEG 2000,JPEG2000,JPG,PNG,PNM,RAW,TIF,TIFF,WBMP"
Normally I read the files as a Binary and put it into memory for manipulation
<cffile action="readBinary" file="#file_location#" variable="binImage" />
<cfimage action="read" source="#binImage#" name="objImage" isbase64="no">
This now results in an error:
"An exception occurred while trying to read the image. No SOF segment in stream"
Reading the file with action="read" and dumping the left(binImage, 999) results:
"...2015:10:07 17:46:58 Kofax standard Multi-Page TIFF Storage Filter v3.03.000,..."
Then I tried reading it into java using:
<cfset tifFileName="#file_location#">
<cfscript>
ss = createObject("Java","com.sun.media.jai.codec.FileSeekableStream").init(tifFileName);
//create JAI ImageDecoder
decoder = createObject("Java","com.sun.media.jai.codec.ImageCodec").createImageDecoder("tiff", ss, JavaCast("null",""));
</cfscript>
Which yields an error:
"Decoding of old style JPEG-in-TIFF data is not supported."
I found this...
Decoding of old style JPEG-in-TIFF data is not supported
Do you think using TwelveMonkeys ImageIO the best path to follow for my issue?
UPDATE: Based on the suggestion that there is an invalid marker 0xFF9E I tried the following:
<cffile action="readBinary" file="#file_location#" variable="binImage" />
<cfset hexEncoding = binaryEncode(binImage, "hex")>
<cfset new_hexEncoding = replaceNoCase(hexEncoding, 'FF9E', 'FFE9', 'ALL')>
<cfset binImage = binaryDecode(new_hexEncoding, "hex")>
isImage(binImage) returns "NO" and the "No SOF segment in stream" error persists. I looped over the hexEncoding and found the FF9E string 23x. I've never edited raw image code so I'm not sure my replace is correct.
Edit: At this point I'm fairly certain my Search and Replace hexEncoding, 'FF9E', 'FFE9' logic is flawed. there is no occurance of 0xff9e in the binaryEncoded binImage.
This was driving me nuts. I tried everything I could find short of installing extra JAVA libraries or routing it through other executables to make the conversion. In my case there is only one JPEG in a TIFF, so I wrote something that literally grabs the binary data for the JPEG out of the TIFF (doesn't account for pages) and serves it up. Once you have the binary of the JPEG you can write it to a file, do conversions on it, even stream it direct to the browser. Here ya go future people who need this. I didn't write it to do pages or detect what kind of tiff it is since for my uses I already know all that. These things are .bin files, but they are all the same single page jpeg in a tiff and I needed a way to serve them up quickly in a format that browsers don't hate. This runs fast enough to be served up on the fly. Is there a better way? Probably, but this works, self contained, copy and paste, and makes complete sense to anyone that needs to edit it.
<cfscript>
strFileName = "test.tiff";
blnOutputImageToBrowser = true;
blnSaveToFile = true;
strSaveFile = GetDirectoryFromPath(GetCurrentTemplatePath())&"test.jpg"
imgByteArray = FileReadBinary(strFileName);
//Convert to HEX String
hexString = binaryEncode(imgByteArray,"hex"); //Convert binary to HEX String, so we can pattern search it
//Set HEX Length
hexLength = arraylen(imgByteArray);
//Find Start of JPG Data in HEX String
jpegStartHEX = find("FFD8FF",hexString);
jpegStartBIN = (jpegStartHEX-1)/2; //-1 because CF arrays start on 1 and everyone else starts on 1. /2 because the HEX string positions are double the byte array positions
objByteBuffer = CreateObject("java","java.nio.ByteBuffer"); //Init JAVA byte buffer class for us to use later (this makes it go faster than trying to convert the hex string back to binary)
//Find Stop of JPG Data
jpegStopHEX = 0;
jpegStopBIN = 0;
intSearchIDX = jpegStartHEX+6; //Might as well start after the JPEG start block
blnStop = false;
while (intSearchIDX < len(hexString) && jpegStopHEX == 0 && !blnStop) {
newIDX = find("FFD9",hexString,intSearchIDX);
if (newIDX == 0) {
blnStop=true;
}
else {
if (newIDX%2 == 0) { //bad search try again (due to indexing in CF starting on 1 instead of 0, the even numbers are in between hex code [they are pairs like 00 and FF])
intSearchIDX = newIDX+1;
}
else { //Found ya
jpegStopHEX = newIDX;
blnStop=true;
}
}
}
jpegStopBIN = (jpegStopHEX-1)/2; //-1 because CF arrays start on 1 and everyone else starts on 1. /2 because the HEX string positions are double the byte array positions
//Dump JPG Binary into ByteArray from the start and stop positions we discovered
jpegLengthBIN = jpegStopBIN+2-jpegStartBIN;
objBufferImage = objByteBuffer.Allocate(JavaCast( "int", jpegLengthBIN ));
objBufferImage.Put(imgByteArray,JavaCast( "int", jpegStartBIN ),JavaCast( "int", jpegLengthBIN ));
if (blnSaveToFile) { //Dump byte array into test file
fileWrite(strSaveFile,objBufferImage.Array());
}
if (blnOutputImageToBrowser) {
img = ImageNew( objBufferImage.Array() );
ImageResize(img,"1200","","highestPerformance"); //Because we might as well show an example of resizing
outputImage(toBinary(toBase64(img))); //You could skip loading the byte array as an image object and just plop the binary in directly if you don't need to manipulate it any
}
</cfscript>
<cffunction name="outputImage" returntype="void">
<cfargument name="binInput" type="binary">
<cfcontent variable="#binInput#" type="image/png" reset="true" />
<cfreturn>
</cffunction>

Some Functions seems to be not exist when creating new bucket or checking if bucket exists using OpenBD

I am using OpenBD and trying to check whether bucket exists or not on my S3 server, if it is not exist then, to create new bucket. Here's my code:
index.cfm
<cfset request.awsaccess = "zzzzawsaccesszzzz">
<cfset request.awskey = "zzzzzzzzawskeyzzzzzzzz">
<cfset request.datasource="tcs">
<cfset request.region="us-west-2">
<cfscript>
AmazonRegisterdatasource(datasource=request.datasource,awsaccess=request.awsaccess,awskey=request.awskey,region=request.region );
result = AmazonS3listbuckets( datasource=request.datasource );
WriteDump(result);
WriteOutput(result.bucket[1]);
</cfscript>
For the above code I am getting this output:
Now I am adding one more function AmazonS3createbucket(),
<cfscript>
result = AmazonS3createbucket( datasource=request.datasource, bucket="anyBucket" );
</cfscript>
For the above script I am getting error: that No such function exists - amazons3createbucket.. Here's the screenshot:
I am referring the OpenBD Manual to filter these function.
Also faced the same problem while using this functions also:
<cfscript>
result = AmazonS3bucketexists( datasource=request.datasource, bucket="anyBucket" );
</cfscript>
Have you tried using an alternate syntax?
<cfscript>
result = AmazonS3bucketexists(ArgumentCollection = {
datasource : request.datasource,
bucket : "anyBucket"
});
</cfscript>

ColdFusion hash_hmac256 output format / encoding

I have this script to output an hash_hmac similar function in CFML:
<cfprocessingdirective pageencoding = "iso-8859-1">
<cfset msg = "AgostinoSqueglinPiccolinMonachin">
<cfset jMsg = JavaCast("string",msg).getBytes() />
<cfset jKey = JavaCast("string","cicciolin").getBytes() />
<cfset key = createObject("java","javax.crypto.spec.SecretKeySpec") />
<cfset mac = createObject("java","javax.crypto.Mac") />
<!--- this line had to be changed to the 256 version --->
<cfset key = key.init(jKey,"hmacSHA256") />
<cfset mac = mac.getInstance(key.getAlgorithm()) />
<cfset mac.init(key) />
<cfset mac.update(jMsg) />
<cfset cc = mac.doFinal()>
<cfset strBase64Value = ToString( cc,"Utf-8" ) />
<cfscript>
writeDump(msg);
writeDump(strBase64Value);
</cfscript>
This should output the same result as this php:
<?php
$uu = hash_hmac('sha256', "AgostinoSqueglinPiccolinMonachin", "cicciolin", true);
echo $uu;
?>
But I got this different result, due probably to an format error:
ColdFusion : �GK�襍}Ÿ�}��B�}9w�(���u�m�
PHP: ÐGKÒè¥}Ÿ»}©ì¬B§}9w´(«æüu§mÃ
Seems some characters does not output in the correct way.
How can I solve this?
UPDATE:
The solution works perfectly, but there are other problem if I try to encode new line:
for example
Php:
$sign = "GET\n" . "agostinsqueglin" . "". "piccolin";
$uu = base64_encode(hash_hmac('sha256', $sign, "cicciolin", true));
If I try with:
sign = "GET#chr(13)##chr(10)#" & "agostinsqueglin" & "" & "piccolin";
I got two different results.
This is due to the way coldfusion handling "\n" newline...
The code you've provided is a little more long-winded than it needs to be, and ... well, here's an improved version:
<cfscript>
msg = "AgostinoSqueglinPiccolinMonachin";
key = "cicciolin";
algorithm = "HmacSHA256";
encoding = "iso-8859-1";
secret = createObject('java',"javax.crypto.spec.SecretKeySpec").init( charsetDecode(key,encoding) , algorithm );
mac = createObject('java',"javax.crypto.Mac").getInstance(algorithm);
mac.init(secret);
digest = mac.doFinal( charsetDecode(msg,encoding) );
writeDump( msg );
writeDump( toString(digest,encoding) );
</cfscript>
This is based on the answer and comments here: Calculate HMAC-SHA256 digest in ColdFusion using Java
Obviously for regular use it should be wrapped up in a suitable function.
It looks like you're trying to output a UTF-8 string while your processingdirective is set to iso-8859-1. Try changing it:
<cfprocessingdirective pageencoding = "UTF-8">

How to create Java object in CFSCRIPT?

I am using ColdFusion 9.1.0
I am trying to create a java object using CFSCRIPT and I just can't get the right combination of stuff to work.
This works perfectly:
<cfobject action="create" type="Java" class="CyberSource" name="auth">
<cfset VARIABLES.ResponseString = auth.runTransaction(LOCAL.PropsFile,LOCAL.MyXML)>
When I do this, I get an error:
LOCAL.MyObject = createObject("java", "CyberSource.auth");
LOCAL.ResponseString = auth.runTransaction(LOCAL.PropsFile,LOCAL.MyXML);
This is the error I get:
Object Instantiation Exception.
Class not found: CyberSource.auth
The object is an external piece of code available to ColdFusion. I don't see what the problem is. Do you?
The classname is CyberSource and the variable you are trying to assign the instance to is "auth" in your tagbased approach. You mixed it up with "MyObject".
LOCAL.auth = createObject("java", "CyberSource");
LOCAL.ResponseString = LOCAL.auth.runTransaction(LOCAL.PropsFile,LOCAL.MyXML);
This should work.
One thing to be aware of.
The java class names are case sensitive!
// Fail
myFile = createObject( 'java', 'java.io.file' );
// Win!
myFile = createObject( 'java', 'java.io.File' );
And to call their constructor, use .init() eg.
myFile = createObject( 'java', 'java.io.File' ).init( '/Users/Mike/Dev/Test' );

Downloading large file in ColdFusion using CFHTTP

I'm trying to download a large (600MB) binary file to the server using CFHTTP on Coldfusion 8:
<cfhttp
method="get"
url="#fileURL#"
path="#filePath#"
file="#fileName#"
timeout="600"
getasbinary="auto"
>
It's working fine for smaller files (100something MB) but for the large one's I'm getting the Server 500 error: "java.lang.OutOfMemoryError: Java heap space".
The file is being downloaded from a Dropbox folder - so only available option is to use HTTP GET.
Does anyone have idea how to download it, so it wouldn't kill the server or timeout?
You can do this by calling Java from CF code. The buffered input and output stream classees are designed to hold onto chunks of data, rather than the whole thing, avoiding OutOfMemory errors.
getByteArray() is a helper method because there's not way to declare something like byte buf[]=new byte[1024]; in CF directly.
In the example change the source and destination variables.
Example
<cfset source = 'protocol://domain/path/to/file.ext'>
<cfset destination = getDirectoryFromPath(getCurrentTemplatePath()) & listlast(source, "/")>
<cffunction name="getByteArray" access="private" returnType="binary" output="no">
<cfargument name="size" type="numeric" required="true"/>
<cfset var emptyByteArray =
createObject("java", "java.io.ByteArrayOutputStream").init().toByteArray()/>
<cfset var byteClass = emptyByteArray.getClass().getComponentType()/>
<cfset var byteArray =
createObject("java","java.lang.reflect.Array").newInstance(byteClass, arguments.size)/>
<cfreturn byteArray/>
</cffunction>
<cfscript>
uri = createObject("java", "java.net.URL").init(source);
uis = uri.openStream();
bis = createObject("java", "java.io.BufferedInputStream").init(uis);
fos = createObject("java", "java.io.FileOutputStream").init(destination);
bos = createObject("java", "java.io.BufferedOutputStream").init(fos);
buffer = getByteArray(1024);
len = bis.read(buffer);
while(len > 0) {
bos.write(buffer,0,len);
len = bis.read(buffer);
}
bos.close();
bis.close();
fos.close();
uis.close();
</cfscript>
The problem is is that it's too large. ColdFusion reads the entire thing into memory before writing it to disk.
You'll be better off using some other method to get the file. wget can do http requests from a command-line. That with judicious use of CFEXECUTE is probably a good way to go.