IMPORT util IMPORT com IMPORT os IMPORT security IMPORT XML IMPORT FGL recepcion IMPORT FGL aprobacion CONSTANT dpy_verb=TRUE -- send messages to standard output DEFINE doc xml.DomDocument DEFINE req com.HTTPServiceRequest DEFINE url,msg,method,headers,mensaje,filexml,tipoecf,rnc_e,rnc_c,e_ncf,fileacuse,resp, ruta_firmados,fileafirmar_f STRING, tout, n, x,rcode INTEGER, start_time DATETIME YEAR TO SECOND DEFINE d0 DATETIME YEAR TO SECOND DEFINE a om.SaxAttributes DEFINE out om.SaxDocumentHandler, i INT, fechaFirma DATETIME YEAR TO SECOND DEFINE result INTEGER MAIN LET filexml = ".\\ArchRecibidos\\" LET fileacuse = ".\\Acuses\\" LET ruta_firmados = fgl_getenv("RUTA_XML_FIRMADOS") CALL check_utf8() RETURNING x, msg IF x != 0 THEN DISPLAY "ERROR: ", msg EXIT PROGRAM 1 END IF CALL show_verb("Inicio Api server: ...") CALL com.WebServiceEngine.RegisterRestService("recepcion","aprobacion") CALL com.WebServiceEngine.Start() WHILE TRUE LET result = com.WebServiceEngine.ProcessServices(-1) -- handling of result found here -- http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_gws_restful_high_level_publish_module.html CASE result WHEN 0 DISPLAY "Request processed." WHEN -1 DISPLAY "Timeout reached." WHEN -2 DISPLAY "Disconnected from application server." EXIT PROGRAM # The Application server has closed the connection WHEN -3 DISPLAY "Client Connection lost." WHEN -4 DISPLAY "Server interrupted with Ctrl-C." WHEN -9 DISPLAY "Unsupported operation." WHEN -10 DISPLAY "Internal server error." WHEN -23 DISPLAY "Deserialization error." WHEN -35 DISPLAY "No such REST operation found." WHEN -36 DISPLAY "Missing REST parameter." OTHERWISE DISPLAY "Unexpected server error " || result || "." EXIT WHILE END CASE IF int_flag<>0 THEN LET int_flag=0 EXIT WHILE END IF END WHILE END MAIN FUNCTION check_utf8() IF ORD("€") == 8364 AND LENGTH("€") == 1 THEN RETURN 0, NULL ELSE RETURN -1, "Application locale must be UTF-8, with char length semantics" END IF END FUNCTION FUNCTION show_verb(msg) DEFINE msg STRING IF dpy_verb THEN DISPLAY msg END IF # IF log_verb THEN # CALL errorlog(msg CLIPPED) # END IF END FUNCTION FUNCTION read_request(req,tipooperacion) # DEFINE doc xml.DomDocument DEFINE req com.HttpServiceRequest DEFINE cmd,recibido,tmpfile,pfechafirmadigital,tipooperacion STRING, p RECORD oper STRING, data RECORD usuario STRING, clave STRING, codigo STRING END RECORD END RECORD INITIALIZE cmd TO NULL LET cmd = req.readFileRequest() DISPLAY "request: ",cmd # LET cmd = "cp ",cmd CLIPPED," /home/fourjs/gas/appdata/services/mbs/bin/tmp/recibido.xml" LET cmd = "copy ",cmd CLIPPED, " C:\\ProgramData\\FourJs\\gas\\3.20.06-201906131721\\services\\ecf\\tmp\\recibido.xml" RUN cmd # LET tmpfile = "/home/fourjs/gas/appdata/services/mbs/bin/tmp/recibido.xml" LET tmpfile = ".\\tmp\\recibido.xml" LET recibido = filexml CLIPPED,"recibido.xml" LET filexml = recibido # TRY LET doc = xml.DomDocument.Create() CALL doc.setFeature("whitespace-in-element-content",FALSE) IF os.Path.exists(tmpfile) THEN CALL doc.load(tmpfile) CALL doc.save(recibido) CALL getxmldata(filexml) RETURNING tipoecf,pfechafirmadigital,rnc_e,e_ncf,rnc_c LET filexml = filexml CLIPPED,rnc_e CLIPPED,e_ncf CLIPPED,".xml" CALL doc.save(filexml) LET fileafirmar_f = filexml IF tipooperacion = "recepcion" THEN CALL formaracuse() RETURNING filexml CALL firmadocumento(filexml) END IF CALL doc.load(fileafirmar_f) LET cmd = doc.saveToString() RETURN 200,cmd ELSE RETURN 401,"Falla en el proceso del file" END IF END FUNCTION FUNCTION show_err(msg) DEFINE msg STRING DISPLAY "ERROR:",msg # CALL errorlog(msg CLIPPED) END FUNCTION FUNCTION formaracuse() DEFINE chFechaFirma STRING LET fileacuse = fileacuse CLIPPED,"acuse",rnc_c CLIPPED,".xml" LET out=om.XmlWriter.createFileWriter(fileacuse) LET a=om.SaxAttributes.create() CALL out.startDocument() CALL a.addAttribute("xmlns:xs","http://www.w3.org/2001/XMLSchema") CALL out.startElement("ARECF",a) CALL a.clear() CALL out.startElement("DetalleAcusedeRecibo",a) CALL out.startElement("Version",a) CALL out.characters("1.0") CALL out.endElement("Version") CALL out.startElement("RNCEmisor",a) CALL out.characters(rnc_e) CALL out.endElement("RNCEmisor") CALL out.startElement("RNCComprador",a) CALL out.characters(rnc_c) CALL out.endElement("RNCComprador") CALL out.startElement("eNCF",a) CALL out.characters(e_ncf) CALL out.endElement("eNCF") CALL out.startElement("Estado",a) CALL out.characters("0") CALL out.endElement("Estado") LET chFechaFirma = util.Datetime.format(CURRENT, "%d-%m-%Y %H:%M:%S" ) DISPLAY "FECHA ",chFechaFirma CALL out.startElement("FechaHoraAcuseRecibo",a) CALL out.characters(chFechaFirma) CALL out.endElement("FechaHoraAcuseRecibo") CALL out.endElement("DetalleAcusedeRecibo") CALL out.endElement("ARECF") CALL out.endDocument() RETURN fileacuse END FUNCTION FUNCTION limpiatmp() DISPLAY "BORRANDO XML FILES..." RUN 'rm /tmp/*.xml' END FUNCTION FUNCTION firmadocumento(fileafirmar) DEFINE doc xml.DomDocument DEFINE doc2 xml.DomDocument DEFINE root xml.DomNode DEFINE node xml.DomNode DEFINE signNode xml.DomNode DEFINE sig xml.Signature DEFINE key xml.CryptoKey DEFINE cert xml.CryptoX509 DEFINE index INTEGER, fileafirmar STRING, codsecure VARCHAR(6) # Create DomDocument object LET doc = xml.DomDocument.Create() # Notice that whitespaces are significant in cryptography, # therefore it is recommended to remove unnecessary ones CALL doc.setFeature("whitespace-in-element-content",FALSE) #DISPLAY "file ",fileafirmar LET filexml = fileafirmar CALL doc.load(fileafirmar) TRY # Create rsa key LET key = xml.CryptoKey.Create("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") CALL key.loadPEM("onlyRSA.pem") # Create an X509 certificate with the constructor of the CryptoX509 class. LET cert = xml.CryptoX509.Create() CALL cert.setFeature("X509Certificate",TRUE) # Load the X509 certificate associated to the RSA or DSA private key into the CryptoKey object. # CALL cert.loadPEM("cert509.crt") CALL cert.loadPEM("onlyCert.pem") # Create signature object with the key to use LET sig = xml.Signature.Create() # Assign the CryptoKey object to the Signature object. CALL sig.setKey(KEY) # Assign the CryptoX509 object to the Signature object. CALL sig.setCertificate(cert) # Set XML node to be signed. In our case, the entire document # LET index = sig.createReference("", # "http://www.w3.org/2001/04/xmlenc#sha256") LET index = sig.createReference('""', "http://www.w3.org/2001/04/xmlenc#sha256") # Add enveloped method to not take the XML signature node into account # when computing the entire document. CALL sig.appendReferenceTransformation(index, "http://www.w3.org/2000/09/xmldsig#enveloped-signature",doc.getDocumentElement()) # Set canonicalization method on the XML fragment to be signed. # Compute enveloped signature CALL sig.compute(doc) # Retrieve signature document LET doc2=sig.getDocument() # Append the signature node to the original document to get # a valid enveloped signature # Notice that the enveloped signature can be added anywhere in the # original document LET signNode = doc2.getDocumentElement() # Get Signature node # Import it into the original document LET node = doc.importNode(signNode,true) # Retrieve the original document root node LET root = doc.getDocumentElement() # Append the signature node as last child of the original document CALL root.appendChild(node) # Save document with enveloped signature back to disk CALL doc.setFeature("format-pretty-print",TRUE) LET fileafirmar = ruta_firmados CLIPPED,"\\",os.Path.baseName(fileafirmar) CALL doc.save(fileafirmar) LET fileafirmar_f = fileafirmar CATCH DISPLAY "Unable to create an enveloped signature :",status," ",sqlca.sqlerrm END TRY END FUNCTION