Last active
March 14, 2025 01:14
-
-
Save JamoCA/fbbd2599102216448ada8e9f85d40b9c to your computer and use it in GitHub Desktop.
This file contains 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
<cfscript> | |
/* | |
* getQRSVG UDF | |
* @displayname getQRSVG | |
* @Dependency Requires Zint executable from https://zint.org.uk/ | |
* @Dependency_Documentation https://zint.org.uk/manual/chapter/4 | |
* @author James Moberg http://sunstarmedia.com, @sunstarmedia | |
* @version 1 | |
* @lastUpdate 2025-03-13 | |
* @gist https://gist.github.com/JamoCA/fbbd2599102216448ada8e9f85d40b9c | |
* @blog https://dev.to/gamesover/coldfusion-getqrsvg-returns-responsive-svg-source-37hf | |
* @twitter https://x.com/gamesover/status/1900234390921502840 | |
* @LinkedIn https://www.linkedin.com/posts/jamesmoberg_coldfusion-getqrsvg-udf-returns-responsive-activity-7306001304919650305-CcRp | |
* @param String data The data to encode. | |
* @param String exePath The filepath to the Zint executable. | |
*/ | |
string function getQRSVG(required string data, string exePath="") hint="I create a temp SVG file and return the SVG source code (requires zint.exe)" { | |
local.sanitizedData = tostring(arguments.data).replaceAll("""", "\"""); | |
local.cmd = "-b 58 --scale=8 --direct --filetype=svg -d ""#local.sanitizedData#"""; | |
try { | |
cfexecute(name="#arguments.exePath#", arguments="#local.cmd#", timeout="90", variable="local.svg"); | |
} catch (any error){ | |
throw(message="getQRSVG UDF: Zint.exe error"); | |
} | |
if (!find("<?xml", local.svg) || !find("<!", local.svg)){ | |
throw(message="getQRSVG UDF: Zint.exe generated invalid SVG QR Code."); | |
} | |
local.svg = replace(local.svg, "<desc>Zint Generated Symbol</desc>", "<desc>#encodeforxml(arguments.data)#</desc>"); | |
// replace fixed width/height to make responsive | |
local.wResults = refindnocase("width\s*=\s*""(\d+)+", local.svg, 1, true); | |
local.w = val(local.wResults.match[2]); | |
local.hResults = refindnocase("height\s*=\s*""(\d+)+", local.svg, 1, true); | |
local.h = val(local.hResults.match[2]); | |
local.svg = local.svg.replaceAll('width="\d+" height="\d+"', 'viewbox="0 0 #val(local.w)# #val(local.h)#" style="width:100%; display:block;"'); | |
// remove xml header & html doctype | |
local.svg = local.svg.replaceAll("\<\?xml.*?\>", "").replaceAll("\s*\<\!.*?\>", ""); | |
return trim(local.svg); | |
} | |
</cfscript> |
This file contains 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
<cfscript> | |
/** | |
* generateZint UDF | |
* @displayname generateZint | |
* @Dependency Requires Zint executable from https://zint.org.uk/ | |
* @Dependency_Documentation https://zint.org.uk/manual/chapter/4 | |
* @author James Moberg http://sunstarmedia.com, @sunstarmedia | |
* @version 1 | |
* @lastUpdate 2024-10-30 16:00 Pacific | |
* @gist https://gist.github.com/JamoCA/fbbd2599102216448ada8e9f85d40b9c | |
* @blog https://dev.to/gamesover/coldfusion-wrapper-for-zint-barcode-generator-15mc | |
* @twitter https://x.com/gamesover/status/1851768390760960101 | |
* @LinkedIn https://www.linkedin.com/posts/jamesmoberg_coldfusion-activity-7257534479445962752-aeoL | |
* @param String filepath The path and file name to use when storing the generated file. (These params can also be defined in "options".) | |
* @param String barcodeType The barcode type. Normally a integer, but also accepts "QR". (https://zint.org.uk/manual/chapter/4#selecting-barcode-type) | |
* @param String data The data to encode. | |
* @param String exePath The filepath to the Zint executable. | |
* @param struct options All of the configuration data. Some very basic defaults are used if nothing is passed. | |
*/ | |
struct function generateZint(string filepath="", string barcodeType=58, string data="", string exePath="", struct options={}) { | |
local.timestart = gettickcount(); | |
local.response = [ | |
"success": false | |
,"duration": 0 | |
,"filePath": "" | |
,"cmd": "" | |
,"output": "" | |
,"errors": [] | |
]; | |
local.options = duplicate(arguments.options); | |
// reset some primary values if found in options & validate | |
if (local.options.keyexists("exePath")){ | |
arguments.exePath = local.options.exePath; | |
structdelete(local.options, "exePath"); | |
} | |
if (!fileexists(arguments.exePath)){ | |
arrayappend(local.response.errors, "exePath is required."); | |
} | |
if (local.options.keyexists("o")){ | |
arguments.filePath = local.options.o; | |
structdelete(local.options, "o"); | |
}else if (local.options.keyexists("filePath")){ | |
arguments.filePath = local.options.filePath; | |
structdelete(local.options, "filePath"); | |
} | |
if (!len(arguments.filepath)){ | |
arrayappend(local.response.errors, "filePath is required."); | |
} | |
if (local.options.keyexists("b")){ | |
arguments.barcodeType = local.options.b; | |
structdelete(local.options, "b"); | |
} else if (local.options.keyexists("barcodeType")){ | |
arguments.barcodeType = local.options.barcodeType; | |
structdelete(local.options, "barcodeType"); | |
} | |
arguments.barcodeType = (arguments.barcodeType eq "qr") ? 58 : arguments.barcodeType; | |
if (!val(arguments.barcodeType)){ | |
arrayappend(local.response.errors, "barcodeType is required."); | |
} | |
if (local.options.keyexists("d")){ | |
arguments.data = local.options.d; | |
structdelete(local.options, "d"); | |
} else if (local.options.keyexists("data")){ | |
arguments.data = local.options.data; | |
structdelete(local.options, "data"); | |
} | |
if (!issimplevalue(arguments.data) || !len(arguments.data)){ | |
arrayappend(local.response.errors, "data is required."); | |
} | |
// populate options with some default setting (if empty) | |
if (!structcount(local.options)){ | |
// if QR code, set default options for barcode type 58 | |
if (arguments.barcodeType eq 58){ | |
local.options = [ | |
"scale": javacast("int", 12) | |
,"fg": javacast("string", "000000") | |
,"bg": "ffffff" | |
,"nobackground": true | |
,"whitesp": javacast("int", 2) | |
,"vwhitesp": javacast("int", 2) | |
]; | |
// default scale | |
} else { | |
local.options = [ | |
"scale": javacast("int", 5) | |
]; | |
} | |
} | |
local.cmd = [ | |
"-o ""#arguments.filePath#""" | |
,"-b #javacast("int", val(arguments.barcodeType))#" | |
]; | |
if (structcount(local.options)){ | |
for (local.p in local.options){ | |
local.v = trim(local.options[local.p]); | |
if (refindnocase("^([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$", local.v)){ | |
local.v = javacast("string", local.v); // hex | |
} else if (isvalid("integer", local.v)) { | |
local.v = javacast("int", local.v); // integers | |
} else if (refind(local.v, "[:space:]")){ | |
local.v = """#local.v#"""; // values with spaces | |
} | |
if (local.p eq "nobackground"){ | |
if (isvalid("boolean", local.v) && local.v){ | |
arrayappend(local.cmd, "--nobackground"); | |
} | |
} else if (len(local.p) gt 1){ | |
local.s = len(trim(local.v)) ? "--#local.p#=#local.v#" : "--#local.p#"; | |
arrayappend(local.cmd, local.s); | |
} else if (len(local.p) eq 1){ | |
local.s = len(trim(local.v)) ? "-#local.p# #local.v#" : "-#local.p#"; | |
arrayappend(local.cmd, local.s); | |
} | |
} | |
} | |
arrayappend(local.cmd, "-d ""#replace(arguments.data, """", "\""", "all")#"""); | |
local.response["cmd"] = arraytolist(local.cmd, " "); | |
if (!arraylen(local.response.errors)){ | |
cfexecute(name="#arguments.exePath#", arguments="#local.response.cmd#", timeout="90", variable="local.response.output"); | |
local.response.success = fileexists(arguments.filePath); | |
local.response.filePath = fileexists(arguments.filePath) ? arguments.filePath : ""; | |
} | |
local.response.duration = javacast("int", gettickcount() - local.timestart); | |
return local.response; | |
} | |
/* Example | |
testImageName = "this-is-a-test.svg"; | |
options = [ | |
"filePath": "D:\www\#testImageName#" | |
,"data": "This is a test" | |
,"exePath": "C:\zint\zint.exe" | |
]; | |
zintData = request.generateZint(options=options); | |
writeoutput('<img src="/#testImageName#" style="width:250px; height:auto;">'); | |
writedump(var=zintData, label="zintData"); | |
*/ | |
</cfscript> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment