Question Anna Golitsyna · Sep 13, 2023

Cache: Binary export output

I have an odd binary result exporting a specific routine via Studio, Export. Below is the beginning. The seemingly same routine in a different directory is exported fine, regular human readable code. Inspecting ^ROUTINE and ^rIndex did not give me any clues. Any insights?

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25" zv="Cache for Windows (x86-64) 2017.2.1 (Build 801U)" ts="2023-09-13 10:49:52">
<RoutineBase64 name="Utils" type="INT" languagemode="0" timestamp="66728,61062.933847">VXRpbHMJOyBVdGlsaXR5IE1ldGhvZHM7MjAyMy0wOS0xMSAxNjo1Nzo0MiBBTgoJcSAKY2hrQ3Ry
bChmaXg9MCkKCWsgXmdnRwoJcyB0PSJeUkZHIgoJcyBjdHI9MAoJdyAiUkZHIiwhCglmICBzIHQ9

Product version: Caché 2017.1

Comments

Pravin Barton · Sep 13, 2023

This can happen if the routine contains an ASCII character that cannot be printed to XML. Here is an example from a routine I created:

> set routine = ##class(%Routine).%OpenId("pbarton.test.MAC")
> zw routine.Read()
"pbarton"_$c(10)_" write ""hello"_$c(7)_""""

You can see the routine contains $c(7), which is a non-printable ASCII character. When I export the routine it looks like this:

<?xml version="1.0" encoding="UTF-8"?><Exportgenerator="IRIS"version="26"zv="IRIS for Windows (x86-64) 2023.2.0L (Build 159U)"ts="2023-09-13 11:20:00"><RoutineBase64name="pbarton.test"type="MAC"languagemode="0"timestamp="66730,40577.6434199">cGJhcnRvbgogd3JpdGUgImhlbGxvByI=
</RoutineBase64></Export>
0
Alex Woodhead · Sep 13, 2023

You can check for XML invalid characters by decoding the encoded payload. For example:

zw $SYSTEM.Encryption.Base64Decode("VXRpbHMJOyBVdGlsaXR5IE1ldGhvZHM7MjAyMy0wOS0xMSAxNjo1Nzo0MiBBTgoJcSAKY2hrQ3RybChmaXg9MCkKCWsgXmdnRwoJcyB0PSJeUkZHIgoJcyBjdHI9MAoJdyAiUkZHIiwhCglmICBzIHQ9")
"Utils"_$c(9)_"; Utility Methods;2023-09-11 16:57:42 AN"_$c(10,9)_"q "_$c(10)_"chkCtrl(fix=0)"_$c(10,9)_"k ^ggG"_$c(10,9)_"s t=""^RFG"""_$c(10,9)_"s ctr=0"_$c(10,9)_"w ""RFG"",!"_$c(10,9)_"f  s t="

Look for a $C( ? ) where ? is in 0,1,2,3 .. 30,31.

Note: Tab $C(9) and  New line ($C(10) and $C(13,10) are fine.

Sometimes cut-n-paste from an email / word document will use $C(22) as a quote character.

0
Anna Golitsyna · Apr 15, 2024

I wrote a simple function to find non-printable characters in a routine:

findNonAscii
stream = ##class(%FileCharacterStream).%New()
stream.Filename="C:\TestAGbackup_2024-04-15_AG.txt"
f  {
        q:stream.AtEnd
        s line = stream.ReadLine()
        ; Strip all control characters, including non-processable by XML export, except for tabs and newlines
        s l2=$ZSTRIP(line,"*C","",$C(9)_$C(10)_$C(13))
        w:l2'=line line,!,l2,!
}
q

0