go to post Vitaliy Serdtsev · Jul 11, 2017 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 -nopadOr on COS: #include %systemInclude #include %occErrors main() public { s fileMsg="test.txt", fileSig="test.sig", file64="test.b64", filePubKey="pubkey.pem", fileCert="C:\SSL\cert.pem", fileKey="C:\SSL\key.pem" try { $$$AddAllRoleTemporaryInTry n $namespace if '##class(%File).Exists(filePubKey) { ; Only be done once ; Extract the public key from certificate s cmd=$$$FormatText("openssl x509 -pubkey -in %1 -noout > %2",fileCert,filePubKey) w cmd,!! d $zf(-1,cmd) } f i=fileMsg,fileSig,file64 d ##class(%File).Delete(i) s file=##class(%Stream.FileCharacter).%New() s file.Filename=fileMsg s file.TranslateTable="UTF8" d file.WriteLine("{Date}") d file.WriteLine("{Password}") d file.Write("{etc}{Message Body}") $$$ThrowOnError(file.%Save()) w $$$FormatText("Create signature (%1)",fileSig),! s cmd=$$$FormatText("openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -sign %1 -out %2 %3",fileKey,fileSig,fileMsg) w cmd,!! d $zf(-1,cmd) w $$$FormatText("Convert signature to Base64 (%1)",file64),! s cmd=$$$FormatText("openssl base64 -in %1 -out %2 -nopad",fileSig,file64) w cmd,!! d $zf(-1,cmd) ;here we read our file test.b64 (file64) and place it in a Signature field in the header }catch(ex) { w "Error ", ex.DisplayString(),! } f i=fileMsg,fileSig d ##class(%File).Delete(i) }
go to post Vitaliy Serdtsev · Jul 11, 2017 #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) s newClass=##class(%Dictionary.ClassDefinition).%New() s newClass.Name=className s newClass.ProcedureBlock=$$$YES s newClass.Super="%RegisteredObject" s newProp=##class(%Dictionary.PropertyDefinition).%New() s newProp.parent=newClass s newProp.Name="p1" s newProp.Type="%String" s newMethod=##class(%Dictionary.MethodDefinition).%New() s newMethod.parent=newClass s newMethod.Name="Main" s newMethod.ReturnType="%Status" s newMethod.FormalSpec=$$$FormatText("a:%String=%1",$$$quote("Hello, World!")) d newMethod.Implementation.WriteLine($$$TAB_"w a,!") d newMethod.Implementation.WriteLine($$$TAB_"q $$$OK") $$$ThrowOnError(newClass.%Save()) d $system.OBJ.Compile(className,"cu/multicompile=1") }catch(ex) { w "Error ", ex.DisplayString(),! } }Result: Class demo.test Extends %RegisteredObject [ ProcedureBlock ] { Property p1 As %String; Method Main(a As %String = "Hello, World!") As %Status { w a,! q $$$OK } }
go to post Vitaliy Serdtsev · Jul 11, 2017 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.
go to post Vitaliy Serdtsev · Jul 10, 2017 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 }
go to post Vitaliy Serdtsev · Jul 10, 2017 See Queries Invoking User-defined Functions [SqlProc] E.x.: https://community.intersystems.com/post/hash-values-columns#node-433096
go to post Vitaliy Serdtsev · Jul 10, 2017 Could the issue be something with the dataBinding? Most likely - yes, see <dataController> Methods. Simple example: Class demo.relationModel Extends %ZEN.DataModel.ObjectDataModel { Property Relation As %String(MAXLEN = 36); Method %OnLoadModel(pSource As %RegisteredObject) As %Status { s ..Relation = $g(^tmp,"BLACKFIN CAPITAL PARTNERS") q $$$OK } Method %OnStoreModel(pSource As %RegisteredObject) As %Status { k ^tmp s ^tmp=..Relation q $$$OK } } Class demo.test Extends %ZEN.Component.page { XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ] { <page xmlns="http://www.intersystems.com/zen" title=""> <dataController id="relationData" modelClass="demo.relationModel" /> <form id="MyForm" controllerId="relationData" > <text id="Relation" label="Relation" name="Relation" dataBinding="Relation" size="36" /> <button caption="1. Convert" onclick="zenPage.convertToTitle();"/> <button caption="2. Save" onclick="zen('MyForm').save();" /> </form> </page> } ClientMethod convertToTitle() [ Language = javascript ] { var controller = zen('relationData'); controller.setDataByName('Relation',this.stringConvert(zen('Relation').getValue())); controller.raiseDataChange(); } 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 i = 0; i < pieces.length; i++ ) { var j = pieces[i].charAt(0).toUpperCase(); pieces[i] = j + pieces[i].substr(1); } return pieces.join(" "); } }
go to post Vitaliy Serdtsev · Jul 7, 2017 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 i = 0; i < pieces.length; i++ ) { var j = pieces[i].charAt(0).toUpperCase(); pieces[i] = j + pieces[i].substr(1); } return pieces.join(" "); } /// Callback to get values for form Method LoadForm( pKey As %String, ByRef pValues As %String) As %Status { s pValues("Relation") = $g(^tmp,"BLACKFIN CAPITAL PARTNERS") q $$$OK } /// Callback to process values submitted for form. ClassMethod SubmitForm(pSubmit As %ZEN.Submit) As %Status { k ^tmp s:pSubmit.%Action="save" ^tmp=pSubmit.%GetValue("Relation") q $$$OK } }
go to post Vitaliy Serdtsev · Jul 7, 2017 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)
go to post Vitaliy Serdtsev · Jul 6, 2017 The main downside would be having to either implement software on the same server as Caché installation Establishing a TCP/IP Connection
go to post Vitaliy Serdtsev · Jul 5, 2017 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>>
go to post Vitaliy Serdtsev · Jul 3, 2017 But so? Call USER.SP('select * from Sample.Person where SSN=''aaaaa''','0','S')
go to post Vitaliy Serdtsev · Jul 3, 2017 Demo for [F1], [F7] and [Home]: s key(##class(%xsd.hexBinary).XSDToLogical("1B5B31387E"))="F7" s key(##class(%xsd.hexBinary).XSDToLogical("1B4F50"))="F1" s key(##class(%xsd.hexBinary).XSDToLogical("1B5B317E"))="Home" u:$zu(96,14)=1 0:(:"+S") r "Input: ",*x u:$zu(96,14)=1 0:(:"-S") ;zzdump $key w "You press [",$g(key($key),"unknown"),"]",!
go to post Vitaliy Serdtsev · Jul 3, 2017 error code 100 do not exist, but there is a code 101. See documentation: General Error Messages USER>s $mvv(58)="es" USER>d $SYSTEM.OBJ.DisplayError($System.Status.Error(101)) 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.
go to post Vitaliy Serdtsev · Jul 3, 2017 Indicates that your version is below 2011.x See documentation: 2010.2 (absent) 2011.1 (present)
go to post Vitaliy Serdtsev · Jul 3, 2017 Yes, see part "Creation of a custom error message dictionary" PS: you can even use the letters, for example: <?xml version="1.0" encoding="UTF-8"?> <MsgFile Language="en"> <MsgDomain Domain="asd"> <Message Id="a" Name="ErrorName1">Message about some error 1</Message> <Message Id="b" Name="ErrorName2">Message about some error 2 %1 %2</Message> </MsgDomain> </MsgFile>
go to post Vitaliy Serdtsev · Jun 29, 2017 #dim list As %ListOfDataTypes d ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject("[""a"",""b"",""c""]",,.list) w list.Count(),!
go to post Vitaliy Serdtsev · Jun 21, 2017 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>w ##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 !"#$%&'()*/