Vitaliy Serdtsev · Jul 11, 2017 go to post

You can try to do it using the OpenSSL libraries, which comes complete with Caché/Ensemble/etc. To google: "openssl rsa-pss sign", "openssl SHA256 with RSA PSS padding"

Here is a small example on Windows, where it is assumed that

  • cert.pem is your certificate:
    -----BEGIN CERTIFICATE-----
    <...>
    -----END CERTIFICATE-----
  • key.pem is your private key:
    -----BEGIN RSA PRIVATE KEY-----
    <...>
    -----END RSA PRIVATE KEY-----
So (test.bat):
@echo off
 
echo Delete all temporary files
del /Q /F test.txt test.sig pubkey.pem test.b64
 
echo Extract the public key from certificate (only be done once)
openssl x509 -pubkey -in cert.pem -noout > pubkey.pem
 
echo Create test file (test.txt)
echo bla-bla-bla test123 {Date}{newline}{Password}{newline}{etc}{Message Body} > test.txt
 
echo Create signature (test.sig)
openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -sign key.pem -out test.sig test.txt
 
echo This step is only for information/verification.
echo Verify signature (The result should be: "Verified OK")
openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -signature test.sig -verify pubkey.pem test.txt
 
echo Convert signature to Base64 (test.b64)
echo You can this step be make on COS.
openssl base64 -in test.sig -out test.b64 -nopad

Or on COS:

<FONT COLOR="#0000ff">#include </FONT><FONT COLOR="#000000">%systemInclude
</FONT><FONT COLOR="#0000ff">#include </FONT><FONT COLOR="#000000">%occErrors
</FONT><FONT COLOR="#ff0000">main</FONT><FONT COLOR="#000000">() </FONT><FONT COLOR="#0000ff">public </FONT><FONT COLOR="#800080">{
  
  </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">fileMsg</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"test.txt"</FONT><FONT COLOR="#000000">,
    </FONT><FONT COLOR="#800000">fileSig</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"test.sig"</FONT><FONT COLOR="#000000">,
    </FONT><FONT COLOR="#800000">file64</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"test.b64"</FONT><FONT COLOR="#000000">,
    </FONT><FONT COLOR="#800000">filePubKey</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"pubkey.pem"</FONT><FONT COLOR="#000000">,
    </FONT><FONT COLOR="#800000">fileCert</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"C:\SSL\cert.pem"</FONT><FONT COLOR="#000000">,
    </FONT><FONT COLOR="#800000">fileKey</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"C:\SSL\key.pem"

  </FONT><FONT COLOR="#0000ff">try </FONT><FONT COLOR="#800080">{     </FONT><FONT COLOR="#0000ff">$$$AddAllRoleTemporaryInTry     n $namespace

    if </FONT><FONT COLOR="#000000">'</FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%File</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">Exists</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">filePubKey</FONT><FONT COLOR="#000000">) </FONT><FONT COLOR="#800080">{       </FONT><FONT COLOR="#008000">; Only be done once       ; Extract the public key from certificate       </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">cmd</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#0000ff">$$$FormatText</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"openssl x509 -pubkey -in %1 -noout > %2"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">fileCert</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">filePubKey</FONT><FONT COLOR="#000000">)       </FONT><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#800000">cmd</FONT><FONT COLOR="#000000">,!!       </FONT><FONT COLOR="#0000ff">d $zf</FONT><FONT COLOR="#000000">(-1,</FONT><FONT COLOR="#800000">cmd</FONT><FONT COLOR="#000000">)     </FONT><FONT COLOR="#800080">}          </FONT><FONT COLOR="#0000ff">f </FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#800000">fileMsg</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">fileSig</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">file64 </FONT><FONT COLOR="#0000ff">d </FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%File</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">Delete</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">)          </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">file</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%Stream.FileCharacter</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">%New</FONT><FONT COLOR="#000000">()     </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">file</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">Filename</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#800000">fileMsg     </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">file</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">TranslateTable</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"UTF8"     </FONT><FONT COLOR="#0000ff">d </FONT><FONT COLOR="#800000">file</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">WriteLine</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"{Date}"</FONT><FONT COLOR="#000000">)     </FONT><FONT COLOR="#0000ff">d </FONT><FONT COLOR="#800000">file</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">WriteLine</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"{Password}"</FONT><FONT COLOR="#000000">)     </FONT><FONT COLOR="#0000ff">d </FONT><FONT COLOR="#800000">file</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">Write</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"{etc}{Message Body}"</FONT><FONT COLOR="#000000">)     </FONT><FONT COLOR="#0000ff">$$$ThrowOnError</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">file</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">%Save</FONT><FONT COLOR="#000000">())          </FONT><FONT COLOR="#0000ff">w $$$FormatText</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"Create signature (%1)"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">fileSig</FONT><FONT COLOR="#000000">),!     </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">cmd</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#0000ff">$$$FormatText</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -sign %1 -out %2 %3"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">fileKey</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">fileSig</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">fileMsg</FONT><FONT COLOR="#000000">)     </FONT><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#800000">cmd</FONT><FONT COLOR="#000000">,!!     </FONT><FONT COLOR="#0000ff">d $zf</FONT><FONT COLOR="#000000">(-1,</FONT><FONT COLOR="#800000">cmd</FONT><FONT COLOR="#000000">)          </FONT><FONT COLOR="#0000ff">w $$$FormatText</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"Convert signature to Base64 (%1)"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">file64</FONT><FONT COLOR="#000000">),!     </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">cmd</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#0000ff">$$$FormatText</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"openssl base64 -in %1 -out %2 -nopad"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">fileSig</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">file64</FONT><FONT COLOR="#000000">)     </FONT><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#800000">cmd</FONT><FONT COLOR="#000000">,!!     </FONT><FONT COLOR="#0000ff">d $zf</FONT><FONT COLOR="#000000">(-1,</FONT><FONT COLOR="#800000">cmd</FONT><FONT COLOR="#000000">)          </FONT><FONT COLOR="#008000">;here we read our file test.b64 (file64) and place it in a Signature field in the header        </FONT><FONT COLOR="#800080">}</FONT><FONT COLOR="#0000ff">catch</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">ex</FONT><FONT COLOR="#000000">) </FONT><FONT COLOR="#800080">{     </FONT><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#008000">"Error "</FONT><FONT COLOR="#000000">, </FONT><FONT COLOR="#800000">ex</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">DisplayString</FONT><FONT COLOR="#000000">(),!   </FONT><FONT COLOR="#800080">}

  </FONT><FONT COLOR="#0000ff">f </FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#800000">fileMsg</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">fileSig </FONT><FONT COLOR="#0000ff">d </FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%File</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">Delete</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">) </FONT><FONT COLOR="#800080">}</FONT>

Vitaliy Serdtsev · Jul 11, 2017 go to post

Thanks, fixed the code. Now <FONT COLOR="#0000ff">$$$TAB </FONT><FONT COLOR="#000000">= </FONT><FONT COLOR="#0000ff">$C</FONT><FONT COLOR="#000000">(9)</FONT>

Vitaliy Serdtsev · Jul 11, 2017 go to post
#include %systemInclude
#include %occErrors
#include %occCPTJSgen
CreateClass() public {
  
  #dim ex As %Exception.AbstractException
  try {
    $$$AddAllRoleTemporaryInTry
    new $namespace
    
    s className="demo.test"
    
    d:##class(%Dictionary.ClassDefinition).%ExistsId(className##class(%Dictionary.ClassDefinition).%DeleteId(className)
    
    newClass=##class(%Dictionary.ClassDefinition).%New()
    newClass.Name=className
    newClass.ProcedureBlock=$$$YES
    s newClass.Super="%RegisteredObject"

    newProp=##class(%Dictionary.PropertyDefinition).%New()
    newProp.parent=newClass
    newProp.Name="p1"
    newProp.Type="%String"
    
    newMethod=##class(%Dictionary.MethodDefinition).%New()
    newMethod.parent=newClass
    newMethod.Name="Main"
    newMethod.ReturnType="%Status"
    newMethod.FormalSpec=$$$FormatText("a:%String=%1",$$$quote("Hello, World!"))
    newMethod.Implementation.WriteLine($$$TAB_"w a,!")
    newMethod.Implementation.WriteLine($$$TAB_"q $$$OK")
    
    $$$ThrowOnError(newClass.%Save())

    d $system.OBJ.Compile(className,"cu/multicompile=1")
     
    
  }catch(ex{
    "Error "ex.DisplayString(),!
  }
}
Result:
Class demo.test Extends %RegisteredObject ProcedureBlock ]

{

</FONT><FONT COLOR="#000080">Property </FONT><FONT COLOR="#000000">p1 </FONT><FONT COLOR="#000080">As %String</FONT><FONT COLOR="#000000">;

</FONT><FONT COLOR="#000080">Method </FONT><FONT COLOR="#000000">Main(</FONT><FONT COLOR="#ff00ff">a </FONT><FONT COLOR="#000080">As %String </FONT><FONT COLOR="#000000">= </FONT><FONT COLOR="#800080">"Hello, World!"</FONT><FONT COLOR="#000000">) </FONT><FONT COLOR="#000080">As %Status </FONT><FONT COLOR="#000000">{  </FONT><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#800000">a</FONT><FONT COLOR="#000000">,!  </FONT><FONT COLOR="#0000ff">q $$$OK </FONT><FONT COLOR="#000000">}

}</FONT>

Vitaliy Serdtsev · Jul 11, 2017 go to post

It seems that "CREATE TRIGGER" does not support INSERT/UPDATE, INSERT/UPDATE/DELETE, etc. It's either a bug or a feature. I believe that is still a bug. In any case you need to contact the WRC.

Vitaliy Serdtsev · Jul 10, 2017 go to post
ClassMethod Main(ByRef Text)
{
f i=1:1:$o(Text(""),-1)-1 s t=$l(Text(i+1))+1 s:$l(Text(i))+1>t $e(Text(i+1),*+1)=$e(Text(i),t,*),$e(Text(i),t,*)="",i=1
}
Vitaliy Serdtsev · Jul 10, 2017 go to post
Could the issue be something with the dataBinding?
Most likely - yes, see <dataController> Methods. Simple example:
Class demo.relationModel Extends %ZEN.DataModel.ObjectDataModel
{

</FONT><FONT COLOR="#000080">Property </FONT><FONT COLOR="#000000">Relation </FONT><FONT COLOR="#000080">As %String</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#000080">MAXLEN </FONT><FONT COLOR="#000000">= </FONT><FONT COLOR="#000080">36</FONT><FONT COLOR="#000000">);

</FONT><FONT COLOR="#000080">Method </FONT><FONT COLOR="#000000">%OnLoadModel(</FONT><FONT COLOR="#ff00ff">pSource </FONT><FONT COLOR="#000080">As %RegisteredObject</FONT><FONT COLOR="#000000">) </FONT><FONT COLOR="#000080">As %Status </FONT><FONT COLOR="#000000">{   </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#000000">..</FONT><FONT COLOR="#0000ff">Relation </FONT><FONT COLOR="#000000">= </FONT><FONT COLOR="#0000ff">$g</FONT><FONT COLOR="#000000">(^tmp,</FONT><FONT COLOR="#008000">"BLACKFIN CAPITAL PARTNERS"</FONT><FONT COLOR="#000000">)   </FONT><FONT COLOR="#0000ff">q $$$OK </FONT><FONT COLOR="#000000">}

</FONT><FONT COLOR="#000080">Method </FONT><FONT COLOR="#000000">%OnStoreModel(</FONT><FONT COLOR="#ff00ff">pSource </FONT><FONT COLOR="#000080">As %RegisteredObject</FONT><FONT COLOR="#000000">) </FONT><FONT COLOR="#000080">As %Status </FONT><FONT COLOR="#000000">{   </FONT><FONT COLOR="#0000ff">k </FONT><FONT COLOR="#000000">^tmp   </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#000000">^tmp=..</FONT><FONT COLOR="#0000ff">Relation   q $$$OK </FONT><FONT COLOR="#000000">} }</FONT>

<FONT COLOR="#000080">Class demo.test Extends %ZEN.Component.page </FONT><FONT COLOR="#000000">{

</FONT><FONT COLOR="#000080">XData </FONT><FONT COLOR="#000000">Contents [ </FONT><FONT COLOR="#000080">XMLNamespace </FONT><FONT COLOR="#000000">= </FONT><FONT COLOR="#800080">"http://www.intersystems.com/zen" </FONT><FONT COLOR="#000000">] { <</FONT><FONT COLOR="#000080">page </FONT><FONT COLOR="#800000">xmlns</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"http://www.intersystems.com/zen" </FONT><FONT COLOR="#800000">title</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">""</FONT><FONT COLOR="#000000">>   <</FONT><FONT COLOR="#000080">dataController     </FONT><FONT COLOR="#800000">id</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"relationData"     </FONT><FONT COLOR="#800000">modelClass</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"demo.relationModel"   </FONT><FONT COLOR="#000000">/>   <</FONT><FONT COLOR="#000080">form     </FONT><FONT COLOR="#800000">id</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"MyForm"     </FONT><FONT COLOR="#800000">controllerId</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"relationData"   </FONT><FONT COLOR="#000000">>     <</FONT><FONT COLOR="#000080">text       </FONT><FONT COLOR="#800000">id</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"Relation"       </FONT><FONT COLOR="#800000">label</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"Relation"       </FONT><FONT COLOR="#800000">name</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"Relation"       </FONT><FONT COLOR="#800000">dataBinding</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"Relation"       </FONT><FONT COLOR="#800000">size</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"36"     </FONT><FONT COLOR="#000000">/>     <</FONT><FONT COLOR="#000080">button </FONT><FONT COLOR="#800000">caption</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"1. Convert" </FONT><FONT COLOR="#800000">onclick</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"zenPage.convertToTitle();"</FONT><FONT COLOR="#000000">/>     <</FONT><FONT COLOR="#000080">button </FONT><FONT COLOR="#800000">caption</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"2. Save" </FONT><FONT COLOR="#800000">onclick</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"zen('MyForm').save();" </FONT><FONT COLOR="#000000">/>   </</FONT><FONT COLOR="#000080">form</FONT><FONT COLOR="#000000">> </</FONT><FONT COLOR="#000080">page</FONT><FONT COLOR="#000000">> }

</FONT><FONT COLOR="#000080">ClientMethod </FONT><FONT COLOR="#000000">convertToTitle() [ </FONT><FONT COLOR="#000080">Language </FONT><FONT COLOR="#000000">= javascript ] {   </FONT><FONT COLOR="#008080">var </FONT><FONT COLOR="#000000">controller </FONT><FONT COLOR="#000080">= </FONT><FONT COLOR="#000000">zen(</FONT><FONT COLOR="#800000">'relationData'</FONT><FONT COLOR="#000000">);      controller.setDataByName(</FONT><FONT COLOR="#800000">'Relation'</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">this</FONT><FONT COLOR="#000000">.stringConvert(zen(</FONT><FONT COLOR="#800000">'Relation'</FONT><FONT COLOR="#000000">).getValue()));   controller.raiseDataChange(); }

</FONT><FONT COLOR="#000080">ClientMethod </FONT><FONT COLOR="#000000">stringConvert(</FONT><FONT COLOR="#ff00ff">str</FONT><FONT COLOR="#000000">) [ </FONT><FONT COLOR="#000080">Language </FONT><FONT COLOR="#000000">= javascript ] {   </FONT><FONT COLOR="#008000">///alert (str)   </FONT><FONT COLOR="#000000">str </FONT><FONT COLOR="#000080">= </FONT><FONT COLOR="#000000">str.substring(</FONT><FONT COLOR="#000080">0</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#000080">1</FONT><FONT COLOR="#000000">).toLowerCase() </FONT><FONT COLOR="#000080">+ </FONT><FONT COLOR="#000000">str.substring(</FONT><FONT COLOR="#000080">1</FONT><FONT COLOR="#000000">).toLowerCase();   </FONT><FONT COLOR="#008000">///alert (str)   </FONT><FONT COLOR="#008080">var </FONT><FONT COLOR="#000000">pieces </FONT><FONT COLOR="#000080">= </FONT><FONT COLOR="#000000">str.split(</FONT><FONT COLOR="#800000">" "</FONT><FONT COLOR="#000000">);   </FONT><FONT COLOR="#008000">for </FONT><FONT COLOR="#000000">( </FONT><FONT COLOR="#008000">var </FONT><FONT COLOR="#000000">i </FONT><FONT COLOR="#000080">= 0</FONT><FONT COLOR="#000000">; i </FONT><FONT COLOR="#000080">< </FONT><FONT COLOR="#000000">pieces.length; i</FONT><FONT COLOR="#000080">++ </FONT><FONT COLOR="#000000">)   {     </FONT><FONT COLOR="#008080">var </FONT><FONT COLOR="#000000">j </FONT><FONT COLOR="#000080">= </FONT><FONT COLOR="#000000">pieces[i].charAt(</FONT><FONT COLOR="#000080">0</FONT><FONT COLOR="#000000">).toUpperCase();          pieces[i] </FONT><FONT COLOR="#000080">= </FONT><FONT COLOR="#000000">j </FONT><FONT COLOR="#000080">+ </FONT><FONT COLOR="#000000">pieces[i].substr(</FONT><FONT COLOR="#000080">1</FONT><FONT COLOR="#000000">);   }          </FONT><FONT COLOR="#008000">return </FONT><FONT COLOR="#000000">pieces.join(</FONT><FONT COLOR="#800000">" "</FONT><FONT COLOR="#000000">); } }</FONT>

Vitaliy Serdtsev · Jul 7, 2017 go to post

At me converted string is stored correctly.

Here is a small example:

Class demo.test Extends %ZEN.Component.page
{

XData Contents [ XMLNamespace "http://www.intersystems.com/zen" ]
{
<page xmlns="http://www.intersystems.com/zen" title="">
  <form
    id="MyForm"
    OnLoadForm="LoadForm"
    OnSubmitForm="SubmitForm"
  >
    <text
      id="Relation"
      name="Relation"
      label="Relation"
      size="50"
    />
    <button caption="1.Convert" onclick="zenPage.convertToTitle();"/>
    <submit caption="2.Save" action="save"/>
  </form>
</page>
}

ClientMethod convertToTitle() [ Language = javascript ]
{
  var ctrl zen('Relation');
  ctrl.setValue(this.stringConvert(ctrl.getValue()));
}

ClientMethod stringConvert(str) [ Language = javascript ]
{
  ///alert (str)
  str str.substring(0,1).toLowerCase() str.substring(1).toLowerCase();
  ///alert (str)
  var pieces str.split(" ");
  for var = 0; i pieces.length; i++ )
  {
    var pieces[i].charAt(0).toUpperCase();
    
    pieces[i] pieces[i].substr(1);
  }
      
  return pieces.join(" ");
}

/// Callback to get values for form
Method LoadForm(
  pKey As %String,
  ByRef pValues As %StringAs %Status
{
  pValues("Relation") = $g(^tmp,"BLACKFIN CAPITAL PARTNERS")
  q $$$OK
}

/// Callback to process values submitted for form.
ClassMethod SubmitForm(pSubmit As %ZEN.SubmitAs %Status
{
  ^tmp
  s:pSubmit.%Action="save" ^tmp=pSubmit.%GetValue("Relation")
  q $$$OK
}
}
Vitaliy Serdtsev · Jul 7, 2017 go to post
By the way: some server side alternative solution sample(s) are more than welcome!
$zcvt
USER>w $zcvt("BLACKFIN CAPITAL PARTNERS","W")
Blackfin Capital Partners
USER>w $zcvt("MARK'S 'MARK'S (MARK'S)","W")
Mark's 'Mark's (Mark's)
Vitaliy Serdtsev · Jul 5, 2017 go to post
SAMPLES>d $system.SQL.Shell()
SQL Command Line Shell
----------------------------------------------------
 
The command prefix is currently set to: <>.
Enter q to quit, ? for help.
SAMPLES>>?=CALL %SYSTEM.SQL_TableExists('Sample.Person')
1.      ?=CALL %SYSTEM.SQL_TableExists('Sample.Person')
 
 
executing statement with parameter values: set %tResult=%tStatement.%Execute()
 
 
Output Values:
 
 0. 1
statement prepare time(s)/globals/lines/disk: 0.0025s/14/862/0ms
          execute time(s)/globals/lines/disk: 0.0003s/7/179/0ms
                          cached query class: %sqlcq.SAMPLES.cls2
---------------------------------------------------------------------------
SAMPLES>>
Vitaliy Serdtsev · Jul 3, 2017 go to post

Demo for [F1], [F7] and [Home]:

<FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">key</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%xsd.hexBinary</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">XSDToLogical</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"1B5B31387E"</FONT><FONT COLOR="#000000">))=</FONT><FONT COLOR="#008000">"F7"
</FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">key</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%xsd.hexBinary</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">XSDToLogical</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"1B4F50"</FONT><FONT COLOR="#000000">))=</FONT><FONT COLOR="#008000">"F1"
</FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">key</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%xsd.hexBinary</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">XSDToLogical</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"1B5B317E"</FONT><FONT COLOR="#000000">))=</FONT><FONT COLOR="#008000">"Home"
</FONT><FONT COLOR="#0000ff">u</FONT><FONT COLOR="#000000">:</FONT><FONT COLOR="#0000ff">$zu</FONT><FONT COLOR="#000000">(96,14)=1 0:(:</FONT><FONT COLOR="#008000">"+S"</FONT><FONT COLOR="#000000">) </FONT><FONT COLOR="#0000ff">r </FONT><FONT COLOR="#008000">"Input: "</FONT><FONT COLOR="#000000">,*</FONT><FONT COLOR="#800000">x </FONT><FONT COLOR="#0000ff">u</FONT><FONT COLOR="#000000">:</FONT><FONT COLOR="#0000ff">$zu</FONT><FONT COLOR="#000000">(96,14)=1 0:(:</FONT><FONT COLOR="#008000">"-S"</FONT><FONT COLOR="#000000">)

</FONT><FONT COLOR="#008000">;zzdump $key     </FONT><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#008000">"You press ["</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#0000ff">$g</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">key</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#0000ff">$key</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">"unknown"</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">"]"</FONT><FONT COLOR="#000000">,!</FONT>

Vitaliy Serdtsev · Jul 3, 2017 go to post
  • error code 100 do not exist, but there is a code 101. See documentation: General Error Messages
    USER>s $mvv(58)="es"
    

    USER><FONT COLOR="#0000ff">d $SYSTEM</FONT><FONT COLOR="#008080">.OBJ</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">DisplayError</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#0000ff">$System</FONT><FONT COLOR="#008080">.Status</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">Error</FONT><FONT COLOR="#000000">(101))</FONT>

    ERROR #101: Nivel puntero superior: nº bloques=%1 %2kb (%3% total)

  • error with some positive codes are reserved by the system, so you can't use them.
    Two error codes, 83 and 5001, are provided to enable you to generate your own custom error messages.
Vitaliy Serdtsev · Jul 3, 2017 go to post

Yes, see part "Creation of a custom error message dictionary"

PS: you can even use the letters, for example:

<?xml <FONT COLOR="#008000">version</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"1.0" encoding</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"UTF-8"</FONT><FONT COLOR="#000000">?>
<</FONT><FONT COLOR="#000080">MsgFile </FONT><FONT COLOR="#800000">Language</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"en"</FONT><FONT COLOR="#000000">>
  <</FONT><FONT COLOR="#000080">MsgDomain </FONT><FONT COLOR="#800000">Domain</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"asd"</FONT><FONT COLOR="#000000">>
    <</FONT><FONT COLOR="#000080">Message </FONT><FONT COLOR="#800000">Id</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"a" </FONT><FONT COLOR="#800000">Name</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"ErrorName1"</FONT><FONT COLOR="#000000">>Message about some error 1</</FONT><FONT COLOR="#000080">Message</FONT><FONT COLOR="#000000">>
    <</FONT><FONT COLOR="#000080">Message </FONT><FONT COLOR="#800000">Id</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"b" </FONT><FONT COLOR="#800000">Name</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"ErrorName2"</FONT><FONT COLOR="#000000">>Message about some error 2 %1 %2</</FONT><FONT COLOR="#000080">Message</FONT><FONT COLOR="#000000">>
  </</FONT><FONT COLOR="#000080">MsgDomain</FONT><FONT COLOR="#000000">>
</</FONT><FONT COLOR="#000080">MsgFile</FONT><FONT COLOR="#000000">></FONT>

Vitaliy Serdtsev · Jun 29, 2017 go to post
#dim list As %ListOfDataTypes
##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject("[""a"",""b"",""c""]",,.list)
list.Count(),!
Vitaliy Serdtsev · Jun 21, 2017 go to post

It is not clear what it will give. To Richard need to save the binary data encoded in hex.

For example, instead of '0x2122232425262728292A2F' to the database should persist the value !"#$%&'()*/

USER>w $c(33,34,35,36,37,38,39,40,41,42,47)
!"#$%&'()*/

USER>##class(%xsd.hexBinary).LogicalToXSD($c(33,34,35,36,37,38,39,40,41,42,47))
2122232425262728292A2F

USER>zzdump ##class(%xsd.hexBinary).XSDToLogical("2122232425262728292A2F"; 0x omitted
 
0000: 21 22 23 24 25 26 27 28 29 2A 2F                        !"#$%&'()*/
Vitaliy Serdtsev · Jun 20, 2017 go to post

The solution:

USER><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">ITPlanet.BlackBox</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">Main</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#d3d3d3">{"trantable":"JSON"},"I"</FONT><FONT COLOR="#000000">)</FONT>
Hello World!
USER><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">ITPlanet.BlackBox</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">Main</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#f5f5f5">{"trantable":"JS"},"I"</FONT><FONT COLOR="#000000">)</FONT>
Hello World!

Vitaliy Serdtsev · Jun 16, 2017 go to post

URL and URI Conversions

Try: <FONT COLOR="#0000ff">Set </FONT><FONT COLOR="#800000">tURL</FONT><FONT COLOR="#000000">=..</FONT><FONT COLOR="#0000ff">Adapter</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">URL</FONT><FONT COLOR="#000000"></FONT><FONT COLOR="#008000">"/claims/"</FONT><FONT COLOR="#000000"></FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%CSP.Page</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">EscapeURL</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">pRequest</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">claimBlob</FONT><FONT COLOR="#000000">)</FONT> or <FONT COLOR="#0000ff">Set </FONT><FONT COLOR="#800000">tURL</FONT><FONT COLOR="#000000">=..</FONT><FONT COLOR="#0000ff">Adapter</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">URL</FONT><FONT COLOR="#000000"></FONT><FONT COLOR="#008000">"/claims/"</FONT><FONT COLOR="#000000"></FONT><FONT COLOR="#0000ff">$zcvt</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#0000ff">$zcvt</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">pRequest</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">claimBlob</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"O"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"UTF8"</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">"O"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"URL"</FONT><FONT COLOR="#000000">)</FONT>

USER>w $zcvt($zcvt($c(0,1,2,1025),"O","UTF8"),"O","URL")
%00%01%02%D0%81
USER>##class(%CSP.Page).EscapeURL($c(0,1,2,1025))
%00%01%02%D0%81
Vitaliy Serdtsev · Jun 15, 2017 go to post

See $zcvt for JSON, e.g.:

USER><FONT COLOR="#0000ff">w $zcvt</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#0000ff">$c</FONT><FONT COLOR="#000000">(0,1,2),</FONT><FONT COLOR="#008000">"O"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"JSON"</FONT><FONT COLOR="#000000">)</FONT>
\u0000\u0001\u0002
USER><FONT COLOR="#0000ff">zw $zcvt</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"\u0000\u0001\u0002"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"I"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"JSON"</FONT><FONT COLOR="#000000">)</FONT>
<FONT COLOR="#0000ff">$c</FONT><FONT COLOR="#000000">(0,1,2)</FONT>
USER><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#ff00ff">{</FONT><FONT COLOR="#008000">"binary"</FONT><FONT COLOR="#808080">:</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#0000ff">$c</FONT><FONT COLOR="#000000">(0,1,2))</FONT><FONT COLOR="#ff00ff">}</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">%ToJSON</FONT><FONT COLOR="#000000">()</FONT>
<FONT COLOR="#ff00ff">{</FONT><FONT COLOR="#008000">"binary"</FONT><FONT COLOR="#808080">:</FONT><FONT COLOR="#008000">"\u0000\u0001\u0002"</FONT><FONT COLOR="#ff00ff">}</FONT>

Vitaliy Serdtsev · Jun 15, 2017 go to post

Nikita is an employee of InterSystems? If so, then it seems to me that it would be easier and more effective if upgrade a standard Caché Terminal, turning to the achievements of Nikita.

Vitaliy Serdtsev · Jun 15, 2017 go to post

Congratulations, John.

To be a moderator is a big responsibility, so I wish you a lot of patience.

Vitaliy Serdtsev · Jun 15, 2017 go to post
The jsonProvider code may also be invoked from a non-Zen context by calling one of the following APIs:
  • %WriteJSONFromArray
  • %WriteJSONFromObject
  • %WriteJSONStreamFromArray
  • %WriteJSONStreamFromObject
  • %ConvertJSONToObject
proof
Example:
##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.stream,..%OpenId(1),,,1,"aelqoc")
"<- json = ",stream.Read(),!