go to post Vitaliy Serdtsev · Jul 18, 2017 The solution with ##class(%xsd.hexBinary).LogicalToXSD works, but be careful, it only works when all characters in the string have codes <256. All right, because the function works with an array of bytes (binary). Therefore pre-to need lead N-byte string to single-byte string and only then do the conversion, for example: f trantable="SAME","UTF8" { w "-------",!,trantable,! s xN="π=3.14159..." zzdump xN w ! s x1=$zcvt(xN,"O",trantable) zzdump x1 w !! s hex=##class(%xsd.hexBinary).LogicalToXSD(x1) zw hex w $zcvt(##class(%xsd.hexBinary).XSDToLogical(hex),"I",trantable),!! } USER>d ^test ------- SAME 0000: 03C0 003D 0033 002E 0031 0034 0031 0035 π=3.1415 0008: 0039 002E 002E 002E 9... 0000: C0 03 3D 00 33 00 2E 00 31 00 34 00 31 00 35 00 À.=.3...1.4.1.5. 0010: 39 00 2E 00 2E 00 2E 00 9....... hex="C0033D0033002E00310034003100350039002E002E002E00" π=3.14159... ------- UTF8 0000: 03C0 003D 0033 002E 0031 0034 0031 0035 π=3.1415 0008: 0039 002E 002E 002E 9... 0000: CF 80 3D 33 2E 31 34 31 35 39 2E 2E 2E Ï.=3.14159... hex="CF803D332E31343135392E2E2E" π=3.14159...
go to post Vitaliy Serdtsev · Jul 14, 2017 s l=$lb("",,,,,"",,,"BOOLEAN","0",2,2,"1",,"bla",$lb(,,"bla","20050502123400"),"",1,"bla",,0) s jsonStr=[(l)].%ToJSON() w jsonStr,!! s obj=[].%FromJSON(jsonStr) s list=obj."0" zw list Result: ["\u0002\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0001\u0001\t\u0001BOOLEAN\u0003\u00010\u0003\u0004\u0002\u0003\u0004\u0002\u0003\u00011\u0001\u0005\u0001bla\u0019\u0001\u0001\u0001\u0005\u0001bla\u0010\u000120050502123400\u0002\u0001\u0003\u0004\u0001\u0005\u0001bla\u0001\u0002\u0004"] list=$lb("",,,,,"",,,"BOOLEAN","0",2,2,"1",,"bla",$lb(,,"bla","20050502123400"),"",1,"bla",,0)
go to post Vitaliy Serdtsev · Jul 13, 2017 Hi Uri. In my opinion, this possible hear only empirically through load testing on specific hardware. It is also important and the interface between Caché and the world .NET, namely the number of calls made to a DLLBetter performance. Sometimes the performance gain is observed when .NET refers to Caché (ADO.NET, eXTreme .NET Provider), and not vice versa (.NET Gateway). But it always requires a revision of the architecture. By the way, for .NET Provider/ADO.NET there is Connection Pooling
go to post Vitaliy Serdtsev · Jul 13, 2017 Personally, I prefer to use all out of the box, so as not to produce zoo libraries/technologies/languages, etc. Really, both operations possible to execute at a time, for instance so: w $$$FormatText("Create a signature and convert it to base64 (%1)",file64),! s cmd=$$$FormatText("openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -sign %1 %2 | openssl base64 -out %3 -nopad",fileKey,fileMsg,file64) w cmd,!! d $zf(-1,cmd)
go to post Vitaliy Serdtsev · Jul 13, 2017 In addition to said by Eduard: OpenSSL and error in reading openssl.conf file
go to post Vitaliy Serdtsev · Jul 13, 2017 Take a look at the source code of the queries ##class(%Global).[Find/Get()] Pattern Matching
go to post Vitaliy Serdtsev · Jul 13, 2017 What exactly did you do? Quote from doc: By default, the session timeout is to 900 seconds (15 minutes). You can change this default for a CSP application in the Management Portal; [Home] > [Security] > [Web Applications] page. Select the application and click Edit. Note that if a session changes CSP applications during its life span, its timeout value will not be updated according to the default timeout defined in the application that the session moved into. For example, if a session starts out in CSP Application A, with a default timeout of 900 seconds, and then moves into CSP Application B, which has a default timeout of 1800 seconds, the session will still timeout after 900 seconds. Check these points. Still see the page parameter AUTOLOGOUT.
go to post Vitaliy Serdtsev · Jul 13, 2017 It's the wrong solution, because it works not for all cases such as this: Set Text(1) = "Planet" Set Text(2) = "Championship" Set Text(3) = "2017" Set Text(4) = "IT"Here is more optimized code Sean: ClassMethod Main(ByRef Text) { f j=2:1:$o(Text(""),-1) f k=j:-1:2 s l=$l(Text(k))+1,$e(Text(k),l)=$e(Text(k-1),l,*),$e(Text(k-1),l,*)="" }
go to post Vitaliy Serdtsev · Jul 11, 2017 Session TimeoutFind: Session Termination and Cleanup Session Timeout Session Timeout for CSP Gateway
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 } }