I'm trying to write a Coldfusion script that compresses JavaScript files using a recent version of Google's closure compiler.
This program ends with two errors:
JSC_UNDEFINED_VARIABLE. variable module is undeclared at jquery-3.1.1.js line 9767 : 12
JSC_UNDEFINED_VARIABLE. variable define is undeclared at jquery-3.1.1.js line 9784 : 13
I wonder what's the magic. module and define are common JS variables; I trust Closure knows them. What setting am I missing? Is there an extern missing? Do I have to set a certain CompilerOption?
<cfset options = createObject( "java", "com.google.javascript.jscomp.CompilerOptions" ).init()>
<cfset cl = createObject( "java", "com.google.javascript.jscomp.CompilationLevel" )>
<cfset wl = createObject( "java", "com.google.javascript.jscomp.WarningLevel" )>
<cfset cl.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options)>
<cfset cl.SIMPLE_OPTIMIZATIONS.setDebugOptionsForCompilationLevel(options)>
<cfset lm = createobject( "java", "com.google.javascript.jscomp.CompilerOptions$LanguageMode" )>
<cfset options.setEnvironment(options.Environment.BROWSER)>
<cfset schar = createobject( "java", "java.nio.charset.StandardCharsets")>
<cfset options.setOutputCharset( schar.UTF_8 )>
<cfset wl.VERBOSE.setOptionsForWarningLevel(options)>
<cfset comp = createObject( "java", "com.google.javascript.jscomp.Compiler" ).init()>
<cfset clr = createObject( "java", "com.google.javascript.jscomp.CommandLineRunner" )>
<cfset sourceFile = createObject( "java", "com.google.javascript.jscomp.SourceFile" )>
<cfset arrInputs = createObject( "java", "java.util.ArrayList" ).init()>
<cfset arrExterns = createObject( "java", "java.util.ArrayList" ).init()>
<cfset arrInputs.add(
sourceFile.fromCode(
javaCast( "string", "jquery-3.1.1.js" ),
javaCast( "string", fileRead( expandPath( "../advanced/js/jquery-3.1.1.js" ), "utf-8" ) )
)
)>
<cfset arrExterns.addAll( clr.getBuiltinExterns(options.Environment) )>
<cfset result = comp.compile( arrExterns, arrInputs , options )>
<cfoutput>
|#result.success#|
<cfloop from="1" to="#arrayLen( result.errors )#" index="i">
err: #result.errors[i]#<br>
</cfloop>
</cfoutput>
module and define are common JS variables
module is typically an indicator of the CommonJS module system. define is used by the AMD module system. Neither are default JS variables or known to browsers.
jQuery is using a Universal Module Definition pattern to export the jQuery object either as a module (CommonJS or AMD as appropriate), or if none are found, as a global variable. Closure-compiler can recognize this pattern and remove the module specific parts when the --process_common_js_modules flag is specified.
Related
I am having issues using the cf9 encrypt and decrypt function. Specifically,the code I use needs to be able to encrypt with AES/ECB/PKCS5Padding 256. I am trying to post data to a third party bank with the following code:
<cfparam name="theKey" default="someStaticKey">
<cfset strName = leaddetail.leadlast&','&leaddetail.leadfirst />
<cfset stFields = {requesttype = "eftaddonetimecompletetransaction"
,clientid = "XXXXXX"
,urltoredirect = "#RedirectURl#"
,customerid = "#leaddetail.leadid#"
,isdebitcardonly = "No"
,customername = "#strName#"
,customeraddress1 = "#form.billingaddress#"
,customercity = "#form.billingcity#"
,customerstate = "#form.billingstate#"
,customerzip = "#form.billingzip#"
,cardbillingaddr1 = "#form.billingaddress#"
,cardbillingcity = "#form.billingcity#"
,cardbillingstate = "#form.billingstate#"
,cardbillingzip = "#form.billingzip#"
,accounttype = "CC"
,name_on_card = "#form.leadname#"
,accountnumber = "#form.ccacctnum#"
,expmonth = "#Left(form.ccexpdate,2)#"
,expyear = "#Right(form.ccexpdate,2)#"
,cvvcode = "#form.ccv2#"
,amount = "#NumberFormat(esigninfo.esignpayamt,'9999.99')#"
,startdate = "#DateFormat(Now(),'YYYY-MM-DD')#"
,transactiontypecode = "WEB"}/>
<cfset theEncryptedStr = ToBase64(encrypt(serializeJson(stFields),theKey))>
<!--- shake hands and login to api --->
<cfhttp url="https://www.somebank.com/cgi-bin/wsnvptest.vps" method="post" charset="ISO-8859-1" throwonerror="yes" result="httpResponse">
<!--- login Variables --->
<cfhttpparam type="Header" name="User-Agent" value="Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.41">
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded" >
<cfhttpparam type="header" name="Accept" value="application/json" >
<!--- Login Credentials --->
<cfhttpparam type="formfield"name="nvpvar"value="''"/>
<cfhttpparam type="formfield"name="requesttype"value="login"/>
<cfhttpparam type="formfield"name="userid"value="Dauserid"/>
<cfhttpparam type="formfield"name="password"value="password"/>
<cfhttpparam type="formfield"name="requestid"value="#uniquerequestid#"/>
<cfhttpparam type="formfield"name="PostData" value="#theEncryptedStr#"/>
<cfif isDefined('CheckSession.sessionID') AND CheckSession.sessionID NEQ ''>
<cfhttpparam type="formfield"name="sessionid" value="#checkSession.sessionID#"/>
</cfif>
</cfhttp>
for some reason I can encrypt but cant decrypt the response. Is there anyone out there that has more experience with this that can put on a path to success?
(Update from rejected edit)
I am using the following script to decrypt my cfhttp response string:
<cfset content = httpResponse.filecontent>
<cfset authdata = structNew()>
<cfloop index="line" list="#content#">
<cfset dtype = listFirst(line, "=")/>
<cfset EncodedString = listRest(line, "=")/>
<cfset authdata[dtype] = EncodedString />
</cfloop>
<cfscript>
keyInBase64 = "Some64baseKey;
// Now decrypt the base64 encoded encryption string
decryptedValue = decrypt(EncodedString , keyInBase64 , "AES/ECB/PKCS5Padding" , "base64" );
WriteDump(variables);
</cfscript>
The string I am trying to decrypt looks similar to the following:
nvpvar=fKsJGJ-Fe-2zoqUROAeE8N8a87USuQpE7dVd5IvRa67cHsVkPwx9taKLuXKwsCKFC_-NW3j6IOQAvCnRNc4cRNfq2fqyRHBUrFbFDCCmwpk=
encrypt(serializeJson(stFields),theKey)
First, that is NOT AES encryption. You omitted the algorithm parameter, so encrypt() defaults to the legacy CFMX_COMPAT algorithm (weakest). CFMX_COMPAT it is not a "real" encryption algorithm at all, so do not use it - for anything!
Second, with AES you are limited to 128 bit keys out of the box. In order to use 256 bit keys you must first install the (JCE) Unlimited
Strength Jurisdiction Policy Files.
Copy them into your /lib/security/ directory. Then restart the CF server to apply the changes.
Note: If you have multiple JVM's installed,
be sure to update the correct one. ie The one listed in
the CF Administrator).
After restarting, you will be able to encrypt with a 256 bit key. With ECB mode, the syntax is: encrypt(string, key, algorithm, encoding)
string - plain text to encrypt
key - a 256 bit key, must be base64 encoded
algorithm - single string representing the desired: algorithm, mode and padding scheme. Note: "AES" is actually a shorthand for the longer "AES/ECB/PKCS5Padding"
encoding - "The binary encoding in which to represent the data as a string"
Putting it all together:
<cfscript>
// some sample data to encrypt
stFields = { clientid = "AA-BB-CC-123"
, customername = "ABC Incorporated"
};
// some 256 bit key, must be base64 encoded
// hard coded for demo purposes only
keyInBase64 = "9NJU2L3FZ8Rr0WKZUFC3lyE/yRrQ7sIZmQRk3kx9MLE=";
// AES encrypt the value, and base64 encode the result
encryptedValue = encrypt( serializeJson(stFields)
, keyInBase64
, "AES/ECB/PKCS5Padding"
, "base64"
);
// Now decrypt the base64 encoded encryption string
decryptedValue = decrypt( encryptedValue
, keyInBase64
, "AES/ECB/PKCS5Padding"
, "base64"
);
// display results
WriteDump( variables );
</cfscript>
Update based on comments:
I notice you are manipulating the raw http response string. Without seeing the API, I would guess that either a) You need to decrypt the whole string first, then extract the parts -OR- b) the code is not extracting the values correctly and that is why you cannot decrypt it. The cfloop treats the response as a comma separated list. Based on the variable names, I am guessing it is actually separated by new lines instead, ie:
param1=xxxxx -- new line
param2=yyyyy -- new line
param3=zzzzz
Those are just guesses though. Check your API. What is the actual format of the returned response? Also, can you please edit your question to include the full error message?
I am using the following code to encrypt user password.
<cfset "EncryptedNewPass" = Encrypt(#HTMLCodeFormat(NewPass)#, Request.PasswordKey)>
Then compare it to the value stored in the database and it works fine. However, if i get the value from the database and use decrypt as follows
<cfset DecryptedPass = Decrypt(#getOrigPassFP.pass#, Request.PasswordKey)>
and do cfout, the value is wrapped with <pre> </pre> tag. The issue that I am having is since we also use the password to open a PDF document, it is throwing an error. I tried using replace to strip the tag but when it is displayed or passed to a variable, it still contains the <pre> tag.
You are putting the <pre> tags in there yourself!! What do you think HTMLCodeFormat() does??!
From the comments: I understand what you are saying but my issue is how do I remove the pre tags once it is decrypted before encrypting it back?
The following code is one example of how to remove the <PRE> and </PRE> tags from your decrypted values. (I am outputting all of the values so you can follow along when you execute this code.)
<cfset NewPass = "this_is_the_password">
<cfset PasswordKey = "this_is_the_really_weak_key">
<cfset EncryptedNewPass = Encrypt(HTMLCodeFormat(NewPass), PasswordKey)>
<cfset DecryptedPass = Decrypt(EncryptedNewPass, PasswordKey)>
<cfoutput>
<p>NewPass = #NewPass#</p>
<p>PasswordKey = #PasswordKey#</p>
<p>EncryptedNewPass = #EncryptedNewPass#</p>
<p>DecryptedPass = #HTMLEditFormat(DecryptedPass)#</p>
<cfif Left(DecryptedPass,5) EQ "<PRE>">
<cfset DecryptedPass = Right(DecryptedPass,(Len(DecryptedPass)-5))>
<p>Found and removed <PRE> tag = #HTMLEditFormat(DecryptedPass)#</p>
</cfif>
<cfif Right(DecryptedPass,6) EQ "</PRE>">
<cfset DecryptedPass = Left(DecryptedPass,(Len(DecryptedPass)-6))>
<p>Found and removed </PRE> tag = #HTMLEditFormat(DecryptedPass)#</p>
</cfif>
</cfoutput>
Looking at that code, this block will remove the <PRE> from the beginning of the string:
<cfif Left(DecryptedPass,5) EQ "<PRE>">
<cfset DecryptedPass = Right(DecryptedPass,(Len(DecryptedPass)-5))>
<p>Found and removed <PRE> tag = #HTMLEditFormat(DecryptedPass)#</p>
</cfif>
And this block will remove the </PRE> from the end of the string:
<cfif Right(DecryptedPass,6) EQ "</PRE>">
<cfset DecryptedPass = Left(DecryptedPass,(Len(DecryptedPass)-6))>
<p>Found and removed </PRE> tag = #HTMLEditFormat(DecryptedPass)#</p>
</cfif>
I only used HTMLEditFormat() to output the values for you to see in the browser. Do NOT use these functions when encrypting or decrypting your values.
You also need to be aware that the HTMLCodeFormat() function does more than just wrap the given string in <PRE> tags. That function also changes the characters: <, >, &, and " to their HTML character entity equivalent. If any of your users used those characters in their password then your decryption of them will fail (will not be equal to their actual password).
This function converts the following characters to HTML character entities:
Text character Encoding
< <
> >
& &
" "
I am updating some code as we are now on a US server but we are based in the UK so our timezones need to be changed with both dates and times.
I created this script.
<cfset tztemp = GetTimeZoneInfo()>
<cfset isDST = tztemp.isDSTOn >
<cfif isDST eq "Yes">
<cfset dtGMT = #CreateODBCDateTime(DateAdd("s",tztemp.utcTotalOffset+3600,now()))#>
<cfelse>
<cfset dtGMT = #CreateODBCDateTime(DateAdd("s",tztemp.utcTotalOffset,now()))#>
</cfif>
My question is how would I change the value #dtGMT# into the formats below?
#DateFormat(Now(), "YYMMDD")#
#TimeFormat(Now(), "HHMM")#
Thankyou
#DateFormat(dtGMT, "YYMMDD")#
#TimeFormat(dtGMT "HHMM")#
In my application the user uploads a photos and the cfc resizes the photo, creates a new image and resizes that new image to a thumbnail. Trouble is, this function wasn't available earlier on in the game. I want to now look at the images directory and figure out which images don't have thumbnails.
I'm thinking that I could use cfdirectory to output a struct of both directories then loop over the files that only exist in the images and not in the thumbnails directory and run a function to resize the images and send them to the thumbnails directory.
Is this flawed thinking? Is there an easier way?
That's a perfectly reasonable approach, and you don't even have to use recursive code. Just use the recursive option in CFDirectory to get a list of all files and use both the file name and path combined as the key, which guarantees a unique file you're checking. You may have to modify the result a bit so you know exactly where to put the new thumbnail, but this should get you pretty close.
<cfset originals_path = expandPath('originals') />
<cfset thumbs_path = expandPath('thumbs') />
<cfset no_thumbs = find_missing_thumbs(originals_path, thumbs_path) />
<cfdump var="#no_thumbs#" />
<cffunction name="find_missing_thumbs">
<cfargument name="o" />
<cfargument name="t" />
<cfset var originals = 0 />
<cfset var thumbs = 0 />
<cfset var missing_thumbs = [] />
<cfset var massaged_originals = 0 />
<cfset var massaged_thumbs = 0 />
<cfset var qSearch = 0 />
<cfdirectory action="list" directory="#arguments.o#" name="originals" recurse="true" />
<cfdirectory action="list" directory="#arguments.t#" name="thumbs" recurse="true" />
<cfquery name="massaged_originals" dbtype="query">
select name, directory + name as fullpath from originals
</cfquery>
<cfquery name="massaged_thumbs" dbtype="query">
select name, directory + name as fullpath from thumbs
</cfquery>
<cfloop query="massaged_originals">
<cfquery name="qSearch" dbtype="query">
select massaged_thumbs.name from massaged_thumbs where massaged_thumbs.fullpath = '#massaged_originals.fullpath#'
</cfquery>
<cfif qSearch.recordCount eq 0>
<cfset arrayAppend(missing_thumbs, massaged_originals.name) />
</cfif>
</cfloop>
<cfreturn missing_thumbs />
</cffunction>
Using CF8 and MySQL 5.1, I am trying to encrypt() a password upon creation and then decrypt() at login. I can get the decrypt() to work fine on a test page but when I put it in a cfincluded page with cflogin I get the error "An error occurred while trying to encrypt or decrypt your input string: com.rsa.jsafe.crypto.dr: Could not perform unpadding: invalid pad byte.. ". It is the same code and DB from my test page to my app.
application.cfc:
<cfif NOT IsDefined("Request.PasswordKey")>
<cfset request.PasswordKey = generateSecretKey("AES")>
<cfset request.algorithm = "AES">
<cfset request.encoding = "hex">
</cfif>
test page which works fine:
FORM DATA: <br/>
form password:<cfoutput>#form.passwd#</cfoutput><br/>
<cfset encrypted = Encrypt(form.passwd,Request.PasswordKey,Request.algorithm,Request.encoding)>
Encrypted: <cfoutput>#encrypted#</cfoutput><br/>
Decrypted: <cfoutput>#Decrypt(variables.encrypted,Request.PasswordKey,Request.algorithm,Request.encoding)#</cfoutput><br/>
<br/>
QUERY DATA<br/>
<cfinvoke component="components.userQ" method="login" returnvariable="qLogin">
<cfinvokeargument name="formData" value="#form#">
</cfinvoke>
<cfoutput>qLogin password: #qlogin.encPasswd#</cfoutput><br/>
<cfoutput>Decrypted encPasswd from qLogin: #Decrypt(qlogin.encPasswd,Request.PasswordKey,Request.algorithm,Request.encoding)#</cfoutput>
Decrypt() in app page that is erroring:
<cfset unEnPasswd = #Decrypt(qlogin.encPasswd,Request.PasswordKey,Request.algorithm,Request.encoding)#>
I can get the default CFMX_COMPAT encrypt() and decrypt() to work fine in my app with the same code, just changing the key, algorithm, and encoding variables.
BTW, I am also storing the encrypted strings as varchar() in the DB so it doesn't mess up the padding (so I read). I tried BLOB but get a bytearray error.
Any help or thoughts are greatly appreciated.
You're creating a new secret key on every request,
Really your code should be more like:
<cffunction name="onApplicationStart" returnType="boolean" output="false">
<cfset application.PasswordKey = generateSecretKey("AES")>
</cffunction>
<cffunction name="onRequestStart" returnType="boolean" output="false">
<cfset request.PasswordKey = application.PasswordKey />
<cfset request.algorithm = "AES" />
<cfset request.encoding = "hex" />
</cffunction>
Though really you want to have the password key hardcoded in a config file otherwise if you restart your server you won't be able to access any of your passwords ever again...
Disable jsafe. Add -Dcoldfusion.disablejsafe=true to your jvm config.