Compare commits
	
		
			38 Commits
		
	
	
		
			machete_no
			...
			morfo
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 48d1ba3735 | ||
|  | 2e130d39e6 | ||
|  | 6716efd121 | ||
|  | 302812328e | ||
|  | 3a89c6d3e5 | ||
|  | 3a349a746e | ||
|  | efe93ecc3c | ||
|  | 64b312a432 | ||
|  | 088fa9e6e0 | ||
|  | ddee0e45c1 | ||
|  | 69a74c0714 | ||
|  | a1a9746353 | ||
|  | b3e4a088b7 | ||
|  | 507ddbe558 | ||
|  | 2e8aa35b29 | ||
|  | ba908b938c | ||
|  | 4f15926656 | ||
|  | 1d6d1e2601 | ||
|  | 47a0dd33e2 | ||
|  | 53b5207e35 | ||
|  | bd25bef21f | ||
|  | 5f5a6182c9 | ||
|  | ab462a6ca5 | ||
|  | c694603505 | ||
|  | b6219bd171 | ||
|  | a9dde83e81 | ||
|  | 3eacb29afa | ||
|  | f630a544c2 | ||
|  | ba4e3d546f | ||
|  | 92bae58e51 | ||
|  | 58e7387292 | ||
|  | a015a9361b | ||
|  | 0216d0141a | ||
|  | 6cc4610b45 | ||
|  | 49feee8809 | ||
|  | d78a429711 | ||
|  | 84996066fa | ||
|  | 7d060e1786 | 
							
								
								
									
										31
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,31 +0,0 @@ | ||||
| # DERIVADO DE https://alextereshenkov.github.io/run-python-tests-with-tox-in-docker.html | ||||
| FROM ubuntu:18.04 | ||||
|  | ||||
| RUN apt-get -qq update | ||||
| RUN apt-get install -y --no-install-recommends \ | ||||
|   python3.7 python3.7-distutils python3.7-dev \ | ||||
|   python3.8 python3.8-distutils python3.8-dev \ | ||||
|   wget \ | ||||
|   ca-certificates | ||||
|  | ||||
| RUN wget https://bootstrap.pypa.io/get-pip.py \ | ||||
|   && python3 get-pip.py pip==21.3 \ | ||||
|   && python3.7 get-pip.py pip==21.3 \ | ||||
|   && python3.8 get-pip.py pip==21.3 \ | ||||
|   && rm get-pip.py | ||||
|  | ||||
| RUN apt-get install -y --no-install-recommends \ | ||||
|         libxml2-dev \ | ||||
|         libxmlsec1-dev \ | ||||
|         build-essential \ | ||||
|         zip | ||||
|  | ||||
| RUN python3.6 --version | ||||
| RUN python3.7 --version | ||||
| RUN python3.8 --version | ||||
|  | ||||
| RUN pip3.6 install setuptools setuptools-rust | ||||
| RUN pip3.7 install setuptools setuptools-rust | ||||
| RUN pip3.8 install setuptools setuptools-rust | ||||
|  | ||||
| RUN pip3 install tox pytest | ||||
| @@ -3,4 +3,4 @@ History | ||||
| ======= | ||||
|  | ||||
|  | ||||
| * First release on PyPI. | ||||
| * 0.2.1 version usada en produccion. | ||||
|   | ||||
							
								
								
									
										24
									
								
								Makefile.dev
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								Makefile.dev
									
									
									
									
									
								
							| @@ -1,24 +0,0 @@ | ||||
| # Entorno de desarrollo | ||||
| # | ||||
| # solo es necesario una vez: | ||||
| #  * make -f Makefile.dev dev-setup | ||||
| # | ||||
| # luego se pueden ejecutar las pruebas: | ||||
| #  * make -f Makefile.dev test | ||||
|  | ||||
| .PHONY: dev-setup dev-shell py-develop test tox | ||||
|  | ||||
| dev-setup: | ||||
| 	docker build -t facho . | ||||
|  | ||||
| py-develop: | ||||
| 	docker run -t -v $(PWD):/app -w /app facho sh -c 'python3.7 setup.py develop --user' | ||||
|  | ||||
| dev-shell: | ||||
| 	docker run --rm -ti -v "$(PWD):/app" -w /app --name facho-cli facho bash | ||||
|  | ||||
| test: | ||||
| 	docker run -t -v $(PWD):/app -w /app facho sh -c 'cd /app; python3.7 setup.py test' | ||||
|  | ||||
| tox: | ||||
| 	docker run -it -v $(PWD)/:/app -w /app facho tox | ||||
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -1,13 +0,0 @@ | ||||
| # notas | ||||
|  | ||||
| * se extrae documento tecnico de resolucion usando **pdfarranger** | ||||
|  | ||||
| ## CUNE | ||||
|  | ||||
|  ver 8.1.1.1 del archivo **Resolucion 000013 de 11-02-2021.pdf** | ||||
|  | ||||
| # enlaces | ||||
|  | ||||
| * https://www.dian.gov.co/impuestos/Paginas/Sistema-de-Factura-Electronica/documento-soporte-de-pago-de-nomina-electronica.aspx | ||||
| * https://bitbucket.org/presik/electronic_payroll.git | ||||
| * https://bitbucket.org/presik/trytonpsk-staff_payroll_co.git | ||||
										
											Binary file not shown.
										
									
								
							| @@ -1,93 +0,0 @@ | ||||
|  | ||||
| from facho import fe | ||||
|  | ||||
| def extensions(nomina): | ||||
|     return [] | ||||
|  | ||||
| def nomina(): | ||||
|     nomina = fe.nomina.DIANNominaIndividual() | ||||
|  | ||||
|     nomina.asignar_metadata(fe.nomina.Metadata( | ||||
|         secuencia=fe.nomina.NumeroSecuencia( | ||||
|             numero = 'N00001', | ||||
|             consecutivo=232 | ||||
|         ), | ||||
|         lugar_generacion=fe.nomina.Lugar( | ||||
|             pais = fe.nomina.Pais( | ||||
|                 code = 'CO' | ||||
|             ), | ||||
|             departamento = fe.nomina.Departamento( | ||||
|                 code = '05' | ||||
|             ), | ||||
|             municipio = fe.nomina.Municipio( | ||||
|                 code = '05001' | ||||
|             ), | ||||
|         ), | ||||
|         proveedor=fe.nomina.Proveedor( | ||||
|             nit='999999', | ||||
|             dv=2, | ||||
|             software_id='xx', | ||||
|             software_sc='yy' | ||||
|         ) | ||||
|     )) | ||||
|  | ||||
|     nomina.asignar_informacion_general(fe.nomina.InformacionGeneral( | ||||
|         fecha_generacion = '2020-01-16', | ||||
|         hora_generacion = '1053:10-05:00', | ||||
|         tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRODUCCION, | ||||
|         software_pin = '693', | ||||
|         periodo_nomina = fe.nomina.PeriodoNomina(code='1'), | ||||
|         tipo_moneda = fe.nomina.TipoMoneda(code='COP') | ||||
|     )) | ||||
|  | ||||
|     nomina.asignar_empleador(fe.nomina.Empleador( | ||||
|         nit = '700085371', | ||||
|         dv = '1', | ||||
|         pais = fe.nomina.Pais( | ||||
|             code = 'CO' | ||||
|         ), | ||||
|         departamento = fe.nomina.Departamento( | ||||
|             code = '05' | ||||
|         ), | ||||
|         municipio = fe.nomina.Municipio( | ||||
|             code = '05001' | ||||
|         ), | ||||
|         direccion = 'calle etrivial' | ||||
|     )) | ||||
|  | ||||
|     nomina.asignar_trabajador(fe.nomina.Trabajador( | ||||
|         tipo_contrato = fe.nomina.TipoContrato( | ||||
|             code = '1' | ||||
|         ), | ||||
|         alto_riesgo = False, | ||||
|         tipo_documento = fe.nomina.TipoDocumento( | ||||
|             code = '11' | ||||
|         ), | ||||
|         primer_apellido = 'gnu', | ||||
|         segundo_apellido = 'emacs', | ||||
|         primer_nombre = 'facho', | ||||
|         lugar_trabajo = fe.nomina.LugarTrabajo( | ||||
|             pais = fe.nomina.Pais(code='CO'), | ||||
|             departamento = fe.nomina.Departamento(code='05'), | ||||
|             municipio = fe.nomina.Municipio(code='05001'), | ||||
|             direccion = 'calle facho' | ||||
|         ), | ||||
|         numero_documento = '800199436', | ||||
|         tipo = fe.nomina.TipoTrabajador( | ||||
|             code = '01' | ||||
|         ), | ||||
|         salario_integral = True, | ||||
|         sueldo = fe.nomina.Amount(1_500_000) | ||||
|     )) | ||||
|  | ||||
|     nomina.adicionar_devengado(fe.nomina.DevengadoBasico( | ||||
|         dias_trabajados = 60, | ||||
|         sueldo_trabajado = fe.nomina.Amount(3_500_000) | ||||
|     )) | ||||
|  | ||||
|     nomina.adicionar_deduccion(fe.nomina.DeduccionSalud( | ||||
|         porcentaje = fe.nomina.Amount(19), | ||||
|         deduccion = fe.nomina.Amount(1_000_000) | ||||
|     )) | ||||
|  | ||||
|     return nomina | ||||
| @@ -1,674 +0,0 @@ | ||||
|                     GNU GENERAL PUBLIC LICENSE | ||||
|                        Version 3, 29 June 2007 | ||||
|  | ||||
|  Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
|  | ||||
|                             Preamble | ||||
|  | ||||
|   The GNU General Public License is a free, copyleft license for | ||||
| software and other kinds of works. | ||||
|  | ||||
|   The licenses for most software and other practical works are designed | ||||
| to take away your freedom to share and change the works.  By contrast, | ||||
| the GNU General Public License is intended to guarantee your freedom to | ||||
| share and change all versions of a program--to make sure it remains free | ||||
| software for all its users.  We, the Free Software Foundation, use the | ||||
| GNU General Public License for most of our software; it applies also to | ||||
| any other work released this way by its authors.  You can apply it to | ||||
| your programs, too. | ||||
|  | ||||
|   When we speak of free software, we are referring to freedom, not | ||||
| price.  Our General Public Licenses are designed to make sure that you | ||||
| have the freedom to distribute copies of free software (and charge for | ||||
| them if you wish), that you receive source code or can get it if you | ||||
| want it, that you can change the software or use pieces of it in new | ||||
| free programs, and that you know you can do these things. | ||||
|  | ||||
|   To protect your rights, we need to prevent others from denying you | ||||
| these rights or asking you to surrender the rights.  Therefore, you have | ||||
| certain responsibilities if you distribute copies of the software, or if | ||||
| you modify it: responsibilities to respect the freedom of others. | ||||
|  | ||||
|   For example, if you distribute copies of such a program, whether | ||||
| gratis or for a fee, you must pass on to the recipients the same | ||||
| freedoms that you received.  You must make sure that they, too, receive | ||||
| or can get the source code.  And you must show them these terms so they | ||||
| know their rights. | ||||
|  | ||||
|   Developers that use the GNU GPL protect your rights with two steps: | ||||
| (1) assert copyright on the software, and (2) offer you this License | ||||
| giving you legal permission to copy, distribute and/or modify it. | ||||
|  | ||||
|   For the developers' and authors' protection, the GPL clearly explains | ||||
| that there is no warranty for this free software.  For both users' and | ||||
| authors' sake, the GPL requires that modified versions be marked as | ||||
| changed, so that their problems will not be attributed erroneously to | ||||
| authors of previous versions. | ||||
|  | ||||
|   Some devices are designed to deny users access to install or run | ||||
| modified versions of the software inside them, although the manufacturer | ||||
| can do so.  This is fundamentally incompatible with the aim of | ||||
| protecting users' freedom to change the software.  The systematic | ||||
| pattern of such abuse occurs in the area of products for individuals to | ||||
| use, which is precisely where it is most unacceptable.  Therefore, we | ||||
| have designed this version of the GPL to prohibit the practice for those | ||||
| products.  If such problems arise substantially in other domains, we | ||||
| stand ready to extend this provision to those domains in future versions | ||||
| of the GPL, as needed to protect the freedom of users. | ||||
|  | ||||
|   Finally, every program is threatened constantly by software patents. | ||||
| States should not allow patents to restrict development and use of | ||||
| software on general-purpose computers, but in those that do, we wish to | ||||
| avoid the special danger that patents applied to a free program could | ||||
| make it effectively proprietary.  To prevent this, the GPL assures that | ||||
| patents cannot be used to render the program non-free. | ||||
|  | ||||
|   The precise terms and conditions for copying, distribution and | ||||
| modification follow. | ||||
|  | ||||
|                        TERMS AND CONDITIONS | ||||
|  | ||||
|   0. Definitions. | ||||
|  | ||||
|   "This License" refers to version 3 of the GNU General Public License. | ||||
|  | ||||
|   "Copyright" also means copyright-like laws that apply to other kinds of | ||||
| works, such as semiconductor masks. | ||||
|  | ||||
|   "The Program" refers to any copyrightable work licensed under this | ||||
| License.  Each licensee is addressed as "you".  "Licensees" and | ||||
| "recipients" may be individuals or organizations. | ||||
|  | ||||
|   To "modify" a work means to copy from or adapt all or part of the work | ||||
| in a fashion requiring copyright permission, other than the making of an | ||||
| exact copy.  The resulting work is called a "modified version" of the | ||||
| earlier work or a work "based on" the earlier work. | ||||
|  | ||||
|   A "covered work" means either the unmodified Program or a work based | ||||
| on the Program. | ||||
|  | ||||
|   To "propagate" a work means to do anything with it that, without | ||||
| permission, would make you directly or secondarily liable for | ||||
| infringement under applicable copyright law, except executing it on a | ||||
| computer or modifying a private copy.  Propagation includes copying, | ||||
| distribution (with or without modification), making available to the | ||||
| public, and in some countries other activities as well. | ||||
|  | ||||
|   To "convey" a work means any kind of propagation that enables other | ||||
| parties to make or receive copies.  Mere interaction with a user through | ||||
| a computer network, with no transfer of a copy, is not conveying. | ||||
|  | ||||
|   An interactive user interface displays "Appropriate Legal Notices" | ||||
| to the extent that it includes a convenient and prominently visible | ||||
| feature that (1) displays an appropriate copyright notice, and (2) | ||||
| tells the user that there is no warranty for the work (except to the | ||||
| extent that warranties are provided), that licensees may convey the | ||||
| work under this License, and how to view a copy of this License.  If | ||||
| the interface presents a list of user commands or options, such as a | ||||
| menu, a prominent item in the list meets this criterion. | ||||
|  | ||||
|   1. Source Code. | ||||
|  | ||||
|   The "source code" for a work means the preferred form of the work | ||||
| for making modifications to it.  "Object code" means any non-source | ||||
| form of a work. | ||||
|  | ||||
|   A "Standard Interface" means an interface that either is an official | ||||
| standard defined by a recognized standards body, or, in the case of | ||||
| interfaces specified for a particular programming language, one that | ||||
| is widely used among developers working in that language. | ||||
|  | ||||
|   The "System Libraries" of an executable work include anything, other | ||||
| than the work as a whole, that (a) is included in the normal form of | ||||
| packaging a Major Component, but which is not part of that Major | ||||
| Component, and (b) serves only to enable use of the work with that | ||||
| Major Component, or to implement a Standard Interface for which an | ||||
| implementation is available to the public in source code form.  A | ||||
| "Major Component", in this context, means a major essential component | ||||
| (kernel, window system, and so on) of the specific operating system | ||||
| (if any) on which the executable work runs, or a compiler used to | ||||
| produce the work, or an object code interpreter used to run it. | ||||
|  | ||||
|   The "Corresponding Source" for a work in object code form means all | ||||
| the source code needed to generate, install, and (for an executable | ||||
| work) run the object code and to modify the work, including scripts to | ||||
| control those activities.  However, it does not include the work's | ||||
| System Libraries, or general-purpose tools or generally available free | ||||
| programs which are used unmodified in performing those activities but | ||||
| which are not part of the work.  For example, Corresponding Source | ||||
| includes interface definition files associated with source files for | ||||
| the work, and the source code for shared libraries and dynamically | ||||
| linked subprograms that the work is specifically designed to require, | ||||
| such as by intimate data communication or control flow between those | ||||
| subprograms and other parts of the work. | ||||
|  | ||||
|   The Corresponding Source need not include anything that users | ||||
| can regenerate automatically from other parts of the Corresponding | ||||
| Source. | ||||
|  | ||||
|   The Corresponding Source for a work in source code form is that | ||||
| same work. | ||||
|  | ||||
|   2. Basic Permissions. | ||||
|  | ||||
|   All rights granted under this License are granted for the term of | ||||
| copyright on the Program, and are irrevocable provided the stated | ||||
| conditions are met.  This License explicitly affirms your unlimited | ||||
| permission to run the unmodified Program.  The output from running a | ||||
| covered work is covered by this License only if the output, given its | ||||
| content, constitutes a covered work.  This License acknowledges your | ||||
| rights of fair use or other equivalent, as provided by copyright law. | ||||
|  | ||||
|   You may make, run and propagate covered works that you do not | ||||
| convey, without conditions so long as your license otherwise remains | ||||
| in force.  You may convey covered works to others for the sole purpose | ||||
| of having them make modifications exclusively for you, or provide you | ||||
| with facilities for running those works, provided that you comply with | ||||
| the terms of this License in conveying all material for which you do | ||||
| not control copyright.  Those thus making or running the covered works | ||||
| for you must do so exclusively on your behalf, under your direction | ||||
| and control, on terms that prohibit them from making any copies of | ||||
| your copyrighted material outside their relationship with you. | ||||
|  | ||||
|   Conveying under any other circumstances is permitted solely under | ||||
| the conditions stated below.  Sublicensing is not allowed; section 10 | ||||
| makes it unnecessary. | ||||
|  | ||||
|   3. Protecting Users' Legal Rights From Anti-Circumvention Law. | ||||
|  | ||||
|   No covered work shall be deemed part of an effective technological | ||||
| measure under any applicable law fulfilling obligations under article | ||||
| 11 of the WIPO copyright treaty adopted on 20 December 1996, or | ||||
| similar laws prohibiting or restricting circumvention of such | ||||
| measures. | ||||
|  | ||||
|   When you convey a covered work, you waive any legal power to forbid | ||||
| circumvention of technological measures to the extent such circumvention | ||||
| is effected by exercising rights under this License with respect to | ||||
| the covered work, and you disclaim any intention to limit operation or | ||||
| modification of the work as a means of enforcing, against the work's | ||||
| users, your or third parties' legal rights to forbid circumvention of | ||||
| technological measures. | ||||
|  | ||||
|   4. Conveying Verbatim Copies. | ||||
|  | ||||
|   You may convey verbatim copies of the Program's source code as you | ||||
| receive it, in any medium, provided that you conspicuously and | ||||
| appropriately publish on each copy an appropriate copyright notice; | ||||
| keep intact all notices stating that this License and any | ||||
| non-permissive terms added in accord with section 7 apply to the code; | ||||
| keep intact all notices of the absence of any warranty; and give all | ||||
| recipients a copy of this License along with the Program. | ||||
|  | ||||
|   You may charge any price or no price for each copy that you convey, | ||||
| and you may offer support or warranty protection for a fee. | ||||
|  | ||||
|   5. Conveying Modified Source Versions. | ||||
|  | ||||
|   You may convey a work based on the Program, or the modifications to | ||||
| produce it from the Program, in the form of source code under the | ||||
| terms of section 4, provided that you also meet all of these conditions: | ||||
|  | ||||
|     a) The work must carry prominent notices stating that you modified | ||||
|     it, and giving a relevant date. | ||||
|  | ||||
|     b) The work must carry prominent notices stating that it is | ||||
|     released under this License and any conditions added under section | ||||
|     7.  This requirement modifies the requirement in section 4 to | ||||
|     "keep intact all notices". | ||||
|  | ||||
|     c) You must license the entire work, as a whole, under this | ||||
|     License to anyone who comes into possession of a copy.  This | ||||
|     License will therefore apply, along with any applicable section 7 | ||||
|     additional terms, to the whole of the work, and all its parts, | ||||
|     regardless of how they are packaged.  This License gives no | ||||
|     permission to license the work in any other way, but it does not | ||||
|     invalidate such permission if you have separately received it. | ||||
|  | ||||
|     d) If the work has interactive user interfaces, each must display | ||||
|     Appropriate Legal Notices; however, if the Program has interactive | ||||
|     interfaces that do not display Appropriate Legal Notices, your | ||||
|     work need not make them do so. | ||||
|  | ||||
|   A compilation of a covered work with other separate and independent | ||||
| works, which are not by their nature extensions of the covered work, | ||||
| and which are not combined with it such as to form a larger program, | ||||
| in or on a volume of a storage or distribution medium, is called an | ||||
| "aggregate" if the compilation and its resulting copyright are not | ||||
| used to limit the access or legal rights of the compilation's users | ||||
| beyond what the individual works permit.  Inclusion of a covered work | ||||
| in an aggregate does not cause this License to apply to the other | ||||
| parts of the aggregate. | ||||
|  | ||||
|   6. Conveying Non-Source Forms. | ||||
|  | ||||
|   You may convey a covered work in object code form under the terms | ||||
| of sections 4 and 5, provided that you also convey the | ||||
| machine-readable Corresponding Source under the terms of this License, | ||||
| in one of these ways: | ||||
|  | ||||
|     a) Convey the object code in, or embodied in, a physical product | ||||
|     (including a physical distribution medium), accompanied by the | ||||
|     Corresponding Source fixed on a durable physical medium | ||||
|     customarily used for software interchange. | ||||
|  | ||||
|     b) Convey the object code in, or embodied in, a physical product | ||||
|     (including a physical distribution medium), accompanied by a | ||||
|     written offer, valid for at least three years and valid for as | ||||
|     long as you offer spare parts or customer support for that product | ||||
|     model, to give anyone who possesses the object code either (1) a | ||||
|     copy of the Corresponding Source for all the software in the | ||||
|     product that is covered by this License, on a durable physical | ||||
|     medium customarily used for software interchange, for a price no | ||||
|     more than your reasonable cost of physically performing this | ||||
|     conveying of source, or (2) access to copy the | ||||
|     Corresponding Source from a network server at no charge. | ||||
|  | ||||
|     c) Convey individual copies of the object code with a copy of the | ||||
|     written offer to provide the Corresponding Source.  This | ||||
|     alternative is allowed only occasionally and noncommercially, and | ||||
|     only if you received the object code with such an offer, in accord | ||||
|     with subsection 6b. | ||||
|  | ||||
|     d) Convey the object code by offering access from a designated | ||||
|     place (gratis or for a charge), and offer equivalent access to the | ||||
|     Corresponding Source in the same way through the same place at no | ||||
|     further charge.  You need not require recipients to copy the | ||||
|     Corresponding Source along with the object code.  If the place to | ||||
|     copy the object code is a network server, the Corresponding Source | ||||
|     may be on a different server (operated by you or a third party) | ||||
|     that supports equivalent copying facilities, provided you maintain | ||||
|     clear directions next to the object code saying where to find the | ||||
|     Corresponding Source.  Regardless of what server hosts the | ||||
|     Corresponding Source, you remain obligated to ensure that it is | ||||
|     available for as long as needed to satisfy these requirements. | ||||
|  | ||||
|     e) Convey the object code using peer-to-peer transmission, provided | ||||
|     you inform other peers where the object code and Corresponding | ||||
|     Source of the work are being offered to the general public at no | ||||
|     charge under subsection 6d. | ||||
|  | ||||
|   A separable portion of the object code, whose source code is excluded | ||||
| from the Corresponding Source as a System Library, need not be | ||||
| included in conveying the object code work. | ||||
|  | ||||
|   A "User Product" is either (1) a "consumer product", which means any | ||||
| tangible personal property which is normally used for personal, family, | ||||
| or household purposes, or (2) anything designed or sold for incorporation | ||||
| into a dwelling.  In determining whether a product is a consumer product, | ||||
| doubtful cases shall be resolved in favor of coverage.  For a particular | ||||
| product received by a particular user, "normally used" refers to a | ||||
| typical or common use of that class of product, regardless of the status | ||||
| of the particular user or of the way in which the particular user | ||||
| actually uses, or expects or is expected to use, the product.  A product | ||||
| is a consumer product regardless of whether the product has substantial | ||||
| commercial, industrial or non-consumer uses, unless such uses represent | ||||
| the only significant mode of use of the product. | ||||
|  | ||||
|   "Installation Information" for a User Product means any methods, | ||||
| procedures, authorization keys, or other information required to install | ||||
| and execute modified versions of a covered work in that User Product from | ||||
| a modified version of its Corresponding Source.  The information must | ||||
| suffice to ensure that the continued functioning of the modified object | ||||
| code is in no case prevented or interfered with solely because | ||||
| modification has been made. | ||||
|  | ||||
|   If you convey an object code work under this section in, or with, or | ||||
| specifically for use in, a User Product, and the conveying occurs as | ||||
| part of a transaction in which the right of possession and use of the | ||||
| User Product is transferred to the recipient in perpetuity or for a | ||||
| fixed term (regardless of how the transaction is characterized), the | ||||
| Corresponding Source conveyed under this section must be accompanied | ||||
| by the Installation Information.  But this requirement does not apply | ||||
| if neither you nor any third party retains the ability to install | ||||
| modified object code on the User Product (for example, the work has | ||||
| been installed in ROM). | ||||
|  | ||||
|   The requirement to provide Installation Information does not include a | ||||
| requirement to continue to provide support service, warranty, or updates | ||||
| for a work that has been modified or installed by the recipient, or for | ||||
| the User Product in which it has been modified or installed.  Access to a | ||||
| network may be denied when the modification itself materially and | ||||
| adversely affects the operation of the network or violates the rules and | ||||
| protocols for communication across the network. | ||||
|  | ||||
|   Corresponding Source conveyed, and Installation Information provided, | ||||
| in accord with this section must be in a format that is publicly | ||||
| documented (and with an implementation available to the public in | ||||
| source code form), and must require no special password or key for | ||||
| unpacking, reading or copying. | ||||
|  | ||||
|   7. Additional Terms. | ||||
|  | ||||
|   "Additional permissions" are terms that supplement the terms of this | ||||
| License by making exceptions from one or more of its conditions. | ||||
| Additional permissions that are applicable to the entire Program shall | ||||
| be treated as though they were included in this License, to the extent | ||||
| that they are valid under applicable law.  If additional permissions | ||||
| apply only to part of the Program, that part may be used separately | ||||
| under those permissions, but the entire Program remains governed by | ||||
| this License without regard to the additional permissions. | ||||
|  | ||||
|   When you convey a copy of a covered work, you may at your option | ||||
| remove any additional permissions from that copy, or from any part of | ||||
| it.  (Additional permissions may be written to require their own | ||||
| removal in certain cases when you modify the work.)  You may place | ||||
| additional permissions on material, added by you to a covered work, | ||||
| for which you have or can give appropriate copyright permission. | ||||
|  | ||||
|   Notwithstanding any other provision of this License, for material you | ||||
| add to a covered work, you may (if authorized by the copyright holders of | ||||
| that material) supplement the terms of this License with terms: | ||||
|  | ||||
|     a) Disclaiming warranty or limiting liability differently from the | ||||
|     terms of sections 15 and 16 of this License; or | ||||
|  | ||||
|     b) Requiring preservation of specified reasonable legal notices or | ||||
|     author attributions in that material or in the Appropriate Legal | ||||
|     Notices displayed by works containing it; or | ||||
|  | ||||
|     c) Prohibiting misrepresentation of the origin of that material, or | ||||
|     requiring that modified versions of such material be marked in | ||||
|     reasonable ways as different from the original version; or | ||||
|  | ||||
|     d) Limiting the use for publicity purposes of names of licensors or | ||||
|     authors of the material; or | ||||
|  | ||||
|     e) Declining to grant rights under trademark law for use of some | ||||
|     trade names, trademarks, or service marks; or | ||||
|  | ||||
|     f) Requiring indemnification of licensors and authors of that | ||||
|     material by anyone who conveys the material (or modified versions of | ||||
|     it) with contractual assumptions of liability to the recipient, for | ||||
|     any liability that these contractual assumptions directly impose on | ||||
|     those licensors and authors. | ||||
|  | ||||
|   All other non-permissive additional terms are considered "further | ||||
| restrictions" within the meaning of section 10.  If the Program as you | ||||
| received it, or any part of it, contains a notice stating that it is | ||||
| governed by this License along with a term that is a further | ||||
| restriction, you may remove that term.  If a license document contains | ||||
| a further restriction but permits relicensing or conveying under this | ||||
| License, you may add to a covered work material governed by the terms | ||||
| of that license document, provided that the further restriction does | ||||
| not survive such relicensing or conveying. | ||||
|  | ||||
|   If you add terms to a covered work in accord with this section, you | ||||
| must place, in the relevant source files, a statement of the | ||||
| additional terms that apply to those files, or a notice indicating | ||||
| where to find the applicable terms. | ||||
|  | ||||
|   Additional terms, permissive or non-permissive, may be stated in the | ||||
| form of a separately written license, or stated as exceptions; | ||||
| the above requirements apply either way. | ||||
|  | ||||
|   8. Termination. | ||||
|  | ||||
|   You may not propagate or modify a covered work except as expressly | ||||
| provided under this License.  Any attempt otherwise to propagate or | ||||
| modify it is void, and will automatically terminate your rights under | ||||
| this License (including any patent licenses granted under the third | ||||
| paragraph of section 11). | ||||
|  | ||||
|   However, if you cease all violation of this License, then your | ||||
| license from a particular copyright holder is reinstated (a) | ||||
| provisionally, unless and until the copyright holder explicitly and | ||||
| finally terminates your license, and (b) permanently, if the copyright | ||||
| holder fails to notify you of the violation by some reasonable means | ||||
| prior to 60 days after the cessation. | ||||
|  | ||||
|   Moreover, your license from a particular copyright holder is | ||||
| reinstated permanently if the copyright holder notifies you of the | ||||
| violation by some reasonable means, this is the first time you have | ||||
| received notice of violation of this License (for any work) from that | ||||
| copyright holder, and you cure the violation prior to 30 days after | ||||
| your receipt of the notice. | ||||
|  | ||||
|   Termination of your rights under this section does not terminate the | ||||
| licenses of parties who have received copies or rights from you under | ||||
| this License.  If your rights have been terminated and not permanently | ||||
| reinstated, you do not qualify to receive new licenses for the same | ||||
| material under section 10. | ||||
|  | ||||
|   9. Acceptance Not Required for Having Copies. | ||||
|  | ||||
|   You are not required to accept this License in order to receive or | ||||
| run a copy of the Program.  Ancillary propagation of a covered work | ||||
| occurring solely as a consequence of using peer-to-peer transmission | ||||
| to receive a copy likewise does not require acceptance.  However, | ||||
| nothing other than this License grants you permission to propagate or | ||||
| modify any covered work.  These actions infringe copyright if you do | ||||
| not accept this License.  Therefore, by modifying or propagating a | ||||
| covered work, you indicate your acceptance of this License to do so. | ||||
|  | ||||
|   10. Automatic Licensing of Downstream Recipients. | ||||
|  | ||||
|   Each time you convey a covered work, the recipient automatically | ||||
| receives a license from the original licensors, to run, modify and | ||||
| propagate that work, subject to this License.  You are not responsible | ||||
| for enforcing compliance by third parties with this License. | ||||
|  | ||||
|   An "entity transaction" is a transaction transferring control of an | ||||
| organization, or substantially all assets of one, or subdividing an | ||||
| organization, or merging organizations.  If propagation of a covered | ||||
| work results from an entity transaction, each party to that | ||||
| transaction who receives a copy of the work also receives whatever | ||||
| licenses to the work the party's predecessor in interest had or could | ||||
| give under the previous paragraph, plus a right to possession of the | ||||
| Corresponding Source of the work from the predecessor in interest, if | ||||
| the predecessor has it or can get it with reasonable efforts. | ||||
|  | ||||
|   You may not impose any further restrictions on the exercise of the | ||||
| rights granted or affirmed under this License.  For example, you may | ||||
| not impose a license fee, royalty, or other charge for exercise of | ||||
| rights granted under this License, and you may not initiate litigation | ||||
| (including a cross-claim or counterclaim in a lawsuit) alleging that | ||||
| any patent claim is infringed by making, using, selling, offering for | ||||
| sale, or importing the Program or any portion of it. | ||||
|  | ||||
|   11. Patents. | ||||
|  | ||||
|   A "contributor" is a copyright holder who authorizes use under this | ||||
| License of the Program or a work on which the Program is based.  The | ||||
| work thus licensed is called the contributor's "contributor version". | ||||
|  | ||||
|   A contributor's "essential patent claims" are all patent claims | ||||
| owned or controlled by the contributor, whether already acquired or | ||||
| hereafter acquired, that would be infringed by some manner, permitted | ||||
| by this License, of making, using, or selling its contributor version, | ||||
| but do not include claims that would be infringed only as a | ||||
| consequence of further modification of the contributor version.  For | ||||
| purposes of this definition, "control" includes the right to grant | ||||
| patent sublicenses in a manner consistent with the requirements of | ||||
| this License. | ||||
|  | ||||
|   Each contributor grants you a non-exclusive, worldwide, royalty-free | ||||
| patent license under the contributor's essential patent claims, to | ||||
| make, use, sell, offer for sale, import and otherwise run, modify and | ||||
| propagate the contents of its contributor version. | ||||
|  | ||||
|   In the following three paragraphs, a "patent license" is any express | ||||
| agreement or commitment, however denominated, not to enforce a patent | ||||
| (such as an express permission to practice a patent or covenant not to | ||||
| sue for patent infringement).  To "grant" such a patent license to a | ||||
| party means to make such an agreement or commitment not to enforce a | ||||
| patent against the party. | ||||
|  | ||||
|   If you convey a covered work, knowingly relying on a patent license, | ||||
| and the Corresponding Source of the work is not available for anyone | ||||
| to copy, free of charge and under the terms of this License, through a | ||||
| publicly available network server or other readily accessible means, | ||||
| then you must either (1) cause the Corresponding Source to be so | ||||
| available, or (2) arrange to deprive yourself of the benefit of the | ||||
| patent license for this particular work, or (3) arrange, in a manner | ||||
| consistent with the requirements of this License, to extend the patent | ||||
| license to downstream recipients.  "Knowingly relying" means you have | ||||
| actual knowledge that, but for the patent license, your conveying the | ||||
| covered work in a country, or your recipient's use of the covered work | ||||
| in a country, would infringe one or more identifiable patents in that | ||||
| country that you have reason to believe are valid. | ||||
|  | ||||
|   If, pursuant to or in connection with a single transaction or | ||||
| arrangement, you convey, or propagate by procuring conveyance of, a | ||||
| covered work, and grant a patent license to some of the parties | ||||
| receiving the covered work authorizing them to use, propagate, modify | ||||
| or convey a specific copy of the covered work, then the patent license | ||||
| you grant is automatically extended to all recipients of the covered | ||||
| work and works based on it. | ||||
|  | ||||
|   A patent license is "discriminatory" if it does not include within | ||||
| the scope of its coverage, prohibits the exercise of, or is | ||||
| conditioned on the non-exercise of one or more of the rights that are | ||||
| specifically granted under this License.  You may not convey a covered | ||||
| work if you are a party to an arrangement with a third party that is | ||||
| in the business of distributing software, under which you make payment | ||||
| to the third party based on the extent of your activity of conveying | ||||
| the work, and under which the third party grants, to any of the | ||||
| parties who would receive the covered work from you, a discriminatory | ||||
| patent license (a) in connection with copies of the covered work | ||||
| conveyed by you (or copies made from those copies), or (b) primarily | ||||
| for and in connection with specific products or compilations that | ||||
| contain the covered work, unless you entered into that arrangement, | ||||
| or that patent license was granted, prior to 28 March 2007. | ||||
|  | ||||
|   Nothing in this License shall be construed as excluding or limiting | ||||
| any implied license or other defenses to infringement that may | ||||
| otherwise be available to you under applicable patent law. | ||||
|  | ||||
|   12. No Surrender of Others' Freedom. | ||||
|  | ||||
|   If conditions are imposed on you (whether by court order, agreement or | ||||
| otherwise) that contradict the conditions of this License, they do not | ||||
| excuse you from the conditions of this License.  If you cannot convey a | ||||
| covered work so as to satisfy simultaneously your obligations under this | ||||
| License and any other pertinent obligations, then as a consequence you may | ||||
| not convey it at all.  For example, if you agree to terms that obligate you | ||||
| to collect a royalty for further conveying from those to whom you convey | ||||
| the Program, the only way you could satisfy both those terms and this | ||||
| License would be to refrain entirely from conveying the Program. | ||||
|  | ||||
|   13. Use with the GNU Affero General Public License. | ||||
|  | ||||
|   Notwithstanding any other provision of this License, you have | ||||
| permission to link or combine any covered work with a work licensed | ||||
| under version 3 of the GNU Affero General Public License into a single | ||||
| combined work, and to convey the resulting work.  The terms of this | ||||
| License will continue to apply to the part which is the covered work, | ||||
| but the special requirements of the GNU Affero General Public License, | ||||
| section 13, concerning interaction through a network will apply to the | ||||
| combination as such. | ||||
|  | ||||
|   14. Revised Versions of this License. | ||||
|  | ||||
|   The Free Software Foundation may publish revised and/or new versions of | ||||
| the GNU General Public License from time to time.  Such new versions will | ||||
| be similar in spirit to the present version, but may differ in detail to | ||||
| address new problems or concerns. | ||||
|  | ||||
|   Each version is given a distinguishing version number.  If the | ||||
| Program specifies that a certain numbered version of the GNU General | ||||
| Public License "or any later version" applies to it, you have the | ||||
| option of following the terms and conditions either of that numbered | ||||
| version or of any later version published by the Free Software | ||||
| Foundation.  If the Program does not specify a version number of the | ||||
| GNU General Public License, you may choose any version ever published | ||||
| by the Free Software Foundation. | ||||
|  | ||||
|   If the Program specifies that a proxy can decide which future | ||||
| versions of the GNU General Public License can be used, that proxy's | ||||
| public statement of acceptance of a version permanently authorizes you | ||||
| to choose that version for the Program. | ||||
|  | ||||
|   Later license versions may give you additional or different | ||||
| permissions.  However, no additional obligations are imposed on any | ||||
| author or copyright holder as a result of your choosing to follow a | ||||
| later version. | ||||
|  | ||||
|   15. Disclaimer of Warranty. | ||||
|  | ||||
|   THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | ||||
| APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | ||||
| HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | ||||
| OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | ||||
| THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||
| PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | ||||
| IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | ||||
| ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||||
|  | ||||
|   16. Limitation of Liability. | ||||
|  | ||||
|   IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | ||||
| WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | ||||
| THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | ||||
| GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | ||||
| USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | ||||
| DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | ||||
| PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | ||||
| EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | ||||
| SUCH DAMAGES. | ||||
|  | ||||
|   17. Interpretation of Sections 15 and 16. | ||||
|  | ||||
|   If the disclaimer of warranty and limitation of liability provided | ||||
| above cannot be given local legal effect according to their terms, | ||||
| reviewing courts shall apply local law that most closely approximates | ||||
| an absolute waiver of all civil liability in connection with the | ||||
| Program, unless a warranty or assumption of liability accompanies a | ||||
| copy of the Program in return for a fee. | ||||
|  | ||||
|                      END OF TERMS AND CONDITIONS | ||||
|  | ||||
|             How to Apply These Terms to Your New Programs | ||||
|  | ||||
|   If you develop a new program, and you want it to be of the greatest | ||||
| possible use to the public, the best way to achieve this is to make it | ||||
| free software which everyone can redistribute and change under these terms. | ||||
|  | ||||
|   To do so, attach the following notices to the program.  It is safest | ||||
| to attach them to the start of each source file to most effectively | ||||
| state the exclusion of warranty; and each file should have at least | ||||
| the "copyright" line and a pointer to where the full notice is found. | ||||
|  | ||||
|     <one line to give the program's name and a brief idea of what it does.> | ||||
|     Copyright (C) <year>  <name of author> | ||||
|  | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  | ||||
| Also add information on how to contact you by electronic and paper mail. | ||||
|  | ||||
|   If the program does terminal interaction, make it output a short | ||||
| notice like this when it starts in an interactive mode: | ||||
|  | ||||
|     facho-signer  Copyright (C) 2021  Jovany Leandro G.C <bit4bit@riseup.net> | ||||
|     This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | ||||
|     This is free software, and you are welcome to redistribute it | ||||
|     under certain conditions; type `show c' for details. | ||||
|  | ||||
| The hypothetical commands `show w' and `show c' should show the appropriate | ||||
| parts of the General Public License.  Of course, your program's commands | ||||
| might be different; for a GUI interface, you would use an "about box". | ||||
|  | ||||
|   You should also get your employer (if you work as a programmer) or school, | ||||
| if any, to sign a "copyright disclaimer" for the program, if necessary. | ||||
| For more information on this, and how to apply and follow the GNU GPL, see | ||||
| <https://www.gnu.org/licenses/>. | ||||
|  | ||||
|   The GNU General Public License does not permit incorporating your program | ||||
| into proprietary programs.  If your program is a subroutine library, you | ||||
| may consider it more useful to permit linking proprietary applications with | ||||
| the library.  If this is what you want to do, use the GNU Lesser General | ||||
| Public License instead of this License.  But first, please read | ||||
| <https://www.gnu.org/licenses/why-not-lgpl.html>. | ||||
| @@ -1 +0,0 @@ | ||||
| SUBDIRS = src | ||||
| @@ -1,3 +0,0 @@ | ||||
| #!/bin/sh | ||||
| libtoolize -c --force | ||||
| autoreconf --install --force | ||||
| @@ -1,56 +0,0 @@ | ||||
| #                                               -*- Autoconf -*- | ||||
| # Process this file with autoconf to produce a configure script. | ||||
|  | ||||
| AC_PREREQ([2.71]) | ||||
| AC_INIT([facho-signer], [0.0.1], [bit4bit@riseup.net]) | ||||
| AM_INIT_AUTOMAKE | ||||
| AC_CONFIG_SRCDIR([src/facho_signer.c]) | ||||
| AC_CONFIG_HEADERS([config.h]) | ||||
| AC_CONFIG_MACRO_DIRS([m4]) | ||||
|  | ||||
| # Checks for programs. | ||||
| AC_PROG_CC | ||||
|  | ||||
| # Checks for libraries. | ||||
| PKG_CHECK_MODULES([OPENSSL], [openssl]) | ||||
| PKG_CHECK_MODULES([XMLSEC1], [xmlsec1-openssl], [ | ||||
|                              AC_DEFINE([XMLSEC_CRYPTO_OPENSSL], [1], [enable crypto openssl]) | ||||
|                              ]) | ||||
| PKG_CHECK_MODULES([LZMA], [liblzma]) | ||||
|  | ||||
| AC_ARG_ENABLE([xmlsec-crypto-dynamic-loading], | ||||
|         AS_HELP_STRING([--enable-xmlsec-crypto-dynamic-loading], | ||||
|         [enable crypto xmlsec dynamic loading]) | ||||
|        ) | ||||
|  | ||||
| if test "x$enable_xmlsec_crypto_dynamic_loading" == xyes; then | ||||
|   AC_DEFINE([XMLSEC_CRYPTO_DYNAMIC_LOADING], [1], [enable xmlsec crypto dynamic loading]) | ||||
|   AC_CHECK_HEADER([ltdl.h], [ | ||||
| 		AC_CHECK_LIB( | ||||
| 			[ltdl], | ||||
| 			[lt_dlopenext], | ||||
| 			[LIBLTDL=-lltdl], | ||||
| 			[LIBLTDL=] | ||||
| 			) | ||||
| 		], [ LIBLTDL= ]) | ||||
|  | ||||
| else | ||||
|   AC_DEFINE([XMLSEC_NO_CRYPTO_DYNAMIC_LOADING], [1], [disable xmlsec crypto dynamic loading]) | ||||
| fi | ||||
|  | ||||
| # Checks for header files. | ||||
| AC_CHECK_HEADERS([sys/time.h unistd.h]) | ||||
|  | ||||
| # Checks for typedefs, structures, and compiler characteristics. | ||||
| AC_TYPE_SIZE_T | ||||
|  | ||||
| # Checks for library functions. | ||||
| AC_FUNC_MALLOC | ||||
| AC_CHECK_FUNCS([clock_gettime gethrtime gettimeofday memset strdup]) | ||||
|  | ||||
| # libtool | ||||
|  | ||||
| LT_INIT | ||||
|  | ||||
| AC_CONFIG_FILES([Makefile src/Makefile]) | ||||
| AC_OUTPUT | ||||
| @@ -1,12 +0,0 @@ | ||||
| SOURCES = xades/xmlsec1/xmltree.c xades/xmlsec1/errors.c xades/templates.c xades/xades.c facho_signer.c | ||||
|  | ||||
| lib_LTLIBRARIES = libfachosigner.la | ||||
| libfachosigner_la_SOURCES = $(LTDL_SOURCE_FILES) $(SOURCES) | ||||
| libfachosigner_la_CFLAGS = $(OPENSSL_CFLAGS) $(XMLSEC1_CFLAGS) -DXMLSEC_NOT_CRYPTO_DYNAMIC_LOADING | ||||
| libfachosigner_la_LDFLAGS = $(OPENSSL_LIBS) $(LIBLTDL) $(XMLSEC1_LIBS) | ||||
|  | ||||
| bin_PROGRAMS = facho_signer | ||||
| facho_signer_SOURCES = main.c | ||||
| facho_signer_CFLAGS = $(OPENSSL_CFLAGS) $(XMLSEC1_CFLAGS) -DXMLSEC_NOT_CRYPTO_DYNAMIC_LOADING | ||||
| facho_signer_LDADD = libfachosigner.la | ||||
|  | ||||
| @@ -1,11 +0,0 @@ | ||||
| # facho-signer | ||||
|  | ||||
|  | ||||
| ## guia | ||||
|  | ||||
| - http://xmlsoft.org/html/libxml-tree.html | ||||
| - http://xmlsoft.org/html/libxml-xpath.html | ||||
| - http://xmlsoft.org/examples/xpath1.c | ||||
| - http://xmlsoft.org/tutorial/ar01s05.html | ||||
| - https://www.aleksey.com/xmlsec/api/xmlsec-reference.html | ||||
| - https://zakird.com/2013/10/13/certificate-parsing-with-openssl | ||||
| @@ -1,371 +0,0 @@ | ||||
| /** | ||||
|  * This file is part of facho.  The COPYRIGHT file at the top level of | ||||
|  * this repository contains the full copyright notices and license terms. | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
| #include "xades/xades.h" | ||||
|  | ||||
| #include <xmlsec/xmlsec.h> | ||||
| #include <xmlsec/xmltree.h> | ||||
| #include <xmlsec/xmldsig.h> | ||||
| #include <xmlsec/templates.h> | ||||
| #include <xmlsec/crypto.h> | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #define xmlFachoPrintError(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) | ||||
| #define xmlFachoPrintInfo(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__) | ||||
|  | ||||
| static const xmlChar ublExtensionDSigNs[] = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"; | ||||
| static const xmlChar policyIdDescription[] = "Política de firma para facturas electrónicas de la República de Colombia."; | ||||
| static const xmlChar policyIdIdentifier[] = "https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf"; | ||||
|    | ||||
| // crea elemento /Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent | ||||
| static xmlNodePtr | ||||
| xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc); | ||||
|  | ||||
| // FeC requiere que el digest value del policy identifier sea | ||||
| // apartir del contenido de la url. | ||||
| static int | ||||
| xmlFachoPolicyIdentifierCtxFromFilename(const xmlChar *, xmlSecBufferPtr); | ||||
|  | ||||
|  | ||||
| static int | ||||
| xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) { | ||||
|   xmlNodePtr qualifyingPropertiesNode = NULL; | ||||
|   xmlNodePtr signedPropertiesNode = NULL; | ||||
|   xmlNodePtr signedSignaturePropertiesNode = NULL; | ||||
|   xmlNodePtr signingCertificateNode = NULL; | ||||
|   xmlNodePtr signaturePolicyIdentifierNode = NULL; | ||||
|   xmlNodePtr signaturePolicyIdNode = NULL; | ||||
|   xmlNodePtr sigPolicyIdNode = NULL; | ||||
|   xmlNodePtr sigPolicyHashNode = NULL; | ||||
|   xmlNodePtr signerRoleNode = NULL; | ||||
|   xmlNodePtr refNode = NULL; | ||||
|   const xmlChar signedPropertiesId[] = "xmldsig-facho-signed-props"; | ||||
|   const xmlChar signedPropertiesRef[] = "#xmldsig-facho-signed-props"; | ||||
|    | ||||
|   qualifyingPropertiesNode = xmlXadesTmplQualifyingPropertiesCreate(doc, signNode, BAD_CAST "xades-ref1"); | ||||
|   if (  qualifyingPropertiesNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add QualifyingProperties node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   signedPropertiesNode = xmlXadesTmplAddSignedProperties(qualifyingPropertiesNode, signedPropertiesId); | ||||
|   if ( signedPropertiesNode == NULL ) { | ||||
|     xmlFachoPrintError("error: xades failed to add signed properties node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   refNode = xmlSecTmplSignatureAddReference(signNode, | ||||
|                                             xmlSecTransformSha256Id, | ||||
|                                             BAD_CAST "xmldsig-facho-ref1", | ||||
|                                             signedPropertiesRef, | ||||
|                                             BAD_CAST "http://uri.etsi.org/01903#SignedProperties"); | ||||
|   if ( refNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add reference to signature template xades.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|   if ( xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformInclC14NId) == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add enveloped transform to reference for xades\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   const time_t now = time(NULL); | ||||
|   signedSignaturePropertiesNode = xmlXadesTmplAddSignedSignatureProperties(signedPropertiesNode, localtime(&now)); | ||||
|   if ( signedSignaturePropertiesNode == NULL ) { | ||||
|     xmlFachoPrintError("error: xades failed to add signed signature properties node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   signingCertificateNode = xmlXadesTmplAddSigningCertificate(signedSignaturePropertiesNode, xmlSecTransformSha256Id); | ||||
|   if ( signingCertificateNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add SigningCertificate node \n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   signaturePolicyIdentifierNode = xmlXadesTmplAddSignaturePolicyIdentifier(signedSignaturePropertiesNode); | ||||
|   if ( signaturePolicyIdentifierNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add PolicyIdentifier node\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   signaturePolicyIdNode = xmlXadesTmplAddSignaturePolicyId(signaturePolicyIdentifierNode); | ||||
|   if ( signaturePolicyIdNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add SignaturePolicyId node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   sigPolicyIdNode = xmlXadesTmplAddSigPolicyId(signaturePolicyIdNode, policyIdIdentifier, policyIdDescription); | ||||
|   if ( sigPolicyIdNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add SigPolicyId node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   sigPolicyHashNode = xmlXadesTmplAddSigPolicyHash(signaturePolicyIdNode, xmlSecTransformSha256Id); | ||||
|   if ( sigPolicyHashNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add SigPolicyHash node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   signerRoleNode = xmlXadesTmplAddSignerRole(signedSignaturePropertiesNode, BAD_CAST "supplier"); | ||||
|   if ( signerRoleNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add SignerRole node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|    | ||||
|   return(0); | ||||
|  fail: | ||||
|   xmlUnlinkNode(qualifyingPropertiesNode); | ||||
|   xmlFreeNode(qualifyingPropertiesNode); | ||||
|   return(-1); | ||||
| } | ||||
|  | ||||
| int | ||||
| xmlFachoInit() { | ||||
|   xmlInitParser(); | ||||
|   LIBXML_TEST_VERSION; | ||||
|    | ||||
|   if ( xmlSecInit() < 0 ) { | ||||
|     xmlFachoPrintError("xmlsec initialization failed.\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   if ( xmlSecCheckVersion() != 1 ) { | ||||
|     xmlFachoPrintError("loaded xmlsec library version is not compatible.\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
| #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING | ||||
|     if(xmlSecCryptoDLLoadLibrary( NULL ) < 0) { | ||||
|         fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n" | ||||
|                         "that you have it installed and check shared libraries path\n" | ||||
|                         "(LD_LIBRARY_PATH and/or LTDL_LIBRARY_PATH) environment variables.\n"); | ||||
|         return(-1);      | ||||
|     } | ||||
| #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */ | ||||
|     | ||||
|   if ( xmlSecCryptoAppInit(NULL) < 0 ) { | ||||
|     xmlFachoPrintError("crypto initialization failed.\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   if ( xmlSecCryptoInit() < 0 ) { | ||||
|     xmlFachoPrintError("xmlsec-crypto initialization failed.\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   return(0); | ||||
| } | ||||
|  | ||||
| int | ||||
| xmlFachoShutdown() { | ||||
|  | ||||
|   if ( xmlSecCryptoShutdown() < 0 ) { | ||||
|     xmlFachoPrintError("xmlSecCryptoShutdown failed.\n"); | ||||
|   } | ||||
|  | ||||
|   if ( xmlSecCryptoAppShutdown() < 0 ) { | ||||
|     xmlFachoPrintError("xmlSecCryptoAppShutdown failed.\n"); | ||||
|   } | ||||
|    | ||||
|   if ( xmlSecShutdown() < 0 ) { | ||||
|     xmlFachoPrintError("xmlsec shutdown failed.\n"); | ||||
|   } | ||||
|  | ||||
|   xmlCleanupParser(); | ||||
|   return(0); | ||||
| } | ||||
|  | ||||
| int | ||||
| xmlFachoSignFile(FILE *out, const char *filename, const char *pkcs12name, const char *password) { | ||||
|   xmlDocPtr doc = NULL; | ||||
|   xmlNodePtr signNode = NULL; | ||||
|   xmlNodePtr refNode = NULL; | ||||
|   xmlNodePtr keyInfoNode = NULL; | ||||
|   xmlNodePtr x509DataNode = NULL; | ||||
|   xmlNodePtr node = NULL; | ||||
|   xmlSecDSigCtxPtr dsigCtx = NULL; | ||||
|   xmlXadesDSigCtxPtr xadesDsigCtx = NULL; | ||||
|  | ||||
|   int res = -1; | ||||
|    | ||||
|   if (filename == NULL) { | ||||
|    return(-1); | ||||
|   } | ||||
|  | ||||
|   doc = xmlParseFile(filename); | ||||
|   if ( (doc == NULL) || (xmlDocGetRootElement(doc) == NULL) ) { | ||||
|     xmlFachoPrintError("error: unable to parse file %s\n", filename); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformInclC14NId, | ||||
|                                        xmlSecTransformRsaSha256Id, NULL); | ||||
|   if ( signNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to create signature template.\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   xmlAddChild(xmlDocGetRootElement(doc), signNode); | ||||
|  | ||||
|   refNode = xmlSecTmplSignatureAddReference(signNode, | ||||
|                                             xmlSecTransformSha256Id, | ||||
|                                             BAD_CAST "xmldsig-facho-ref0", // id | ||||
|                                             BAD_CAST "", //uri | ||||
|                                             NULL); //type | ||||
|   if ( refNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add reference to signature template.\n"); | ||||
|     goto done; | ||||
|   } | ||||
|   if ( xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add enveloped transform to reference\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   refNode = xmlSecTmplSignatureAddReference(signNode, | ||||
|                                             xmlSecTransformSha256Id, | ||||
|                                             BAD_CAST "xmldsig-facho-ref2", | ||||
|                                             BAD_CAST "#xmldsig-facho-KeyInfo", | ||||
|                                             NULL); | ||||
|   if ( refNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add reference to signature template key-info.\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, BAD_CAST "xmldsig-facho-KeyInfo"); | ||||
|   if ( keyInfoNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add key info.\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   x509DataNode = xmlSecTmplKeyInfoAddX509Data(keyInfoNode); | ||||
|   if ( x509DataNode == NULL ) { | ||||
|     xmlFachoPrintError("error: failde to add x509 DATA \n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   if ( xmlSecTmplX509DataAddCertificate(x509DataNode) == NULL ) { | ||||
|     xmlFachoPrintError("error: failde to add x509Certificate node\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   if ( xmlFachoTmplXadesCreate(doc, signNode) < 0 ){ | ||||
|     xmlFachoPrintError("error: xmlFachoTmplXadesCreate failed.\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   dsigCtx = xmlSecDSigCtxCreate(NULL); | ||||
|   if ( dsigCtx == NULL ) { | ||||
|     xmlFachoPrintError("error: dsig context creating failed\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   // cargamos el archivo pkcs12 con llave privado y certificados x509 | ||||
|   dsigCtx->signKey = xmlSecCryptoAppKeyLoad(pkcs12name, | ||||
|                                             xmlSecKeyDataFormatPkcs12, | ||||
|                                             password, | ||||
|                                             NULL, NULL); | ||||
|   if ( dsigCtx->signKey == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to load pkcs12\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   xmlXadesPolicyIdentifierCtx policyIdCtx; | ||||
|  | ||||
|   // por ahora el hash del identificador lo tomamos del pdf de la dian | ||||
|   policyIdCtx.contentCallback = &xmlFachoPolicyIdentifierCtxFromFilename; | ||||
|      | ||||
|   xadesDsigCtx = xmlXadesDSigCtxCreate(dsigCtx, XADES_DIGEST_SHA256, &policyIdCtx); | ||||
|   if ( xadesDsigCtx == NULL ) { | ||||
|     xmlFachoPrintError("error: xades context creating failed.\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   // debe existir el elemento antes del firmado | ||||
|   node = xmlFachoTmplUBLExtensionAddExtensionContent(doc); | ||||
|   if ( node == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add UBLExtensions/UBLExtension/ExtensionContent\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   // realizar firma de documento | ||||
|   if ( xmlXadesDSigCtxSign(xadesDsigCtx, signNode) < 0 ) { | ||||
|     xmlFachoPrintError("error: signature failed\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   xmlUnlinkNode(signNode); | ||||
|   xmlSecAddChildNode(node, signNode); | ||||
|  | ||||
|   xmlDocDump(out, doc); | ||||
|  | ||||
|   res = 0; | ||||
|  | ||||
|  done: | ||||
|   if ( xadesDsigCtx != NULL ) { | ||||
|     xmlXadesDSigCtxDestroy(xadesDsigCtx); | ||||
|   } | ||||
|  | ||||
|   if ( dsigCtx != NULL ) { | ||||
|     xmlSecDSigCtxDestroy(dsigCtx); | ||||
|   } | ||||
|  | ||||
|   if ( doc != NULL ) { | ||||
|     xmlFreeDoc(doc); | ||||
|   } | ||||
|   return(res); | ||||
| } | ||||
|  | ||||
| static xmlNodePtr | ||||
| xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc) { | ||||
|   xmlNodePtr node = NULL; | ||||
|   xmlNodePtr parent = NULL; | ||||
|   const xmlChar ublExtensionsName[] = "UBLExtensions"; | ||||
|   const xmlChar ublExtensionName[] = "UBLExtension"; | ||||
|   const xmlChar extensionContentName[] = "ExtensionContent"; | ||||
|      | ||||
|   parent = xmlSecFindNode(xmlDocGetRootElement(doc), ublExtensionsName, ublExtensionDSigNs); | ||||
|   if ( parent == NULL ) { | ||||
|     parent = xmlSecAddChild(xmlDocGetRootElement(doc), ublExtensionsName,  ublExtensionDSigNs); | ||||
|     if ( parent == NULL ) { | ||||
|       xmlFachoPrintError("error: failed to cleate UBLExtensions.\n"); | ||||
|       return(NULL); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // adicionamos nuevo elemento UBLExtension | ||||
|   node = xmlSecAddChild(parent, ublExtensionName, ublExtensionDSigNs); | ||||
|   if ( node == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add UBLExtension\n"); | ||||
|     xmlFreeNode(parent); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   // adicionamos nuevo elemento ExtensionContent | ||||
|   node = xmlSecAddChild(node, extensionContentName, ublExtensionDSigNs); | ||||
|   if ( node == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add ExtensionContent"); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(node); | ||||
| } | ||||
|  | ||||
| static int | ||||
| xmlFachoPolicyIdentifierCtxFromFilename(const xmlChar *policyId, xmlSecBufferPtr buffer) { | ||||
|   static unsigned char politicafirmav2[] = { | ||||
|     /** | ||||
|      * generado con https://github.com/Jamesits/bin2array | ||||
|      */ | ||||
| #include "politicafirmav2.c" | ||||
|   }; | ||||
|  | ||||
|   return xmlSecBufferAppend(buffer, politicafirmav2, sizeof(politicafirmav2)); | ||||
| } | ||||
| @@ -1,20 +0,0 @@ | ||||
| /** | ||||
|  * This file is part of facho.  The COPYRIGHT file at the top level of | ||||
|  * this repository contains the full copyright notices and license terms. | ||||
|  */ | ||||
|  | ||||
| #ifndef FACHO_SIGNER_H | ||||
| #define FACHO_SIGNER_H | ||||
|  | ||||
| #include <stdio.h> | ||||
|  | ||||
| int | ||||
| xmlFachoInit(); | ||||
|  | ||||
| int | ||||
| xmlFachoShutdown(); | ||||
|  | ||||
| int | ||||
| xmlFachoSignFile(FILE *out, const char *filename, const char *pkcs12name, const char *password); | ||||
|  | ||||
| #endif /* FACHO_SIGNER_H */ | ||||
| @@ -1,47 +0,0 @@ | ||||
| /** | ||||
|  * This file is part of facho.  The COPYRIGHT file at the top level of | ||||
|  * this repository contains the full copyright notices and license terms. | ||||
|  */ | ||||
|  | ||||
| #include "xades/xades.h" | ||||
| #include "facho_signer.h" | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
|  | ||||
| static char *basename = NULL; | ||||
|  | ||||
| void usage(FILE *out); | ||||
|  | ||||
| int main(int argc, char *argv[]) { | ||||
|   int exitStatus = EXIT_SUCCESS; | ||||
|   basename = argv[0]; | ||||
|    | ||||
|   if (argc != 4) { | ||||
|     usage(stderr); | ||||
|     return(EXIT_FAILURE); | ||||
|   } | ||||
|  | ||||
|   if ( xmlFachoInit() < 0 ) { | ||||
|     fprintf(stderr, "initialization failed.\n"); | ||||
|     return(EXIT_FAILURE); | ||||
|   } | ||||
|  | ||||
|   if ( xmlFachoSignFile( stdout, argv[1], argv[2], argv[3] ) != 0 ) { | ||||
|     fprintf(stderr, "fail to sign file\n"); | ||||
|     exitStatus = EXIT_FAILURE; | ||||
|   } | ||||
|  | ||||
|   xmlFachoShutdown();   | ||||
|   return(exitStatus); | ||||
| } | ||||
|  | ||||
| void | ||||
| usage(FILE *out) { | ||||
|   fprintf(out, "%s: <factura.xml> <pc12> <password>\n", basename); | ||||
|   fprintf(out, "%s", "Firmado electronico para facturacion en Colombia.\n" | ||||
|           "Segun el documento (Anexo Técnico de Factura Electrónica de Venta – Versión 1.7.-2020).\n" | ||||
|           "A considerar:\n" \ | ||||
|           " * adiciona un nuevo elemento //ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent\n"); | ||||
| } | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -1,391 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (c) 2012 David Siñuela Pastor, siu.4coders@gmail.com | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||
|  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||
|  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
|  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| #ifndef MINUNIT_MINUNIT_H | ||||
| #define MINUNIT_MINUNIT_H | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| 	extern "C" { | ||||
| #endif | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| #include <Windows.h> | ||||
| #if defined(_MSC_VER) && _MSC_VER < 1900 | ||||
|   #define snprintf _snprintf | ||||
|   #define __func__ __FUNCTION__ | ||||
| #endif | ||||
|  | ||||
| #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) | ||||
|  | ||||
| /* Change POSIX C SOURCE version for pure c99 compilers */ | ||||
| #if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L | ||||
| #undef _POSIX_C_SOURCE | ||||
| #define _POSIX_C_SOURCE 200112L | ||||
| #endif | ||||
|  | ||||
| #include <unistd.h>	/* POSIX flags */ | ||||
| #include <time.h>	/* clock_gettime(), time() */ | ||||
| #include <sys/time.h>	/* gethrtime(), gettimeofday() */ | ||||
| #include <sys/resource.h> | ||||
| #include <sys/times.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #if defined(__MACH__) && defined(__APPLE__) | ||||
| #include <mach/mach.h> | ||||
| #include <mach/mach_time.h> | ||||
| #endif | ||||
|  | ||||
| #if __GNUC__ >= 5 && !defined(__STDC_VERSION__) | ||||
| #define __func__ __extension__ __FUNCTION__ | ||||
| #endif | ||||
|  | ||||
| #else | ||||
| #error "Unable to define timers for an unknown OS." | ||||
| #endif | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <math.h> | ||||
|  | ||||
| /*  Maximum length of last message */ | ||||
| #define MINUNIT_MESSAGE_LEN 1024 | ||||
| /*  Accuracy with which floats are compared */ | ||||
| #define MINUNIT_EPSILON 1E-12 | ||||
|  | ||||
| /*  Misc. counters */ | ||||
| static int minunit_run = 0; | ||||
| static int minunit_assert = 0; | ||||
| static int minunit_fail = 0; | ||||
| static int minunit_status = 0; | ||||
|  | ||||
| /*  Timers */ | ||||
| static double minunit_real_timer = 0; | ||||
| static double minunit_proc_timer = 0; | ||||
|  | ||||
| /*  Last message */ | ||||
| static char minunit_last_message[MINUNIT_MESSAGE_LEN]; | ||||
|  | ||||
| /*  Test setup and teardown function pointers */ | ||||
| static void (*minunit_setup)(void) = NULL; | ||||
| static void (*minunit_teardown)(void) = NULL; | ||||
|  | ||||
| /*  Definitions */ | ||||
| #define MU_TEST(method_name) static void method_name(void) | ||||
| #define MU_TEST_SUITE(suite_name) static void suite_name(void) | ||||
|  | ||||
| #define MU__SAFE_BLOCK(block) do {\ | ||||
| 	block\ | ||||
| } while(0) | ||||
|  | ||||
| /*  Run test suite and unset setup and teardown functions */ | ||||
| #define MU_RUN_SUITE(suite_name) MU__SAFE_BLOCK(\ | ||||
| 	suite_name();\ | ||||
| 	minunit_setup = NULL;\ | ||||
| 	minunit_teardown = NULL;\ | ||||
| ) | ||||
|  | ||||
| /*  Configure setup and teardown functions */ | ||||
| #define MU_SUITE_CONFIGURE(setup_fun, teardown_fun) MU__SAFE_BLOCK(\ | ||||
| 	minunit_setup = setup_fun;\ | ||||
| 	minunit_teardown = teardown_fun;\ | ||||
| ) | ||||
|  | ||||
| /*  Test runner */ | ||||
| #define MU_RUN_TEST(test) MU__SAFE_BLOCK(\ | ||||
| 	if (minunit_real_timer==0 && minunit_proc_timer==0) {\ | ||||
| 		minunit_real_timer = mu_timer_real();\ | ||||
| 		minunit_proc_timer = mu_timer_cpu();\ | ||||
| 	}\ | ||||
| 	if (minunit_setup) (*minunit_setup)();\ | ||||
| 	minunit_status = 0;\ | ||||
| 	test();\ | ||||
| 	minunit_run++;\ | ||||
| 	if (minunit_status) {\ | ||||
| 		minunit_fail++;\ | ||||
| 		printf("F");\ | ||||
| 		printf("\n%s\n", minunit_last_message);\ | ||||
| 	}\ | ||||
| 	fflush(stdout);\ | ||||
| 	if (minunit_teardown) (*minunit_teardown)();\ | ||||
| ) | ||||
|  | ||||
| /*  Report */ | ||||
| #define MU_REPORT() MU__SAFE_BLOCK(\ | ||||
| 	double minunit_end_real_timer;\ | ||||
| 	double minunit_end_proc_timer;\ | ||||
| 	printf("\n\n%d tests, %d assertions, %d failures\n", minunit_run, minunit_assert, minunit_fail);\ | ||||
| 	minunit_end_real_timer = mu_timer_real();\ | ||||
| 	minunit_end_proc_timer = mu_timer_cpu();\ | ||||
| 	printf("\nFinished in %.8f seconds (real) %.8f seconds (proc)\n\n",\ | ||||
| 		minunit_end_real_timer - minunit_real_timer,\ | ||||
| 		minunit_end_proc_timer - minunit_proc_timer);\ | ||||
| ) | ||||
| #define MU_EXIT_CODE minunit_fail | ||||
|  | ||||
| /*  Assertions */ | ||||
| #define mu_check(test) MU__SAFE_BLOCK(\ | ||||
| 	minunit_assert++;\ | ||||
| 	if (!(test)) {\ | ||||
| 		snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, #test);\ | ||||
| 		minunit_status = 1;\ | ||||
| 		return;\ | ||||
| 	} else {\ | ||||
| 		printf(".");\ | ||||
| 	}\ | ||||
| ) | ||||
|  | ||||
| #define mu_fail(message) MU__SAFE_BLOCK(\ | ||||
| 	minunit_assert++;\ | ||||
| 	snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, message);\ | ||||
| 	minunit_status = 1;\ | ||||
| 	return;\ | ||||
| ) | ||||
|  | ||||
| #define mu_assert(test, message) MU__SAFE_BLOCK(\ | ||||
| 	minunit_assert++;\ | ||||
| 	if (!(test)) {\ | ||||
| 		snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, message);\ | ||||
| 		minunit_status = 1;\ | ||||
| 		return;\ | ||||
| 	} else {\ | ||||
| 		printf(".");\ | ||||
| 	}\ | ||||
| ) | ||||
|  | ||||
| #define mu_assert_int_eq(expected, result) MU__SAFE_BLOCK(\ | ||||
| 	int minunit_tmp_e;\ | ||||
| 	int minunit_tmp_r;\ | ||||
| 	minunit_assert++;\ | ||||
| 	minunit_tmp_e = (expected);\ | ||||
| 	minunit_tmp_r = (result);\ | ||||
| 	if (minunit_tmp_e != minunit_tmp_r) {\ | ||||
| 		snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %d expected but was %d", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\ | ||||
| 		minunit_status = 1;\ | ||||
| 		return;\ | ||||
| 	} else {\ | ||||
| 		printf(".");\ | ||||
| 	}\ | ||||
| ) | ||||
|  | ||||
| #define mu_assert_double_eq(expected, result) MU__SAFE_BLOCK(\ | ||||
| 	double minunit_tmp_e;\ | ||||
| 	double minunit_tmp_r;\ | ||||
| 	minunit_assert++;\ | ||||
| 	minunit_tmp_e = (expected);\ | ||||
| 	minunit_tmp_r = (result);\ | ||||
| 	if (fabs(minunit_tmp_e-minunit_tmp_r) > MINUNIT_EPSILON) {\ | ||||
| 		int minunit_significant_figures = 1 - log10(MINUNIT_EPSILON);\ | ||||
| 		snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %.*g expected but was %.*g", __func__, __FILE__, __LINE__, minunit_significant_figures, minunit_tmp_e, minunit_significant_figures, minunit_tmp_r);\ | ||||
| 		minunit_status = 1;\ | ||||
| 		return;\ | ||||
| 	} else {\ | ||||
| 		printf(".");\ | ||||
| 	}\ | ||||
| ) | ||||
|  | ||||
| #define mu_assert_string_eq(expected, result) MU__SAFE_BLOCK(\ | ||||
| 	const char* minunit_tmp_e = expected;\ | ||||
| 	const char* minunit_tmp_r = result;\ | ||||
| 	minunit_assert++;\ | ||||
| 	if (!minunit_tmp_e) {\ | ||||
| 		minunit_tmp_e = "<null pointer>";\ | ||||
| 	}\ | ||||
| 	if (!minunit_tmp_r) {\ | ||||
| 		minunit_tmp_r = "<null pointer>";\ | ||||
| 	}\ | ||||
| 	if(strcmp(minunit_tmp_e, minunit_tmp_r)) {\ | ||||
| 		snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: '%s' expected but was '%s'", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\ | ||||
| 		minunit_status = 1;\ | ||||
| 		return;\ | ||||
| 	} else {\ | ||||
| 		printf(".");\ | ||||
| 	}\ | ||||
| ) | ||||
|  | ||||
| /* | ||||
|  * The following two functions were written by David Robert Nadeau | ||||
|  * from http://NadeauSoftware.com/ and distributed under the | ||||
|  * Creative Commons Attribution 3.0 Unported License | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Returns the real time, in seconds, or -1.0 if an error occurred. | ||||
|  * | ||||
|  * Time is measured since an arbitrary and OS-dependent start time. | ||||
|  * The returned real time is only useful for computing an elapsed time | ||||
|  * between two calls to this function. | ||||
|  */ | ||||
| static double mu_timer_real(void) | ||||
| { | ||||
| #if defined(_WIN32) | ||||
| 	/* Windows 2000 and later. ---------------------------------- */ | ||||
| 	LARGE_INTEGER Time; | ||||
| 	LARGE_INTEGER Frequency; | ||||
| 	 | ||||
| 	QueryPerformanceFrequency(&Frequency); | ||||
| 	QueryPerformanceCounter(&Time); | ||||
| 	 | ||||
| 	Time.QuadPart *= 1000000; | ||||
| 	Time.QuadPart /= Frequency.QuadPart; | ||||
| 	 | ||||
| 	return (double)Time.QuadPart / 1000000.0; | ||||
|  | ||||
| #elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__))) | ||||
| 	/* HP-UX, Solaris. ------------------------------------------ */ | ||||
| 	return (double)gethrtime( ) / 1000000000.0; | ||||
|  | ||||
| #elif defined(__MACH__) && defined(__APPLE__) | ||||
| 	/* OSX. ----------------------------------------------------- */ | ||||
| 	static double timeConvert = 0.0; | ||||
| 	if ( timeConvert == 0.0 ) | ||||
| 	{ | ||||
| 		mach_timebase_info_data_t timeBase; | ||||
| 		(void)mach_timebase_info( &timeBase ); | ||||
| 		timeConvert = (double)timeBase.numer / | ||||
| 			(double)timeBase.denom / | ||||
| 			1000000000.0; | ||||
| 	} | ||||
| 	return (double)mach_absolute_time( ) * timeConvert; | ||||
|  | ||||
| #elif defined(_POSIX_VERSION) | ||||
| 	/* POSIX. --------------------------------------------------- */ | ||||
| 	struct timeval tm; | ||||
| #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) | ||||
| 	{ | ||||
| 		struct timespec ts; | ||||
| #if defined(CLOCK_MONOTONIC_PRECISE) | ||||
| 		/* BSD. --------------------------------------------- */ | ||||
| 		const clockid_t id = CLOCK_MONOTONIC_PRECISE; | ||||
| #elif defined(CLOCK_MONOTONIC_RAW) | ||||
| 		/* Linux. ------------------------------------------- */ | ||||
| 		const clockid_t id = CLOCK_MONOTONIC_RAW; | ||||
| #elif defined(CLOCK_HIGHRES) | ||||
| 		/* Solaris. ----------------------------------------- */ | ||||
| 		const clockid_t id = CLOCK_HIGHRES; | ||||
| #elif defined(CLOCK_MONOTONIC) | ||||
| 		/* AIX, BSD, Linux, POSIX, Solaris. ----------------- */ | ||||
| 		const clockid_t id = CLOCK_MONOTONIC; | ||||
| #elif defined(CLOCK_REALTIME) | ||||
| 		/* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */ | ||||
| 		const clockid_t id = CLOCK_REALTIME; | ||||
| #else | ||||
| 		const clockid_t id = (clockid_t)-1;	/* Unknown. */ | ||||
| #endif /* CLOCK_* */ | ||||
| 		if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 ) | ||||
| 			return (double)ts.tv_sec + | ||||
| 				(double)ts.tv_nsec / 1000000000.0; | ||||
| 		/* Fall thru. */ | ||||
| 	} | ||||
| #endif /* _POSIX_TIMERS */ | ||||
|  | ||||
| 	/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */ | ||||
| 	gettimeofday( &tm, NULL ); | ||||
| 	return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0; | ||||
| #else | ||||
| 	return -1.0;		/* Failed. */ | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns the amount of CPU time used by the current process, | ||||
|  * in seconds, or -1.0 if an error occurred. | ||||
|  */ | ||||
| static double mu_timer_cpu(void) | ||||
| { | ||||
| #if defined(_WIN32) | ||||
| 	/* Windows -------------------------------------------------- */ | ||||
| 	FILETIME createTime; | ||||
| 	FILETIME exitTime; | ||||
| 	FILETIME kernelTime; | ||||
| 	FILETIME userTime; | ||||
|  | ||||
| 	/* This approach has a resolution of 1/64 second. Unfortunately, Windows' API does not offer better */ | ||||
| 	if ( GetProcessTimes( GetCurrentProcess( ), | ||||
| 		&createTime, &exitTime, &kernelTime, &userTime ) != 0 ) | ||||
| 	{ | ||||
| 		ULARGE_INTEGER userSystemTime; | ||||
| 		memcpy(&userSystemTime, &userTime, sizeof(ULARGE_INTEGER)); | ||||
| 		return (double)userSystemTime.QuadPart / 10000000.0; | ||||
| 	} | ||||
|  | ||||
| #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) | ||||
| 	/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris --------- */ | ||||
|  | ||||
| #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) | ||||
| 	/* Prefer high-res POSIX timers, when available. */ | ||||
| 	{ | ||||
| 		clockid_t id; | ||||
| 		struct timespec ts; | ||||
| #if _POSIX_CPUTIME > 0 | ||||
| 		/* Clock ids vary by OS.  Query the id, if possible. */ | ||||
| 		if ( clock_getcpuclockid( 0, &id ) == -1 ) | ||||
| #endif | ||||
| #if defined(CLOCK_PROCESS_CPUTIME_ID) | ||||
| 			/* Use known clock id for AIX, Linux, or Solaris. */ | ||||
| 			id = CLOCK_PROCESS_CPUTIME_ID; | ||||
| #elif defined(CLOCK_VIRTUAL) | ||||
| 			/* Use known clock id for BSD or HP-UX. */ | ||||
| 			id = CLOCK_VIRTUAL; | ||||
| #else | ||||
| 			id = (clockid_t)-1; | ||||
| #endif | ||||
| 		if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 ) | ||||
| 			return (double)ts.tv_sec + | ||||
| 				(double)ts.tv_nsec / 1000000000.0; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| #if defined(RUSAGE_SELF) | ||||
| 	{ | ||||
| 		struct rusage rusage; | ||||
| 		if ( getrusage( RUSAGE_SELF, &rusage ) != -1 ) | ||||
| 			return (double)rusage.ru_utime.tv_sec + | ||||
| 				(double)rusage.ru_utime.tv_usec / 1000000.0; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| #if defined(_SC_CLK_TCK) | ||||
| 	{ | ||||
| 		const double ticks = (double)sysconf( _SC_CLK_TCK ); | ||||
| 		struct tms tms; | ||||
| 		if ( times( &tms ) != (clock_t)-1 ) | ||||
| 			return (double)tms.tms_utime / ticks; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| #if defined(CLOCKS_PER_SEC) | ||||
| 	{ | ||||
| 		clock_t cl = clock( ); | ||||
| 		if ( cl != (clock_t)-1 ) | ||||
| 			return (double)cl / (double)CLOCKS_PER_SEC; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|  | ||||
| 	return -1;		/* Failed. */ | ||||
| } | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* MINUNIT_MINUNIT_H */ | ||||
| @@ -1,13 +0,0 @@ | ||||
| #ifndef MINUNIT_EXT_H | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include "minunit.h" | ||||
|  | ||||
| // cuando escribe esto el compilar me arrojo que si no era | ||||
| // mejor usar mu_assert_string_eq increble a  | ||||
| //int mu_assert_string_equals(const char *a, const char *b) { | ||||
| //  return mu_assert(strcmp(a, b) == 0, "string not equals"); | ||||
| //} | ||||
|  | ||||
| #endif //MINUNIT_EXT_H | ||||
| @@ -1,456 +0,0 @@ | ||||
| /** | ||||
|  * This file is part of facho.  The COPYRIGHT file at the top level of | ||||
|  * this repository contains the full copyright notices and license terms. | ||||
|  */ | ||||
|  | ||||
| #include "xades.h" | ||||
|  | ||||
| #include <xmlsec/templates.h> | ||||
|  | ||||
| #include <time.h> | ||||
| #include <string.h> | ||||
|  | ||||
| static const xmlChar xmlXadesNodeQualifyingProperties[] = "QualifyingProperties"; | ||||
| static const xmlChar xmlXadesNodeSignedProperties[] = "SignedProperties"; | ||||
|  | ||||
| static const xmlChar xmlXadesNodeSignedSignatureProperties[] = "SignedSignatureProperties"; | ||||
| static const xmlChar xmlXadesNodeSigningTime[] = "SigningTime"; | ||||
| static const xmlChar xmlXadesNodeSigningCertificate[] = "SigningCertificate"; | ||||
| static const xmlChar xmlXadesNodeCert[] = "Cert"; | ||||
| static const xmlChar xmlXadesNodeCertDigest[] = "CertDigest"; | ||||
| static const xmlChar xmlXadesNodeSignaturePolicyIdentifier[] = "SignaturePolicyIdentifier"; | ||||
| static const xmlChar xmlXadesNodeSignaturePolicyId[] = "SignaturePolicyId"; | ||||
| static const xmlChar xmlXadesNodeSigPolicyId[] = "SigPolicyId"; | ||||
| static const xmlChar xmlXadesNodeIdentifier[] = "Identifier"; | ||||
| static const xmlChar xmlXadesNodeDescription[] = "Description"; | ||||
| static const xmlChar xmlXadesNodeSigPolicyHash[] = "SigPolicyHash"; | ||||
|  | ||||
| static const xmlChar xmlXadesNodeSignerRole[] = "SignerRole"; | ||||
| static const xmlChar xmlXadesNodeClaimedRoles[] = "ClaimedRoles"; | ||||
| static const xmlChar xmlXadesNodeClaimedRole[] = "ClaimedRole"; | ||||
| static const xmlChar xmlXadesNodeIssuerSerial[] = "IssuerSerial"; | ||||
| static const xmlChar xmlXadesNodeX509IssuerName[] = "X509IssuerName"; | ||||
| static const xmlChar xmlXadesNodeX509IssuerNumber[] = "X509IssuerNumber"; | ||||
|    | ||||
| static const xmlChar xmlXadesDSigNs[] = "http://uri.etsi.org/01903/v1.3.2#"; | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesAddChildRecursiveNs(xmlNodePtr startNode, const xmlChar* path, const xmlChar* nsPrefix) { | ||||
|   char *curToken; | ||||
|   char* cpath = strdup((char *)path); | ||||
|   char* savePtr; | ||||
|   xmlNodePtr curNode = NULL; | ||||
|   xmlNodePtr parentNode = startNode; | ||||
|  | ||||
|  | ||||
|   curToken = strtok_r(cpath, "/", &savePtr); | ||||
|   while(curToken != NULL) { | ||||
|     curNode = xmlSecFindChild(parentNode, BAD_CAST curToken, nsPrefix); | ||||
|     if (curNode == NULL) { | ||||
|       curNode = xmlSecAddChild(parentNode, BAD_CAST curToken, nsPrefix); | ||||
|       if (curNode == NULL) { | ||||
|         xmlXadesInternalError("xmlSecAddChild(%s)", curToken); | ||||
|         return(NULL); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     parentNode = curNode; | ||||
|  | ||||
|     curToken = strtok_r(NULL, "/", &savePtr); | ||||
|   } | ||||
|  | ||||
|   free(cpath); | ||||
|   return(curNode); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplQualifyingPropertiesCreate(xmlDocPtr doc, xmlNodePtr signatureNode, const xmlChar *id) { | ||||
|   xmlNodePtr objectNode; | ||||
|   xmlNodePtr qualifyingPropertiesNode; | ||||
|  | ||||
|   xmlNewGlobalNs(doc, xmlXadesDSigNs, BAD_CAST "xades"); | ||||
|  | ||||
|   objectNode = xmlSecTmplSignatureAddObject(signatureNode, NULL, NULL, NULL); | ||||
|   if (objectNode == NULL) { | ||||
|     xmlXadesInternalError("xmlSecTmplSignatureAddObject(signatureNode)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   qualifyingPropertiesNode = xmlSecAddChild(objectNode, xmlXadesNodeQualifyingProperties, xmlXadesDSigNs); | ||||
|   if (qualifyingPropertiesNode == NULL) { | ||||
|     xmlXadesXmlError2("xmlNewDocNode", NULL, "node=%s", xmlXadesErrorsSafeString(xmlXadesNodeQualifyingProperties)); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   if (id != NULL) { | ||||
|     xmlSetProp(qualifyingPropertiesNode, BAD_CAST "Id", id); | ||||
|   } | ||||
|  | ||||
|   return(qualifyingPropertiesNode); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplQualifyingPropertiesCreateNsPref(xmlDocPtr doc, const xmlChar* id, const xmlChar* nsPrefix) { | ||||
|   xmlNodePtr qualifyingPropertiesNode; | ||||
|   xmlNsPtr ns; | ||||
|  | ||||
|   // crear nodo | ||||
|   qualifyingPropertiesNode = xmlNewDocNode(doc, NULL, xmlXadesNodeQualifyingProperties, NULL); | ||||
|   if (qualifyingPropertiesNode == NULL) { | ||||
|     xmlXadesXmlError2("xmlNewDocNode", NULL, "node=%s", xmlXadesErrorsSafeString(xmlXadesNodeQualifyingProperties)); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   // crear namespace y asignar | ||||
|   ns = xmlNewNs(qualifyingPropertiesNode, xmlXadesDSigNs, nsPrefix); | ||||
|   if (ns == NULL) { | ||||
|     xmlXadesXmlError2("xmlNewNs", NULL, | ||||
|                    "ns=%s", xmlXadesErrorsSafeString(xmlXadesDSigNs)); | ||||
|     xmlFreeNode(qualifyingPropertiesNode); | ||||
|     return(NULL); | ||||
|   } | ||||
|   xmlSetNs(qualifyingPropertiesNode, ns); | ||||
|  | ||||
|   if (id != NULL) { | ||||
|     xmlSetProp(qualifyingPropertiesNode, BAD_CAST "Id", id); | ||||
|   } | ||||
|  | ||||
|   | ||||
|   return (qualifyingPropertiesNode); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSignedProperties(xmlNodePtr qualifyingPropertiesNode, const xmlChar* id) { | ||||
|   xmlNodePtr cur; | ||||
|  | ||||
|   xmlXadesAssert2(qualifyingPropertiesNode != NULL, NULL); | ||||
|    | ||||
|   cur = xmlSecAddChild(qualifyingPropertiesNode, xmlXadesNodeSignedProperties, xmlXadesDSigNs); | ||||
|   if (cur == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSignedProperties)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   if (id != NULL) { | ||||
|     xmlSetProp(cur, BAD_CAST "Id", id); | ||||
|   } | ||||
|  | ||||
|   return(cur); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSignedSignatureProperties(xmlNodePtr signedPropertiesNode, struct tm* signingTime) { | ||||
|   xmlNodePtr cur; | ||||
|   xmlNodePtr node; | ||||
|  | ||||
|   xmlXadesAssert2(signedPropertiesNode != NULL, NULL); | ||||
|    | ||||
|   // add SignedSignatureProperties | ||||
|   node = xmlSecAddChild(signedPropertiesNode, xmlXadesNodeSignedSignatureProperties, xmlXadesDSigNs); | ||||
|   if (node == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSignedSignatureProperties)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   // add SignigTime | ||||
|   cur = xmlSecAddChild(node, xmlXadesNodeSigningTime, xmlXadesDSigNs); | ||||
|   if (cur == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSigningTime)", NULL); | ||||
|     xmlFreeNode(node); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   { | ||||
|     int ret; | ||||
|     char strtime[200]; | ||||
|  | ||||
|     if (strftime(strtime, sizeof(strtime), "%Y-%m-%dT%T", signingTime) == 0) { | ||||
|       xmlXadesInternalError("strftime", NULL); | ||||
|       xmlFreeNode(cur); | ||||
|       xmlFreeNode(node); | ||||
|       return(NULL); | ||||
|     } | ||||
|  | ||||
|     ret = xmlSecNodeEncodeAndSetContent(cur, BAD_CAST strtime); | ||||
|     if (ret < 0) { | ||||
|       xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL); | ||||
|       xmlFreeNode(cur); | ||||
|       xmlFreeNode(node); | ||||
|       return(NULL); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return(node); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSigningCertificate(xmlNodePtr signedSignaturePropertiesNode, xmlSecTransformId digestMethodId) { | ||||
|   xmlNodePtr node; | ||||
|  | ||||
|   xmlXadesAssert2(signedSignaturePropertiesNode != NULL, NULL); | ||||
|   if (xmlSecFindChild(signedSignaturePropertiesNode, xmlXadesNodeSigningCertificate, xmlXadesDSigNs) != NULL) { | ||||
|     xmlXadesNodeAlreadyPresentError(signedSignaturePropertiesNode, xmlXadesNodeSigningCertificate, NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   node = xmlSecAddChild(signedSignaturePropertiesNode, xmlXadesNodeSigningCertificate, xmlXadesDSigNs); | ||||
|   if (node == NULL) { | ||||
|     xmlXadesInternalError("xmlsecAddChild(xmlXadesNodeSigningCertificate)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(node); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddCert(xmlNodePtr signingCertificateNode) { | ||||
|   xmlNodePtr certNode; | ||||
|  | ||||
|   xmlXadesAssert2(signingCertificateNode != NULL, NULL); | ||||
|  | ||||
|   certNode = xmlSecAddChild(signingCertificateNode, xmlXadesNodeCert, xmlXadesDSigNs); | ||||
|   if (certNode == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeCert)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(certNode); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddCertDigest(xmlNodePtr certNode, const xmlChar *digestMethod, const xmlChar *digestValue) { | ||||
|   xmlNodePtr node; | ||||
|  | ||||
|   xmlXadesAssert2(certNode != NULL, NULL); | ||||
|  | ||||
|   node = xmlSecAddChild(certNode, xmlXadesNodeCertDigest, xmlXadesDSigNs); | ||||
|   if ( node == NULL ) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeCertDigest)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   if ( xmlXadesTmplAddDigest(node, digestMethod, digestValue) == NULL) { | ||||
|     xmlXadesInternalError("xmlXadesTmplAddDigest(node, digestMethodId)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(certNode); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSignaturePolicyIdentifier(xmlNodePtr signedSignaturePropertiesNode) { | ||||
|   xmlNodePtr cur; | ||||
|  | ||||
|   xmlXadesAssert2(signedSignaturePropertiesNode != NULL, NULL); | ||||
|  | ||||
|   cur = xmlSecAddChild(signedSignaturePropertiesNode, xmlXadesNodeSignaturePolicyIdentifier, xmlXadesDSigNs); | ||||
|   if (cur == NULL) { | ||||
|     xmlXadesInternalError("xmlsecAddChild(xmlXadesNodeSignaturePolicyIdentifier)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(cur); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSignaturePolicyId(xmlNodePtr signaturePolicyIdentifierNode) { | ||||
|   xmlNodePtr cur; | ||||
|  | ||||
|   xmlXadesAssert2(signaturePolicyIdentifierNode != NULL, NULL); | ||||
|  | ||||
|   cur = xmlSecAddChild(signaturePolicyIdentifierNode, xmlXadesNodeSignaturePolicyId, xmlXadesDSigNs); | ||||
|   if (cur == NULL) { | ||||
|     xmlXadesInternalError("xmlsecAddChild(cur)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(cur); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description) { | ||||
|   xmlNodePtr sigPolicyIdNode; | ||||
|   xmlNodePtr node; | ||||
|   int ret; | ||||
|    | ||||
|   sigPolicyIdNode = xmlSecAddChild(signaturePolicyId, xmlXadesNodeSigPolicyId, xmlXadesDSigNs); | ||||
|   if (sigPolicyIdNode == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSigPolicyId)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   node = xmlSecAddChild(sigPolicyIdNode, xmlXadesNodeIdentifier, xmlXadesDSigNs); | ||||
|   if (node == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeIdentifier)", NULL); | ||||
|     xmlFreeNode(sigPolicyIdNode); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   ret = xmlSecNodeEncodeAndSetContent(node, identifier); | ||||
|   if (ret < 0) { | ||||
|     xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL); | ||||
|     xmlFreeNode(sigPolicyIdNode); | ||||
|     xmlFreeNode(node); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   node = xmlSecAddChild(sigPolicyIdNode, xmlXadesNodeDescription, xmlXadesDSigNs); | ||||
|   if (node == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeDescription)", NULL); | ||||
|     xmlFreeNode(sigPolicyIdNode); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   ret = xmlSecNodeEncodeAndSetContent(node, description); | ||||
|   if (ret < 0) { | ||||
|     xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL); | ||||
|     xmlFreeNode(sigPolicyIdNode); | ||||
|     xmlFreeNode(node); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(sigPolicyIdNode); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode, xmlSecTransformId digestMethodId) { | ||||
|   xmlNodePtr node; | ||||
|   xmlXadesAssert2(parentNode != NULL, NULL); | ||||
|  | ||||
|   //add policyHash | ||||
|   node = xmlSecAddChild(parentNode, xmlXadesNodeSigPolicyHash, xmlXadesDSigNs); | ||||
|   if (node == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSigPolicyHash)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   if ( xmlXadesTmplAddDigest(node, digestMethodId->href, NULL) == NULL) { | ||||
|     xmlXadesInternalError("xmlXadesTmplAddDigest(node, digestMethodId)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return node; | ||||
| } | ||||
|  | ||||
| // MACHETE(bit4bit) como usar SecTransform para almacenar el digest | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddDigest(xmlNodePtr parentNode, const xmlChar *digestMethod, const xmlChar *digestValue) { | ||||
|   xmlNodePtr node; | ||||
|    | ||||
|   xmlXadesAssert2(parentNode != NULL, NULL); | ||||
|  | ||||
|   if ( digestMethod != NULL ) { | ||||
|     node = xmlSecAddChild(parentNode, xmlSecNodeDigestMethod, xmlSecDSigNs); | ||||
|     if (node == NULL) { | ||||
|       xmlXadesInternalError("xmlSecAddChild(xmlSecNodeDigestMethod)", NULL); | ||||
|       return(NULL); | ||||
|     } | ||||
|     if (xmlSetProp(node, xmlSecAttrAlgorithm, digestMethod) == NULL) { | ||||
|       xmlXadesXmlError2("xmlSetProp", NULL, | ||||
|                         "name=%s", xmlXadesErrorsSafeString(xmlSecAttrAlgorithm)); | ||||
|       xmlUnlinkNode(node); | ||||
|       xmlFreeNode(node); | ||||
|       return(NULL); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ( digestValue != NULL ) { | ||||
|     node = xmlSecAddChild(parentNode, xmlSecNodeDigestValue, xmlSecDSigNs); | ||||
|     if (node == NULL) { | ||||
|       xmlXadesInternalError("xmlSecAddChild(xmlSecNodeDigestValue)", NULL); | ||||
|       return(NULL); | ||||
|     } | ||||
|      | ||||
|     if (xmlSecNodeEncodeAndSetContent(node, digestValue) < 0) { | ||||
|       xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL); | ||||
|       return(NULL); | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   return parentNode; | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSignerRole(xmlNodePtr signedSignaturePropertiesNode, const xmlChar* role) { | ||||
|   xmlNodePtr signerRoleNode; | ||||
|   xmlNodePtr claimedRolesNode; | ||||
|   xmlNodePtr claimedRoleNode; | ||||
|   int ret; | ||||
|  | ||||
|   signerRoleNode = xmlSecAddChild(signedSignaturePropertiesNode, xmlXadesNodeSignerRole, xmlXadesDSigNs); | ||||
|   if (signerRoleNode == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSignerRole)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   claimedRolesNode = xmlSecAddChild(signerRoleNode, xmlXadesNodeClaimedRoles, xmlXadesDSigNs); | ||||
|   if (claimedRolesNode == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeClaimedRoles)", NULL); | ||||
|     xmlUnlinkNode(signerRoleNode); | ||||
|     xmlFreeNode(signerRoleNode); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   claimedRoleNode = xmlSecAddChild(claimedRolesNode, xmlXadesNodeClaimedRole, xmlXadesDSigNs); | ||||
|   if (claimedRoleNode == NULL) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeClaimedRole)", NULL); | ||||
|     xmlUnlinkNode(signerRoleNode); | ||||
|     xmlFreeNode(signerRoleNode); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   ret = xmlSecNodeEncodeAndSetContent(claimedRoleNode, role); | ||||
|   if (ret < 0) { | ||||
|     xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL); | ||||
|     xmlUnlinkNode(signerRoleNode); | ||||
|     xmlFreeNode(signerRoleNode); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(signerRoleNode); | ||||
| } | ||||
|  | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddIssuerSerial(xmlNodePtr certNode, const xmlChar *issuerName, const xmlChar *issuerNumber) { | ||||
|   xmlNodePtr issuerSerialNode; | ||||
|   xmlNodePtr node; | ||||
|  | ||||
|   xmlXadesAssert2(certNode != NULL, NULL); | ||||
|  | ||||
|   issuerSerialNode = xmlSecAddChild(certNode, xmlXadesNodeIssuerSerial, xmlXadesDSigNs); | ||||
|   if ( issuerSerialNode == NULL ) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(certNode, xmlXadesIssuerSerial)", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   node = xmlSecAddChild(issuerSerialNode, xmlXadesNodeX509IssuerName, xmlSecDSigNs); | ||||
|   if ( node == NULL ) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeX509IssuerName)", NULL); | ||||
|     xmlFreeNode(issuerSerialNode); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   if (xmlSecNodeEncodeAndSetContent(node, issuerName) < 0) { | ||||
|     xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL); | ||||
|     xmlUnlinkNode(issuerSerialNode); | ||||
|     xmlFreeNode(issuerSerialNode); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   node = xmlSecAddChild(issuerSerialNode, xmlXadesNodeX509IssuerNumber, xmlSecDSigNs); | ||||
|   if ( node == NULL ) { | ||||
|     xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeX509IssuerNumber)", NULL); | ||||
|     xmlFreeNode(issuerSerialNode); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   if (xmlSecNodeEncodeAndSetContent(node, issuerNumber) < 0) { | ||||
|     xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL); | ||||
|     xmlUnlinkNode(issuerSerialNode); | ||||
|     xmlFreeNode(issuerSerialNode); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(issuerSerialNode); | ||||
| } | ||||
| @@ -1,301 +0,0 @@ | ||||
| /** | ||||
|  * This file is part of facho.  The COPYRIGHT file at the top level of | ||||
|  * this repository contains the full copyright notices and license terms. | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "xades.h" | ||||
|  | ||||
| #include <libxml/xpath.h> | ||||
| #include <libxml/xpathInternals.h> | ||||
| #include <openssl/x509.h> | ||||
| #include <openssl/x509v3.h> | ||||
| #include <openssl/bio.h> | ||||
| #include <openssl/asn1.h> | ||||
| #include <openssl/bn.h> | ||||
|  | ||||
| #include <xmlsec/buffer.h> | ||||
| #include <xmlsec/app.h> | ||||
| #include <xmlsec/transforms.h> | ||||
| #include <xmlsec/keysdata.h> | ||||
|  | ||||
| #ifdef XMLSEC_NO_CRYPTO_DYNAMIC_LOADING | ||||
| #include <xmlsec/openssl/x509.h> | ||||
| #include <xmlsec/openssl/crypto.h> | ||||
| #include <xmlsec/openssl/symbols.h> | ||||
| #endif | ||||
|  | ||||
| #include <string.h> | ||||
| #include <ctype.h> | ||||
|  | ||||
|  | ||||
| static xmlChar * | ||||
| xmlXadesSha256DigestValueInBase64(const unsigned char *message, size_t message_len); | ||||
|  | ||||
| static xmlNodePtr | ||||
| xmlXadesXPathFirstElement(xmlDocPtr doc, const xmlChar *xpath); | ||||
|  | ||||
| xmlXadesDSigCtxPtr | ||||
| xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx, XADES_DIGEST_METHOD digestMethod, xmlXadesPolicyIdentifierCtxPtr policyCtx) { | ||||
|   xmlXadesDSigCtxPtr ctx = NULL; | ||||
|  | ||||
|   ctx = malloc(sizeof(xmlXadesDSigCtx)); | ||||
|   if ( ctx == NULL ) { | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   ctx->dsigCtx = dsigCtx; | ||||
|   ctx->digestMethod = digestMethod; | ||||
|   ctx->policyCtx = policyCtx; | ||||
|   return ctx; | ||||
| } | ||||
|  | ||||
| int | ||||
| xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode) { | ||||
|   xmlNodePtr signingCertificateNode = NULL; | ||||
|   xmlSecKeyDataPtr keyDataX509; | ||||
|   xmlSecSize certsSize; | ||||
|  | ||||
|   signingCertificateNode = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//ds:Object/xades:QualifyingProperties//xades:SigningCertificate[1]"); | ||||
|   if ( signingCertificateNode == NULL ) { | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   keyDataX509 = xmlSecKeyEnsureData(ctx->dsigCtx->signKey, xmlSecKeyDataX509Id); | ||||
|   if ( keyDataX509 == NULL ) { | ||||
|     xmlXadesInternalError("failed to get X509.\n", NULL); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   certsSize = xmlSecOpenSSLKeyDataX509GetCertsSize(keyDataX509); | ||||
|   for (xmlSecSize i = 0; i < certsSize; i++) { | ||||
|     // calculamos el digest del certificado | ||||
|     unsigned char md[EVP_MAX_MD_SIZE]; | ||||
|     unsigned int md_n; | ||||
|     // TODO(bit4bit) podemos obtener el digest de openssl por medio de la transformacion? o se puede usar la transformacion para generar el digest? | ||||
|     xmlChar *digestMethod = NULL; | ||||
|     EVP_MD *digest = NULL; | ||||
|  | ||||
|     switch(ctx->digestMethod) { | ||||
|     case XADES_DIGEST_SHA256: | ||||
|       digestMethod = (xmlChar *)xmlSecTransformSha256Id->href; | ||||
|       digest = (EVP_MD *) EVP_sha256(); | ||||
|       break; | ||||
|     default: | ||||
|       xmlXadesInternalError("xmlXadesDSigCtxSign not known how to handle digest method.\n", NULL); | ||||
|       return(-1); | ||||
|     } | ||||
|  | ||||
|     X509 *cert = xmlSecOpenSSLKeyDataX509GetCert(keyDataX509, i); | ||||
|     if ( cert == NULL ) { | ||||
|       xmlXadesInternalError("openssl: failed to get X509 cert.\n", NULL); | ||||
|       return(-1); | ||||
|     } | ||||
|  | ||||
|     X509_digest(cert, digest, md, &md_n); | ||||
|     xmlChar *digestValue = xmlSecBase64Encode(md, md_n, 0); | ||||
|  | ||||
|     xmlNodePtr certNode = xmlXadesTmplAddCert(signingCertificateNode); | ||||
|     if ( certNode == NULL ) { | ||||
|       xmlXadesInternalError("xmlXadesTmplAddCert(signingCertificateNode)\n", NULL); | ||||
|       return(-1); | ||||
|     } | ||||
|  | ||||
|     // adicionamos digest  | ||||
|     xmlXadesTmplAddCertDigest(certNode, | ||||
|                               digestMethod, | ||||
|                               digestValue); | ||||
|  | ||||
|     char *issuerName = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); | ||||
|  | ||||
|     /* TODO(bit4bit) formatear? | ||||
|     char *issuerNamePtr = issuerName; | ||||
|      | ||||
|     for(issuerNamePtr = strchr(issuerNamePtr, '/'); issuerNamePtr != NULL; issuerNamePtr = strchr(issuerNamePtr, '/')) { | ||||
|       if (issuerNamePtr == issuerName) { | ||||
|         issuerName += 1; | ||||
|       } else { | ||||
|         *issuerNamePtr = ','; | ||||
|       } | ||||
|       }*/ | ||||
|  | ||||
|     ASN1_INTEGER *serial = X509_get_serialNumber(cert); | ||||
|     BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL); | ||||
|     if ( bn == NULL ) { | ||||
|       xmlXadesInternalError("unable to convert ASN1_INTEGER_to_BN to BN\n", NULL); | ||||
|       return(-1); | ||||
|     } | ||||
|     char *issuerNumber = BN_bn2dec(bn); | ||||
|     if ( issuerNumber == NULL ) { | ||||
|       xmlXadesInternalError("unable to convert BN to decimal string\n", NULL); | ||||
|       return(-1); | ||||
|     } | ||||
|  | ||||
|     if (xmlXadesTmplAddIssuerSerial(certNode, BAD_CAST issuerName, BAD_CAST issuerNumber) == NULL) { | ||||
|       xmlXadesInternalError("xmlXadesTmplAddIssuerSerial", NULL); | ||||
|       return(-1); | ||||
|     } | ||||
|     BN_free(bn); | ||||
|     OPENSSL_free(issuerNumber); | ||||
|   } | ||||
|  | ||||
|   // digest de policy identifier | ||||
|   xmlNodePtr sigPolicyId = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//xades:SigPolicyId/xades:Identifier[1]"); | ||||
|   if ( sigPolicyId == NULL ) { | ||||
|     xmlXadesInternalError("xmlXadesXPathFirstElement(xades:SigPolicyId/xades:Identifier\n", NULL); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   if ( ctx->policyCtx == NULL ) { | ||||
|     xmlXadesInternalError("not found policy context.\n", NULL); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   if ( ctx->policyCtx != NULL ) { | ||||
|  | ||||
|  | ||||
|     if ( ctx->policyCtx->contentCallback == NULL ) { | ||||
|       xmlXadesInternalError("not found policy content callback.\n", NULL); | ||||
|       return(-1); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     xmlSecTransformCtxPtr transformCtx = xmlSecTransformCtxCreate(); | ||||
|     if (transformCtx == NULL ) { | ||||
|       xmlXadesInternalError("xmlSecTransformCtxCreate().\n", NULL); | ||||
|       return(-1); | ||||
|     } | ||||
|  | ||||
|     // elemento del digest | ||||
|     xmlNodePtr sigPolicyHashDigestMethod = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//xades:SigPolicyHash/ds:DigestMethod[1]"); | ||||
|     if ( sigPolicyHashDigestMethod == NULL ) { | ||||
|       xmlXadesInternalError("xmlXadesXPathFirstElement(xades:SigPolicyHash/xades:DigestMethod\n", NULL); | ||||
|       return(-1); | ||||
|     } | ||||
|     xmlSecTransformPtr transformPolicyDigestMethod = xmlSecTransformNodeRead(sigPolicyHashDigestMethod, | ||||
|                                                                              xmlSecTransformUsageDigestMethod, | ||||
|                                                                              transformCtx); | ||||
|     if ( transformPolicyDigestMethod == NULL ) { | ||||
|       xmlXadesInternalError("xmlSecTransformNodeRead\n", NULL); | ||||
|       xmlFreeNode(sigPolicyHashDigestMethod); | ||||
|       return(-1); | ||||
|     } | ||||
|  | ||||
|     if ( xmlSecTransformCheckId(transformPolicyDigestMethod, xmlSecTransformSha256Id) == 0 ) { | ||||
|       xmlXadesInternalError("sigPolicyHash only support sha256 digest method .\n", NULL); | ||||
|       xmlFreeNode(sigPolicyHashDigestMethod); | ||||
|       return(-1); | ||||
|     } | ||||
|  | ||||
|     // TODO(bit4bit) podemos usar xmlSecTransform para calcular el digest? | ||||
|     xmlNodePtr sigPolicyHashNode = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//xades:SigPolicyHash[1]"); | ||||
|     if ( sigPolicyHashNode == NULL ) { | ||||
|       xmlXadesInternalError("failed to find sigPolicyHash node.\n", NULL); | ||||
|       xmlFreeNode(sigPolicyHashDigestMethod); | ||||
|       return(-1); | ||||
|     } | ||||
|  | ||||
|     // obtenemos contenido de la policy | ||||
|     xmlChar *identifier = xmlNodeListGetString(signNode->doc, sigPolicyId->xmlChildrenNode, 1); | ||||
|     xmlSecBufferPtr policyContent = xmlSecBufferCreate(1024); | ||||
|     ; | ||||
|     if ( (ctx->policyCtx->contentCallback)(identifier, policyContent) < 0 ) { | ||||
|       xmlXadesInternalError("policyContext callback fails.\n", NULL); | ||||
|       xmlFree(identifier); | ||||
|       return(-1); | ||||
|     } | ||||
|     xmlFree(identifier); | ||||
|  | ||||
|     xmlChar *policyHashValue = xmlXadesSha256DigestValueInBase64(xmlSecBufferGetData(policyContent), | ||||
|                                                                  xmlSecBufferGetSize(policyContent)); | ||||
|  | ||||
|     xmlSecBufferDestroy(policyContent); | ||||
|     xmlXadesTmplAddDigest(sigPolicyHashNode, NULL, policyHashValue); | ||||
|   } | ||||
|  | ||||
|   return xmlSecDSigCtxSign(ctx->dsigCtx, signNode); | ||||
| } | ||||
|  | ||||
|  | ||||
| int | ||||
| xmlXadesDSigCtxDestroy(xmlXadesDSigCtxPtr ctx) { | ||||
|   if ( ctx == NULL ) { | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   free(ctx); | ||||
|   return(0); | ||||
| } | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesXPathFirstElement(xmlDocPtr doc, const xmlChar *xpath) { | ||||
|   xmlXPathContextPtr xpathCtx; | ||||
|   xmlXPathObjectPtr xpathResult; | ||||
|   xmlNodePtr node; | ||||
|  | ||||
|   // obtener QualifyingProteries | ||||
|  | ||||
|   xpathCtx = xmlXPathNewContext(doc); | ||||
|   /* register namespaces */ | ||||
|   // TOMADO DE: xmlsec1/src/xpath.c | ||||
|   for(xmlNsPtr ns = xmlDocGetRootElement(doc)->nsDef; ns != NULL; ns = ns->next) { | ||||
|     /* check that we have no other namespace with same prefix already */ | ||||
|     if((ns->prefix != NULL) && (xmlXPathNsLookup(xpathCtx, ns->prefix) == NULL)){ | ||||
|       int ret = xmlXPathRegisterNs(xpathCtx, ns->prefix, ns->href); | ||||
|       if(ret != 0) { | ||||
|         xmlXadesXmlError2("xmlXPathRegisterNs", NULL, | ||||
|                           "prefix=%s", xmlSecErrorsSafeString(ns->prefix)); | ||||
|         return(NULL); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   xpathResult = xmlXPathEvalExpression(xpath, xpathCtx); | ||||
|   if ( xmlXPathNodeSetIsEmpty( xpathResult->nodesetval ) ) { | ||||
|     xmlXadesInternalError("can't find %s \n", xpath); | ||||
|     xmlXPathFreeObject(xpathResult); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   // obtener puntero a nodo | ||||
|   node = xpathResult->nodesetval->nodeTab[0]; | ||||
|   if ( node->type != XML_ELEMENT_NODE ) { | ||||
|     xmlXadesInternalError("expected element\n", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(node); | ||||
| } | ||||
|  | ||||
| static xmlChar * | ||||
| xmlXadesSha256DigestValueInBase64(const unsigned char *message, size_t message_len) | ||||
| { | ||||
|   unsigned char digest[2048]; | ||||
|   unsigned int digest_len; | ||||
|   EVP_MD_CTX *mdctx; | ||||
|  | ||||
|   if((mdctx = EVP_MD_CTX_new()) == NULL) { | ||||
|     xmlXadesInternalError("EVP_MD_CTX_new().\n", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   if(1 != EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL)) { | ||||
|     xmlXadesInternalError("EVP_DigestInit_ex().\n", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   if(1 != EVP_DigestUpdate(mdctx, message, message_len)) { | ||||
|     xmlXadesInternalError("EVP_DigestUpdate().\n", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   if(1 != EVP_DigestFinal_ex(mdctx, digest, &digest_len)) { | ||||
|     xmlXadesInternalError("EVP_DigestFinal_ex().\n", NULL); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   EVP_MD_CTX_free(mdctx); | ||||
|   return(xmlSecBase64Encode(digest, digest_len, 0)); | ||||
| } | ||||
| @@ -1,108 +0,0 @@ | ||||
| /** | ||||
|  * This file is part of facho.  The COPYRIGHT file at the top level of | ||||
|  * this repository contains the full copyright notices and license terms. | ||||
|  */ | ||||
|  | ||||
| #ifndef XADES_H | ||||
| #define XADES_H | ||||
|  | ||||
|  | ||||
|  | ||||
| #include <libxml/tree.h> | ||||
|  | ||||
| #define XMLSEC_NO_XSLT 1 | ||||
|  | ||||
| #include <xmlsec/xmltree.h> | ||||
| #include <xmlsec/transforms.h> | ||||
| #include <xmlsec/xmldsig.h> | ||||
| #include <xmlsec/base64.h> | ||||
|  | ||||
| #include "xmlsec1/errors_helpers.h" | ||||
|  | ||||
| #define xmlXadesAssert2(p, ret) \ | ||||
|   xmlSecAssert2(p, ret) | ||||
|  | ||||
| #define xmlXadesNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject) \ | ||||
|   xmlSecNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject) | ||||
|  | ||||
| #define xmlXadesXmlError2(errorFunction, errorObject, msg, param) \ | ||||
|   xmlSecXmlError2(errorFunction, errorObject, msg, param) | ||||
|  | ||||
| #define xmlXadesErrorsSafeString(msg) \ | ||||
|   xmlSecErrorsSafeString(msg) | ||||
|  | ||||
| #define xmlXadesInternalError(errorFunction, errorObject) \ | ||||
|   xmlSecInternalError(errorFunction, errorObject) | ||||
|  | ||||
| #define xmlXadesNodeAlreadyPresentError(parent, nodeName, errObject) \ | ||||
|   xmlSecNodeAlreadyPresentError(parent, nodeName, errObject) | ||||
|  | ||||
|  | ||||
| typedef int xmlXadesSize; | ||||
| typedef enum _XADES_DIGEST_METHOD{ | ||||
|   XADES_DIGEST_SHA256 | ||||
| } XADES_DIGEST_METHOD; | ||||
|  | ||||
| typedef int(*xmlXadesPolicyIdentifierContentCallback)(const xmlChar *policyId, xmlSecBuffer *); | ||||
|  | ||||
| typedef struct _xmlXadesPolicyIdentifierCtx  xmlXadesPolicyIdentifierCtx, *xmlXadesPolicyIdentifierCtxPtr; | ||||
| struct _xmlXadesPolicyIdentifierCtx { | ||||
|   xmlXadesPolicyIdentifierContentCallback contentCallback; | ||||
| }; | ||||
|    | ||||
| typedef struct _xmlXadesDSigCtx xmlXadesDSigCtx, *xmlXadesDSigCtxPtr; | ||||
| struct _xmlXadesDSigCtx { | ||||
|   xmlSecDSigCtxPtr dsigCtx; | ||||
|   XADES_DIGEST_METHOD digestMethod; | ||||
|   xmlXadesPolicyIdentifierCtxPtr policyCtx; | ||||
| }; | ||||
|  | ||||
| xmlXadesDSigCtxPtr | ||||
| xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx, XADES_DIGEST_METHOD digestMethod,  xmlXadesPolicyIdentifierCtxPtr policyCtx); | ||||
|  | ||||
| int | ||||
| xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode); | ||||
|  | ||||
| int | ||||
| xmlXadesDSigCtxDestroy(xmlXadesDSigCtxPtr ctx); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplQualifyingPropertiesCreate(xmlDocPtr doc, xmlNodePtr signatureNode, const xmlChar *id); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSignedProperties(xmlNodePtr qualifyingPropertiesNode, const xmlChar* id); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSigningCertificate(xmlNodePtr parentNode, xmlSecTransformId digestMethodId); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddCert(xmlNodePtr signingCertificateNode); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddCertDigest(xmlNodePtr signingCertificateNode, const xmlChar *digestMethod, const xmlChar *digestValue); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSignedSignatureProperties(xmlNodePtr parentNode, struct tm* signingTime); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSignaturePolicyIdentifier(xmlNodePtr signedSignaturePropertiesNode); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSignaturePolicyId(xmlNodePtr signaturePolicyIdentifierNode); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode, xmlSecTransformId digestMethodId); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddSignerRole(xmlNodePtr signedSignaturePropertiesNode, const xmlChar* role); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddDigest(xmlNodePtr parentNode, const xmlChar *digestMethod, const xmlChar *digestValue); | ||||
|  | ||||
| xmlNodePtr | ||||
| xmlXadesTmplAddIssuerSerial(xmlNodePtr certNode, const xmlChar *issuerName, const xmlChar *issuerNumber); | ||||
|  | ||||
| #endif //XADES_H | ||||
| @@ -1,94 +0,0 @@ | ||||
| /** | ||||
|  * This file is part of facho.  The COPYRIGHT file at the top level of | ||||
|  * this repository contains the full copyright notices and license terms. | ||||
|  */ | ||||
|  | ||||
| #include <time.h> | ||||
|  | ||||
| #include <libxml/tree.h> | ||||
| #include "minunit.h" | ||||
|  | ||||
| #include "xades.h" | ||||
|  | ||||
|  | ||||
| MU_TEST(test_xml_add_node_recursive) { | ||||
|   xmlDocPtr doc; | ||||
|   xmlNodePtr root; | ||||
|   xmlNodePtr child; | ||||
|   xmlChar* xmlbuff; | ||||
|   int xmlbuffsize; | ||||
|    | ||||
|   doc = xmlNewDoc(BAD_CAST "1.0"); | ||||
|   root = xmlNewNode(NULL, BAD_CAST "root"); | ||||
|   xmlDocSetRootElement(doc, root); | ||||
|  | ||||
|   child = xmlXadesAddChildRecursiveNs(root, BAD_CAST "A/B/C", NULL); | ||||
|   mu_check(child != NULL); | ||||
|  | ||||
|   xmlDocDumpMemory(doc, &xmlbuff, &xmlbuffsize); | ||||
|   mu_assert_string_eq("<?xml version=\"1.0\"?>\n" | ||||
|                       "<root>\n" | ||||
|                       "<A>\n" | ||||
|                       "<B>\n" | ||||
|                       "<C/>\n" | ||||
|                       "</B>\n" | ||||
|                       "</A>\n" | ||||
|                       "</root>\n" | ||||
|                       , (char *)xmlbuff); | ||||
| } | ||||
|  | ||||
| MU_TEST(test_qualifying_properties_layout) { | ||||
|   xmlDocPtr doc; | ||||
|   xmlNodePtr root; | ||||
|   xmlNodePtr node; | ||||
|   xmlChar* xmlbuff; | ||||
|   int buffersize; | ||||
|   struct tm tm; | ||||
|  | ||||
|   memset(&tm, 0, sizeof(tm)); | ||||
|   tm.tm_year = 2021 - 1900; | ||||
|   tm.tm_mon = 11; | ||||
|   tm.tm_mday = 6; | ||||
|   tm.tm_hour = 12; | ||||
|   tm.tm_min = 0; | ||||
|   tm.tm_sec = 50; | ||||
|  | ||||
|  | ||||
|   doc = xmlNewDoc(BAD_CAST "1.0"); | ||||
|   root = xmlNewNode(NULL, BAD_CAST "root"); | ||||
|   xmlDocSetRootElement(doc, root); | ||||
|    | ||||
|   node = xmlXadesTmplQualifyingPropertiesCreateNsPref(doc, BAD_CAST "123", NULL); | ||||
|   xmlXadesTmplAddSignedSignatureProperties(node, &tm); | ||||
|   mu_check(node != NULL); | ||||
|    | ||||
|   xmlSecAddChildNode(root, node); | ||||
|   xmlDocDumpMemory(doc, &xmlbuff, &buffersize); | ||||
|  | ||||
|   // bit4bit: no se como pasar el namespace al root | ||||
|   mu_assert_string_eq("<?xml version=\"1.0\"?>\n" | ||||
|                       "<root>\n" | ||||
|                       "<QualifyingProperties xmlns=\"http://uri.etsi.org/01903/v1.3.2#\" id=\"123\">\n" | ||||
|                       "<SignedProperties>\n" | ||||
|                       "<SignedSignatureProperties>\n" | ||||
|                       "<SigningTime>2021-12-06T12:00:50</SigningTime>\n" | ||||
|                       "</SignedSignatureProperties>\n" | ||||
|                       "</SignedProperties>\n" | ||||
|                       "</QualifyingProperties>\n" | ||||
|                       "</root>\n" | ||||
|                       , (char *)xmlbuff); | ||||
|    | ||||
|   xmlFree(xmlbuff); | ||||
|   xmlFreeDoc(doc); | ||||
| } | ||||
|  | ||||
| MU_TEST_SUITE(test_suite) { | ||||
|   MU_RUN_TEST(test_xml_add_node_recursive); | ||||
|   MU_RUN_TEST(test_qualifying_properties_layout); | ||||
| } | ||||
|  | ||||
| int main() { | ||||
|   MU_RUN_SUITE(test_suite); | ||||
|   MU_REPORT(); | ||||
|   return MU_EXIT_CODE; | ||||
| } | ||||
| @@ -1,260 +0,0 @@ | ||||
| /* | ||||
|  * XML Security Library (http://www.aleksey.com/xmlsec). | ||||
|  * | ||||
|  * | ||||
|  * This is free software; see Copyright file in the source | ||||
|  * distribution for preciese wording. | ||||
|  * | ||||
|  * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. | ||||
|  */ | ||||
| /** | ||||
|  * SECTION:errors | ||||
|  * @Short_description: Error reporting and logging functions. | ||||
|  * @Stability: Stable | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #define XMLSEC_PRIVATE 1 | ||||
| #define XMLSEC_NO_XSLT 1 | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <time.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include <libxml/tree.h> | ||||
|  | ||||
| #include <xmlsec/xmlsec.h> | ||||
| #include <xmlsec/xmltree.h> | ||||
| #include <xmlsec/private.h> | ||||
| #include <xmlsec/errors.h> | ||||
|  | ||||
| /* Must be bigger than fatal_error */ | ||||
| #define XMLSEC_ERRORS_BUFFER_SIZE       1024 | ||||
|  | ||||
| /* Must fit into xmlChar[XMLSEC_ERRORS_BUFFER_SIZE] */ | ||||
| static const xmlChar fatal_error[] = "Can not format error message"; | ||||
|  | ||||
| typedef struct _xmlSecErrorDescription                  xmlSecErrorDescription, *xmlSecErrorDescriptionPtr; | ||||
| struct _xmlSecErrorDescription { | ||||
|     int                 errorCode; | ||||
|     const char*         errorMsg; | ||||
| }; | ||||
|  | ||||
| static xmlSecErrorDescription xmlSecErrorsTable[XMLSEC_ERRORS_MAX_NUMBER + 1] = { | ||||
|   { XMLSEC_ERRORS_R_XMLSEC_FAILED,              "xmlsec library function failed" }, | ||||
|   { XMLSEC_ERRORS_R_MALLOC_FAILED,              "malloc function failed" }, | ||||
|   { XMLSEC_ERRORS_R_STRDUP_FAILED,              "strdup function failed" }, | ||||
|   { XMLSEC_ERRORS_R_CRYPTO_FAILED,              "crypto library function failed" }, | ||||
|   { XMLSEC_ERRORS_R_XML_FAILED,                 "libxml2 library function failed" }, | ||||
|   { XMLSEC_ERRORS_R_XSLT_FAILED,                "libxslt library function failed" }, | ||||
|   { XMLSEC_ERRORS_R_IO_FAILED,                  "io function failed" }, | ||||
|   { XMLSEC_ERRORS_R_DISABLED,                   "feature is disabled" }, | ||||
|   { XMLSEC_ERRORS_R_NOT_IMPLEMENTED,            "feature is not implemented" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_CONFIG,             "invalid configuration" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_SIZE,               "invalid size" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_DATA,               "invalid data" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_RESULT,             "invalid result" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_TYPE,               "invalid type" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_OPERATION,          "invalid operation" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_STATUS,             "invalid status" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_FORMAT,             "invalid format" }, | ||||
|   { XMLSEC_ERRORS_R_DATA_NOT_MATCH,             "data do not match" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_VERSION,            "invalid version" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_NODE,               "invalid node" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,       "invalid node content" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,     "invalid node attribute" }, | ||||
|   { XMLSEC_ERRORS_R_MISSING_NODE_ATTRIBUTE,     "missing node attribute" }, | ||||
|   { XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,       "node already present" }, | ||||
|   { XMLSEC_ERRORS_R_UNEXPECTED_NODE,            "unexpected node" }, | ||||
|   { XMLSEC_ERRORS_R_NODE_NOT_FOUND,             "node node found" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_TRANSFORM,          "invalid transform" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_TRANSFORM_KEY,      "invalid transform key" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_URI_TYPE,           "invalid URI type" }, | ||||
|   { XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED,   "same document is required for transform" }, | ||||
|   { XMLSEC_ERRORS_R_TRANSFORM_DISABLED,         "transform is disabled" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_KEY_DATA,           "invalid key data" }, | ||||
|   { XMLSEC_ERRORS_R_KEY_DATA_NOT_FOUND,         "key data is not found" }, | ||||
|   { XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,     "key data already exist" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,      "invalid key data size" }, | ||||
|   { XMLSEC_ERRORS_R_KEY_NOT_FOUND,              "key is not found" }, | ||||
|   { XMLSEC_ERRORS_R_KEYDATA_DISABLED,           "key data is disabled" }, | ||||
|   { XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL,       "maximum key retrieval level" }, | ||||
|   { XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,"key retrieval type mismatch" }, | ||||
|   { XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL,           "maximum encrypted key level" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,         "certificate verification failed" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_NOT_FOUND,             "certificate is not found" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_REVOKED,               "certificate is revoked" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,         "certificate issuer check failed" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_NOT_YET_VALID,         "certificate is not yet valid" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,           "certificate has expired" }, | ||||
|   { XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,         "Reference nodes are not found" }, | ||||
|   { XMLSEC_ERRORS_R_DSIG_INVALID_REFERENCE,     "Reference verification failed" }, | ||||
|   { XMLSEC_ERRORS_R_ASSERTION,                  "assertion" }, | ||||
|   { 0,                                          NULL} | ||||
| }; | ||||
|  | ||||
| static xmlSecErrorsCallback xmlSecErrorsClbk = xmlSecErrorsDefaultCallback; | ||||
| static int  xmlSecPrintErrorMessages = 1;       /* whether the error messages will be printed immediately */ | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsInit: | ||||
|  * | ||||
|  * Initializes the errors reporting. It is called from #xmlSecInit function. | ||||
|  * and applications must not call this function directly. | ||||
|  */ | ||||
| void | ||||
| xmlSecErrorsInit(void) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsShutdown: | ||||
|  * | ||||
|  * Cleanups the errors reporting. It is called from #xmlSecShutdown function. | ||||
|  * and applications must not call this function directly. | ||||
|  */ | ||||
| void | ||||
| xmlSecErrorsShutdown(void) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsSetCallback: | ||||
|  * @callback:           the new errors callback function. | ||||
|  * | ||||
|  * Sets the errors callback function to @callback that will be called | ||||
|  * every time an error occurs. | ||||
|  */ | ||||
| void | ||||
| xmlSecErrorsSetCallback(xmlSecErrorsCallback callback) { | ||||
|     xmlSecErrorsClbk = callback; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsDefaultCallback: | ||||
|  * @file:               the error location file name (__FILE__ macro). | ||||
|  * @line:               the error location line number (__LINE__ macro). | ||||
|  * @func:               the error location function name (__FUNCTION__ macro). | ||||
|  * @errorObject:        the error specific error object | ||||
|  * @errorSubject:       the error specific error subject. | ||||
|  * @reason:             the error code. | ||||
|  * @msg:                the additional error message. | ||||
|  * | ||||
|  * The default error reporting callback that utilizes LibXML | ||||
|  * error reporting #xmlGenericError function. | ||||
|  */ | ||||
| void | ||||
| xmlSecErrorsDefaultCallback(const char* file, int line, const char* func, | ||||
|                             const char* errorObject, const char* errorSubject, | ||||
|                             int reason, const char* msg) { | ||||
|     if(xmlSecPrintErrorMessages) { | ||||
|         const char* error_msg = NULL; | ||||
|         xmlSecSize i; | ||||
|  | ||||
|         for(i = 0; (i < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(i) != NULL); ++i) { | ||||
|             if(xmlSecErrorsGetCode(i) == reason) { | ||||
|                 error_msg = xmlSecErrorsGetMsg(i); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         xmlGenericError(xmlGenericErrorContext, | ||||
|             "func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:%s:%s\n", | ||||
|             (func != NULL) ? func : "unknown", | ||||
|             (file != NULL) ? file : "unknown", | ||||
|             line, | ||||
|             (errorObject != NULL) ? errorObject : "unknown", | ||||
|             (errorSubject != NULL) ? errorSubject : "unknown", | ||||
|             reason, | ||||
|             (error_msg != NULL) ? error_msg : "", | ||||
|             (msg != NULL) ? msg : ""); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsDefaultCallbackEnableOutput: | ||||
|  * @enabled:            the flag. | ||||
|  * | ||||
|  * Enables or disables calling LibXML2 callback from the default | ||||
|  * errors callback. | ||||
|  */ | ||||
| void | ||||
| xmlSecErrorsDefaultCallbackEnableOutput(int enabled) { | ||||
|     xmlSecPrintErrorMessages = enabled; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsGetCode: | ||||
|  * @pos:                the error position. | ||||
|  * | ||||
|  * Gets the known error code at position @pos. | ||||
|  * | ||||
|  * Returns: the known error code or 0 if @pos is greater than | ||||
|  * total number of known error codes. | ||||
|  */ | ||||
| int | ||||
| xmlSecErrorsGetCode(xmlSecSize pos) { | ||||
|     /* could not use asserts here! */ | ||||
|     if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) { | ||||
|         return(xmlSecErrorsTable[pos].errorCode); | ||||
|     } | ||||
|     return(0); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsGetMsg: | ||||
|  * @pos:                the error position. | ||||
|  * | ||||
|  * Gets the known error message at position @pos. | ||||
|  * | ||||
|  * Returns: the known error message or NULL if @pos is greater than | ||||
|  * total number of known error codes. | ||||
|  */ | ||||
| const char* | ||||
| xmlSecErrorsGetMsg(xmlSecSize pos) { | ||||
|     /* could not use asserts here! */ | ||||
|     if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) { | ||||
|         return(xmlSecErrorsTable[pos].errorMsg); | ||||
|     } | ||||
|     return(NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecError: | ||||
|  * @file:               the error location filename (__FILE__). | ||||
|  * @line:               the error location line number (__LINE__). | ||||
|  * @func:               the error location function (__FUNCTION__). | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @errorSubject:       the error specific error subject (e.g. failed function name). | ||||
|  * @reason:             the error code. | ||||
|  * @msg:                the error message in printf format. | ||||
|  * @...:                the parameters for the @msg. | ||||
|  * | ||||
|  * Reports an error to the default (#xmlSecErrorsDefaultCallback) or | ||||
|  * application specific callback installed using #xmlSecErrorsSetCallback | ||||
|  * function. | ||||
|  */ | ||||
| void | ||||
| xmlSecError(const char* file, int line, const char* func, | ||||
|             const char* errorObject, const char* errorSubject, | ||||
|             int reason, const char* msg, ...) { | ||||
|     if(xmlSecErrorsClbk != NULL) { | ||||
|         xmlChar error_msg[XMLSEC_ERRORS_BUFFER_SIZE]; | ||||
|         int ret; | ||||
|  | ||||
|         if(msg != NULL) { | ||||
|             va_list va; | ||||
|  | ||||
|             va_start(va, msg); | ||||
|             ret = xmlStrVPrintf(error_msg, sizeof(error_msg), msg, va); | ||||
|             if(ret < 0) { | ||||
|                 /* Can't really report an error from an error callback */ | ||||
|                 memcpy(error_msg, fatal_error, sizeof(fatal_error)); | ||||
|             } | ||||
|             error_msg[sizeof(error_msg) - 1] = '\0'; /* just in case */ | ||||
|             va_end(va); | ||||
|         } else { | ||||
|             error_msg[0] = '\0'; | ||||
|         } | ||||
|         xmlSecErrorsClbk(file, line, func, errorObject, errorSubject, reason, (char*)error_msg); | ||||
|     } | ||||
| } | ||||
| @@ -1,869 +0,0 @@ | ||||
| /* | ||||
|  * XML Security Library (http://www.aleksey.com/xmlsec). | ||||
|  * | ||||
|  * Internal header only used during the compilation, | ||||
|  * | ||||
|  * This is free software; see Copyright file in the source | ||||
|  * distribution for preciese wording. | ||||
|  * | ||||
|  * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. | ||||
|  */ | ||||
|  | ||||
| #ifndef __XMLSEC_ERROR_HELPERS_H__ | ||||
| #define __XMLSEC_ERROR_HELPERS_H__ | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <xmlsec/errors.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif /* __cplusplus */ | ||||
|  | ||||
| /********************************************************************** | ||||
|  * | ||||
|  * Error handling macros. | ||||
|  * | ||||
|  **********************************************************************/ | ||||
|  | ||||
| /** | ||||
|  * xmlSecInternalError: | ||||
|  * @errorFunction:      the failed function name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting internal XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecInternalError(errorFunction, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     (errorFunction),                        \ | ||||
|                     XMLSEC_ERRORS_R_XMLSEC_FAILED,          \ | ||||
|                     XMLSEC_ERRORS_NO_MESSAGE                \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInternalError2: | ||||
|  * @errorFunction:      the failed function name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param:              the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting internal XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecInternalError2(errorFunction, errorObject, msg, param) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     (errorFunction),                        \ | ||||
|                     XMLSEC_ERRORS_R_XMLSEC_FAILED,          \ | ||||
|                     (msg), (param)                          \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInternalError3: | ||||
|  * @errorFunction:      the failed function name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param1:             the extra message param1. | ||||
|  * @param2:             the extra message param2. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting internal XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecInternalError3(errorFunction, errorObject, msg, param1, param2) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     (errorFunction),                        \ | ||||
|                     XMLSEC_ERRORS_R_XMLSEC_FAILED,          \ | ||||
|                     (msg), (param1), (param2)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInternalError4: | ||||
|  * @errorFunction:      the failed function name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param1:             the extra message param1. | ||||
|  * @param2:             the extra message param2. | ||||
|  * @param3:             the extra message param3. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting internal XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecInternalError4(errorFunction, errorObject, msg, param1, param2, param3) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     (errorFunction),                        \ | ||||
|                     XMLSEC_ERRORS_R_XMLSEC_FAILED,          \ | ||||
|                     (msg), (param1), (param2), (param3)     \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecMallocError: | ||||
|  * @allocSize:          the failed allocation size. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting xmlMalloc() errors. | ||||
|  */ | ||||
| #define xmlSecMallocError(allocSize, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     "xmlMalloc",                            \ | ||||
|                     XMLSEC_ERRORS_R_MALLOC_FAILED,          \ | ||||
|                     "size=%lu", (unsigned long)(allocSize)  \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecStrdupError: | ||||
|  * @str:                the failed string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting xmlStrdup() errors. | ||||
|  */ | ||||
| #define xmlSecStrdupError(str, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     "xmlStrdup",                            \ | ||||
|                     XMLSEC_ERRORS_R_STRDUP_FAILED,          \ | ||||
|                     "size=%lu", (unsigned long)xmlStrlen(str) \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecXmlError: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting generic XML errors. | ||||
|  */ | ||||
| #define xmlSecXmlError(errorFunction, errorObject) \ | ||||
|     {                                                 \ | ||||
|         xmlErrorPtr error = xmlGetLastError();        \ | ||||
|         int code = (error != NULL) ? error->code : 0; \ | ||||
|         const char* message = (error != NULL) ? error->message : NULL; \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_XML_FAILED,        \ | ||||
|                    "xml error: %lu: %s",              \ | ||||
|                    (unsigned long)code,               \ | ||||
|                    xmlSecErrorsSafeString(message)    \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecXmlError2: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param:              the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting generic XML errors. | ||||
|  */ | ||||
| #define xmlSecXmlError2(errorFunction, errorObject, msg, param) \ | ||||
|     {                                                 \ | ||||
|         xmlErrorPtr error = xmlGetLastError();        \ | ||||
|         int code = (error != NULL) ? error->code : 0; \ | ||||
|         const char* message = (error != NULL) ? error->message : NULL; \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_XML_FAILED,        \ | ||||
|                    msg "; xml error: %lu: %s",        \ | ||||
|                    (param),                           \ | ||||
|                    (unsigned long)code,               \ | ||||
|                    xmlSecErrorsSafeString(message)    \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecXmlParserError: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @ctxt:               the parser context. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting XML parser errors. | ||||
|  */ | ||||
| #define xmlSecXmlParserError(errorFunction, ctxt, errorObject) \ | ||||
|     {                                                 \ | ||||
|         xmlErrorPtr error = xmlCtxtGetLastError(ctxt);\ | ||||
|         int code = (error != NULL) ? error->code : 0; \ | ||||
|         const char* message = (error != NULL) ? error->message : NULL; \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_XML_FAILED,        \ | ||||
|                    "xml error: %lu: %s",              \ | ||||
|                    (unsigned long)code,               \ | ||||
|                    xmlSecErrorsSafeString(message)    \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecXmlParserError2: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @ctxt:               the parser context. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param:              the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting XML parser errors. | ||||
|  */ | ||||
| #define xmlSecXmlParserError2(errorFunction, ctxt, errorObject, msg, param) \ | ||||
|     {                                                 \ | ||||
|         xmlErrorPtr error = xmlCtxtGetLastError(ctxt);\ | ||||
|         int code = (error != NULL) ? error->code : 0; \ | ||||
|         const char* message = (error != NULL) ? error->message : NULL; \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_XML_FAILED,        \ | ||||
|                    msg "; xml error: %lu: %s",        \ | ||||
|                    (param),                           \ | ||||
|                    (unsigned long)code,               \ | ||||
|                    xmlSecErrorsSafeString(message)    \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecXsltError: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @ctxt:               the parser context. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting XSLT errors. | ||||
|  */ | ||||
| #define xmlSecXsltError(errorFunction, ctxt, errorObject) \ | ||||
|     {                                                 \ | ||||
|         xmlErrorPtr error = xmlGetLastError();        \ | ||||
|         int code = (error != NULL) ? error->code : 0; \ | ||||
|         const char* message = (error != NULL) ? error->message : NULL; \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_XSLT_FAILED,       \ | ||||
|                    "xslt error: %lu: %s",             \ | ||||
|                    (unsigned long)code,               \ | ||||
|                    xmlSecErrorsSafeString(message)    \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecIOError: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @name:               the filename, function name, uri, etc. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting IO errors. | ||||
|  */ | ||||
| #define xmlSecIOError(errorFunction, name, errorObject) \ | ||||
|     {                                                 \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_IO_FAILED,         \ | ||||
|                    "name=\"%s\"; errno=%d",           \ | ||||
|                    xmlSecErrorsSafeString(name),      \ | ||||
|                    errno                              \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecNotImplementedError: | ||||
|  * @details:           the additional details. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "not implemented" errors. | ||||
|  */ | ||||
| #define xmlSecNotImplementedError(details) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     NULL,                                   \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_NOT_IMPLEMENTED,        \ | ||||
|                     "details=%s",                           \ | ||||
|                     xmlSecErrorsSafeString(details)         \ | ||||
|         ) | ||||
| /** | ||||
|  * xmlSecInvalidSizeError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value. | ||||
|  * @expected:           the expected value. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid size" errors when | ||||
|  * we expect exact match. | ||||
|  */ | ||||
| #define xmlSecInvalidSizeError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_SIZE,           \ | ||||
|                     "invalid size for '%s': actual=%lu is not equal to expected=%lu", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (unsigned long)(expected)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidSizeLessThanError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value. | ||||
|  * @expected:           the expected value. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid size" errors when | ||||
|  * we expect at least the expected size. | ||||
|  */ | ||||
| #define xmlSecInvalidSizeLessThanError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_SIZE,           \ | ||||
|                     "invalid size for '%s': actual=%lu is less than expected=%lu", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (unsigned long)(expected)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidSizeMoreThanError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value. | ||||
|  * @expected:           the expected value. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid size" errors when | ||||
|  * we expect at most the expected size. | ||||
|  */ | ||||
| #define xmlSecInvalidSizeMoreThanError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_NOT_IMPLEMENTED,        \ | ||||
|                     "invalid size for '%s': actual=%lu is more than expected=%lu", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (unsigned long)(expected)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidSizeNotMultipleOfError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value. | ||||
|  * @divider:            the expected divider. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid size" errors when | ||||
|  * we expect the size to be a multiple of the divider. | ||||
|  */ | ||||
| #define xmlSecInvalidSizeNotMultipleOfError(name, actual, divider, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_NOT_IMPLEMENTED,        \ | ||||
|                     "invalid size for '%s': actual=%lu is not a multiple of %lu", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (unsigned long)(divider)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidSizeOtherError: | ||||
|  * @msg:                the message about the error. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid size" errors when | ||||
|  * we expect exact match. | ||||
|  */ | ||||
| #define xmlSecInvalidSizeOtherError(msg, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_SIZE,           \ | ||||
|                     "invalid size: %s",                     \ | ||||
|                     xmlSecErrorsSafeString(msg)             \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidDataError: | ||||
|  * @msg:                the msg with explanation. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid data" errors. | ||||
|  */ | ||||
| #define xmlSecInvalidDataError(msg, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_DATA,           \ | ||||
|                     "%s",                                   \ | ||||
|                     xmlSecErrorsSafeString(msg)             \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidStringDataError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value as a string. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid data" errors for string. | ||||
|  */ | ||||
| #define xmlSecInvalidStringDataError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_DATA,           \ | ||||
|                     "invalid data for '%s': actual='%s' and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     xmlSecErrorsSafeString(actual),         \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidIntegerDataError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value as an integer. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid data" errors for integers. | ||||
|  */ | ||||
| #define xmlSecInvalidIntegerDataError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_DATA,           \ | ||||
|                     "invalid data for '%s': actual=%ld and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidIntegerDataError2: | ||||
|  * @name1:              the name of the first variable, parameter, etc. | ||||
|  * @actual1:            the actual first value as an integer. | ||||
|  * @name2:              the name of the second variable, parameter, etc. | ||||
|  * @actual2:            the actual second value as an integer. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid data" errors for integers. | ||||
|  */ | ||||
| #define xmlSecInvalidIntegerDataError2(name1, actual1, name2, actual2, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_DATA,           \ | ||||
|                     "invalid data: actual value '%s'=%ld, actual value '%s'=%ld and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name1),          \ | ||||
|                     (unsigned long)(actual1),               \ | ||||
|                     xmlSecErrorsSafeString(name2),          \ | ||||
|                     (unsigned long)(actual2),               \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidTypeError: | ||||
|  * @msg:                the msg with explanation. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid type" errors. | ||||
|  */ | ||||
| #define xmlSecInvalidTypeError(msg, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_TYPE,           \ | ||||
|                     "%s",                                   \ | ||||
|                     xmlSecErrorsSafeString(msg)             \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidStringTypeError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value as a string. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid type" errors for string. | ||||
|  */ | ||||
| #define xmlSecInvalidStringTypeError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_TYPE,           \ | ||||
|                     "invalid type for '%s': actual='%s' and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     xmlSecErrorsSafeString(actual),         \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidIntegerTypeError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value as an integer. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid type" errors for integers. | ||||
|  */ | ||||
| #define xmlSecInvalidIntegerTypeError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_TYPE,           \ | ||||
|                     "invalid type for '%s': actual=%ld and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidIntegerTypeError2: | ||||
|  * @name1:              the name of the first variable, parameter, etc. | ||||
|  * @actual1:            the actual first value as an integer. | ||||
|  * @name2:              the name of the second variable, parameter, etc. | ||||
|  * @actual2:            the actual second value as an integer. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid type" errors for integers. | ||||
|  */ | ||||
| #define xmlSecInvalidIntegerTypeError2(name1, actual1, name2, actual2, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_TYPE,           \ | ||||
|                     "invalid type: actual value '%s'=%ld, actual value '%s'=%ld and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name1),          \ | ||||
|                     (unsigned long)(actual1),               \ | ||||
|                     xmlSecErrorsSafeString(name2),          \ | ||||
|                     (unsigned long)(actual2),               \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidNodeError: | ||||
|  * @actualNode:         the actual node. | ||||
|  * @expectedNodeName:   the expected node name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid node errors. | ||||
|  */ | ||||
| #define xmlSecInvalidNodeError(actualNode, expectedNodeName, errorObject) \ | ||||
|     {                                                 \ | ||||
|         const char* actualNodeName = xmlSecNodeGetName(actualNode); \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_NODE,      \ | ||||
|                    "actual=%s; expected=%s",          \ | ||||
|                    xmlSecErrorsSafeString(actualNodeName),  \ | ||||
|                    xmlSecErrorsSafeString(expectedNodeName) \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidNodeContentError: | ||||
|  * @node:               the node. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @reason:             the reason why node content is invalid. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid node content errors. | ||||
|  */ | ||||
| #define xmlSecInvalidNodeContentError(node, errorObject, reason) \ | ||||
|     {                                                 \ | ||||
|         const char* nName = xmlSecNodeGetName(node);  \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, \ | ||||
|                    "node=%s; reason=%s",              \ | ||||
|                    xmlSecErrorsSafeString(nName),     \ | ||||
|                    xmlSecErrorsSafeString(reason)     \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidNodeAttributeError: | ||||
|  * @node:               the node. | ||||
|  * @attrName:           the attribute name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @reason:             the reason why node content is invalid. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid node attribute errors. | ||||
|  */ | ||||
| #define xmlSecInvalidNodeAttributeError(node, attrName, errorObject, reason) \ | ||||
|     {                                                 \ | ||||
|         const char* nName = xmlSecNodeGetName(node);  \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, \ | ||||
|                    "node=%s; attribute=%s; reason=%s",\ | ||||
|                    xmlSecErrorsSafeString(nName),     \ | ||||
|                    xmlSecErrorsSafeString(attrName),  \ | ||||
|                    xmlSecErrorsSafeString(reason)     \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecNodeAlreadyPresentError: | ||||
|  * @parent:             the parent node. | ||||
|  * @nodeName:           the node name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting node already present errors. | ||||
|  */ | ||||
| #define xmlSecNodeAlreadyPresentError(parent, nodeName, errorObject) \ | ||||
|     {                                                 \ | ||||
|         const char* pName = xmlSecNodeGetName(parent);\ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, \ | ||||
|                    "parent=%s; node=%s",              \ | ||||
|                    xmlSecErrorsSafeString(pName),     \ | ||||
|                    xmlSecErrorsSafeString(nodeName)   \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecUnexpectedNodeError: | ||||
|  * @node:               the node. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid node errors. | ||||
|  */ | ||||
| #define xmlSecUnexpectedNodeError(node, errorObject) \ | ||||
|     {                                                 \ | ||||
|         const char* nName = xmlSecNodeGetName(node);  \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_UNEXPECTED_NODE,   \ | ||||
|                    "node=%s",                         \ | ||||
|                    xmlSecErrorsSafeString(nName)      \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecNodeNotFoundError: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @startNode:          the search start node. | ||||
|  * @targetNodeName:     the expected child node name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting node not found errors. | ||||
|  */ | ||||
| #define xmlSecNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject) \ | ||||
|     {                                                 \ | ||||
|         const char* startNodeName = xmlSecNodeGetName(startNode); \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_NODE_NOT_FOUND,    \ | ||||
|                    "startNode=%s; target=%s",         \ | ||||
|                    xmlSecErrorsSafeString(startNodeName), \ | ||||
|                    xmlSecErrorsSafeString(targetNodeName) \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidTransfromError: | ||||
|  * @transform:          the transform. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid transform errors. | ||||
|  */ | ||||
| #define xmlSecInvalidTransfromError(transform) \ | ||||
|     {                                                 \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)xmlSecTransformGetName(transform), \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_TRANSFORM, \ | ||||
|                    XMLSEC_ERRORS_NO_MESSAGE           \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidTransfromError2: | ||||
|  * @transform:          the transform. | ||||
|  * @msg:                the extra message. | ||||
|  * @param:              the extra message param. | ||||
|  * | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid transform errors. | ||||
|  */ | ||||
| #define xmlSecInvalidTransfromError2(transform, msg, param) \ | ||||
|     {                                                 \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)xmlSecTransformGetName(transform), \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_TRANSFORM, \ | ||||
|                    (msg), (param)                     \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidTransfromStatusError: | ||||
|  * @transform:          the transform. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid transform status errors. | ||||
|  */ | ||||
| #define xmlSecInvalidTransfromStatusError(transform) \ | ||||
|     {                                                 \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)xmlSecTransformGetName(transform), \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_STATUS,    \ | ||||
|                    "transformStatus=%d",              \ | ||||
|                    (int)((transform)->status)         \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidTransfromStatusError2: | ||||
|  * @transform:          the transform. | ||||
|  * @msg:                the extra message. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid transform status errors. | ||||
|  */ | ||||
| #define xmlSecInvalidTransfromStatusError2(transform, msg) \ | ||||
|     {                                                 \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)xmlSecTransformGetName(transform), \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_STATUS,    \ | ||||
|                    "transformStatus=%ld, msg=%s",     \ | ||||
|                    (long int)((transform)->status),   \ | ||||
|                    msg                                \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidKeyDataSizeError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value. | ||||
|  * @expected:           the expected value(s). | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid keydata size" errors. | ||||
|  */ | ||||
| #define xmlSecInvalidKeyDataSizeError(actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,  \ | ||||
|                     "invalid key data size: actual=%ld and expected=%ld", \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (unsigned long)(expected)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidZeroKeyDataSizeError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid keydata size" errors. | ||||
|  */ | ||||
| #define xmlSecInvalidZeroKeyDataSizeError(errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,  \ | ||||
|                     "invalid zero key data size"            \ | ||||
|         ) | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * xmlSecOtherError: | ||||
|  * @code:               the error code. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @details:            the error message. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting other XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecOtherError(code, errorObject, details) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     (code),                                 \ | ||||
|                     "details=%s",                           \ | ||||
|                     xmlSecErrorsSafeString(details)         \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecOtherError2: | ||||
|  * @code:               the error code. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param:              the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting other XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecOtherError2(code, errorObject, msg, param) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     (code),                                 \ | ||||
|                     (msg), (param)                          \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecOtherError3: | ||||
|  * @code:               the error code. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param1:             the extra message param. | ||||
|  * @param2:             the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting other XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecOtherError3(code, errorObject, msg, param1, param2) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     (code),                                 \ | ||||
|                     (msg), (param1), (param2)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecOtherError4: | ||||
|  * @code:               the error code. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param1:             the extra message param. | ||||
|  * @param2:             the extra message param. | ||||
|  * @param3:             the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting other XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecOtherError4(code, errorObject, msg, param1, param2, param3) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     (code),                                 \ | ||||
|                     (msg), (param1), (param2), (param3)     \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecOtherError5: | ||||
|  * @code:               the error code. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param1:             the extra message param. | ||||
|  * @param2:             the extra message param. | ||||
|  * @param3:             the extra message param. | ||||
|  * @param4:             the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting other XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecOtherError5(code, errorObject, msg, param1, param2, param3, param4) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     (code),                                 \ | ||||
|                     (msg), (param1), (param2), (param3), (param4) \ | ||||
|         ) | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif /* __cplusplus */ | ||||
|  | ||||
| #endif /* __XMLSEC_ERROR_HELPERS_H__ */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,259 +0,0 @@ | ||||
| /* | ||||
|  * XML Security Library (http://www.aleksey.com/xmlsec). | ||||
|  * | ||||
|  * | ||||
|  * This is free software; see Copyright file in the source | ||||
|  * distribution for preciese wording. | ||||
|  * | ||||
|  * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. | ||||
|  */ | ||||
| /** | ||||
|  * SECTION:errors | ||||
|  * @Short_description: Error reporting and logging functions. | ||||
|  * @Stability: Stable | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #define XMLSEC_PRIVATE 1 | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <time.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include <libxml/tree.h> | ||||
|  | ||||
| #include <xmlsec/xmlsec.h> | ||||
| #include <xmlsec/xmltree.h> | ||||
| #include <xmlsec/private.h> | ||||
| #include <xmlsec/errors.h> | ||||
|  | ||||
| /* Must be bigger than fatal_error */ | ||||
| #define XMLSEC_ERRORS_BUFFER_SIZE       1024 | ||||
|  | ||||
| /* Must fit into xmlChar[XMLSEC_ERRORS_BUFFER_SIZE] */ | ||||
| static const xmlChar fatal_error[] = "Can not format error message"; | ||||
|  | ||||
| typedef struct _xmlSecErrorDescription                  xmlSecErrorDescription, *xmlSecErrorDescriptionPtr; | ||||
| struct _xmlSecErrorDescription { | ||||
|     int                 errorCode; | ||||
|     const char*         errorMsg; | ||||
| }; | ||||
|  | ||||
| static xmlSecErrorDescription xmlSecErrorsTable[XMLSEC_ERRORS_MAX_NUMBER + 1] = { | ||||
|   { XMLSEC_ERRORS_R_XMLSEC_FAILED,              "xmlsec library function failed" }, | ||||
|   { XMLSEC_ERRORS_R_MALLOC_FAILED,              "malloc function failed" }, | ||||
|   { XMLSEC_ERRORS_R_STRDUP_FAILED,              "strdup function failed" }, | ||||
|   { XMLSEC_ERRORS_R_CRYPTO_FAILED,              "crypto library function failed" }, | ||||
|   { XMLSEC_ERRORS_R_XML_FAILED,                 "libxml2 library function failed" }, | ||||
|   { XMLSEC_ERRORS_R_XSLT_FAILED,                "libxslt library function failed" }, | ||||
|   { XMLSEC_ERRORS_R_IO_FAILED,                  "io function failed" }, | ||||
|   { XMLSEC_ERRORS_R_DISABLED,                   "feature is disabled" }, | ||||
|   { XMLSEC_ERRORS_R_NOT_IMPLEMENTED,            "feature is not implemented" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_CONFIG,             "invalid configuration" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_SIZE,               "invalid size" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_DATA,               "invalid data" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_RESULT,             "invalid result" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_TYPE,               "invalid type" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_OPERATION,          "invalid operation" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_STATUS,             "invalid status" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_FORMAT,             "invalid format" }, | ||||
|   { XMLSEC_ERRORS_R_DATA_NOT_MATCH,             "data do not match" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_VERSION,            "invalid version" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_NODE,               "invalid node" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,       "invalid node content" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,     "invalid node attribute" }, | ||||
|   { XMLSEC_ERRORS_R_MISSING_NODE_ATTRIBUTE,     "missing node attribute" }, | ||||
|   { XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,       "node already present" }, | ||||
|   { XMLSEC_ERRORS_R_UNEXPECTED_NODE,            "unexpected node" }, | ||||
|   { XMLSEC_ERRORS_R_NODE_NOT_FOUND,             "node node found" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_TRANSFORM,          "invalid transform" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_TRANSFORM_KEY,      "invalid transform key" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_URI_TYPE,           "invalid URI type" }, | ||||
|   { XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED,   "same document is required for transform" }, | ||||
|   { XMLSEC_ERRORS_R_TRANSFORM_DISABLED,         "transform is disabled" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_KEY_DATA,           "invalid key data" }, | ||||
|   { XMLSEC_ERRORS_R_KEY_DATA_NOT_FOUND,         "key data is not found" }, | ||||
|   { XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,     "key data already exist" }, | ||||
|   { XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,      "invalid key data size" }, | ||||
|   { XMLSEC_ERRORS_R_KEY_NOT_FOUND,              "key is not found" }, | ||||
|   { XMLSEC_ERRORS_R_KEYDATA_DISABLED,           "key data is disabled" }, | ||||
|   { XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL,       "maximum key retrieval level" }, | ||||
|   { XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,"key retrieval type mismatch" }, | ||||
|   { XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL,           "maximum encrypted key level" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,         "certificate verification failed" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_NOT_FOUND,             "certificate is not found" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_REVOKED,               "certificate is revoked" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,         "certificate issuer check failed" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_NOT_YET_VALID,         "certificate is not yet valid" }, | ||||
|   { XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,           "certificate has expired" }, | ||||
|   { XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,         "Reference nodes are not found" }, | ||||
|   { XMLSEC_ERRORS_R_DSIG_INVALID_REFERENCE,     "Reference verification failed" }, | ||||
|   { XMLSEC_ERRORS_R_ASSERTION,                  "assertion" }, | ||||
|   { 0,                                          NULL} | ||||
| }; | ||||
|  | ||||
| static xmlSecErrorsCallback xmlSecErrorsClbk = xmlSecErrorsDefaultCallback; | ||||
| static int  xmlSecPrintErrorMessages = 1;       /* whether the error messages will be printed immediately */ | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsInit: | ||||
|  * | ||||
|  * Initializes the errors reporting. It is called from #xmlSecInit function. | ||||
|  * and applications must not call this function directly. | ||||
|  */ | ||||
| void | ||||
| xmlSecErrorsInit(void) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsShutdown: | ||||
|  * | ||||
|  * Cleanups the errors reporting. It is called from #xmlSecShutdown function. | ||||
|  * and applications must not call this function directly. | ||||
|  */ | ||||
| void | ||||
| xmlSecErrorsShutdown(void) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsSetCallback: | ||||
|  * @callback:           the new errors callback function. | ||||
|  * | ||||
|  * Sets the errors callback function to @callback that will be called | ||||
|  * every time an error occurs. | ||||
|  */ | ||||
| void | ||||
| xmlSecErrorsSetCallback(xmlSecErrorsCallback callback) { | ||||
|     xmlSecErrorsClbk = callback; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsDefaultCallback: | ||||
|  * @file:               the error location file name (__FILE__ macro). | ||||
|  * @line:               the error location line number (__LINE__ macro). | ||||
|  * @func:               the error location function name (__FUNCTION__ macro). | ||||
|  * @errorObject:        the error specific error object | ||||
|  * @errorSubject:       the error specific error subject. | ||||
|  * @reason:             the error code. | ||||
|  * @msg:                the additional error message. | ||||
|  * | ||||
|  * The default error reporting callback that utilizes LibXML | ||||
|  * error reporting #xmlGenericError function. | ||||
|  */ | ||||
| void | ||||
| xmlSecErrorsDefaultCallback(const char* file, int line, const char* func, | ||||
|                             const char* errorObject, const char* errorSubject, | ||||
|                             int reason, const char* msg) { | ||||
|     if(xmlSecPrintErrorMessages) { | ||||
|         const char* error_msg = NULL; | ||||
|         xmlSecSize i; | ||||
|  | ||||
|         for(i = 0; (i < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(i) != NULL); ++i) { | ||||
|             if(xmlSecErrorsGetCode(i) == reason) { | ||||
|                 error_msg = xmlSecErrorsGetMsg(i); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         xmlGenericError(xmlGenericErrorContext, | ||||
|             "func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:%s:%s\n", | ||||
|             (func != NULL) ? func : "unknown", | ||||
|             (file != NULL) ? file : "unknown", | ||||
|             line, | ||||
|             (errorObject != NULL) ? errorObject : "unknown", | ||||
|             (errorSubject != NULL) ? errorSubject : "unknown", | ||||
|             reason, | ||||
|             (error_msg != NULL) ? error_msg : "", | ||||
|             (msg != NULL) ? msg : ""); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsDefaultCallbackEnableOutput: | ||||
|  * @enabled:            the flag. | ||||
|  * | ||||
|  * Enables or disables calling LibXML2 callback from the default | ||||
|  * errors callback. | ||||
|  */ | ||||
| void | ||||
| xmlSecErrorsDefaultCallbackEnableOutput(int enabled) { | ||||
|     xmlSecPrintErrorMessages = enabled; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsGetCode: | ||||
|  * @pos:                the error position. | ||||
|  * | ||||
|  * Gets the known error code at position @pos. | ||||
|  * | ||||
|  * Returns: the known error code or 0 if @pos is greater than | ||||
|  * total number of known error codes. | ||||
|  */ | ||||
| int | ||||
| xmlSecErrorsGetCode(xmlSecSize pos) { | ||||
|     /* could not use asserts here! */ | ||||
|     if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) { | ||||
|         return(xmlSecErrorsTable[pos].errorCode); | ||||
|     } | ||||
|     return(0); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecErrorsGetMsg: | ||||
|  * @pos:                the error position. | ||||
|  * | ||||
|  * Gets the known error message at position @pos. | ||||
|  * | ||||
|  * Returns: the known error message or NULL if @pos is greater than | ||||
|  * total number of known error codes. | ||||
|  */ | ||||
| const char* | ||||
| xmlSecErrorsGetMsg(xmlSecSize pos) { | ||||
|     /* could not use asserts here! */ | ||||
|     if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) { | ||||
|         return(xmlSecErrorsTable[pos].errorMsg); | ||||
|     } | ||||
|     return(NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * xmlSecError: | ||||
|  * @file:               the error location filename (__FILE__). | ||||
|  * @line:               the error location line number (__LINE__). | ||||
|  * @func:               the error location function (__FUNCTION__). | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @errorSubject:       the error specific error subject (e.g. failed function name). | ||||
|  * @reason:             the error code. | ||||
|  * @msg:                the error message in printf format. | ||||
|  * @...:                the parameters for the @msg. | ||||
|  * | ||||
|  * Reports an error to the default (#xmlSecErrorsDefaultCallback) or | ||||
|  * application specific callback installed using #xmlSecErrorsSetCallback | ||||
|  * function. | ||||
|  */ | ||||
| void | ||||
| xmlSecError(const char* file, int line, const char* func, | ||||
|             const char* errorObject, const char* errorSubject, | ||||
|             int reason, const char* msg, ...) { | ||||
|     if(xmlSecErrorsClbk != NULL) { | ||||
|         xmlChar error_msg[XMLSEC_ERRORS_BUFFER_SIZE]; | ||||
|         int ret; | ||||
|  | ||||
|         if(msg != NULL) { | ||||
|             va_list va; | ||||
|  | ||||
|             va_start(va, msg); | ||||
|             ret = xmlStrVPrintf(error_msg, sizeof(error_msg), msg, va); | ||||
|             if(ret < 0) { | ||||
|                 /* Can't really report an error from an error callback */ | ||||
|                 memcpy(error_msg, fatal_error, sizeof(fatal_error)); | ||||
|             } | ||||
|             error_msg[sizeof(error_msg) - 1] = '\0'; /* just in case */ | ||||
|             va_end(va); | ||||
|         } else { | ||||
|             error_msg[0] = '\0'; | ||||
|         } | ||||
|         xmlSecErrorsClbk(file, line, func, errorObject, errorSubject, reason, (char*)error_msg); | ||||
|     } | ||||
| } | ||||
| @@ -1,869 +0,0 @@ | ||||
| /* | ||||
|  * XML Security Library (http://www.aleksey.com/xmlsec). | ||||
|  * | ||||
|  * Internal header only used during the compilation, | ||||
|  * | ||||
|  * This is free software; see Copyright file in the source | ||||
|  * distribution for preciese wording. | ||||
|  * | ||||
|  * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. | ||||
|  */ | ||||
|  | ||||
| #ifndef __XMLSEC_ERROR_HELPERS_H__ | ||||
| #define __XMLSEC_ERROR_HELPERS_H__ | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <xmlsec/errors.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif /* __cplusplus */ | ||||
|  | ||||
| /********************************************************************** | ||||
|  * | ||||
|  * Error handling macros. | ||||
|  * | ||||
|  **********************************************************************/ | ||||
|  | ||||
| /** | ||||
|  * xmlSecInternalError: | ||||
|  * @errorFunction:      the failed function name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting internal XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecInternalError(errorFunction, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     (errorFunction),                        \ | ||||
|                     XMLSEC_ERRORS_R_XMLSEC_FAILED,          \ | ||||
|                     XMLSEC_ERRORS_NO_MESSAGE                \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInternalError2: | ||||
|  * @errorFunction:      the failed function name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param:              the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting internal XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecInternalError2(errorFunction, errorObject, msg, param) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     (errorFunction),                        \ | ||||
|                     XMLSEC_ERRORS_R_XMLSEC_FAILED,          \ | ||||
|                     (msg), (param)                          \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInternalError3: | ||||
|  * @errorFunction:      the failed function name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param1:             the extra message param1. | ||||
|  * @param2:             the extra message param2. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting internal XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecInternalError3(errorFunction, errorObject, msg, param1, param2) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     (errorFunction),                        \ | ||||
|                     XMLSEC_ERRORS_R_XMLSEC_FAILED,          \ | ||||
|                     (msg), (param1), (param2)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInternalError4: | ||||
|  * @errorFunction:      the failed function name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param1:             the extra message param1. | ||||
|  * @param2:             the extra message param2. | ||||
|  * @param3:             the extra message param3. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting internal XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecInternalError4(errorFunction, errorObject, msg, param1, param2, param3) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     (errorFunction),                        \ | ||||
|                     XMLSEC_ERRORS_R_XMLSEC_FAILED,          \ | ||||
|                     (msg), (param1), (param2), (param3)     \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecMallocError: | ||||
|  * @allocSize:          the failed allocation size. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting xmlMalloc() errors. | ||||
|  */ | ||||
| #define xmlSecMallocError(allocSize, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     "xmlMalloc",                            \ | ||||
|                     XMLSEC_ERRORS_R_MALLOC_FAILED,          \ | ||||
|                     "size=%lu", (unsigned long)(allocSize)  \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecStrdupError: | ||||
|  * @str:                the failed string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting xmlStrdup() errors. | ||||
|  */ | ||||
| #define xmlSecStrdupError(str, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     "xmlStrdup",                            \ | ||||
|                     XMLSEC_ERRORS_R_STRDUP_FAILED,          \ | ||||
|                     "size=%lu", (unsigned long)xmlStrlen(str) \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecXmlError: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting generic XML errors. | ||||
|  */ | ||||
| #define xmlSecXmlError(errorFunction, errorObject) \ | ||||
|     {                                                 \ | ||||
|         xmlErrorPtr error = xmlGetLastError();        \ | ||||
|         int code = (error != NULL) ? error->code : 0; \ | ||||
|         const char* message = (error != NULL) ? error->message : NULL; \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_XML_FAILED,        \ | ||||
|                    "xml error: %lu: %s",              \ | ||||
|                    (unsigned long)code,               \ | ||||
|                    xmlSecErrorsSafeString(message)    \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecXmlError2: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param:              the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting generic XML errors. | ||||
|  */ | ||||
| #define xmlSecXmlError2(errorFunction, errorObject, msg, param) \ | ||||
|     {                                                 \ | ||||
|         xmlErrorPtr error = xmlGetLastError();        \ | ||||
|         int code = (error != NULL) ? error->code : 0; \ | ||||
|         const char* message = (error != NULL) ? error->message : NULL; \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_XML_FAILED,        \ | ||||
|                    msg "; xml error: %lu: %s",        \ | ||||
|                    (param),                           \ | ||||
|                    (unsigned long)code,               \ | ||||
|                    xmlSecErrorsSafeString(message)    \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecXmlParserError: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @ctxt:               the parser context. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting XML parser errors. | ||||
|  */ | ||||
| #define xmlSecXmlParserError(errorFunction, ctxt, errorObject) \ | ||||
|     {                                                 \ | ||||
|         xmlErrorPtr error = xmlCtxtGetLastError(ctxt);\ | ||||
|         int code = (error != NULL) ? error->code : 0; \ | ||||
|         const char* message = (error != NULL) ? error->message : NULL; \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_XML_FAILED,        \ | ||||
|                    "xml error: %lu: %s",              \ | ||||
|                    (unsigned long)code,               \ | ||||
|                    xmlSecErrorsSafeString(message)    \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecXmlParserError2: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @ctxt:               the parser context. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param:              the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting XML parser errors. | ||||
|  */ | ||||
| #define xmlSecXmlParserError2(errorFunction, ctxt, errorObject, msg, param) \ | ||||
|     {                                                 \ | ||||
|         xmlErrorPtr error = xmlCtxtGetLastError(ctxt);\ | ||||
|         int code = (error != NULL) ? error->code : 0; \ | ||||
|         const char* message = (error != NULL) ? error->message : NULL; \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_XML_FAILED,        \ | ||||
|                    msg "; xml error: %lu: %s",        \ | ||||
|                    (param),                           \ | ||||
|                    (unsigned long)code,               \ | ||||
|                    xmlSecErrorsSafeString(message)    \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecXsltError: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @ctxt:               the parser context. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting XSLT errors. | ||||
|  */ | ||||
| #define xmlSecXsltError(errorFunction, ctxt, errorObject) \ | ||||
|     {                                                 \ | ||||
|         xmlErrorPtr error = xmlGetLastError();        \ | ||||
|         int code = (error != NULL) ? error->code : 0; \ | ||||
|         const char* message = (error != NULL) ? error->message : NULL; \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_XSLT_FAILED,       \ | ||||
|                    "xslt error: %lu: %s",             \ | ||||
|                    (unsigned long)code,               \ | ||||
|                    xmlSecErrorsSafeString(message)    \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecIOError: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @name:               the filename, function name, uri, etc. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting IO errors. | ||||
|  */ | ||||
| #define xmlSecIOError(errorFunction, name, errorObject) \ | ||||
|     {                                                 \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_IO_FAILED,         \ | ||||
|                    "name=\"%s\"; errno=%d",           \ | ||||
|                    xmlSecErrorsSafeString(name),      \ | ||||
|                    errno                              \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecNotImplementedError: | ||||
|  * @details:           the additional details. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "not implemented" errors. | ||||
|  */ | ||||
| #define xmlSecNotImplementedError(details) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     NULL,                                   \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_NOT_IMPLEMENTED,        \ | ||||
|                     "details=%s",                           \ | ||||
|                     xmlSecErrorsSafeString(details)         \ | ||||
|         ) | ||||
| /** | ||||
|  * xmlSecInvalidSizeError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value. | ||||
|  * @expected:           the expected value. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid size" errors when | ||||
|  * we expect exact match. | ||||
|  */ | ||||
| #define xmlSecInvalidSizeError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_SIZE,           \ | ||||
|                     "invalid size for '%s': actual=%lu is not equal to expected=%lu", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (unsigned long)(expected)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidSizeLessThanError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value. | ||||
|  * @expected:           the expected value. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid size" errors when | ||||
|  * we expect at least the expected size. | ||||
|  */ | ||||
| #define xmlSecInvalidSizeLessThanError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_SIZE,           \ | ||||
|                     "invalid size for '%s': actual=%lu is less than expected=%lu", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (unsigned long)(expected)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidSizeMoreThanError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value. | ||||
|  * @expected:           the expected value. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid size" errors when | ||||
|  * we expect at most the expected size. | ||||
|  */ | ||||
| #define xmlSecInvalidSizeMoreThanError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_NOT_IMPLEMENTED,        \ | ||||
|                     "invalid size for '%s': actual=%lu is more than expected=%lu", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (unsigned long)(expected)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidSizeNotMultipleOfError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value. | ||||
|  * @divider:            the expected divider. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid size" errors when | ||||
|  * we expect the size to be a multiple of the divider. | ||||
|  */ | ||||
| #define xmlSecInvalidSizeNotMultipleOfError(name, actual, divider, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_NOT_IMPLEMENTED,        \ | ||||
|                     "invalid size for '%s': actual=%lu is not a multiple of %lu", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (unsigned long)(divider)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidSizeOtherError: | ||||
|  * @msg:                the message about the error. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid size" errors when | ||||
|  * we expect exact match. | ||||
|  */ | ||||
| #define xmlSecInvalidSizeOtherError(msg, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_SIZE,           \ | ||||
|                     "invalid size: %s",                     \ | ||||
|                     xmlSecErrorsSafeString(msg)             \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidDataError: | ||||
|  * @msg:                the msg with explanation. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid data" errors. | ||||
|  */ | ||||
| #define xmlSecInvalidDataError(msg, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_DATA,           \ | ||||
|                     "%s",                                   \ | ||||
|                     xmlSecErrorsSafeString(msg)             \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidStringDataError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value as a string. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid data" errors for string. | ||||
|  */ | ||||
| #define xmlSecInvalidStringDataError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_DATA,           \ | ||||
|                     "invalid data for '%s': actual='%s' and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     xmlSecErrorsSafeString(actual),         \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidIntegerDataError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value as an integer. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid data" errors for integers. | ||||
|  */ | ||||
| #define xmlSecInvalidIntegerDataError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_DATA,           \ | ||||
|                     "invalid data for '%s': actual=%ld and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidIntegerDataError2: | ||||
|  * @name1:              the name of the first variable, parameter, etc. | ||||
|  * @actual1:            the actual first value as an integer. | ||||
|  * @name2:              the name of the second variable, parameter, etc. | ||||
|  * @actual2:            the actual second value as an integer. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid data" errors for integers. | ||||
|  */ | ||||
| #define xmlSecInvalidIntegerDataError2(name1, actual1, name2, actual2, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_DATA,           \ | ||||
|                     "invalid data: actual value '%s'=%ld, actual value '%s'=%ld and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name1),          \ | ||||
|                     (unsigned long)(actual1),               \ | ||||
|                     xmlSecErrorsSafeString(name2),          \ | ||||
|                     (unsigned long)(actual2),               \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidTypeError: | ||||
|  * @msg:                the msg with explanation. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid type" errors. | ||||
|  */ | ||||
| #define xmlSecInvalidTypeError(msg, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_TYPE,           \ | ||||
|                     "%s",                                   \ | ||||
|                     xmlSecErrorsSafeString(msg)             \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidStringTypeError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value as a string. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid type" errors for string. | ||||
|  */ | ||||
| #define xmlSecInvalidStringTypeError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_TYPE,           \ | ||||
|                     "invalid type for '%s': actual='%s' and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     xmlSecErrorsSafeString(actual),         \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidIntegerTypeError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value as an integer. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid type" errors for integers. | ||||
|  */ | ||||
| #define xmlSecInvalidIntegerTypeError(name, actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_TYPE,           \ | ||||
|                     "invalid type for '%s': actual=%ld and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name),           \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidIntegerTypeError2: | ||||
|  * @name1:              the name of the first variable, parameter, etc. | ||||
|  * @actual1:            the actual first value as an integer. | ||||
|  * @name2:              the name of the second variable, parameter, etc. | ||||
|  * @actual2:            the actual second value as an integer. | ||||
|  * @expected:           the expected value(s) as a string. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid type" errors for integers. | ||||
|  */ | ||||
| #define xmlSecInvalidIntegerTypeError2(name1, actual1, name2, actual2, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_TYPE,           \ | ||||
|                     "invalid type: actual value '%s'=%ld, actual value '%s'=%ld and expected %s", \ | ||||
|                     xmlSecErrorsSafeString(name1),          \ | ||||
|                     (unsigned long)(actual1),               \ | ||||
|                     xmlSecErrorsSafeString(name2),          \ | ||||
|                     (unsigned long)(actual2),               \ | ||||
|                     (expected)                              \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidNodeError: | ||||
|  * @actualNode:         the actual node. | ||||
|  * @expectedNodeName:   the expected node name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid node errors. | ||||
|  */ | ||||
| #define xmlSecInvalidNodeError(actualNode, expectedNodeName, errorObject) \ | ||||
|     {                                                 \ | ||||
|         const char* actualNodeName = xmlSecNodeGetName(actualNode); \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_NODE,      \ | ||||
|                    "actual=%s; expected=%s",          \ | ||||
|                    xmlSecErrorsSafeString(actualNodeName),  \ | ||||
|                    xmlSecErrorsSafeString(expectedNodeName) \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidNodeContentError: | ||||
|  * @node:               the node. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @reason:             the reason why node content is invalid. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid node content errors. | ||||
|  */ | ||||
| #define xmlSecInvalidNodeContentError(node, errorObject, reason) \ | ||||
|     {                                                 \ | ||||
|         const char* nName = xmlSecNodeGetName(node);  \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, \ | ||||
|                    "node=%s; reason=%s",              \ | ||||
|                    xmlSecErrorsSafeString(nName),     \ | ||||
|                    xmlSecErrorsSafeString(reason)     \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidNodeAttributeError: | ||||
|  * @node:               the node. | ||||
|  * @attrName:           the attribute name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @reason:             the reason why node content is invalid. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid node attribute errors. | ||||
|  */ | ||||
| #define xmlSecInvalidNodeAttributeError(node, attrName, errorObject, reason) \ | ||||
|     {                                                 \ | ||||
|         const char* nName = xmlSecNodeGetName(node);  \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, \ | ||||
|                    "node=%s; attribute=%s; reason=%s",\ | ||||
|                    xmlSecErrorsSafeString(nName),     \ | ||||
|                    xmlSecErrorsSafeString(attrName),  \ | ||||
|                    xmlSecErrorsSafeString(reason)     \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecNodeAlreadyPresentError: | ||||
|  * @parent:             the parent node. | ||||
|  * @nodeName:           the node name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting node already present errors. | ||||
|  */ | ||||
| #define xmlSecNodeAlreadyPresentError(parent, nodeName, errorObject) \ | ||||
|     {                                                 \ | ||||
|         const char* pName = xmlSecNodeGetName(parent);\ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, \ | ||||
|                    "parent=%s; node=%s",              \ | ||||
|                    xmlSecErrorsSafeString(pName),     \ | ||||
|                    xmlSecErrorsSafeString(nodeName)   \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecUnexpectedNodeError: | ||||
|  * @node:               the node. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid node errors. | ||||
|  */ | ||||
| #define xmlSecUnexpectedNodeError(node, errorObject) \ | ||||
|     {                                                 \ | ||||
|         const char* nName = xmlSecNodeGetName(node);  \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_UNEXPECTED_NODE,   \ | ||||
|                    "node=%s",                         \ | ||||
|                    xmlSecErrorsSafeString(nName)      \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecNodeNotFoundError: | ||||
|  * @errorFunction:      the failed function. | ||||
|  * @startNode:          the search start node. | ||||
|  * @targetNodeName:     the expected child node name. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting node not found errors. | ||||
|  */ | ||||
| #define xmlSecNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject) \ | ||||
|     {                                                 \ | ||||
|         const char* startNodeName = xmlSecNodeGetName(startNode); \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)(errorObject),        \ | ||||
|                    (errorFunction),                   \ | ||||
|                    XMLSEC_ERRORS_R_NODE_NOT_FOUND,    \ | ||||
|                    "startNode=%s; target=%s",         \ | ||||
|                    xmlSecErrorsSafeString(startNodeName), \ | ||||
|                    xmlSecErrorsSafeString(targetNodeName) \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidTransfromError: | ||||
|  * @transform:          the transform. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid transform errors. | ||||
|  */ | ||||
| #define xmlSecInvalidTransfromError(transform) \ | ||||
|     {                                                 \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)xmlSecTransformGetName(transform), \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_TRANSFORM, \ | ||||
|                    XMLSEC_ERRORS_NO_MESSAGE           \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidTransfromError2: | ||||
|  * @transform:          the transform. | ||||
|  * @msg:                the extra message. | ||||
|  * @param:              the extra message param. | ||||
|  * | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid transform errors. | ||||
|  */ | ||||
| #define xmlSecInvalidTransfromError2(transform, msg, param) \ | ||||
|     {                                                 \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)xmlSecTransformGetName(transform), \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_TRANSFORM, \ | ||||
|                    (msg), (param)                     \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidTransfromStatusError: | ||||
|  * @transform:          the transform. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid transform status errors. | ||||
|  */ | ||||
| #define xmlSecInvalidTransfromStatusError(transform) \ | ||||
|     {                                                 \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)xmlSecTransformGetName(transform), \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_STATUS,    \ | ||||
|                    "transformStatus=%d",              \ | ||||
|                    (int)((transform)->status)         \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidTransfromStatusError2: | ||||
|  * @transform:          the transform. | ||||
|  * @msg:                the extra message. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting an invalid transform status errors. | ||||
|  */ | ||||
| #define xmlSecInvalidTransfromStatusError2(transform, msg) \ | ||||
|     {                                                 \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,               \ | ||||
|                    (const char*)xmlSecTransformGetName(transform), \ | ||||
|                    NULL,                              \ | ||||
|                    XMLSEC_ERRORS_R_INVALID_STATUS,    \ | ||||
|                    "transformStatus=%ld, msg=%s",     \ | ||||
|                    (long int)((transform)->status),   \ | ||||
|                    msg                                \ | ||||
|         );                                            \ | ||||
|     } | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidKeyDataSizeError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @actual:             the actual value. | ||||
|  * @expected:           the expected value(s). | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid keydata size" errors. | ||||
|  */ | ||||
| #define xmlSecInvalidKeyDataSizeError(actual, expected, errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,  \ | ||||
|                     "invalid key data size: actual=%ld and expected=%ld", \ | ||||
|                     (unsigned long)(actual),                \ | ||||
|                     (unsigned long)(expected)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecInvalidZeroKeyDataSizeError: | ||||
|  * @name:               the name of the variable, parameter, etc. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting "invalid keydata size" errors. | ||||
|  */ | ||||
| #define xmlSecInvalidZeroKeyDataSizeError(errorObject) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,  \ | ||||
|                     "invalid zero key data size"            \ | ||||
|         ) | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * xmlSecOtherError: | ||||
|  * @code:               the error code. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @details:            the error message. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting other XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecOtherError(code, errorObject, details) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     (code),                                 \ | ||||
|                     "details=%s",                           \ | ||||
|                     xmlSecErrorsSafeString(details)         \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecOtherError2: | ||||
|  * @code:               the error code. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param:              the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting other XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecOtherError2(code, errorObject, msg, param) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     (code),                                 \ | ||||
|                     (msg), (param)                          \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecOtherError3: | ||||
|  * @code:               the error code. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param1:             the extra message param. | ||||
|  * @param2:             the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting other XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecOtherError3(code, errorObject, msg, param1, param2) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     (code),                                 \ | ||||
|                     (msg), (param1), (param2)               \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecOtherError4: | ||||
|  * @code:               the error code. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param1:             the extra message param. | ||||
|  * @param2:             the extra message param. | ||||
|  * @param3:             the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting other XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecOtherError4(code, errorObject, msg, param1, param2, param3) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     (code),                                 \ | ||||
|                     (msg), (param1), (param2), (param3)     \ | ||||
|         ) | ||||
|  | ||||
| /** | ||||
|  * xmlSecOtherError5: | ||||
|  * @code:               the error code. | ||||
|  * @errorObject:        the error specific error object (e.g. transform, key data, etc). | ||||
|  * @msg:                the extra message. | ||||
|  * @param1:             the extra message param. | ||||
|  * @param2:             the extra message param. | ||||
|  * @param3:             the extra message param. | ||||
|  * @param4:             the extra message param. | ||||
|  * | ||||
|  * Macro. The XMLSec library macro for reporting other XMLSec errors. | ||||
|  */ | ||||
| #define xmlSecOtherError5(code, errorObject, msg, param1, param2, param3, param4) \ | ||||
|         xmlSecError(XMLSEC_ERRORS_HERE,                     \ | ||||
|                     (const char*)(errorObject),             \ | ||||
|                     NULL,                                   \ | ||||
|                     (code),                                 \ | ||||
|                     (msg), (param1), (param2), (param3), (param4) \ | ||||
|         ) | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif /* __cplusplus */ | ||||
|  | ||||
| #endif /* __XMLSEC_ERROR_HELPERS_H__ */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,200 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <Invoice xmlns="http://www.dian.gov.co/contratos/facturaelectronica/v1" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cdt="urn:DocumentInformation:names:specification:ubl:colombia:schema:xsd:DocumentInformationAggregateComponents-1" xmlns:clm54217="urn:un:unece:uncefact:codelist:specification:54217:2001" xmlns:clmIANAMIMEMediaType="urn:un:unece:uncefact:codelist:specification:IANAMIMEMediaType:2003" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" xmlns:sts="http://www.dian.gov.co/contratos/facturaelectronica/v1/Structures" xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:sig="http://www.w3.org/2000/09/xmldsig#"> | ||||
|   <ext:UBLExtensions> | ||||
|     <ext:UBLExtension> | ||||
|       <ext:ExtensionContent> | ||||
|         <sts:DianExtensions> | ||||
|           <sts:SoftwareSecurityCode schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195">2bd9a18f23cf1188d36888d218e9b0c31df77aa00bc036eaeaa1619184054237eee56d2d8db4ecab0173f65f8dab7753</sts:SoftwareSecurityCode> | ||||
|           <sts:AuthorizationProvider> | ||||
|             <sts:AuthorizationProviderID schemeID="4" schemeName="31" schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195">800197268</sts:AuthorizationProviderID> | ||||
|           </sts:AuthorizationProvider> | ||||
|           <sts:SoftwareProvider> | ||||
|             <sts:ProviderID schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195" schemeID="5" schemaName="31">900579212</sts:ProviderID> | ||||
|             <sts:SoftwareID schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195">01ab9caa-6838-461e-82fb-da44da36a084</sts:SoftwareID> | ||||
|           </sts:SoftwareProvider> | ||||
|           <sts:InvoiceSource> | ||||
|             <cbc:IdentificationCode>CO</cbc:IdentificationCode> | ||||
|           </sts:InvoiceSource> | ||||
|           <sts:InvoiceControl> | ||||
|             <sts:InvoiceAuthorization>fc8eac422eba16e22ffd8c6f94b3f40a6e38162c</sts:InvoiceAuthorization> | ||||
|             <sts:AuthorizationPeriod> | ||||
|               <cbc:StartDate>2019-01-19</cbc:StartDate> | ||||
|               <cbc:EndDate>2030-01-19</cbc:EndDate> | ||||
|             </sts:AuthorizationPeriod> | ||||
|             <sts:AuthorizedInvoices> | ||||
|               <sts:Prefix>SETP</sts:Prefix> | ||||
|               <sts:From>990000000</sts:From> | ||||
|               <sts:To>995000000</sts:To> | ||||
|             </sts:AuthorizedInvoices> | ||||
|           </sts:InvoiceControl> | ||||
|         </sts:DianExtensions> | ||||
|       </ext:ExtensionContent> | ||||
|     </ext:UBLExtension> | ||||
|   </ext:UBLExtensions> | ||||
|   <cbc:UBLVersionID>UBL 2.1</cbc:UBLVersionID> | ||||
|   <cbc:CustomizationID>10</cbc:CustomizationID> | ||||
|   <cbc:ProfileID>DIAN 2.1</cbc:ProfileID> | ||||
|   <cbc:ProfileExecutionID>2</cbc:ProfileExecutionID> | ||||
|   <cbc:ID>SETP990000001</cbc:ID> | ||||
|   <cbc:UUID schemeID="2" schemeName="CUFE-SHA384">50578625ce1fb2f6bb2bc57b22180d2763c8a868c4e62da72e0e43001f9c7f3459c81e2bf9324830175b1225af37e435</cbc:UUID> | ||||
|   <cbc:DocumentCurrencyCode>COP</cbc:DocumentCurrencyCode> | ||||
|   <cbc:IssueDate>2020-09-05</cbc:IssueDate> | ||||
|   <cbc:IssueTime>22:38:53-05:00</cbc:IssueTime> | ||||
|   <cbc:InvoiceTypeCode listAgencyID="195" listAgencyName="No matching global declaration available for the validation root" listURI="http://www.dian.gov.co">01</cbc:InvoiceTypeCode> | ||||
|   <cbc:LineCountNumeric>1</cbc:LineCountNumeric> | ||||
|   <cac:InvoicePeriod> | ||||
|     <cbc:StartDate>2020-09-05</cbc:StartDate> | ||||
|     <cbc:EndDate>2020-09-05</cbc:EndDate> | ||||
|   </cac:InvoicePeriod> | ||||
|   <cac:AccountingSupplierParty> | ||||
|     <cbc:AdditionalAccountID>1</cbc:AdditionalAccountID> | ||||
|     <cac:Party> | ||||
|       <cac:PartyName> | ||||
|         <cbc:Name>NEUROTEC TECNOLOGIA S.A.S</cbc:Name> | ||||
|       </cac:PartyName> | ||||
|       <cac:PhysicalLocation> | ||||
|         <cac:Address> | ||||
|           <cac:AddressLine> | ||||
|             <cbc:Line/> | ||||
|           </cac:AddressLine> | ||||
|         </cac:Address> | ||||
|       </cac:PhysicalLocation> | ||||
|       <cac:PartyLegalEntity> | ||||
|         <cbc:CompanyID schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195" schemeID="5" schemeName="31">900579212</cbc:CompanyID> | ||||
|         <cbc:RegistrationName>NEUROTEC TECNOLOGIA S.A.S</cbc:RegistrationName> | ||||
|         <cac:RegistrationAddress> | ||||
|           <cbc:CityName/> | ||||
|           <cac:AddressLine> | ||||
|             <cbc:Line/> | ||||
|           </cac:AddressLine> | ||||
|           <cac:Country> | ||||
|             <cbc:IdentificationCode>CO</cbc:IdentificationCode> | ||||
|             <cbc:Name>COLOMBIA</cbc:Name> | ||||
|           </cac:Country> | ||||
|         </cac:RegistrationAddress> | ||||
|       </cac:PartyLegalEntity> | ||||
|       <cac:PartyTaxScheme> | ||||
|         <cbc:RegistrationName>NEUROTEC TECNOLOGIA S.A.S</cbc:RegistrationName> | ||||
|         <cbc:CompanyID schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195" schemeID="5" schemeName="31">900579212</cbc:CompanyID> | ||||
|         <cbc:TaxLevelCode listName="48">O-07;O-09;O-14;O-48</cbc:TaxLevelCode> | ||||
|         <cac:TaxScheme/> | ||||
|       </cac:PartyTaxScheme> | ||||
|       <cac:Contact> | ||||
|         <cbc:ElectronicMail>sdds@sd.com</cbc:ElectronicMail> | ||||
|       </cac:Contact> | ||||
|     </cac:Party> | ||||
|   </cac:AccountingSupplierParty> | ||||
|   <cac:AccountingCustomerParty> | ||||
|     <cbc:AdditionalAccountID>2</cbc:AdditionalAccountID> | ||||
|     <cac:Party> | ||||
|       <cac:PartyName> | ||||
|         <cbc:Name>facho-customer</cbc:Name> | ||||
|       </cac:PartyName> | ||||
|       <cac:PhysicalLocation> | ||||
|         <cac:Address> | ||||
|           <cac:AddressLine> | ||||
|             <cbc:Line/> | ||||
|           </cac:AddressLine> | ||||
|         </cac:Address> | ||||
|       </cac:PhysicalLocation> | ||||
|       <cac:PartyTaxScheme> | ||||
|         <cbc:CompanyID schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195" schemeID="" schemeName="13">43851425</cbc:CompanyID> | ||||
|         <cbc:RegistrationName>facho-customer</cbc:RegistrationName> | ||||
|         <cbc:TaxLevelCode>ZZ</cbc:TaxLevelCode> | ||||
|         <cac:TaxScheme/> | ||||
|       </cac:PartyTaxScheme> | ||||
|       <cac:PartyLegalEntity> | ||||
|         <cbc:RegistrationName>facho-customer</cbc:RegistrationName> | ||||
|         <cac:RegistrationAddress> | ||||
|           <cbc:CityName/> | ||||
|           <cac:AddressLine> | ||||
|             <cbc:Line/> | ||||
|           </cac:AddressLine> | ||||
|           <cac:Country> | ||||
|             <cbc:IdentificationCode>CO</cbc:IdentificationCode> | ||||
|             <cbc:Name>COLOMBIA</cbc:Name> | ||||
|           </cac:Country> | ||||
|         </cac:RegistrationAddress> | ||||
|       </cac:PartyLegalEntity> | ||||
|     </cac:Party> | ||||
|   </cac:AccountingCustomerParty> | ||||
|   <cac:LegalMonetaryTotal> | ||||
|     <cbc:LineExtensionAmount currencyID="COP">100.00</cbc:LineExtensionAmount> | ||||
|     <cbc:TaxExclusiveAmount currencyID="COP">100.00</cbc:TaxExclusiveAmount> | ||||
|     <cbc:TaxInclusiveAmount currencyID="COP">119.00</cbc:TaxInclusiveAmount> | ||||
|     <cbc:ChargeTotalAmount currencyID="COP">19.00</cbc:ChargeTotalAmount> | ||||
|     <cbc:PayableAmount currencyID="COP">119.00</cbc:PayableAmount> | ||||
|   </cac:LegalMonetaryTotal> | ||||
|   <cac:TaxTotal/> | ||||
|   <cac:TaxTotal> | ||||
|     <cac:TaxSubtotal> | ||||
|       <cac:TaxCategory> | ||||
|         <cac:TaxScheme> | ||||
|           <cbc:ID>01</cbc:ID> | ||||
|         </cac:TaxScheme> | ||||
|       </cac:TaxCategory> | ||||
|     </cac:TaxSubtotal> | ||||
|     <cbc:TaxAmount>19.00</cbc:TaxAmount> | ||||
|   </cac:TaxTotal> | ||||
|   <cac:TaxTotal> | ||||
|     <cac:TaxSubtotal> | ||||
|       <cac:TaxCategory> | ||||
|         <cac:TaxScheme> | ||||
|           <cbc:ID>04</cbc:ID> | ||||
|         </cac:TaxScheme> | ||||
|       </cac:TaxCategory> | ||||
|     </cac:TaxSubtotal> | ||||
|     <cbc:TaxAmount>0.00</cbc:TaxAmount> | ||||
|   </cac:TaxTotal> | ||||
|   <cac:TaxTotal> | ||||
|     <cac:TaxSubtotal> | ||||
|       <cac:TaxCategory> | ||||
|         <cac:TaxScheme> | ||||
|           <cbc:ID>03</cbc:ID> | ||||
|         </cac:TaxScheme> | ||||
|       </cac:TaxCategory> | ||||
|     </cac:TaxSubtotal> | ||||
|     <cbc:TaxAmount>0.00</cbc:TaxAmount> | ||||
|   </cac:TaxTotal> | ||||
|   <cac:InvoiceLine> | ||||
|     <cbc:ID>1</cbc:ID> | ||||
|     <cbc:InvoicedQuantity unitCode="NAR">1</cbc:InvoicedQuantity> | ||||
|     <cbc:LineExtensionAmount currencyID="COP">100.0</cbc:LineExtensionAmount> | ||||
|     <cac:TaxTotal> | ||||
|       <cbc:TaxAmount currencyID="COP">19.0</cbc:TaxAmount> | ||||
|       <cac:TaxSubtotal> | ||||
|         <cbc:TaxableAmount currencyID="COP">100.0</cbc:TaxableAmount> | ||||
|         <cbc:TaxAmount currencyID="COP">19.0</cbc:TaxAmount> | ||||
|         <cac:TaxCategory> | ||||
|           <cbc:Percent>19.0</cbc:Percent> | ||||
|           <cac:TaxScheme> | ||||
|             <cbc:ID>01</cbc:ID> | ||||
|             <cbc:Name>IVA</cbc:Name> | ||||
|           </cac:TaxScheme> | ||||
|         </cac:TaxCategory> | ||||
|       </cac:TaxSubtotal> | ||||
|     </cac:TaxTotal> | ||||
|     <cac:PricingReference> | ||||
|       <cac:AlternativeConditionPrice> | ||||
|         <cbc:PriceAmount currencyID="COP">100.0</cbc:PriceAmount> | ||||
|         <cbc:PriceTypeCode>01</cbc:PriceTypeCode> | ||||
|         <cbc:PriceType>x</cbc:PriceType> | ||||
|       </cac:AlternativeConditionPrice> | ||||
|     </cac:PricingReference> | ||||
|     <cac:Item> | ||||
|       <cbc:Description>test</cbc:Description> | ||||
|       <cac:StandardItemIdentification> | ||||
|         <cbc:ID>9999</cbc:ID> | ||||
|       </cac:StandardItemIdentification> | ||||
|     </cac:Item> | ||||
|     <cac:Price> | ||||
|       <cbc:PriceAmount currencyID="COP">100.0</cbc:PriceAmount> | ||||
|     </cac:Price> | ||||
|   </cac:InvoiceLine> | ||||
|   <cac:PaymentMeans> | ||||
|     <cbc:ID>1</cbc:ID> | ||||
|     <cbc:PaymentMeansCode>10</cbc:PaymentMeansCode> | ||||
|     <cbc:PaymentDueDate>2020-09-05</cbc:PaymentDueDate> | ||||
|     <cbc:PaymentID>1</cbc:PaymentID> | ||||
|   </cac:PaymentMeans> | ||||
| </Invoice> | ||||
| @@ -1,7 +0,0 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| set -ex | ||||
|  | ||||
| sh build_openssl.sh | ||||
| sh build_libxml2.sh | ||||
| sh build_xmlsec.sh | ||||
| @@ -1,21 +0,0 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| LIBXML2_VERSION=2.9.12 | ||||
|  | ||||
| tar xf libxml2-${LIBXML2_VERSION}.tar.gz | ||||
|  | ||||
| mv libxml2-${LIBXML2_VERSION} libxml2 | ||||
|  | ||||
| pushd libxml2 | ||||
|  | ||||
| wasiconfigure  ./configure --enable-static --without-http --without-ftp --without-modules --without-python --without-zlib --without-lzma --without-threads --host=x86_64 | ||||
|  | ||||
| wasimake make clean | ||||
| wasimake make -j4 | ||||
|  | ||||
| popd | ||||
|  | ||||
| mkdir -p vendor/libxml2/lib | ||||
| mkdir -p vendor/libxml2/include | ||||
| cp -r libxml2/include/libxml2 vendor/libxml2/include | ||||
| cp -r libxml2/.libs/libxml2.a vendor/libxml2/lib | ||||
| @@ -1,41 +0,0 @@ | ||||
| #!/bin/sh | ||||
| # TOMADO DE: https://github.com/voltbuilder/openssl-wasm | ||||
|  | ||||
| OPENSSL_VERSION=1.1.1l | ||||
|  | ||||
| # get the source | ||||
| tar xf openssl-${OPENSSL_VERSION}.tar.gz | ||||
|  | ||||
| patch -p0 < openssl-${OPENSSL_VERSION}.patch | ||||
|  | ||||
| cd openssl-${OPENSSL_VERSION} | ||||
| make clean | ||||
|  | ||||
| set -e | ||||
|  | ||||
| # why ./Configure instead of ./config? We want to force using the generic gcc profile which is more conservative than linux-x32 | ||||
| # -no-sock - we don't have sockets in WASI | ||||
| # new -no-ui-console - sdk 12 has no termios??? | ||||
| # check in 12 -DHAVE_FORK=0 - no fork() in WASI | ||||
| # new -D_WASI_EMULATED_MMAN - works with the library below to enable WASI mman emulation | ||||
| # new -D_WASI_EMULATED_SIGNAL - with sdk 12 | ||||
| # new -DOPENSSL_NO_SECURE_MEMORY - wasi doesn't have secure mem (madvise, mlock, etc...) | ||||
| # new -DNO_SYSLOG - get rid of need for patch above | ||||
| # --with-rand-seed=getrandom (needed to force using getentropy because WASI has no /dev/random or getrandom) | ||||
| wasiconfigure ./Configure gcc -no-sock -no-ui-console -DHAVE_FORK=0 -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_SIGNAL -DOPENSSL_NO_SECURE_MEMORY -DNO_SYSLOG --with-rand-seed=getrandom | ||||
|  | ||||
| # enables stuff from mman.h (see define above) also add -lwasi-emulated-signal | ||||
| #sed -i -e "s/CNF_EX_LIBS=/CNF_EX_LIBS=-lwasi-emulated-mman -lwasi-emulated-signal /g" Makefile | ||||
|  | ||||
| # build! | ||||
| wasimake make -j4 build_generated libssl.a libcrypto.a | ||||
|  | ||||
| rm -rf ../vendor/openssl/include | ||||
| mkdir -p ../vendor/openssl/include | ||||
| cp -R include/openssl ../vendor/openssl/include | ||||
|  | ||||
| mkdir -p ../vendor/openssl/lib/ | ||||
| cp libssl.a ../vendor/openssl/lib/ | ||||
| cp libcrypto.a ../vendor/openssl/lib/ | ||||
|  | ||||
| exit 0 | ||||
| @@ -1,14 +0,0 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| XMLSEC1_VERSION=1.2.33 | ||||
|  | ||||
| tar xf xmlsec1-${XMLSEC1_VERSION}.tar.gz | ||||
|  | ||||
| cd xmlsec1-${XMLSEC1_VERSION} | ||||
|  | ||||
| cp -r ../libxml2 . | ||||
| cp -r ../vendor . | ||||
|  | ||||
| wasiconfigure ./configure --with-libxml-src=`pwd`/libxml2 --with-openssl=`pwd`/vendor/openssl  --enable-static-linking  --disable-folders-search --disable-apps --disable-apps-crypto-dl --disable-crypto-dl | ||||
|  | ||||
| wasimake make -j4 | ||||
| @@ -1,6 +0,0 @@ | ||||
| # ejemplo | ||||
|  | ||||
| ~~~ | ||||
| $ bash build.sh | ||||
| $ wasirun ./a.out sign1-tmpl.xml example.key | ||||
| ~~~ | ||||
| @@ -1,12 +0,0 @@ | ||||
| cp ../vendor/openssl/lib/*.a . | ||||
| cp ../xmlsec1-1.2.33/src/.libs/*.a . | ||||
| cp ../xmlsec1-1.2.33/src/openssl/.libs/*.a . | ||||
| cp ../libxml2/.libs/libxml2.a . | ||||
|  | ||||
| mkdir -p include | ||||
|  | ||||
| cp -r ../libxml2/include/libxml include/ | ||||
| cp -r ../xmlsec1-1.2.33/include/xmlsec include/ | ||||
| cp -r ../vendor/openssl/include/* include/ | ||||
|  | ||||
| wasicc -Iinclude libxml2.a libcrypto.a libssl.a libxmlsec1.a libxmlsec1-openssl.a sign.c  | ||||
| @@ -1,216 +0,0 @@ | ||||
| /**  | ||||
|  * XML Security Library example: Signing a template file. | ||||
|  *  | ||||
|  * Signs a template file using a key from PEM file | ||||
|  *  | ||||
|  * Usage:  | ||||
|  *      ./sign1 <xml-tmpl> <pem-key>  | ||||
|  * | ||||
|  * Example: | ||||
|  *      ./sign1 sign1-tmpl.xml rsakey.pem > sign1-res.xml | ||||
|  * | ||||
|  * The result signature could be validated using verify1 example: | ||||
|  *      ./verify1 sign1-res.xml rsapub.pem | ||||
|  * | ||||
|  * This is free software; see Copyright file in the source | ||||
|  * distribution for preciese wording. | ||||
|  *  | ||||
|  * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
|  | ||||
| #include <libxml/tree.h> | ||||
| #include <libxml/xmlmemory.h> | ||||
| #include <libxml/parser.h> | ||||
|  | ||||
| #define XMLSEC_NO_XSLT | ||||
| #define XMLSEC_CRYPTO_OPENSSL | ||||
|  | ||||
| #ifndef XMLSEC_NO_XSLT | ||||
| #include <libxslt/xslt.h> | ||||
| #include <libxslt/security.h> | ||||
| #endif /* XMLSEC_NO_XSLT */ | ||||
|  | ||||
| #include <xmlsec/xmlsec.h> | ||||
| #include <xmlsec/xmltree.h> | ||||
| #include <xmlsec/xmldsig.h> | ||||
| #include <xmlsec/crypto.h> | ||||
|  | ||||
| int sign_file(const char* tmpl_file, const char* key_file); | ||||
|  | ||||
| int  | ||||
| main(int argc, char **argv) { | ||||
| #ifndef XMLSEC_NO_XSLT | ||||
|     xsltSecurityPrefsPtr xsltSecPrefs = NULL; | ||||
| #endif /* XMLSEC_NO_XSLT */ | ||||
| 	setenv("RANDFILE", "/dev/random", 1); | ||||
|     assert(argv); | ||||
|  | ||||
|     if(argc != 3) { | ||||
|         fprintf(stderr, "Error: wrong number of arguments.\n"); | ||||
|         fprintf(stderr, "Usage: %s <tmpl-file> <key-file>\n", argv[0]); | ||||
|         return(1); | ||||
|     } | ||||
|  | ||||
|     printf("template %s key %s\n", argv[1], argv[2]); | ||||
|     /* Init libxml and libxslt libraries */ | ||||
|     xmlInitParser(); | ||||
|     LIBXML_TEST_VERSION | ||||
|     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; | ||||
|     xmlSubstituteEntitiesDefault(1); | ||||
| #ifndef XMLSEC_NO_XSLT | ||||
|     xmlIndentTreeOutput = 1;  | ||||
| #endif /* XMLSEC_NO_XSLT */ | ||||
|  | ||||
|     /* Init libxslt */ | ||||
| #ifndef XMLSEC_NO_XSLT | ||||
|     /* disable everything */ | ||||
|     xsltSecPrefs = xsltNewSecurityPrefs();  | ||||
|     xsltSetSecurityPrefs(xsltSecPrefs,  XSLT_SECPREF_READ_FILE,        xsltSecurityForbid); | ||||
|     xsltSetSecurityPrefs(xsltSecPrefs,  XSLT_SECPREF_WRITE_FILE,       xsltSecurityForbid); | ||||
|     xsltSetSecurityPrefs(xsltSecPrefs,  XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid); | ||||
|     xsltSetSecurityPrefs(xsltSecPrefs,  XSLT_SECPREF_READ_NETWORK,     xsltSecurityForbid); | ||||
|     xsltSetSecurityPrefs(xsltSecPrefs,  XSLT_SECPREF_WRITE_NETWORK,    xsltSecurityForbid); | ||||
|     xsltSetDefaultSecurityPrefs(xsltSecPrefs);  | ||||
| #endif /* XMLSEC_NO_XSLT */                 | ||||
|  | ||||
|     /* Init xmlsec library */ | ||||
|     if(xmlSecInit() < 0) { | ||||
|         fprintf(stderr, "Error: xmlsec initialization failed.\n"); | ||||
|         return(-1); | ||||
|     } | ||||
| 	puts("done xmlSecInit"); | ||||
|  | ||||
|     /* Check loaded library version */ | ||||
|     if(xmlSecCheckVersion() != 1) { | ||||
|         fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n"); | ||||
|         return(-1); | ||||
|     } | ||||
| 	puts("done xmlSecCheckVersion"); | ||||
|     /* Load default crypto engine if we are supporting dynamic | ||||
|      * loading for xmlsec-crypto libraries. Use the crypto library | ||||
|      * name ("openssl", "nss", etc.) to load corresponding  | ||||
|      * xmlsec-crypto library. | ||||
|      */ | ||||
| #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING | ||||
|     if(xmlSecCryptoDLLoadLibrary(NULL) < 0) { | ||||
|         fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n" | ||||
|                         "that you have it installed and check shared libraries path\n" | ||||
|                         "(LD_LIBRARY_PATH and/or LTDL_LIBRARY_PATH) environment variables.\n"); | ||||
|         return(-1);      | ||||
|     } | ||||
| #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */ | ||||
|  | ||||
|     /* Init crypto library */ | ||||
|     if(xmlSecCryptoAppInit(NULL) < 0) { | ||||
|         fprintf(stderr, "Error: crypto initialization failed.\n"); | ||||
|         return(-1); | ||||
|     } | ||||
| puts("done xmlSecCryptoAppInit"); | ||||
|     /* Init xmlsec-crypto library */ | ||||
|     if(xmlSecCryptoInit() < 0) { | ||||
|         fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n"); | ||||
|         return(-1); | ||||
|     } | ||||
| puts("done xmlSecCryptoInit"); | ||||
|     if(sign_file(argv[1], argv[2]) < 0) { | ||||
|         return(-1); | ||||
|     }     | ||||
|      | ||||
|     /* Shutdown xmlsec-crypto library */ | ||||
|     xmlSecCryptoShutdown(); | ||||
|      | ||||
|     /* Shutdown crypto library */ | ||||
|     xmlSecCryptoAppShutdown(); | ||||
|      | ||||
|     /* Shutdown xmlsec library */ | ||||
|     xmlSecShutdown(); | ||||
|  | ||||
|     /* Shutdown libxslt/libxml */ | ||||
| #ifndef XMLSEC_NO_XSLT | ||||
|     xsltFreeSecurityPrefs(xsltSecPrefs); | ||||
|     xsltCleanupGlobals(); | ||||
| #endif /* XMLSEC_NO_XSLT */ | ||||
|     xmlCleanupParser(); | ||||
|      | ||||
|     return(0); | ||||
| } | ||||
|  | ||||
| /**  | ||||
|  * sign_file: | ||||
|  * @tmpl_file:          the signature template file name. | ||||
|  * @key_file:           the PEM private key file name. | ||||
|  * | ||||
|  * Signs the #tmpl_file using private key from #key_file. | ||||
|  * | ||||
|  * Returns 0 on success or a negative value if an error occurs. | ||||
|  */ | ||||
| int  | ||||
| sign_file(const char* tmpl_file, const char* key_file) { | ||||
|     xmlDocPtr doc = NULL; | ||||
|     xmlNodePtr node = NULL; | ||||
|     xmlSecDSigCtxPtr dsigCtx = NULL; | ||||
|     int res = -1; | ||||
|      | ||||
|     assert(tmpl_file); | ||||
|     assert(key_file); | ||||
|  | ||||
|     /* load template */ | ||||
|     doc = xmlParseFile(tmpl_file); | ||||
|     if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){ | ||||
|         fprintf(stderr, "Error: unable to parse file \"%s\"\n", tmpl_file); | ||||
|         goto done;       | ||||
|     } | ||||
|      | ||||
|     /* find start node */ | ||||
|     node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs); | ||||
|     if(node == NULL) { | ||||
|         fprintf(stderr, "Error: start node not found in \"%s\"\n", tmpl_file); | ||||
|         goto done;       | ||||
|     } | ||||
|  | ||||
|     /* create signature context, we don't need keys manager in this example */ | ||||
|     dsigCtx = xmlSecDSigCtxCreate(NULL); | ||||
|     if(dsigCtx == NULL) { | ||||
|         fprintf(stderr,"Error: failed to create signature context\n"); | ||||
|         goto done; | ||||
|     } | ||||
|  | ||||
|     /* load private key, assuming that there is not password */ | ||||
|     dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL); | ||||
|     if(dsigCtx->signKey == NULL) { | ||||
|         fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file); | ||||
|         goto done; | ||||
|     } | ||||
|  | ||||
|     /* set key name to the file name, this is just an example! */ | ||||
|     if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) { | ||||
|         fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file); | ||||
|         goto done; | ||||
|     } | ||||
|  | ||||
|     /* sign the template */ | ||||
|     if(xmlSecDSigCtxSign(dsigCtx, node) < 0) { | ||||
|         fprintf(stderr,"Error: signature failed\n"); | ||||
|         goto done; | ||||
|     } | ||||
|          | ||||
|     /* print signed document to stdout */ | ||||
|     xmlDocDump(stdout, doc); | ||||
|      | ||||
|     /* success */ | ||||
|     res = 0; | ||||
|  | ||||
| done:     | ||||
|     /* cleanup */ | ||||
|     if(dsigCtx != NULL) { | ||||
|         xmlSecDSigCtxDestroy(dsigCtx); | ||||
|     } | ||||
|      | ||||
|     if(doc != NULL) { | ||||
|         xmlFreeDoc(doc);  | ||||
|     } | ||||
|     return(res); | ||||
| } | ||||
| @@ -1,27 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!--  | ||||
| XML Security Library example: Simple signature template file for sign1 example.  | ||||
| --> | ||||
| <Envelope xmlns="urn:envelope"> | ||||
|   <Data> | ||||
| 	Hello, World! | ||||
|   </Data> | ||||
|   <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> | ||||
|     <SignedInfo> | ||||
|       <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /> | ||||
|       <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> | ||||
|       <Reference URI=""> | ||||
|         <Transforms> | ||||
|           <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> | ||||
|         </Transforms> | ||||
|         <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> | ||||
|         <DigestValue></DigestValue> | ||||
|       </Reference> | ||||
|     </SignedInfo> | ||||
|     <SignatureValue/> | ||||
|     <KeyInfo> | ||||
| 	<KeyName/> | ||||
|     </KeyInfo> | ||||
|   </Signature> | ||||
| </Envelope> | ||||
|  | ||||
| @@ -1,199 +0,0 @@ | ||||
| diff '--color=auto' -ruN openssl-1.1.1l/crypto/rand/rand_unix.c patch-1.1.1l/crypto/rand/rand_unix.c | ||||
| --- openssl-1.1.1l/crypto/rand/rand_unix.c	2021-08-24 09:38:47.000000000 -0400 | ||||
| +++ patch-1.1.1l/crypto/rand/rand_unix.c	2021-09-12 02:26:35.765347423 -0400 | ||||
| @@ -372,36 +372,36 @@ | ||||
|       * Note: Sometimes getentropy() can be provided but not implemented | ||||
|       * internally. So we need to check errno for ENOSYS | ||||
|       */ | ||||
| -#  if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) | ||||
| -    extern int getentropy(void *buffer, size_t length) __attribute__((weak)); | ||||
| +/* #  if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) */ | ||||
| +/*     extern int getentropy(void *buffer, size_t length) __attribute__((weak)); */ | ||||
|   | ||||
| -    if (getentropy != NULL) { | ||||
| +/*     if (getentropy != NULL) { */ | ||||
|          if (getentropy(buf, buflen) == 0) | ||||
|              return (ssize_t)buflen; | ||||
|          if (errno != ENOSYS) | ||||
|              return -1; | ||||
| -    } | ||||
| -#  elif defined(__APPLE__) | ||||
| -    if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess) | ||||
| -	    return (ssize_t)buflen; | ||||
| - | ||||
| -    return -1; | ||||
| -#  else | ||||
| -    union { | ||||
| -        void *p; | ||||
| -        int (*f)(void *buffer, size_t length); | ||||
| -    } p_getentropy; | ||||
| - | ||||
| -    /* | ||||
| -     * We could cache the result of the lookup, but we normally don't | ||||
| -     * call this function often. | ||||
| -     */ | ||||
| -    ERR_set_mark(); | ||||
| -    p_getentropy.p = DSO_global_lookup("getentropy"); | ||||
| -    ERR_pop_to_mark(); | ||||
| -    if (p_getentropy.p != NULL) | ||||
| -        return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1; | ||||
| -#  endif | ||||
| +/*     } */ | ||||
| +/* #  elif defined(__APPLE__) */ | ||||
| +/*     if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess) */ | ||||
| +/* 	    return (ssize_t)buflen; */ | ||||
| + | ||||
| +/*     return -1; */ | ||||
| +/* #  else */ | ||||
| +/*     union { */ | ||||
| +/*         void *p; */ | ||||
| +/*         int (*f)(void *buffer, size_t length); */ | ||||
| +/*     } p_getentropy; */ | ||||
| + | ||||
| +/*     /\* */ | ||||
| +/*      * We could cache the result of the lookup, but we normally don't */ | ||||
| +/*      * call this function often. */ | ||||
| +/*      *\/ */ | ||||
| +/*     ERR_set_mark(); */ | ||||
| +/*     p_getentropy.p = DSO_global_lookup("getentropy"); */ | ||||
| +/*     ERR_pop_to_mark(); */ | ||||
| +/*     if (p_getentropy.p != NULL) */ | ||||
| +/*         return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1; */ | ||||
| +/* #  endif */ | ||||
|   | ||||
|      /* Linux supports this since version 3.17 */ | ||||
|  #  if defined(__linux) && defined(__NR_getrandom) | ||||
| @@ -635,12 +635,12 @@ | ||||
|   */ | ||||
|  size_t rand_pool_acquire_entropy(RAND_POOL *pool) | ||||
|  { | ||||
| -#  if defined(OPENSSL_RAND_SEED_NONE) | ||||
| -    return rand_pool_entropy_available(pool); | ||||
| -#  else | ||||
| +/* #  if defined(OPENSSL_RAND_SEED_NONE) */ | ||||
| +/*     return rand_pool_entropy_available(pool); */ | ||||
| +/* #  else */ | ||||
|      size_t entropy_available; | ||||
|   | ||||
| -#   if defined(OPENSSL_RAND_SEED_GETRANDOM) | ||||
| +/* #   if defined(OPENSSL_RAND_SEED_GETRANDOM) */ | ||||
|      { | ||||
|          size_t bytes_needed; | ||||
|          unsigned char *buffer; | ||||
| @@ -664,7 +664,7 @@ | ||||
|      entropy_available = rand_pool_entropy_available(pool); | ||||
|      if (entropy_available > 0) | ||||
|          return entropy_available; | ||||
| -#   endif | ||||
| +/* #   endif */ | ||||
|   | ||||
|  #   if defined(OPENSSL_RAND_SEED_LIBRANDOM) | ||||
|      { | ||||
| @@ -752,7 +752,7 @@ | ||||
|  #   endif | ||||
|   | ||||
|      return rand_pool_entropy_available(pool); | ||||
| -#  endif | ||||
| +/* #  endif */ | ||||
|  } | ||||
|  # endif | ||||
|  #endif | ||||
| diff '--color=auto' -ruN openssl-1.1.1l/test/drbgtest.c patch-1.1.1l/test/drbgtest.c | ||||
| --- openssl-1.1.1l/test/drbgtest.c	2021-08-24 09:38:47.000000000 -0400 | ||||
| +++ patch-1.1.1l/test/drbgtest.c	2021-09-12 02:07:38.062332301 -0400 | ||||
| @@ -22,8 +22,21 @@ | ||||
|  # include <windows.h> | ||||
|  #endif | ||||
|   | ||||
| +#ifndef HAVE_FORK | ||||
| +# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VXWORKS) | ||||
| +#  define HAVE_FORK 0 | ||||
| +# else | ||||
| +#  define HAVE_FORK 1 | ||||
| +# endif | ||||
| +#endif | ||||
| + | ||||
| +#if HAVE_FORK | ||||
| +# undef NO_FORK | ||||
| +#else | ||||
| +# define NO_FORK | ||||
| +#endif | ||||
|   | ||||
| -#if defined(OPENSSL_SYS_UNIX) | ||||
| +#if defined(OPENSSL_SYS_UNIX) && !defined(NO_FORK) | ||||
|  # include <sys/types.h> | ||||
|  # include <sys/wait.h> | ||||
|  # include <unistd.h> | ||||
| @@ -676,7 +689,7 @@ | ||||
|  } | ||||
|   | ||||
|   | ||||
| -#if defined(OPENSSL_SYS_UNIX) | ||||
| +#if defined(OPENSSL_SYS_UNIX) && !defined(NO_FORK) | ||||
|  /* | ||||
|   * Test whether master, public and private DRBG are reseeded after | ||||
|   * forking the process. | ||||
| @@ -795,7 +808,7 @@ | ||||
|          goto error; | ||||
|      reset_drbg_hook_ctx(); | ||||
|   | ||||
| -#if defined(OPENSSL_SYS_UNIX) | ||||
| +#if defined(OPENSSL_SYS_UNIX) && !defined(NO_FORK) | ||||
|      if (!TEST_true(test_drbg_reseed_after_fork(master, public, private))) | ||||
|          goto error; | ||||
|  #endif | ||||
| diff '--color=auto' -ruN openssl-1.1.1l/test/run_tests.pl patch-1.1.1l/test/run_tests.pl | ||||
| --- openssl-1.1.1l/test/run_tests.pl	2021-08-24 09:38:47.000000000 -0400 | ||||
| +++ patch-1.1.1l/test/run_tests.pl	2021-09-12 02:03:57.603451471 -0400 | ||||
| @@ -28,7 +28,7 @@ | ||||
|  my $recipesdir = catdir($srctop, "test", "recipes"); | ||||
|  my $libdir = rel2abs(catdir($srctop, "util", "perl")); | ||||
|   | ||||
| -$ENV{OPENSSL_CONF} = catdir($srctop, "apps", "openssl.cnf"); | ||||
| +$ENV{OPENSSL_CONF} = rel2abs(catdir($srctop, "apps", "openssl.cnf")); | ||||
|   | ||||
|  my %tapargs = | ||||
|      ( verbosity => $ENV{VERBOSE} || $ENV{V} || $ENV{HARNESS_VERBOSE} ? 1 : 0, | ||||
| diff '--color=auto' -ruN openssl-1.1.1l/util/perl/OpenSSL/Test.pm patch-1.1.1l/util/perl/OpenSSL/Test.pm | ||||
| --- openssl-1.1.1l/util/perl/OpenSSL/Test.pm	2021-08-24 09:38:47.000000000 -0400 | ||||
| +++ patch-1.1.1l/util/perl/OpenSSL/Test.pm	2021-09-12 02:01:14.155136681 -0400 | ||||
| @@ -65,7 +65,7 @@ | ||||
|                               rel2abs/; | ||||
|  use File::Path 2.00 qw/rmtree mkpath/; | ||||
|  use File::Basename; | ||||
| -use Cwd qw/getcwd abs_path/; | ||||
| +use Cwd qw/abs_path/; | ||||
|   | ||||
|  my $level = 0; | ||||
|   | ||||
| @@ -904,26 +904,26 @@ | ||||
|      BAIL_OUT("Must run setup() first") if (! $test_name); | ||||
|   | ||||
|      my $f = pop; | ||||
| -    return abs2rel(catfile($directories{SRCTOP},@_,$f),getcwd); | ||||
| +    return catfile($directories{SRCTOP},@_,$f); | ||||
|  } | ||||
|   | ||||
|  sub __srctop_dir { | ||||
|      BAIL_OUT("Must run setup() first") if (! $test_name); | ||||
|   | ||||
| -    return abs2rel(catdir($directories{SRCTOP},@_), getcwd); | ||||
| +    return catdir($directories{SRCTOP},@_); | ||||
|  } | ||||
|   | ||||
|  sub __bldtop_file { | ||||
|      BAIL_OUT("Must run setup() first") if (! $test_name); | ||||
|   | ||||
|      my $f = pop; | ||||
| -    return abs2rel(catfile($directories{BLDTOP},@_,$f), getcwd); | ||||
| +    return catfile($directories{BLDTOP},@_,$f); | ||||
|  } | ||||
|   | ||||
|  sub __bldtop_dir { | ||||
|      BAIL_OUT("Must run setup() first") if (! $test_name); | ||||
|   | ||||
| -    return abs2rel(catdir($directories{BLDTOP},@_), getcwd); | ||||
| +    return catdir($directories{BLDTOP},@_); | ||||
|  } | ||||
|   | ||||
|  # __exeext is a function that returns the platform dependent file extension | ||||
							
								
								
									
										98
									
								
								facho/cli.py
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								facho/cli.py
									
									
									
									
									
								
							| @@ -200,18 +200,6 @@ def validate_invoice(invoice_path): | ||||
|     XSD.validate(content, XSD.UBLInvoice) | ||||
|  | ||||
|  | ||||
| @click.command() | ||||
| @click.argument('nomina_path') | ||||
| def validate_nominaindividual(nomina_path): | ||||
|     from facho.fe.data.dian import XSD | ||||
|     content = open(nomina_path, 'r').read() | ||||
|     content = content.replace( | ||||
|         'xmlns="http://www.dian.gov.co/contratos/facturaelectronica/v1"', | ||||
|         'xmlns="dian:gov:co:facturaelectronica:NominaIndividual"', | ||||
|     ) | ||||
|     XSD.validate(content, XSD.NominaIndividual) | ||||
|  | ||||
|  | ||||
| @click.command() | ||||
| @click.option('--private-key', type=click.Path(exists=True)) | ||||
| @click.option('--passphrase') | ||||
| @@ -227,7 +215,7 @@ def sign_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy=False, | ||||
|     if use_cache_policy: | ||||
|         warnings.warn("xades using cache policy") | ||||
|  | ||||
|     signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, localpolicy=use_cache_policy) | ||||
|     signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, mockpolicy=use_cache_policy) | ||||
|     document = open(xmlfile, 'r').read().encode('utf-8') | ||||
|     with open(output, 'w') as f: | ||||
|         f.write(signer.sign_xml_string(document)) | ||||
| @@ -283,65 +271,6 @@ def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=Tr | ||||
|         else: | ||||
|             DIANWrite(xml, output) | ||||
|  | ||||
| @click.command() | ||||
| @click.option('--private-key', type=click.Path(exists=True)) | ||||
| @click.option('--passphrase') | ||||
| @click.option('--ssl/--no-ssl', default=False) | ||||
| @click.option('--sign/--no-sign', default=False) | ||||
| @click.option('--use-cache-policy/--no-use-cache-policy', default=False) | ||||
| @click.argument('scriptname', type=click.Path(exists=True), required=True) | ||||
| @click.argument('output', required=True) | ||||
| def generate_nomina(private_key, passphrase, scriptname, ssl=True, sign=False, use_cache_policy=False, output=None): | ||||
|     """ | ||||
|     imprime xml en pantalla. | ||||
|     SCRIPTNAME espera | ||||
|      def nomina() -> fe.nomina.NominaIndividual | ||||
|      def extensions(fe.nomina.NominaIndividual): -> List[facho.FachoXMLExtension] | ||||
|     """ | ||||
|  | ||||
|     if not ssl: | ||||
|         disable_ssl() | ||||
|  | ||||
|     import importlib.util | ||||
|  | ||||
|     spec = importlib.util.spec_from_file_location('nomina', scriptname) | ||||
|     module = importlib.util.module_from_spec(spec) | ||||
|     spec.loader.exec_module(module) | ||||
|  | ||||
|     from facho.fe.form_xml import DIANWriteSigned, DIANWrite | ||||
|     import facho.fe | ||||
|  | ||||
|     nomina = module.nomina() | ||||
|  | ||||
|     xml = nomina.toFachoXML() | ||||
|  | ||||
|     extensions = module.extensions(nomina) | ||||
|     for extension in extensions: | ||||
|         xml.add_extension(extension) | ||||
|  | ||||
|     if sign: | ||||
|         DIANWriteSigned(xml, output, private_key, passphrase, use_cache_policy, dian_signer=facho.fe.nomina.DianXMLExtensionSigner) | ||||
|     else: | ||||
|         DIANWrite(xml, output) | ||||
|  | ||||
| @click.command() | ||||
| @click.option('--private-key', required=True) | ||||
| @click.option('--public-key', required=True) | ||||
| @click.option('--habilitacion/--produccion', default=False) | ||||
| @click.option('--password') | ||||
| @click.argument('filename', required=True) | ||||
| @click.argument('zipfile', type=click.Path(exists=True)) | ||||
| def soap_send_nomina_sync(private_key, public_key, habilitacion, password, filename, zipfile): | ||||
|     from facho.fe.client import dian | ||||
|  | ||||
|     client = dian.DianSignatureClient(private_key, public_key, password=password) | ||||
|     req = dian.SendNominaSync | ||||
|     if habilitacion: | ||||
|         req = dian.Habilitacion.SendNominaSync | ||||
|     resp = client.request(req( | ||||
|         open(zipfile, 'rb').read() | ||||
|     )) | ||||
|     print(resp) | ||||
|  | ||||
| @click.command() | ||||
| @click.option('--private-key', type=click.Path(exists=True)) | ||||
| @@ -358,7 +287,7 @@ def sign_verify_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy | ||||
|         warnings.warn("xades using cache policy") | ||||
|  | ||||
|     print("THIS ONLY WORKS FOR DOCUMENTS GENERATE WITH FACHO") | ||||
|     signer = fe.DianXMLExtensionSignerVerifier(private_key, passphrase=passphrase, localpolicy=use_cache_policy) | ||||
|     signer = fe.DianXMLExtensionSignerVerifier(private_key, passphrase=passphrase, mockpolicy=use_cache_policy) | ||||
|     document = open(xmlfile, 'r').read().encode('utf-8') | ||||
|  | ||||
|     if signer.verify_string(document): | ||||
| @@ -366,25 +295,6 @@ def sign_verify_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy | ||||
|     else: | ||||
|         print("-INVALID") | ||||
|  | ||||
| @click.command() | ||||
| @click.option('--software-id') | ||||
| @click.option('--software-pin') | ||||
| @click.option('--nit') | ||||
| @click.option('--dv') | ||||
| @click.option('--output-zippath') | ||||
| def generate_nomina_habilitacion(software_id, software_pin, nit, dv, output_zippath): | ||||
|     from facho import fe | ||||
|  | ||||
|     generador = fe.nomina.habilitacion.Habilitacion( | ||||
|         fe.nomina.habilitacion.Habilitacion.Metadata( | ||||
|             software_id=software_id, | ||||
|             software_pin=software_pin, | ||||
|             nit=nit, | ||||
|             dv=dv | ||||
|         ) | ||||
|     ) | ||||
|     generador.generar(output_zippath) | ||||
|  | ||||
| @click.group() | ||||
| def main(): | ||||
|     pass | ||||
| @@ -400,7 +310,3 @@ main.add_command(generate_invoice) | ||||
| main.add_command(validate_invoice) | ||||
| main.add_command(sign_xml) | ||||
| main.add_command(sign_verify_xml) | ||||
| main.add_command(generate_nomina) | ||||
| main.add_command(soap_send_nomina_sync) | ||||
| main.add_command(validate_nominaindividual) | ||||
| main.add_command(generate_nomina_habilitacion) | ||||
|   | ||||
							
								
								
									
										246
									
								
								facho/facho.py
									
									
									
									
									
								
							
							
						
						
									
										246
									
								
								facho/facho.py
									
									
									
									
									
								
							| @@ -4,13 +4,6 @@ | ||||
| from lxml import etree | ||||
| from lxml.etree import Element, SubElement, tostring | ||||
| import re | ||||
| from collections import defaultdict | ||||
| from copy import deepcopy | ||||
| from pprint import pprint | ||||
|  | ||||
| class FachoValueInvalid(Exception): | ||||
|     def __init__(self, xpath): | ||||
|         super().__init__('FachoValueInvalid invalid xpath %s' % (xpath)) | ||||
|  | ||||
|  | ||||
| class FachoXMLExtension: | ||||
| @@ -89,21 +82,15 @@ class LXMLBuilder: | ||||
|     def append(self, elem, child): | ||||
|         elem.append(child) | ||||
|  | ||||
|     def append_next(self, elem, slibing): | ||||
|         elem.addnext(slibing) | ||||
|  | ||||
|     def remove(self, elem): | ||||
|         elem.getparent().remove(elem) | ||||
|  | ||||
|     def set_text(self, elem, text): | ||||
|         elem.text = text | ||||
|  | ||||
|     def xpath(self, elem, xpath, multiple=False): | ||||
|     def xpath(self, elem, xpath): | ||||
|         elems = elem.xpath(xpath, namespaces=self.nsmap) | ||||
|         if elems: | ||||
|             if multiple: | ||||
|                 return elems | ||||
|             else: | ||||
|             return elems[0] | ||||
|  | ||||
|         return None | ||||
| @@ -111,41 +98,13 @@ class LXMLBuilder: | ||||
|     def get_text(self, elem): | ||||
|         return elem.text | ||||
|  | ||||
|     def get_attribute(self, elem, key): | ||||
|         return elem.attrib[key] | ||||
|  | ||||
|     def is_attribute(self, elem, key, value): | ||||
|         return elem.get(key, False) == value | ||||
|  | ||||
|     def set_attribute(self,  elem, key, value): | ||||
|         elem.attrib[key] = value | ||||
|  | ||||
|     @classmethod | ||||
|     def remove_attributes(cls, elem, keys, exclude = []): | ||||
|         for key in keys: | ||||
|             if key in exclude: | ||||
|                 continue | ||||
|  | ||||
|             try: | ||||
|                 del elem.attrib[key] | ||||
|             except KeyError: | ||||
|                 pass | ||||
|  | ||||
|     @classmethod | ||||
|     def tostring(self, oelem, **attrs): | ||||
|         elem = deepcopy(oelem) | ||||
|  | ||||
|     def tostring(self, elem, **attrs): | ||||
|         attrs['pretty_print'] = attrs.pop('pretty_print', False) | ||||
|         attrs['encoding'] = attrs.pop('encoding', 'UTF-8') | ||||
|  | ||||
|         for el in elem.getiterator(): | ||||
|             keys = filter(lambda key: key.startswith('facho_'), el.keys()) | ||||
|             self.remove_attributes(el, keys, exclude=['facho_optional']) | ||||
|  | ||||
|             is_optional = el.get('facho_optional', 'False') == 'True' | ||||
|             if is_optional and el.getchildren() == [] and el.keys() == ['facho_optional']: | ||||
|                 el.getparent().remove(el) | ||||
|  | ||||
|         return tostring(elem, **attrs).decode('utf-8') | ||||
|  | ||||
|  | ||||
| @@ -153,7 +112,7 @@ class FachoXML: | ||||
|     """ | ||||
|     Decora XML con funciones de consulta XPATH de un solo elemento | ||||
|     """ | ||||
|     def __init__(self, root, builder=None, nsmap=None, fragment_prefix='',fragment_root_element=None): | ||||
|     def __init__(self, root, builder=None, nsmap=None, fragment_prefix=''): | ||||
|         if builder is None: | ||||
|             self.builder = LXMLBuilder(nsmap) | ||||
|         else: | ||||
| @@ -166,20 +125,15 @@ class FachoXML: | ||||
|         else: | ||||
|             self.root = root | ||||
|  | ||||
|         self.fragment_root_element = fragment_root_element | ||||
|         self.fragment_prefix = fragment_prefix | ||||
|         self.xpath_for = {} | ||||
|         self.extensions = [] | ||||
|         self._validators = defaultdict(lambda: lambda v, attrs: True) | ||||
|  | ||||
|     @classmethod | ||||
|     def from_string(cls, document: str, namespaces: dict() = []) -> 'FachoXML': | ||||
|         xml = LXMLBuilder.from_string(document) | ||||
|         return FachoXML(xml, nsmap=namespaces) | ||||
|  | ||||
|     def root_namespace(self): | ||||
|         return etree.QName(self.root).namespace | ||||
|  | ||||
|     def append_element(self, elem, new_elem): | ||||
|         #elem = self.find_or_create_element(xpath, append=append) | ||||
|         #self.builder.append(elem, new_elem) | ||||
| @@ -199,7 +153,7 @@ class FachoXML: | ||||
|  | ||||
|         if parent is None: | ||||
|             parent = self.find_or_create_element(xpath, append=append) | ||||
|         return FachoXML(parent, nsmap=self.nsmap, fragment_prefix=root_prefix, fragment_root_element=self.root) | ||||
|         return FachoXML(parent, nsmap=self.nsmap, fragment_prefix=root_prefix) | ||||
|  | ||||
|     def register_alias_xpath(self, alias, xpath): | ||||
|         self.xpath_for[alias] = xpath | ||||
| @@ -215,12 +169,8 @@ class FachoXML: | ||||
|     def _path_xpath_for(self, xpath): | ||||
|         return self._normalize_xpath(self._translate_xpath_for(xpath)) | ||||
|  | ||||
|     def placeholder_for(self, xpath, append=False, optional=False): | ||||
|         elem = self.find_or_create_element(xpath, append) | ||||
|         if optional: | ||||
|             elem.set('facho_optional', 'True') | ||||
|         elem.set('facho_placeholder', 'True') | ||||
|         return elem | ||||
|     def placeholder_for(self, xpath, append=False): | ||||
|         return self.find_or_create_element(xpath, append) | ||||
|  | ||||
|     def replacement_for(self, xpath, new_xpath, content, **attrs): | ||||
|         elem = self.get_element(xpath) | ||||
| @@ -251,12 +201,9 @@ class FachoXML: | ||||
|         # crea jerarquia segun xpath indicado | ||||
|         parent = None | ||||
|         current_elem = self.root | ||||
|         node_tag = node_paths.pop(-1) | ||||
|  | ||||
|         for node_path in node_paths: | ||||
|             node_expr = self.builder.match_expression(node_path) | ||||
|             node = self.builder.build_from_expression(node_path) | ||||
|  | ||||
|             child = self.builder.find_relative(current_elem, node_expr['path'], self.nsmap) | ||||
|  | ||||
|             parent = current_elem | ||||
| @@ -266,56 +213,14 @@ class FachoXML: | ||||
|                 self.builder.append(current_elem, node) | ||||
|                 current_elem = node | ||||
|  | ||||
|         node_expr = self.builder.match_expression(node_tag) | ||||
|         node = self.builder.build_from_expression(node_tag) | ||||
|         child = self.builder.find_relative(current_elem, node_expr['path'], self.nsmap) | ||||
|         parent = current_elem | ||||
|         if child is not None: | ||||
|             current_elem = child | ||||
|             | ||||
|         if parent == current_elem: | ||||
|             self.builder.append(parent, node) | ||||
|             return node | ||||
|  | ||||
|         # se fuerza la adicion como un nuevo elemento | ||||
|         if append: | ||||
|             last_slibing = None | ||||
|             for child in parent.getchildren(): | ||||
|                 if child.tag == node_tag: | ||||
|                     last_slibing = child | ||||
|  | ||||
|             # si no ahi primos se adiciona como hijo | ||||
|             if last_slibing is None: | ||||
|             node = self.builder.build_from_expression(node_paths[-1]) | ||||
|             self.builder.append(parent, node) | ||||
|             return node | ||||
|  | ||||
|             if self.builder.is_attribute(last_slibing, 'facho_placeholder', 'True'): | ||||
|                 self._remove_facho_attributes(last_slibing) | ||||
|                 return last_slibing  | ||||
|             self.builder.append_next(last_slibing, node) | ||||
|             return node | ||||
|  | ||||
|         if child is None: | ||||
|             self.builder.append(current_elem, node) | ||||
|             return node | ||||
|  | ||||
|         self._remove_facho_attributes(current_elem) | ||||
|         return current_elem | ||||
|  | ||||
|     def set_element_validator(self, xpath, validator = False): | ||||
|         """ | ||||
|         validador al asignar contenido a xpath indicado | ||||
|  | ||||
|         @param xpath ruta tipo XPath | ||||
|         @param validator callback(content, attributes) | ||||
|         """ | ||||
|  | ||||
|         key = self._path_xpath_for(xpath) | ||||
|         if not validator: | ||||
|             self._validators[key] = lambda v, attrs: True | ||||
|         else: | ||||
|             self._validators[key] = validator | ||||
|          | ||||
|     def set_element(self, xpath, content, **attrs): | ||||
|         """ | ||||
|         asigna contenido ubicado por ruta tipo XPATH. | ||||
| @@ -327,18 +232,10 @@ class FachoXML: | ||||
|         format_ = attrs.pop('format_', '%s') | ||||
|         append_ = attrs.pop('append_', False) | ||||
|         elem = self.find_or_create_element(xpath, append=append_) | ||||
|  | ||||
|         validator = self._validators[xpath] | ||||
|  | ||||
|         if not validator(content, attrs): | ||||
|             raise FachoValueInvalid(xpath) | ||||
|  | ||||
|         if content: | ||||
|             self.builder.set_text(elem, format_ % content) | ||||
|         for k, v in attrs.items(): | ||||
|             if v is not None or str(v) != 'None': | ||||
|                 self.builder.set_attribute(elem, k, str(v)) | ||||
|  | ||||
|             self.builder.set_attribute(elem, k, v) | ||||
|         return elem | ||||
|  | ||||
|     def set_attributes(self, xpath, **attrs): | ||||
| @@ -349,136 +246,25 @@ class FachoXML: | ||||
|         """ | ||||
|         xpath = self._path_xpath_for(xpath) | ||||
|         elem = self.get_element(xpath) | ||||
|  | ||||
|         if elem is None: | ||||
|             raise ValueError("xpath %s not found" % (xpath)) | ||||
|  | ||||
|         for k, v in attrs.items(): | ||||
|             if v is not None or str(v) != 'None': | ||||
|                 self.builder.set_attribute(elem, k, str(v)) | ||||
|             self.builder.set_attribute(elem, k, v) | ||||
|         return self | ||||
|  | ||||
|     def get_element_attribute(self, xpath, attribute, multiple=False): | ||||
|         elem = self.get_element(xpath, multiple=multiple) | ||||
|     def get_element(self, xpath): | ||||
|         xpath = self.fragment_prefix + self._path_xpath_for(xpath) | ||||
|         return self.builder.xpath(self.root, xpath) | ||||
|  | ||||
|     def get_element_text(self, xpath, format_=str): | ||||
|         xpath = self.fragment_prefix + self._path_xpath_for(xpath) | ||||
|         elem = self.builder.xpath(self.root, xpath) | ||||
|         if elem is None: | ||||
|             raise ValueError("xpath %s not found" % (xpath)) | ||||
|             raise AttributeError('xpath %s invalid' % (xpath)) | ||||
|  | ||||
|         if multiple: | ||||
|             vals = [] | ||||
|             for e in elem: | ||||
|                 vals.append(self.builder.get_attribute(e, attribute)) | ||||
|             return vals | ||||
|         else: | ||||
|             return self.builder.get_attribute(elem, attribute) | ||||
|  | ||||
|     def get_element(self, xpath, multiple=False): | ||||
|         xpath = self.fragment_prefix + self._path_xpath_for(xpath) | ||||
|         return self.builder.xpath(self.root, xpath, multiple=multiple) | ||||
|  | ||||
|     def get_element_text(self, xpath, format_=str, multiple=False): | ||||
|         xpath = self.fragment_prefix + self._path_xpath_for(xpath) | ||||
|         # MACHETE(bit4bit) al usar ./ queda ../ | ||||
|         xpath = re.sub(r'^\.\.+', '.', xpath) | ||||
|  | ||||
|         elem = self.builder.xpath(self.root, xpath, multiple=multiple) | ||||
|         if multiple: | ||||
|             vals = [] | ||||
|             for e in elem: | ||||
|                 text = self.builder.get_text(e) | ||||
|                 if text is not None: | ||||
|                     vals.append(format_(text)) | ||||
|             return vals | ||||
|         else: | ||||
|         text = self.builder.get_text(elem) | ||||
|             if text is None: | ||||
|                 return None | ||||
|         return format_(text) | ||||
|  | ||||
|     def get_element_text_or_attribute(self, xpath, default=None, multiple=False, raise_on_fail=False): | ||||
|         parts = xpath.split('/') | ||||
|         is_attribute =  parts[-1].startswith('@') | ||||
|         if is_attribute: | ||||
|             attribute_name = parts.pop(-1).lstrip('@') | ||||
|             element_path = "/".join(parts) | ||||
|             try: | ||||
|                 val = self.get_element_attribute(element_path, attribute_name, multiple=multiple) | ||||
|                 if val is None: | ||||
|                     return default | ||||
|                 return val | ||||
|             except KeyError as e: | ||||
|                 if raise_on_fail: | ||||
|                     raise e | ||||
|                 return default | ||||
|             except ValueError as e: | ||||
|                 if raise_on_fail: | ||||
|                     raise e | ||||
|                 return default | ||||
|         else: | ||||
|             try: | ||||
|                 val = self.get_element_text(xpath, multiple=multiple) | ||||
|                 if val is None: | ||||
|                     return default | ||||
|                 return val | ||||
|             except ValueError as e: | ||||
|                 if raise_on_fail: | ||||
|                     raise e | ||||
|                 return default | ||||
|  | ||||
|     def get_elements_text_or_attributes(self, xpaths, raise_on_fail=True): | ||||
|         """ | ||||
|         returna el contenido o attributos de un conjunto de XPATHS | ||||
|         si algun XPATH es una tupla se retorna el primer elemento del mismo. | ||||
|         """ | ||||
|         vals = [] | ||||
|         for xpath in xpaths: | ||||
|             if isinstance(xpath, tuple): | ||||
|                 val = xpath[0] | ||||
|             else: | ||||
|                 val = self.get_element_text_or_attribute(xpath, raise_on_fail=raise_on_fail) | ||||
|             vals.append(val) | ||||
|         return vals | ||||
|  | ||||
|     def exist_element(self, xpath): | ||||
|         elem = self.get_element(xpath) | ||||
|  | ||||
|         # no se encontro elemento | ||||
|         if elem is None: | ||||
|             return False | ||||
|  | ||||
|         # el placeholder no ha sido populado | ||||
|         if elem.get('facho_placeholder') == 'True': | ||||
|             return False | ||||
|  | ||||
|         # el valor opcional no ha sido populado | ||||
|         if elem.get('facho_optional') == 'True': | ||||
|             return False | ||||
|  | ||||
|         return True | ||||
|  | ||||
|     def _remove_facho_attributes(self, elem): | ||||
|         self.builder.remove_attributes(elem, ['facho_optional', 'facho_placeholder']) | ||||
|  | ||||
|     def tostring(self, **kw): | ||||
|         return self.builder.tostring(self.root, **kw) | ||||
|  | ||||
|     def xpath_from_root(self, xpath): | ||||
|         nsmap = {} | ||||
|         ns = '' | ||||
|  | ||||
|         root = self.root | ||||
|         if self.fragment_root_element is not None: | ||||
|             root = self.fragment_root_element | ||||
|              | ||||
|         if isinstance(self.nsmap, dict): | ||||
|             nsmap = dict(map(reversed, self.nsmap.items())) | ||||
|             ns = nsmap[etree.QName(root).namespace] + ':' | ||||
|  | ||||
|         if self.fragment_root_element is not None: | ||||
|             new_xpath = '/' + ns + etree.QName(root).localname + '/' + etree.QName(self.root).localname + '/' + xpath.lstrip('/') | ||||
|         else: | ||||
|             new_xpath = '/' + ns + etree.QName(root).localname + '/' + xpath.lstrip('/') | ||||
|         return new_xpath | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.tostring() | ||||
|   | ||||
| @@ -12,4 +12,3 @@ from .fe import DianZIP | ||||
| from .fe import AMBIENTE_PRUEBAS | ||||
| from .fe import AMBIENTE_PRODUCCION | ||||
| from . import form_xml | ||||
| from . import nomina | ||||
|   | ||||
| @@ -27,7 +27,7 @@ class SOAPService: | ||||
|     def get_service(self): | ||||
|         raise NotImplementedError() | ||||
|  | ||||
|     def build_response(self, as_dict): | ||||
|     def builder_response(self, as_dict): | ||||
|         raise NotImplementedError() | ||||
|  | ||||
|     def todict(self): | ||||
| @@ -175,19 +175,6 @@ class GetStatusZip(SOAPService): | ||||
|     def build_response(self, as_dict): | ||||
|         return GetStatusResponse.fromdict(as_dict[0]) | ||||
|  | ||||
| @dataclass | ||||
| class SendNominaSync(SOAPService): | ||||
|     contentFile: bytes | ||||
|  | ||||
|     def get_wsdl(self): | ||||
|         return 'https://vpfe.dian.gov.co/WcfDianCustomerServices.svc?wsdl' | ||||
|  | ||||
|     def get_service(self): | ||||
|         return 'SendNominaSync' | ||||
|  | ||||
|     def build_response(self, as_dict): | ||||
|         return as_dict | ||||
|  | ||||
|  | ||||
| class Habilitacion: | ||||
|     WSDL = 'https://vpfe-hab.dian.gov.co/WcfDianCustomerServices.svc?wsdl' | ||||
| @@ -216,9 +203,6 @@ class Habilitacion: | ||||
|         def get_wsdl(self): | ||||
|             return Habilitacion.WSDL | ||||
|  | ||||
|     class SendNominaSync(SendNominaSync): | ||||
|         def get_wsdl(self): | ||||
|             return Habilitacion.WSDL | ||||
|  | ||||
| class DianGateway: | ||||
|  | ||||
|   | ||||
| @@ -9,8 +9,5 @@ def path_for_xsd(dirname, xsdname): | ||||
|  | ||||
| UBLInvoice= xmlschema.XMLSchema(path_for_xsd('maindoc', 'UBL-Invoice-2.1.xsd')) | ||||
|  | ||||
| NominaIndividual = xmlschema.XMLSchema(path_for_xsd('nomina', 'NominaIndividualElectronicaXSDV1.0.6.xsd')) | ||||
| NominaIndividualDeAjuste = xmlschema.XMLSchema(path_for_xsd('nomina', 'NominaIndividualDeAjusteElectronicaXSDV1.0.6.xsd')) | ||||
|  | ||||
| def validate(xml, schema): | ||||
|     schema.validate(xml) | ||||
|   | ||||
| @@ -1,36 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- | ||||
|      creado por facho, la dian tiene oficial? | ||||
|      poblar usando anexo tecnico 5.3.1 | ||||
| --> | ||||
| <gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/"> | ||||
| 	<Identification> | ||||
| 		<ShortName>Idioma</ShortName> | ||||
| 		<LongName xml:lang="es">Idioma</LongName> | ||||
| 		<Version>1</Version> | ||||
| 	</Identification> | ||||
| 	<ColumnSet> | ||||
| 		<Column Id="iso-639-1" Use="required"> | ||||
| 			<ShortName>ISO 639 1</ShortName> | ||||
| 			<Data Type="normalizedString"/> | ||||
| 		</Column> | ||||
| 		<Column Id="name" Use="required"> | ||||
| 			<ShortName>Nombre</ShortName> | ||||
| 			<Data Type="normalizedString"/> | ||||
| 		</Column> | ||||
| 		<Key Id="codeKey"> | ||||
| 			<ShortName>CodeKey</ShortName> | ||||
| 			<ColumnRef Ref="code"/> | ||||
| 		</Key> | ||||
| 	</ColumnSet> | ||||
| 	<SimpleCodeList> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="iso-639-1"> | ||||
| 				<SimpleValue>es</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Español, castellano</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
|         </SimpleCodeList> | ||||
| </gc:CodeList> | ||||
| @@ -1,76 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- | ||||
|      creado por facho, la dian tiene oficial? | ||||
|      poblar usando anexo tecnico 5.5.1 | ||||
| --> | ||||
| <gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/"> | ||||
| 	<Identification> | ||||
| 		<ShortName>PeriodoNomina</ShortName> | ||||
| 		<LongName xml:lang="es">Periodos Nomina</LongName> | ||||
| 		<Version>1</Version> | ||||
| 	</Identification> | ||||
| 	<ColumnSet> | ||||
| 		<Column Id="code" Use="required"> | ||||
| 			<ShortName>Code</ShortName> | ||||
| 			<Data Type="normalizedString"/> | ||||
| 		</Column> | ||||
| 		<Column Id="name" Use="required"> | ||||
| 			<ShortName>Nombre</ShortName> | ||||
| 			<Data Type="normalizedString"/> | ||||
| 		</Column> | ||||
| 		<Key Id="codeKey"> | ||||
| 			<ShortName>CodeKey</ShortName> | ||||
| 			<ColumnRef Ref="code"/> | ||||
| 		</Key> | ||||
| 	</ColumnSet> | ||||
| 	<SimpleCodeList> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>1</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Semanal</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>2</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Decenal</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>3</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Catorcenal</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>4</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Quincenal</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>5</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Mensual</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>6</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Otro</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
|         </SimpleCodeList> | ||||
| </gc:CodeList> | ||||
| @@ -1,44 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- | ||||
|      creado por facho, la dian tiene oficial? | ||||
|      poblar usando anexo tecnico 5.5.4 | ||||
| --> | ||||
| <gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/"> | ||||
| 	<Identification> | ||||
| 		<ShortName>SubTipoTrabajador</ShortName> | ||||
| 		<LongName xml:lang="es">Sub tipos de trabajador</LongName> | ||||
| 		<Version>1</Version> | ||||
| 	</Identification> | ||||
| 	<ColumnSet> | ||||
| 		<Column Id="code" Use="required"> | ||||
| 			<ShortName>Code</ShortName> | ||||
| 			<Data Type="normalizedString"/> | ||||
| 		</Column> | ||||
| 		<Column Id="name" Use="required"> | ||||
| 			<ShortName>Nombre</ShortName> | ||||
| 			<Data Type="normalizedString"/> | ||||
| 		</Column> | ||||
| 		<Key Id="codeKey"> | ||||
| 			<ShortName>CodeKey</ShortName> | ||||
| 			<ColumnRef Ref="code"/> | ||||
| 		</Key> | ||||
| 	</ColumnSet> | ||||
| 	<SimpleCodeList> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>00</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>No Aplica</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>01</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Dependiente pensionado por vejez activo</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
|         </SimpleCodeList> | ||||
| </gc:CodeList> | ||||
| @@ -1,68 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- | ||||
|      creado por facho, la dian tiene oficial? | ||||
|      poblar usando anexo tecnico 5.5.2 | ||||
| --> | ||||
| <gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/"> | ||||
| 	<Identification> | ||||
| 		<ShortName>TipoContrato</ShortName> | ||||
| 		<LongName xml:lang="es">Tipos de contratos</LongName> | ||||
| 		<Version>1</Version> | ||||
| 	</Identification> | ||||
| 	<ColumnSet> | ||||
| 		<Column Id="code" Use="required"> | ||||
| 			<ShortName>Code</ShortName> | ||||
| 			<Data Type="normalizedString"/> | ||||
| 		</Column> | ||||
| 		<Column Id="name" Use="required"> | ||||
| 			<ShortName>Nombre</ShortName> | ||||
| 			<Data Type="normalizedString"/> | ||||
| 		</Column> | ||||
| 		<Key Id="codeKey"> | ||||
| 			<ShortName>CodeKey</ShortName> | ||||
| 			<ColumnRef Ref="code"/> | ||||
| 		</Key> | ||||
| 	</ColumnSet> | ||||
| 	<SimpleCodeList> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>1</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Termino Fijo</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>2</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Término Indefinido</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>3</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Obra o Labor</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>4</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Aprendizaje</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>5</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Pŕacticas o Pasantías</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
|         </SimpleCodeList> | ||||
| </gc:CodeList> | ||||
| @@ -1,156 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- | ||||
|      creado por facho, la dian tiene oficial? | ||||
|      poblar usando anexo tecnico 5.5.3 | ||||
| --> | ||||
| <gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/"> | ||||
| 	<Identification> | ||||
| 		<ShortName>TipoTrabajador</ShortName> | ||||
| 		<LongName xml:lang="es">Tipos de trabajadores</LongName> | ||||
| 		<Version>1</Version> | ||||
| 	</Identification> | ||||
| 	<ColumnSet> | ||||
| 		<Column Id="code" Use="required"> | ||||
| 			<ShortName>Code</ShortName> | ||||
| 			<Data Type="normalizedString"/> | ||||
| 		</Column> | ||||
| 		<Column Id="name" Use="required"> | ||||
| 			<ShortName>Nombre</ShortName> | ||||
| 			<Data Type="normalizedString"/> | ||||
| 		</Column> | ||||
| 		<Key Id="codeKey"> | ||||
| 			<ShortName>CodeKey</ShortName> | ||||
| 			<ColumnRef Ref="code"/> | ||||
| 		</Key> | ||||
| 	</ColumnSet> | ||||
| 	<SimpleCodeList> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>01</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Dependiente</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>02</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Servicio domestico</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>04</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Madre comunitaria</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>12</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Aprendices del Sena en etapa lectiva</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>18</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Funcionarios públicos sin tope máximo de ibc</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>19</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Aprendices del SENA en etapa productiva</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>21</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Estudiantes de postgrado en salud</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>22</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Profesor de establecimiento particular</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>23</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Estudiantes aportes solo riesgos laborales</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>30</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Dependiente entidades o universidades públicas con régimen especial en salud</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>31</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Cooperados o pre cooperativas de trabajo asociado</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>47</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Trabajador dependiente de entidad beneficiaria del sistema general de participaciones ‐ aportes patronales</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>51</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Trabajador de tiempo parcial</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>54</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Pre pensionado de entidad en liquidación.</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>56</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Pre pensionado con aporte voluntario a salud</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
| 		<Row> | ||||
| 			<Value ColumnRef="code"> | ||||
| 				<SimpleValue>58</SimpleValue> | ||||
| 			</Value> | ||||
| 			<Value ColumnRef="name"> | ||||
| 				<SimpleValue>Estudiantes de prácticas laborales en el sector público</SimpleValue> | ||||
| 			</Value> | ||||
| 		</Row> | ||||
|         </SimpleCodeList> | ||||
| </gc:CodeList> | ||||
| @@ -12,6 +12,9 @@ class CodeList: | ||||
|         self.short_name = '' | ||||
|         self.long_name = '' | ||||
|         self.version = 1 | ||||
|         self.canonical_uri = '' | ||||
|         self.canonical_version_uri = '' | ||||
|         self.location_uri = '' | ||||
|  | ||||
|         self.name_column = name_column | ||||
|         self.rows = {} | ||||
| @@ -24,6 +27,9 @@ class CodeList: | ||||
|         self.short_name = tree.find('./Identification/ShortName').text | ||||
|         self.long_name = tree.find('./Identification/LongName').text | ||||
|         self.version = tree.find('./Identification/Version').text | ||||
|         self.canonical_uri = tree.find('./Identification/CanonicalUri').text | ||||
|         self.canonical_version_uri = tree.find('./Identification/CanonicalVersionUri').text | ||||
|         self.location_uri = tree.find('./Identification/LocationUri').text | ||||
|  | ||||
|         #obtener registros... | ||||
|         for row in tree.findall('./SimpleCodeList/Row'): | ||||
| @@ -84,7 +90,6 @@ TipoImpuesto = CodeList(path_for_codelist('TipoImpuesto-2.1.gc'), 'code', 'name' | ||||
|     .update(CodeList(path_for_codelist('TipoImpuesto-2.1.custom.gc'), 'code', 'name')) | ||||
| CodigoPrecioReferencia = CodeList(path_for_codelist('CodigoPrecioReferencia-2.1.gc'), 'code', 'name') | ||||
| MediosPago = CodeList(path_for_codelist('MediosPago-2.1.gc'), 'code', 'name') | ||||
| FormasPago = CodeList(path_for_codelist('FormasPago-2.1.gc'), 'code', 'name') | ||||
| RegimenFiscal = CodeList(path_for_codelist('RegimenFiscal-2.1.custom.gc'), 'code', 'name') | ||||
| TipoOperacionNC = CodeList(path_for_codelist('TipoOperacionNC-2.1.gc'), 'code', 'name') | ||||
| TipoOperacionND = CodeList(path_for_codelist('TipoOperacionND-2.1 - copia.gc'), 'code', 'name') | ||||
| @@ -96,9 +101,3 @@ Paises = CodeList(path_for_codelist('Paises-2.1.gc'), 'code', 'name') | ||||
| TipoIdFiscal = CodeList(path_for_codelist('TipoIdFiscal-2.1.gc'), 'code', 'name') | ||||
| CodigoDescuento = CodeList(path_for_codelist('CodigoDescuento-2.1.gc'), 'code', 'name') | ||||
| UnidadesMedida = CodeList(path_for_codelist('UnidadesMedida-2.1.gc'), 'code', 'name') | ||||
| TipoTrabajador = CodeList(path_for_codelist('TipoTrabajador-2.1.gc'), 'code', 'name') | ||||
| SubTipoTrabajador = CodeList(path_for_codelist('SubTipoTrabajador-2.1.gc'), 'code', 'name') | ||||
| TipoContrato = CodeList(path_for_codelist('TipoContrato-2.1.gc'), 'code', 'name') | ||||
| PeriodoNomina = CodeList(path_for_codelist('PeriodoNomina-2.1.gc'), 'code', 'name') | ||||
| TipoMoneda = CodeList(path_for_codelist('TipoMoneda-2.1.gc'), 'code', 'name') | ||||
| IdiomaISO6391 = CodeList(path_for_codelist('Idioma-2.1.gc'), 'iso-639-1', 'name') | ||||
|   | ||||
| @@ -26,16 +26,15 @@ SCHEME_AGENCY_ATTRS = { | ||||
| } | ||||
|  | ||||
|  | ||||
| pwd = Path(__file__).parent | ||||
| # RESOLUCION 0001: pagina 516 | ||||
| POLICY_ID = 'https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf' | ||||
| POLICY_ID = 'file://'+str(pwd)+'/data/dian/politicadefirmav2.pdf' | ||||
| POLICY_NAME = u'Política de firma para facturas electrónicas de la República de Colombia.' | ||||
|  | ||||
|  | ||||
| NAMESPACES = { | ||||
|     'atd': 'urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2', | ||||
|     'nomina': 'dian:gov:co:facturaelectronica:NominaIndividual', | ||||
|     'facho': 'http://git.disroot.org/Etrivial/facho', | ||||
|     'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1', | ||||
|     'xs': 'http://www.w3.org/2001/XMLSchema-instance',     | ||||
|     'cac': 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2', | ||||
|     'cbc': 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2', | ||||
|     'cdt': 'urn:DocumentInformation:names:specification:ubl:colombia:schema:xsd:DocumentInformationAggregateComponents-1', | ||||
| @@ -47,7 +46,6 @@ NAMESPACES = { | ||||
|     'udt': 'urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2', | ||||
|     'xsi': 'http://www.w3.org/2001/XMLSchema-instance', | ||||
|     'xades': 'http://uri.etsi.org/01903/v1.3.2#', | ||||
|     'xades141': 'http://uri.etsi.org/01903/v1.4.1#',     | ||||
|     'ds': 'http://www.w3.org/2000/09/xmldsig#', | ||||
|     'sig': 'http://www.w3.org/2000/09/xmldsig#', | ||||
| } | ||||
| @@ -63,7 +61,6 @@ def mock_xades_policy(): | ||||
|     with patch('xades.policy.urllib.urlopen') as mock: | ||||
|         class UrllibPolicyMock: | ||||
|             def read(self): | ||||
|                 # Usamos contenido de archivo local | ||||
|                 cur_dir = os.path.dirname(os.path.abspath(__file__)) | ||||
|                 data_dir = os.path.join(cur_dir, 'data', 'dian') | ||||
|                 policy_file = os.path.join(data_dir, 'politicadefirmav2.pdf') | ||||
| @@ -81,17 +78,19 @@ class FeXML(FachoXML): | ||||
|         super().__init__("{%s}%s" % (namespace, root), | ||||
|                          nsmap=NAMESPACES) | ||||
|  | ||||
|         self._cn = root.rstrip('/') | ||||
|         #self.find_or_create_element(self._cn) | ||||
|  | ||||
|     @classmethod | ||||
|     def from_string(cls, document: str) -> 'FeXML': | ||||
|         return super().from_string(document, namespaces=NAMESPACES) | ||||
|      | ||||
|     def tostring(self, **kw): | ||||
|         # MACHETE(bit4bit) la DIAN espera que la etiqueta raiz no este en un namespace | ||||
|         root_namespace = self.root_namespace() | ||||
|         xmlns_name = {v: k for k, v in NAMESPACES.items()}[root_namespace] | ||||
|         return super().tostring(**kw)\ | ||||
|             .replace(xmlns_name + ':', '')\ | ||||
|             .replace('xmlns:'+xmlns_name, 'xmlns') | ||||
|             .replace("fe:", "")\ | ||||
|             .replace("xmlns:fe", "xmlns") | ||||
|  | ||||
|  | ||||
|  | ||||
| class DianXMLExtensionCUDFE(FachoXMLExtension): | ||||
|  | ||||
| @@ -120,8 +119,7 @@ class DianXMLExtensionCUDFE(FachoXMLExtension): | ||||
|         fachoxml.set_element('./cbc:UUID', cufe, | ||||
|                              schemeID=self.tipo_ambiente, | ||||
|                              schemeName=self.schemeName()) | ||||
|         #DIAN 1.8.-2021: FAD03 | ||||
|         fachoxml.set_element('./cbc:ProfileID', 'DIAN 2.1: Factura Electrónica de Venta') | ||||
|         fachoxml.set_element('./cbc:ProfileID', 'DIAN 2.1') | ||||
|         fachoxml.set_element('./cbc:ProfileExecutionID', self._tipo_ambiente_int()) | ||||
|         #DIAN 1.7.-2020: FAB36 | ||||
|         fachoxml.set_element('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:QRCode', | ||||
| @@ -284,35 +282,32 @@ class DianXMLExtensionSoftwareSecurityCode(FachoXMLExtension): | ||||
|  | ||||
| class DianXMLExtensionSigner: | ||||
|  | ||||
|     def __init__(self, pkcs12_path, passphrase=None, localpolicy=True): | ||||
|     def __init__(self, pkcs12_path, passphrase=None, mockpolicy=False): | ||||
|         self._pkcs12_data = open(pkcs12_path, 'rb').read() | ||||
|         self._passphrase = None | ||||
|         self._localpolicy = localpolicy | ||||
|         self._mockpolicy = mockpolicy | ||||
|         if passphrase: | ||||
|             self._passphrase = passphrase.encode('utf-8') | ||||
|  | ||||
|     @classmethod | ||||
|     def from_bytes(cls, data, passphrase=None, localpolicy=True): | ||||
|     def from_bytes(cls, data, passphrase=None, mockpolicy=False): | ||||
|         self = cls.__new__(cls) | ||||
|          | ||||
|         self._pkcs12_data = data | ||||
|         self._passphrase = None | ||||
|         self._localpolicy = localpolicy | ||||
|         self._mockpolicy = mockpolicy | ||||
|         if passphrase: | ||||
|             self._passphrase = passphrase.encode('utf-8') | ||||
|              | ||||
|         return self | ||||
|      | ||||
|     def _element_extension_content(self, fachoxml): | ||||
|         return fachoxml.builder.xpath(fachoxml.root, './ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent') | ||||
|  | ||||
|     def sign_xml_string(self, document): | ||||
|         xml = LXMLBuilder.from_string(document) | ||||
|         signature = self.sign_xml_element(xml) | ||||
|  | ||||
|         fachoxml = FachoXML(xml,nsmap=NAMESPACES) | ||||
|         #DIAN 1.7.-2020: FAB01 | ||||
|         extcontent = self._element_extension_content(fachoxml) | ||||
|         extcontent = fachoxml.builder.xpath(fachoxml.root, './ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent') | ||||
|         fachoxml.append_element(extcontent, signature) | ||||
|  | ||||
|         return fachoxml.tostring(xml_declaration=True, encoding='UTF-8') | ||||
| @@ -363,7 +358,7 @@ class DianXMLExtensionSigner: | ||||
|         ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(self._pkcs12_data, | ||||
|                                                    self._passphrase)) | ||||
|  | ||||
|         if self._localpolicy: | ||||
|         if self._mockpolicy: | ||||
|             with mock_xades_policy(): | ||||
|                 ctx.sign(signature) | ||||
|                 ctx.verify(signature) | ||||
| @@ -376,7 +371,7 @@ class DianXMLExtensionSigner: | ||||
|  | ||||
|     def build(self, fachoxml): | ||||
|         signature = self.sign_xml_element(fachoxml.root) | ||||
|         extcontent = self._element_extension_content(fachoxml) | ||||
|         extcontent = fachoxml.builder.xpath(fachoxml.root, './ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent') | ||||
|         fachoxml.append_element(extcontent, signature) | ||||
|  | ||||
|          | ||||
| @@ -452,7 +447,7 @@ class DianZIP: | ||||
|         self.zipfile = zipfile.ZipFile(file_like, mode='w', compression=zipfile.ZIP_DEFLATED) | ||||
|         self.num_files = 0 | ||||
|  | ||||
|     def add_xml(self, name, xml_data): | ||||
|     def add_invoice_xml(self, name, xml_data): | ||||
|         self.num_files += 1 | ||||
|         # TODO cual es la norma para los nombres de archivos? | ||||
|         m = hashlib.sha256() | ||||
| @@ -463,18 +458,7 @@ class DianZIP: | ||||
|  | ||||
|         return filename | ||||
|  | ||||
|     # DEPRECATED usar add_xml | ||||
|     def add_invoice_xml(self, name, xml_data): | ||||
|         return self.add_xml(name, xml_data) | ||||
|  | ||||
|     def __enter__(self): | ||||
|         """ | ||||
|         Facilita el uso de esta manera: | ||||
|          | ||||
|         f = open('xxx', 'rb') | ||||
|         with DianZIP(f) as zip: | ||||
|           zip.add_invoice_xml('name', 'data xml') | ||||
|         """ | ||||
|         return self | ||||
|  | ||||
|     def __exit__(self, type, value, traceback): | ||||
| @@ -483,35 +467,34 @@ class DianZIP: | ||||
|  | ||||
| class DianXMLExtensionSignerVerifier: | ||||
|  | ||||
|     def __init__(self, pkcs12_path_or_bytes, passphrase=None, localpolicy=True): | ||||
|     def __init__(self, pkcs12_path_or_bytes, passphrase=None, mockpolicy=False): | ||||
|         self._pkcs12_path_or_bytes = pkcs12_path_or_bytes | ||||
|         self._passphrase = None | ||||
|         self._localpolicy = localpolicy | ||||
|         self._mockpolicy = mockpolicy | ||||
|         if passphrase: | ||||
|             self._passphrase = passphrase.encode('utf-8') | ||||
|  | ||||
|     def verify_string(self, document): | ||||
|         # Obtener FachoXML | ||||
|         xml = LXMLBuilder.from_string(document) | ||||
|         fachoxml = FachoXML(xml,nsmap=NAMESPACES) | ||||
|  | ||||
|         # Obtener Signature | ||||
|         signature = fachoxml.builder.xpath(fachoxml.root, '//ds:Signature') | ||||
|         assert signature is not None | ||||
|  | ||||
|         # Se mueve Signature a elemento raiz para realizar verificaion | ||||
|         signature.getparent().remove(signature) | ||||
|         fachoxml.root.append(signature) | ||||
|  | ||||
|         # Verificar archivo usando Signature | ||||
|         ctx = xades.XAdESContext() | ||||
|  | ||||
|         pkcs12_data = self._pkcs12_path_or_bytes | ||||
|         if isinstance(self._pkcs12_path_or_bytes, str): | ||||
|             pkcs12_data = open(self._pkcs12_path_or_bytes, 'rb').read() | ||||
|         ctx = xades.XAdESContext() | ||||
|  | ||||
|         ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(pkcs12_data, | ||||
|                                                    self._passphrase)) | ||||
|  | ||||
|         try: | ||||
|             if self._localpolicy: | ||||
|             if self._mockpolicy: | ||||
|                 with mock_xades_policy(): | ||||
|                     ctx.verify(signature) | ||||
|             else: | ||||
|   | ||||
| @@ -54,8 +54,8 @@ class AmountCollection(Collection): | ||||
|         return total | ||||
|  | ||||
| class Amount: | ||||
|     def __init__(self, amount: int or float or str or Amount, currency: Currency = Currency('COP')): | ||||
|  | ||||
|     def __init__(self, amount: int or float or str or Amount, currency: Currency = Currency('COP'), precision = DECIMAL_PRECISION): | ||||
|         self.precision = precision | ||||
|         #DIAN 1.7.-2020: 1.2.3.1 | ||||
|         if isinstance(amount, Amount): | ||||
|             if amount < Amount(0.0): | ||||
| @@ -67,7 +67,7 @@ class Amount: | ||||
|             if float(amount) < 0: | ||||
|                 raise ValueError('amount must be positive >= 0') | ||||
|  | ||||
|             self.amount = Decimal(amount, decimal.Context(prec=DECIMAL_PRECISION, | ||||
|             self.amount = Decimal(amount, decimal.Context(prec=self.precision, | ||||
|                                                           #DIAN 1.7.-2020: 1.2.1.1 | ||||
|                                                           rounding=decimal.ROUND_HALF_EVEN )) | ||||
|             self.currency = currency | ||||
| @@ -87,19 +87,22 @@ class Amount: | ||||
|     def __lt__(self, other): | ||||
|         if not self.is_same_currency(other): | ||||
|             raise AmountCurrencyError() | ||||
|         return round(self.amount, DECIMAL_PRECISION) < round(other, 2) | ||||
|         return round(self.amount, self.precision) < round(other, 2) | ||||
|  | ||||
|     def __eq__(self, other): | ||||
|         if not self.is_same_currency(other): | ||||
|             raise AmountCurrencyError() | ||||
|         return round(self.amount, DECIMAL_PRECISION) == round(other.amount, DECIMAL_PRECISION) | ||||
|         return round(self.amount, self.precision) == round(other.amount, self.precision) | ||||
|  | ||||
|     def _cast(self, val): | ||||
|         if type(val) in [int, float]: | ||||
|             return self.fromNumber(val) | ||||
|         if isinstance(val, Amount): | ||||
|             return val | ||||
|         raise TypeError("cant cast to amount") | ||||
|         if isinstance(val, Decimal): | ||||
|             return self.fromNumber(float(val)) | ||||
|  | ||||
|         raise TypeError("cant cast %s to amount" % (type(val))) | ||||
|      | ||||
|     def __add__(self, rother): | ||||
|         other = self._cast(rother) | ||||
|   | ||||
| @@ -2,4 +2,3 @@ from .invoice import * | ||||
| from .credit_note import * | ||||
| from .debit_note import * | ||||
| from .utils import * | ||||
| from .attached_document import * | ||||
|   | ||||
| @@ -1,14 +0,0 @@ | ||||
| from .. import fe | ||||
|  | ||||
| __all__ = ['AttachedDocument'] | ||||
|  | ||||
| class AttachedDocument(): | ||||
|  | ||||
|     def __init__(self, id): | ||||
|         schema = 'urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2' | ||||
|         self.fexml = fe.FeXML('AttachedDocument', schema) | ||||
|         self.fexml.set_element('./cbc:ID', id) | ||||
|  | ||||
|     def toFachoXML(self): | ||||
|         return self.fexml | ||||
|          | ||||
| @@ -427,10 +427,10 @@ class DIANInvoiceXML(fe.FeXML): | ||||
|         #tax_amount_for['01']['tax_amount'] = Amount(0.0) | ||||
|         #tax_amount_for['01']['taxable_amount'] = Amount(0.0) | ||||
|         #DIAN 1.7.-2020: FAS07 => Se debe construir estrategia para  su manejo | ||||
|         #tax_amount_for['04']['tax_amount'] += 0.0 | ||||
|         #tax_amount_for['04']['taxable_amount'] += 0.0 | ||||
|         #tax_amount_for['03']['tax_amount'] += 0.0 | ||||
|         #tax_amount_for['03']['taxable_amount'] += 0.0 | ||||
|         #tax_amount_for['04']['tax_amount'] = 0.0 | ||||
|         #tax_amount_for['04']['taxable_amount'] = 0.0 | ||||
|         #tax_amount_for['03']['tax_amount'] = 0.0 | ||||
|         #tax_amount_for['03']['taxable_amount'] = 0.0 | ||||
|  | ||||
|         total_tax_amount = Amount(0.0) | ||||
|  | ||||
| @@ -445,7 +445,6 @@ class DIANInvoiceXML(fe.FeXML): | ||||
|  | ||||
|                 total_tax_amount += subtotal.tax_amount | ||||
|  | ||||
|         if total_tax_amount != Amount(0.0): | ||||
|         fexml.placeholder_for('./cac:TaxTotal') | ||||
|         fexml.set_element_amount('./cac:TaxTotal/cbc:TaxAmount', | ||||
|                                 total_tax_amount) | ||||
| @@ -457,6 +456,7 @@ class DIANInvoiceXML(fe.FeXML): | ||||
|  | ||||
|             #DIAN 1.7.-2020: FAS01 | ||||
|             line = fexml.fragment('./cac:TaxTotal', append=next_append) | ||||
|  | ||||
|             #DIAN 1.7.-2020: FAU06 | ||||
|             tax_amount = amount_of['tax_amount'] | ||||
|             fexml.set_element_amount_for(line, | ||||
| @@ -482,11 +482,8 @@ class DIANInvoiceXML(fe.FeXML): | ||||
|             if percent_for[cod_impuesto]: | ||||
|                 line.set_element('/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent', | ||||
|                                  percent_for[cod_impuesto]) | ||||
|                  | ||||
|             line.set_element('/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID', | ||||
|                              cod_impuesto) | ||||
|             line.set_element('/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name', | ||||
|                     'IVA') | ||||
|  | ||||
|     # abstract method | ||||
|     def tag_document(fexml): | ||||
| @@ -505,6 +502,7 @@ class DIANInvoiceXML(fe.FeXML): | ||||
|         fexml.set_element_amount_for(line, | ||||
|                                      './cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount', | ||||
|                                      invoice_line.taxable_amount) | ||||
|  | ||||
|         for subtotal in invoice_line.tax.subtotals: | ||||
|             line.set_element('./cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount', subtotal.tax_amount, currencyID='COP') | ||||
|  | ||||
|   | ||||
| @@ -8,12 +8,8 @@ def DIANWrite(xml, filename): | ||||
|         f.write(document) | ||||
|  | ||||
|          | ||||
| def DIANWriteSigned(xml, filename, private_key, passphrase, use_cache_policy=False, dian_signer=None): | ||||
| def DIANWriteSigned(xml, filename, private_key, passphrase, use_cache_policy=False): | ||||
|     document = xml.tostring(xml_declaration=True, encoding='UTF-8').encode('utf-8') | ||||
|     if dian_signer is None: | ||||
|         dian_signer = fe.DianXMLExtensionSigner | ||||
|  | ||||
|     signer = dian_signer(private_key, passphrase=passphrase, localpolicy=use_cache_policy) | ||||
|  | ||||
|     signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, mockpolicy=use_cache_policy) | ||||
|     with open(filename, 'w') as f: | ||||
|         f.write(signer.sign_xml_string(document)) | ||||
|   | ||||
							
								
								
									
										367
									
								
								facho/fe/model/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										367
									
								
								facho/fe/model/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,367 @@ | ||||
| import facho.model as model | ||||
| import facho.model.fields as fields | ||||
| import facho.fe.form as form | ||||
| from facho import fe | ||||
| from .common import * | ||||
| from . import dian | ||||
|  | ||||
| from datetime import date, datetime | ||||
| from collections import defaultdict | ||||
| from copy import copy | ||||
| import hashlib | ||||
|  | ||||
|  | ||||
|  | ||||
| class PhysicalLocation(model.Model): | ||||
|     __name__ = 'PhysicalLocation' | ||||
|  | ||||
|     address = fields.Many2One(Address, namespace='cac') | ||||
|      | ||||
| class PartyTaxScheme(model.Model): | ||||
|     __name__ = 'PartyTaxScheme' | ||||
|  | ||||
|     registration_name = fields.Many2One(Name, name='RegistrationName', namespace='cbc') | ||||
|     company_id = fields.Many2One(ID, name='CompanyID', namespace='cbc') | ||||
|     tax_level_code = fields.Many2One(ID, name='TaxLevelCode', namespace='cbc', default='ZZ') | ||||
|  | ||||
|  | ||||
| class Party(model.Model): | ||||
|     __name__ = 'Party' | ||||
|  | ||||
|     id = fields.Virtual(setter='_on_set_id') | ||||
|     name = fields.Many2One(PartyName, namespace='cac') | ||||
|  | ||||
|     tax_scheme = fields.Many2One(PartyTaxScheme, namespace='cac') | ||||
|     location = fields.Many2One(PhysicalLocation, namespace='cac') | ||||
|     contact = fields.Many2One(Contact, namespace='cac') | ||||
|      | ||||
|     def _on_set_id(self, name, value): | ||||
|         self.tax_scheme.company_id = value | ||||
|         return value | ||||
|  | ||||
| class AccountingCustomerParty(model.Model): | ||||
|     __name__ = 'AccountingCustomerParty' | ||||
|  | ||||
|     party = fields.Many2One(Party, namespace='cac') | ||||
|  | ||||
| class AccountingSupplierParty(model.Model): | ||||
|     __name__ = 'AccountingSupplierParty' | ||||
|  | ||||
|     party = fields.Many2One(Party, namespace='cac') | ||||
|  | ||||
| class Quantity(model.Model): | ||||
|     __name__  = 'Quantity' | ||||
|  | ||||
|     code = fields.Attribute('unitCode', default='NAR') | ||||
|  | ||||
|     def __setup__(self): | ||||
|         self.value = 0 | ||||
|  | ||||
|     def __default_set__(self, value): | ||||
|         self.value = value | ||||
|         return value | ||||
|  | ||||
|     def __default_get__(self, name, value): | ||||
|         return self.value | ||||
|  | ||||
| class Amount(model.Model): | ||||
|     __name__ = 'Amount' | ||||
|  | ||||
|     currency = fields.Attribute('currencyID', default='COP') | ||||
|     value = fields.Amount(name='amount', default=0.00, precision=2) | ||||
|  | ||||
|     def __default_set__(self, value): | ||||
|         self.value = value | ||||
|         return value | ||||
|  | ||||
|     def __default_get__(self, name, value): | ||||
|         return self.value | ||||
|  | ||||
|     def __str__(self): | ||||
|         return str(self.value) | ||||
|  | ||||
| class Price(model.Model): | ||||
|     __name__ = 'Price' | ||||
|  | ||||
|     amount = fields.Many2One(Amount, name='PriceAmount', namespace='cbc') | ||||
|      | ||||
|     def __default_set__(self, value): | ||||
|         self.amount = value | ||||
|         return value | ||||
|  | ||||
|     def __default_get__(self, name, value): | ||||
|         return self.amount | ||||
|  | ||||
| class Percent(model.Model): | ||||
|     __name__ = 'Percent' | ||||
|  | ||||
| class TaxScheme(model.Model): | ||||
|     __name__ = 'TaxScheme' | ||||
|  | ||||
|     id = fields.Many2One(ID, namespace='cbc') | ||||
|     name= fields.Many2One(Name, namespace='cbc') | ||||
|  | ||||
| class TaxCategory(model.Model): | ||||
|     __name__ = 'TaxCategory' | ||||
|  | ||||
|     percent = fields.Many2One(Percent, namespace='cbc') | ||||
|     tax_scheme = fields.Many2One(TaxScheme, namespace='cac') | ||||
|      | ||||
| class TaxSubTotal(model.Model): | ||||
|     __name__ = 'TaxSubTotal' | ||||
|  | ||||
|     taxable_amount = fields.Many2One(Amount, name='TaxableAmount', namespace='cbc', default=0.00) | ||||
|     tax_amount = fields.Many2One(Amount, name='TaxAmount', namespace='cbc', default=0.00) | ||||
|     tax_percent = fields.Many2One(Percent, namespace='cbc') | ||||
|     tax_category = fields.Many2One(TaxCategory, namespace='cac') | ||||
|  | ||||
|     percent = fields.Virtual(setter='set_category', getter='get_category') | ||||
|     scheme = fields.Virtual(setter='set_category', getter='get_category') | ||||
|  | ||||
|     def set_category(self, name, value): | ||||
|         if name == 'percent': | ||||
|             self.tax_category.percent = value | ||||
|             # TODO(bit4bit) debe variar en conjunto? | ||||
|             self.tax_percent = value | ||||
|         elif name == 'scheme': | ||||
|             self.tax_category.tax_scheme.id = value | ||||
|  | ||||
|         return value | ||||
|  | ||||
|     def get_category(self, name, value): | ||||
|         if name == 'percent': | ||||
|             return value | ||||
|         elif name == 'scheme': | ||||
|             return self.tax_category.tax_scheme | ||||
|  | ||||
| class TaxTotal(model.Model): | ||||
|     __name__ = 'TaxTotal' | ||||
|  | ||||
|     tax_amount = fields.Many2One(Amount, name='TaxAmount', namespace='cbc', default=0.00) | ||||
|     subtotals = fields.One2Many(TaxSubTotal, namespace='cac') | ||||
|  | ||||
|  | ||||
| class AllowanceCharge(model.Model): | ||||
|     __name__ = 'AllowanceCharge' | ||||
|  | ||||
|     amount = fields.Many2One(Amount, namespace='cbc') | ||||
|     is_discount = fields.Virtual(default=False) | ||||
|      | ||||
|     def isCharge(self): | ||||
|         return self.is_discount == False | ||||
|  | ||||
|     def isDiscount(self): | ||||
|         return self.is_discount == True | ||||
|  | ||||
| class Taxes: | ||||
|     class Scheme: | ||||
|         def __init__(self, scheme): | ||||
|             self.scheme = scheme | ||||
|  | ||||
|     class Iva(Scheme): | ||||
|         def __init__(self, percent): | ||||
|             super().__init__('01') | ||||
|             self.percent = percent | ||||
|  | ||||
|         def calculate(self, amount): | ||||
|             return form.Amount(amount) * form.Amount(self.percent / 100) | ||||
|      | ||||
| class InvoiceLine(model.Model): | ||||
|     __name__ = 'InvoiceLine' | ||||
|  | ||||
|     id = fields.Many2One(ID, namespace='cbc') | ||||
|     quantity = fields.Many2One(Quantity, name='InvoicedQuantity', namespace='cbc') | ||||
|     taxtotal = fields.Many2One(TaxTotal, namespace='cac') | ||||
|     price = fields.Many2One(Price, namespace='cac') | ||||
|     amount = fields.Many2One(Amount, name='LineExtensionAmount', namespace='cbc') | ||||
|     allowance_charge = fields.One2Many(AllowanceCharge, 'cac') | ||||
|     tax_amount = fields.Virtual(getter='get_tax_amount') | ||||
|      | ||||
|     def __setup__(self): | ||||
|         self._taxs = defaultdict(list) | ||||
|         self._subtotals = {} | ||||
|  | ||||
|     def add_tax(self, tax): | ||||
|         if not isinstance(tax, Taxes.Scheme): | ||||
|             raise ValueError('tax expected TaxIva') | ||||
|  | ||||
|         # inicialiamos subtotal para impuesto | ||||
|         if not tax.scheme in self._subtotals: | ||||
|             subtotal = self.taxtotal.subtotals.create() | ||||
|             subtotal.scheme = tax.scheme | ||||
|              | ||||
|             self._subtotals[tax.scheme] = subtotal | ||||
|          | ||||
|         self._taxs[tax.scheme].append(tax) | ||||
|  | ||||
|     def get_tax_amount(self, name, value): | ||||
|         total = form.Amount(0) | ||||
|         for (scheme, subtotal) in self._subtotals.items(): | ||||
|             total += subtotal.tax_amount | ||||
|  | ||||
|         return total | ||||
|  | ||||
|     @fields.on_change(['price', 'quantity']) | ||||
|     def update_amount(self, name, value): | ||||
|         charge = form.AmountCollection(self.allowance_charge)\ | ||||
|             .filter(lambda charge: charge.isCharge())\ | ||||
|             .map(lambda charge: charge.amount)\ | ||||
|             .sum() | ||||
|  | ||||
|         discount = form.AmountCollection(self.allowance_charge)\ | ||||
|             .filter(lambda charge: charge.isDiscount())\ | ||||
|             .map(lambda charge: charge.amount)\ | ||||
|             .sum() | ||||
|  | ||||
|         total = form.Amount(self.quantity)  * form.Amount(self.price) | ||||
|         self.amount = total + charge - discount | ||||
|          | ||||
|         for (scheme, subtotal) in self._subtotals.items(): | ||||
|             subtotal.tax_amount = 0 | ||||
|  | ||||
|         for (scheme, taxes) in self._taxs.items(): | ||||
|             for tax in taxes: | ||||
|                 self._subtotals[scheme].tax_amount += tax.calculate(self.amount) | ||||
|  | ||||
| class LegalMonetaryTotal(model.Model): | ||||
|     __name__ = 'LegalMonetaryTotal' | ||||
|  | ||||
|     line_extension_amount = fields.Many2One(Amount, name='LineExtensionAmount', namespace='cbc', default=0) | ||||
|  | ||||
|     tax_exclusive_amount = fields.Many2One(Amount, name='TaxExclusiveAmount', namespace='cbc', default=form.Amount(0)) | ||||
|     tax_inclusive_amount = fields.Many2One(Amount, name='TaxInclusiveAmount', namespace='cbc', default=form.Amount(0)) | ||||
|     charge_total_amount = fields.Many2One(Amount, name='ChargeTotalAmount', namespace='cbc', default=form.Amount(0)) | ||||
|     payable_amount = fields.Many2One(Amount, name='PayableAmount', namespace='cbc', default=form.Amount(0)) | ||||
|  | ||||
|     @fields.on_change(['tax_inclusive_amount', 'charge_total']) | ||||
|     def update_payable_amount(self, name, value): | ||||
|         self.payable_amount = self.tax_inclusive_amount + self.charge_total_amount | ||||
|  | ||||
|  | ||||
| class DIANExtensionContent(model.Model): | ||||
|     __name__ = 'ExtensionContent' | ||||
|      | ||||
|     dian = fields.Many2One(dian.DianExtensions, name='DianExtensions', namespace='sts') | ||||
|  | ||||
| class DIANExtension(model.Model): | ||||
|     __name__ = 'UBLExtension' | ||||
|  | ||||
|     content = fields.Many2One(DIANExtensionContent, namespace='ext') | ||||
|  | ||||
|     def __default_get__(self, name, value): | ||||
|         return self.content.dian | ||||
|  | ||||
| class UBLExtension(model.Model): | ||||
|     __name__ = 'UBLExtension' | ||||
|  | ||||
|     content = fields.Many2One(Element, name='ExtensionContent', namespace='ext', default='') | ||||
|      | ||||
| class UBLExtensions(model.Model): | ||||
|     __name__ = 'UBLExtensions' | ||||
|  | ||||
|     dian = fields.Many2One(DIANExtension, namespace='ext', create=True) | ||||
|     extension = fields.Many2One(UBLExtension, namespace='ext', create=True) | ||||
|  | ||||
| class Invoice(model.Model): | ||||
|     __name__ = 'Invoice' | ||||
|     __namespace__ = fe.NAMESPACES | ||||
|  | ||||
|     _ubl_extensions = fields.Many2One(UBLExtensions, namespace='ext') | ||||
|     # nos interesa el acceso solo los atributos de la DIAN | ||||
|     dian = fields.Virtual(getter='get_dian_extension') | ||||
|      | ||||
|     profile_id = fields.Many2One(Element, name='ProfileID', namespace='cbc', default='DIAN 2.1') | ||||
|     profile_execute_id = fields.Many2One(Element, name='ProfileExecuteID', namespace='cbc', default='2') | ||||
|      | ||||
|     id = fields.Many2One(ID, namespace='cbc') | ||||
|     issue = fields.Virtual(setter='set_issue') | ||||
|     issue_date = fields.Many2One(Date, name='IssueDate', namespace='cbc') | ||||
|     issue_time = fields.Many2One(Time, name='IssueTime', namespace='cbc') | ||||
|      | ||||
|     period = fields.Many2One(Period, name='InvoicePeriod', namespace='cac') | ||||
|  | ||||
|     supplier = fields.Many2One(AccountingSupplierParty, namespace='cac') | ||||
|     customer = fields.Many2One(AccountingCustomerParty, namespace='cac') | ||||
|     legal_monetary_total = fields.Many2One(LegalMonetaryTotal, namespace='cac') | ||||
|     lines = fields.One2Many(InvoiceLine, namespace='cac') | ||||
|      | ||||
|     taxtotal_01 = fields.Many2One(TaxTotal) | ||||
|     taxtotal_04 = fields.Many2One(TaxTotal) | ||||
|     taxtotal_03 = fields.Many2One(TaxTotal) | ||||
|  | ||||
|     def __setup__(self): | ||||
|         self._namespace_prefix = 'fe' | ||||
|         # Se requieren minimo estos impuestos para | ||||
|         # validar el cufe | ||||
|         self._subtotal_01 = self.taxtotal_01.subtotals.create() | ||||
|         self._subtotal_01.scheme = '01' | ||||
|         self._subtotal_01.percent = 19.0 | ||||
|  | ||||
|         self._subtotal_04 = self.taxtotal_04.subtotals.create() | ||||
|         self._subtotal_04.scheme = '04' | ||||
|          | ||||
|         self._subtotal_03 = self.taxtotal_03.subtotals.create() | ||||
|         self._subtotal_03.scheme = '03' | ||||
|  | ||||
|     def cufe(self, token, environment): | ||||
|  | ||||
|         valor_bruto = self.legal_monetary_total.line_extension_amount | ||||
|         valor_total_pagar = self.legal_monetary_total.payable_amount | ||||
|  | ||||
|         valor_impuesto_01 = form.Amount(0.0) | ||||
|         valor_impuesto_04 = form.Amount(0.0) | ||||
|         valor_impuesto_03 = form.Amount(0.0) | ||||
|  | ||||
|         for line in self.lines: | ||||
|             for subtotal in line.taxtotal.subtotals: | ||||
|                 if subtotal.scheme.id == '01': | ||||
|                     valor_impuesto_01 += subtotal.tax_amount | ||||
|                 elif subtotal.scheme.id == '04': | ||||
|                     valor_impuesto_04 += subtotal.tax_amount | ||||
|                 elif subtotal.scheme.id == '03': | ||||
|                     valor_impuesto_03 += subtotal.tax_amount | ||||
|  | ||||
|         pattern = [ | ||||
|             '%s' % str(self.id), | ||||
|             '%s' % str(self.issue_date), | ||||
|             '%s' % str(self.issue_time), | ||||
|             valor_bruto.truncate_as_string(2), | ||||
|             '01', valor_impuesto_01.truncate_as_string(2), | ||||
|             '04', valor_impuesto_04.truncate_as_string(2), | ||||
|             '03', valor_impuesto_03.truncate_as_string(2), | ||||
|             valor_total_pagar.truncate_as_string(2), | ||||
|             str(self.supplier.party.id), | ||||
|             str(self.customer.party.id), | ||||
|             str(token), | ||||
|             str(environment) | ||||
|         ] | ||||
|  | ||||
|         cufe = "".join(pattern) | ||||
|         h = hashlib.sha384() | ||||
|         h.update(cufe.encode('utf-8')) | ||||
|         return h.hexdigest() | ||||
|  | ||||
|     @fields.on_change(['lines']) | ||||
|     def update_legal_monetary_total(self, name, value): | ||||
|         self.legal_monetary_total.line_extension_amount = 0 | ||||
|         self.legal_monetary_total.tax_inclusive_amount = 0 | ||||
|  | ||||
|         for line in self.lines: | ||||
|             self.legal_monetary_total.line_extension_amount += line.amount | ||||
|             self.legal_monetary_total.tax_inclusive_amount += line.amount + line.tax_amount | ||||
|  | ||||
|     def set_issue(self, name, value): | ||||
|         if not isinstance(value, datetime): | ||||
|             raise ValueError('expected type datetime') | ||||
|         self.issue_date = value.date() | ||||
|         self.issue_time = value | ||||
|  | ||||
|     def get_dian_extension(self, name, _value): | ||||
|         return self._ubl_extensions.dian | ||||
|  | ||||
|     def to_xml(self, **kw): | ||||
|         # al generar documento el namespace | ||||
|         # se hace respecto a la raiz | ||||
|         return super().to_xml(**kw)\ | ||||
|             .replace("fe:", "")\ | ||||
|             .replace("xmlns:fe", "xmlns") | ||||
							
								
								
									
										90
									
								
								facho/fe/model/common.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								facho/fe/model/common.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| import facho.model as model | ||||
| import facho.model.fields as fields | ||||
|  | ||||
| from datetime import date, datetime | ||||
|  | ||||
| __all__ = ['Element', 'PartyName', 'Name', 'Date', 'Time', 'Period', 'ID', 'Address', 'Country', 'Contact'] | ||||
|  | ||||
| class Element(model.Model): | ||||
|     """ | ||||
|     Lo usuamos para elementos que solo manejan contenido | ||||
|     """ | ||||
|     __name__ = 'Element' | ||||
|  | ||||
| class Name(model.Model): | ||||
|     __name__ = 'Name' | ||||
|  | ||||
| class Date(model.Model): | ||||
|     __name__ = 'Date' | ||||
|  | ||||
|     def __default_set__(self, value): | ||||
|         if isinstance(value, str): | ||||
|             return value | ||||
|         if isinstance(value, date): | ||||
|             return value.isoformat() | ||||
|  | ||||
|     def __str__(self): | ||||
|         return str(self._value) | ||||
|  | ||||
| class Time(model.Model): | ||||
|     __name__ = 'Time' | ||||
|  | ||||
|     def __default_set__(self, value): | ||||
|         if isinstance(value, str): | ||||
|             return value | ||||
|         if isinstance(value, date): | ||||
|             return value.strftime('%H:%M:%S-05:00') | ||||
|  | ||||
|     def __str__(self): | ||||
|         return str(self._value) | ||||
|  | ||||
| class Period(model.Model): | ||||
|     __name__ = 'Period' | ||||
|  | ||||
|     start_date = fields.Many2One(Date, name='StartDate', namespace='cbc') | ||||
|  | ||||
|     end_date = fields.Many2One(Date, name='EndDate', namespace='cbc') | ||||
|  | ||||
| class ID(model.Model): | ||||
|     __name__ = 'ID' | ||||
|  | ||||
|     def __default_get__(self, name, value): | ||||
|         return self._value | ||||
|  | ||||
|     def __str__(self): | ||||
|         return str(self._value) | ||||
|  | ||||
|  | ||||
| class Country(model.Model): | ||||
|     __name__ = 'Country' | ||||
|  | ||||
|     name = fields.Many2One(Element, name='Name', namespace='cbc') | ||||
|  | ||||
| class Address(model.Model): | ||||
|     __name__ = 'Address' | ||||
|  | ||||
|     #DIAN 1.7.-2020: FAJ08 | ||||
|     #DIAN 1.7.-2020: CAJ09 | ||||
|     id = fields.Many2One(Element, name='ID', namespace='cbc') | ||||
|  | ||||
|     #DIAN 1.7.-2020: FAJ09 | ||||
|     #DIAN 1.7.-2020: CAJ10 | ||||
|     city = fields.Many2One(Element, name='CityName', namespace='cbc') | ||||
|      | ||||
|  | ||||
| class PartyName(model.Model): | ||||
|     __name__ = 'PartyName' | ||||
|      | ||||
|     name = fields.Many2One(Name, namespace='cbc') | ||||
|  | ||||
|     def __default_set__(self, value): | ||||
|         self.name = value | ||||
|         return value | ||||
|  | ||||
|     def __default_get__(self, name, value): | ||||
|         return self.name | ||||
|  | ||||
| class Contact(model.Model): | ||||
|     __name__ = 'Contact' | ||||
|  | ||||
|     email = fields.Many2One(Name, name='ElectronicEmail', namespace='cbc') | ||||
							
								
								
									
										58
									
								
								facho/fe/model/dian.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								facho/fe/model/dian.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| import facho.model as model | ||||
| import facho.model.fields as fields | ||||
| from .common import * | ||||
|  | ||||
| class DIANElement(Element): | ||||
|     """ | ||||
|     Elemento que contiene atributos por defecto. | ||||
|      | ||||
|     Puede extender esta clase y modificar los atributos nuevamente | ||||
|     """ | ||||
|     __name__ = 'DIANElement' | ||||
|      | ||||
|     scheme_id = fields.Attribute('schemeID', default='4') | ||||
|     scheme_name = fields.Attribute('schemeName', default='31') | ||||
|     scheme_agency_name = fields.Attribute('schemeAgencyName', default='CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)') | ||||
|     scheme_agency_id = fields.Attribute('schemeAgencyID', default='195') | ||||
|      | ||||
| class SoftwareProvider(model.Model): | ||||
|     __name__ = 'SoftwareProvider' | ||||
|  | ||||
|     provider_id = fields.Many2One(Element, name='ProviderID', namespace='sts') | ||||
|     software_id = fields.Many2One(Element, name='SoftwareID', namespace='sts') | ||||
|  | ||||
| class InvoiceSource(model.Model): | ||||
|     __name__ = 'InvoiceSource' | ||||
|  | ||||
|     identification_code = fields.Many2One(Element, name='IdentificationCode', namespace='sts', default='CO') | ||||
|      | ||||
| class AuthorizedInvoices(model.Model): | ||||
|     __name__ = 'AuthorizedInvoices' | ||||
|  | ||||
|     prefix = fields.Many2One(Element, name='Prefix', namespace='sts') | ||||
|     from_range = fields.Many2One(Element, name='From', namespace='sts') | ||||
|     to_range = fields.Many2One(Element, name='To', namespace='sts') | ||||
|      | ||||
| class InvoiceControl(model.Model): | ||||
|     __name__ = 'InvoiceControl' | ||||
|  | ||||
|     authorization = fields.Many2One(Element, name='InvoiceAuthorization', namespace='sts') | ||||
|     period = fields.Many2One(Period, name='AuthorizationPeriod', namespace='sts') | ||||
|     invoices = fields.Many2One(AuthorizedInvoices, namespace='sts') | ||||
|  | ||||
| class AuthorizationProvider(model.Model): | ||||
|     __name__ = 'AuthorizationProvider' | ||||
|  | ||||
|  | ||||
|     id = fields.Many2One(DIANElement, name='AuthorizationProviderID', namespace='sts', default='800197268') | ||||
|      | ||||
| class DianExtensions(model.Model): | ||||
|     __name__ = 'DianExtensions' | ||||
|  | ||||
|     authorization_provider = fields.Many2One(AuthorizationProvider, namespace='sts', create=True) | ||||
|  | ||||
|     software_security_code = fields.Many2One(Element, name='SoftwareSecurityCode', namespace='sts') | ||||
|     software_provider = fields.Many2One(SoftwareProvider, namespace='sts') | ||||
|     source = fields.Many2One(InvoiceSource, namespace='sts') | ||||
|     control = fields.Many2One(InvoiceControl, namespace='sts') | ||||
|  | ||||
| @@ -1,615 +0,0 @@ | ||||
| # | ||||
| # Para esta implementacion se usa BDD | ||||
| # ver **test_nomina.py**. | ||||
| # | ||||
| # La idea en general es validar comportamiento desde el XML, | ||||
| # creando las estructuras minimas necesaras. | ||||
|  | ||||
| from dataclasses import dataclass | ||||
| from datetime import datetime | ||||
| import hashlib | ||||
| import typing | ||||
|  | ||||
| from .. import fe | ||||
| from .. import form | ||||
| from ..data.dian import codelist | ||||
|  | ||||
| from .devengado import * | ||||
| from .deduccion import * | ||||
| from .trabajador import * | ||||
| from .empleador import * | ||||
| from .pago import * | ||||
| from .lugar import Lugar | ||||
|  | ||||
| from .amount import Amount | ||||
| from .exception import * | ||||
|  | ||||
| class Fecha: | ||||
|     def __init__(self, fecha): | ||||
|         try: | ||||
|             datetime.strptime(fecha, "%Y-%m-%d") | ||||
|         except ValueError: | ||||
|             raise ValueError("fecha debe ser formato YYYY-MM-DD") | ||||
|         self.value = fecha | ||||
|  | ||||
|     @classmethod | ||||
|     def cast(cls, data, optional=False): | ||||
|         if isinstance(data, str): | ||||
|             return cls(data) | ||||
|         elif isinstance(data, cls): | ||||
|             return data | ||||
|         elif data is None and optional: | ||||
|             return None | ||||
|         else: | ||||
|             raise ValueError('no se logra hacer casting a Fecha') | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.value | ||||
|  | ||||
| class FechaPago(Fecha): | ||||
|     def apply(self, fragment): | ||||
|         fragment.set_element('./FechaPago', self.value) | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Novedad: | ||||
|     # cune de nomina a relacionar | ||||
|     # NIE204 | ||||
|     cune: str | ||||
|     # NIE199 | ||||
|     activa: bool = False | ||||
|  | ||||
|     def apply(self, fragment): | ||||
|         if self.cune != "": | ||||
|             fragment.set_attributes('./Novedad', | ||||
|                                     CUNENov=self.cune, | ||||
|                                     ) | ||||
|  | ||||
|     def post_apply(self, fexml, scopexml, fragment): | ||||
|         scopexml.set_element('./Novedad', self.activa) | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class NumeroSecuencia: | ||||
|     consecutivo: int | ||||
|     prefijo: str | ||||
|  | ||||
|     def apply(self, fragment): | ||||
|         numero = f"{self.prefijo}{self.consecutivo}" | ||||
|         fragment.set_attributes('./NumeroSecuenciaXML', | ||||
|                                 # NIE010 | ||||
|                                 Prefijo=self.prefijo, | ||||
|                                 # NIE011 | ||||
|                                 Consecutivo=self.consecutivo, | ||||
|                                 # NIE012 | ||||
|                                 Numero = numero) | ||||
|  | ||||
| @dataclass | ||||
| class Periodo: | ||||
|     fecha_ingreso: typing.Union[str, Fecha] | ||||
|     fecha_liquidacion_inicio: typing.Union[str, Fecha] | ||||
|     fecha_liquidacion_fin: typing.Union[str, Fecha] | ||||
|     fecha_generacion: typing.Union[str, Fecha] | ||||
|  | ||||
|     tiempo_laborado: int = 1 | ||||
|     fecha_retiro: typing.Union[str, Fecha] = None | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         self.fecha_ingreso = Fecha.cast(self.fecha_ingreso) | ||||
|         self.fecha_liquidacion_inicio = Fecha.cast(self.fecha_liquidacion_inicio) | ||||
|         self.fecha_liquidacion_fin = Fecha.cast(self.fecha_liquidacion_fin) | ||||
|         self.fecha_retiro = Fecha.cast(self.fecha_retiro, optional=True) | ||||
|          | ||||
|     def apply(self, fragment): | ||||
|         fragment.set_attributes('./Periodo', | ||||
|                                 #NIE002 | ||||
|                                 FechaIngreso=self.fecha_ingreso, | ||||
|                                 #NIE003 | ||||
|                                 FechaRetiro=self.fecha_retiro, | ||||
|                                 #NIE004 | ||||
|                                 FechaLiquidacionInicio=self.fecha_liquidacion_inicio, | ||||
|                                 #NIE005 | ||||
|                                 FechaLiquidacionFin=self.fecha_liquidacion_fin, | ||||
|                                 #NIE006 | ||||
|                                 TiempoLaborado=self.tiempo_laborado, | ||||
|                                 #NIE008 | ||||
|                                 FechaGen=self.fecha_generacion) | ||||
|          | ||||
| @dataclass | ||||
| class Proveedor: | ||||
|     razon_social: str | ||||
|     nit: str | ||||
|     dv: int | ||||
|     software_id: str | ||||
|     software_pin: str | ||||
|  | ||||
|     def apply(self, fragment): | ||||
|         fragment.set_attributes('./ProveedorXML', | ||||
|                                 # NIE017 | ||||
|                                 NIT=self.nit, | ||||
|                                 # NIE018 | ||||
|                                 DV=self.dv, | ||||
|                                 # NIE019 | ||||
|                                 SoftwareID=self.software_id, | ||||
|  | ||||
|                                 SoftwareSC=None, | ||||
|                                 # NIE025 | ||||
|                                 RazonSocial=self.razon_social | ||||
|                                 ) | ||||
|  | ||||
|     def post_apply(self, fexml, scopexml, fragment): | ||||
|         cune_xpath = scopexml.xpath_from_root('/InformacionGeneral') | ||||
|         cune = fexml.get_element_attribute(cune_xpath, 'CUNE') | ||||
|          | ||||
|         ambiente = fexml.get_element_attribute(scopexml.xpath_from_root('/InformacionGeneral'), 'Ambiente') | ||||
|         codigo_qr = f"https://catalogo-vpfe.dian.gov.co/document/searchqr?documentkey={cune}" | ||||
|  | ||||
|         if InformacionGeneral.AMBIENTE_PRUEBAS.same(ambiente): | ||||
|             codigo_qr = f"https://catalogo-vpfe-hab.dian.gov.co/document/searchqr?documentkey={cune}" | ||||
|         elif ambiente is None: | ||||
|             raise RuntimeError('fail to get InformacionGeneral/@Ambiente') | ||||
|          | ||||
|         scopexml.set_element('./CodigoQR', codigo_qr) | ||||
|         scopexml.set_element('./Novedad', "false")         | ||||
|  | ||||
|         # NIE020 | ||||
|         software_code = self._software_security_code(fexml, scopexml) | ||||
|         fexml.set_attributes(scopexml.xpath_from_root('/ProveedorXML'), SoftwareSC=software_code) | ||||
|  | ||||
|     def _software_security_code(self, fexml, scopexml): | ||||
|          | ||||
|  | ||||
|         # 8.2 | ||||
|         numero = fexml.get_element_attribute(scopexml.xpath_from_root('/NumeroSecuenciaXML'), 'Numero') | ||||
|         if numero is None: | ||||
|             raise RuntimeError('fallo obtener NumeroSequenciaXML/@Numero') | ||||
|          | ||||
|         id_software = self.software_id | ||||
|         software_pin = self.software_pin | ||||
|  | ||||
|         code = "".join([id_software, software_pin, numero]) | ||||
|  | ||||
|         fexml.set_attributes(scopexml.xpath_from_root('/ProveedorXML')) | ||||
|         h = hashlib.sha384() | ||||
|         h.update(code.encode('utf-8')) | ||||
|         return h.hexdigest() | ||||
|      | ||||
| @dataclass | ||||
| class Metadata: | ||||
|     novedad: Novedad | ||||
|     secuencia: NumeroSecuencia | ||||
|     # NIE013, NIE014, NIE015, NIE016 | ||||
|     lugar_generacion: Lugar | ||||
|     proveedor: Proveedor | ||||
|  | ||||
|     def apply(self, novedad, numero_secuencia_xml, lugar_generacion_xml, proveedor_xml): | ||||
|         self.novedad.apply(novedad) | ||||
|         self.secuencia.apply(numero_secuencia_xml) | ||||
|         self.lugar_generacion.apply(lugar_generacion_xml, './LugarGeneracionXML') | ||||
|         self.proveedor.apply(proveedor_xml) | ||||
|  | ||||
|     def post_apply(self, fexml, scopexml, novedad, numero_secuencia_xml, lugar_generacion_xml, proveedor_xml): | ||||
|         self.proveedor.post_apply(fexml, scopexml, proveedor_xml) | ||||
|         self.novedad.post_apply(fexml, scopexml, proveedor_xml)         | ||||
|          | ||||
| @dataclass | ||||
| class PeriodoNomina: | ||||
|     code: str | ||||
|     name: str = '' | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         if self.code not in codelist.PeriodoNomina: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.PeriodoNomina[self.code]['name'] | ||||
|  | ||||
| @dataclass | ||||
| class TipoMoneda: | ||||
|     code: str | ||||
|     name: str = '' | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         if self.code not in codelist.TipoMoneda: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.TipoMoneda[self.code]['name'] | ||||
|  | ||||
| @dataclass | ||||
| class InformacionGeneral: | ||||
|     @dataclass | ||||
|     class TIPO_AMBIENTE: | ||||
|         valor: str | ||||
|  | ||||
|         @classmethod | ||||
|         def same(cls, value): | ||||
|             return cls.valor == str(value) | ||||
|  | ||||
|     # TABLA 5.1.1 | ||||
|     @dataclass | ||||
|     class AMBIENTE_PRODUCCION(TIPO_AMBIENTE): | ||||
|         valor: str = '1' | ||||
|  | ||||
|         def __str__(self): | ||||
|             self.valor | ||||
|  | ||||
|     @dataclass | ||||
|     class AMBIENTE_PRUEBAS(TIPO_AMBIENTE): | ||||
|         valor: str = '2' | ||||
|  | ||||
|         def __str__(self): | ||||
|             self.valor | ||||
|  | ||||
|     fecha_generacion: typing.Union[str, Fecha] | ||||
|     hora_generacion: str | ||||
|     periodo_nomina: PeriodoNomina | ||||
|     tipo_moneda: TipoMoneda | ||||
|     tipo_ambiente: TIPO_AMBIENTE | ||||
|     software_pin: str | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         self.fecha_generacion = Fecha.cast(self.fecha_generacion) | ||||
|  | ||||
|     def apply(self, fragment, version): | ||||
|         fragment.set_attributes('./InformacionGeneral', | ||||
|                                 # NIE022 | ||||
|                                 Version = version, | ||||
|                                 # NIE023 | ||||
|                                 Ambiente = self.tipo_ambiente.valor, | ||||
|                                 # NIE202 | ||||
|                                 # TABLA 5.5.2 | ||||
|                                 # TODO(bit4bit) solo NominaIndividual | ||||
|                                 TipoXML = '102', | ||||
|                                 # NIE024 | ||||
|                                 CUNE = None, | ||||
|                                 # NIE025 | ||||
|                                 EncripCUNE = 'CUNE-SHA384', | ||||
|                                 # NIE026 | ||||
|                                 FechaGen = self.fecha_generacion, | ||||
|                                 # NIE027 | ||||
|                                 HoraGen = self.hora_generacion, | ||||
|                                 # NIE029 | ||||
|                                 PeriodoNomina = self.periodo_nomina.code, | ||||
|                                 # NIE030 | ||||
|                                 TipoMoneda = self.tipo_moneda.code, | ||||
|                                 TRM = 0 | ||||
|                                 # TODO(bit4bit) resto... | ||||
|                                 # ..... | ||||
|                                 ) | ||||
|  | ||||
|     def post_apply(self, fexml, scopexml, fragment): | ||||
|         # generar cune | ||||
|         # ver 8.1.1.1 | ||||
|         xpaths = [ | ||||
|             scopexml.xpath_from_root('/NumeroSecuenciaXML/@Numero'), | ||||
|             scopexml.xpath_from_root('/InformacionGeneral/@FechaGen'), | ||||
|             scopexml.xpath_from_root('/InformacionGeneral/@HoraGen'), | ||||
|             scopexml.xpath_from_root('/DevengadosTotal'), | ||||
|             scopexml.xpath_from_root('/DeduccionesTotal'), | ||||
|             scopexml.xpath_from_root('/ComprobanteTotal'), | ||||
|             scopexml.xpath_from_root('/Empleador/@NIT'), | ||||
|             scopexml.xpath_from_root('/Trabajador/@NumeroDocumento'), | ||||
|             scopexml.xpath_from_root('/InformacionGeneral/@TipoXML'), | ||||
|             tuple([self.software_pin]), | ||||
|             scopexml.xpath_from_root('/InformacionGeneral/@Ambiente') | ||||
|         ] | ||||
|  | ||||
|         campos = fexml.get_elements_text_or_attributes(xpaths) | ||||
|  | ||||
|         cune = "".join(campos) | ||||
|  | ||||
|         h = hashlib.sha384() | ||||
|         h.update(cune.encode('utf-8')) | ||||
|         cune_hash = h.hexdigest() | ||||
|      | ||||
|         fragment.set_attributes( | ||||
|             './InformacionGeneral', | ||||
|             # NIE024 | ||||
|             CUNE = cune_hash | ||||
|         ) | ||||
|  | ||||
| class DianXMLExtensionSigner(fe.DianXMLExtensionSigner): | ||||
|  | ||||
|     def __init__(self, pkcs12_path, passphrase=None, localpolicy=True): | ||||
|         super().__init__(pkcs12_path, passphrase=passphrase, localpolicy=localpolicy) | ||||
|  | ||||
|     def _element_extension_content(self, fachoxml): | ||||
|         return fachoxml.builder.xpath(fachoxml.root, './ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent') | ||||
|  | ||||
|  | ||||
| class DIANNominaXML: | ||||
|     def __init__(self, tag_document, xpath_ajuste=None,schemaLocation=None): | ||||
|         self.informacion_general_version = None | ||||
|  | ||||
|         self.tag_document = tag_document | ||||
|         self.fexml = fe.FeXML(tag_document, 'dian:gov:co:facturaelectronica:NominaIndividual') | ||||
|  | ||||
|         if schemaLocation is not None: | ||||
|             self.fexml.root.set("SchemaLocation", schemaLocation)             | ||||
|  | ||||
|         # layout, la dian requiere que los elementos | ||||
|         # esten ordenados segun el anexo tecnico | ||||
|         self.fexml.placeholder_for('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent') | ||||
|         self.fexml.placeholder_for('./TipoNota', optional=True) | ||||
|  | ||||
|         self.root_fragment = self.fexml | ||||
|         if xpath_ajuste is not None: | ||||
|             self.root_fragment = self.fexml.fragment(xpath_ajuste) | ||||
|         self.root_fragment.placeholder_for('./ReemplazandoPredecesor', optional=True) | ||||
|         self.root_fragment.placeholder_for('./EliminandoPredecesor', optional=True) | ||||
|         self.root_fragment.placeholder_for('./Novedad', optional=False) | ||||
|         self.root_fragment.placeholder_for('./Periodo') | ||||
|         self.root_fragment.placeholder_for('./NumeroSecuenciaXML') | ||||
|         self.root_fragment.placeholder_for('./LugarGeneracionXML') | ||||
|         self.root_fragment.placeholder_for('./ProveedorXML') | ||||
|         self.root_fragment.placeholder_for('./CodigoQR') | ||||
|         self.root_fragment.placeholder_for('./InformacionGeneral') | ||||
|         self.root_fragment.placeholder_for('./Empleador') | ||||
|         self.root_fragment.placeholder_for('./Trabajador') | ||||
|         self.root_fragment.placeholder_for('./Pago') | ||||
|         self.root_fragment.placeholder_for('./FechasPagos') | ||||
|         self.root_fragment.placeholder_for('./Devengados/Basico') | ||||
|         self.root_fragment.placeholder_for('./Devengados/Transporte', optional=True) | ||||
|  | ||||
|         self.novedad = self.root_fragment.fragment('./Novedad') | ||||
|         self.informacion_general_xml = self.root_fragment.fragment('./InformacionGeneral') | ||||
|         self.periodo_xml = self.root_fragment.fragment('./Periodo') | ||||
|         self.fecha_pagos_xml = self.root_fragment.fragment('./FechasPagos') | ||||
|         self.numero_secuencia_xml = self.root_fragment.fragment('./NumeroSecuenciaXML') | ||||
|         self.lugar_generacion_xml = self.root_fragment.fragment('./LugarGeneracionXML') | ||||
|         self.proveedor_xml = self.root_fragment.fragment('./ProveedorXML') | ||||
|         self.empleador = self.root_fragment.fragment('./Empleador') | ||||
|         self.trabajador = self.root_fragment.fragment('./Trabajador') | ||||
|         self.pago_xml = self.root_fragment.fragment('./Pago') | ||||
|         self.devengados = self.root_fragment.fragment('./Devengados') | ||||
|         self.deducciones = self.root_fragment.fragment('./Deducciones') | ||||
|  | ||||
|         self.informacion_general = None | ||||
|         self.metadata = None | ||||
|  | ||||
|     def asignar_metadata(self, metadata): | ||||
|         if not isinstance(metadata, Metadata): | ||||
|             raise ValueError('se espera tipo Metadata') | ||||
|         self.metadata = metadata | ||||
|         self.metadata.apply(self.novedad, self.numero_secuencia_xml, self.lugar_generacion_xml, self.proveedor_xml) | ||||
|          | ||||
|     def asignar_informacion_general(self, general): | ||||
|         if not isinstance(general, InformacionGeneral): | ||||
|             raise ValueError('se espera tipo InformacionGeneral') | ||||
|         self.informacion_general = general | ||||
|         self.informacion_general.apply(self.informacion_general_xml, self.informacion_general_version) | ||||
|  | ||||
|     def asignar_periodo(self, periodo): | ||||
|         if not isinstance(periodo, Periodo): | ||||
|             raise ValueError('se espera tipo Periodo') | ||||
|  | ||||
|         periodo.apply(self.periodo_xml) | ||||
|  | ||||
|     def asignar_pago(self, pago): | ||||
|         if not isinstance(pago, Pago): | ||||
|             raise ValueError('se espera tipo Pago') | ||||
|         pago.apply(self.pago_xml) | ||||
|  | ||||
|     def asignar_fecha_pago(self, data): | ||||
|         if isinstance(data, str): | ||||
|             fecha = FechaPago(data) | ||||
|         elif isinstance(data, FechaPago): | ||||
|             fecha = data | ||||
|  | ||||
|         fecha.apply(self.fecha_pagos_xml) | ||||
|  | ||||
|     def asignar_empleador(self, empleador): | ||||
|         if not isinstance(empleador, Empleador): | ||||
|             raise ValueError('se espera tipo Empleador') | ||||
|         empleador.apply(self.empleador) | ||||
|  | ||||
|     def asignar_trabajador(self, trabajador): | ||||
|         if not isinstance(trabajador, Trabajador): | ||||
|             raise ValueError('se espera tipo Trabajador') | ||||
|         trabajador.apply(self.trabajador) | ||||
|          | ||||
|     def adicionar_devengado(self, devengado): | ||||
|         if not isinstance(devengado, Devengado): | ||||
|             raise ValueError('se espera tipo Devengado') | ||||
|  | ||||
|         devengado.apply(self.devengados) | ||||
|  | ||||
|     def adicionar_deduccion(self, deduccion): | ||||
|         if not isinstance(deduccion, Deduccion): | ||||
|             raise ValueError('se espera tipo Devengado') | ||||
|  | ||||
|         deduccion.apply(self.deducciones) | ||||
|  | ||||
|     def validate(self): | ||||
|         """ | ||||
|         Valida requisitos segun anexo tecnico | ||||
|         """ | ||||
|         errors = [] | ||||
|  | ||||
|         def check_element(xpath, msg): | ||||
|             if not self.fexml.exist_element(xpath): | ||||
|                 errors.append(DIANNominaIndividualError(msg)) | ||||
|  | ||||
|         def check_attribute(xpath, key, msg): | ||||
|             err = DIANNominaIndividualError(msg) | ||||
|             elem = self.fexml.get_element(xpath) | ||||
|  | ||||
|             if elem is None: | ||||
|                 return errors.append(err) | ||||
|  | ||||
|             if elem.get(key, None) is None: | ||||
|                 return errors.append(err) | ||||
|  | ||||
|         check_attribute( | ||||
|             self.fexml.xpath_from_root('/Periodo'), | ||||
|             'FechaIngreso', | ||||
|             'se requiere Periodo') | ||||
|  | ||||
|         check_element( | ||||
|             self.fexml.xpath_from_root('/Pago'), | ||||
|             'se requiere Pago' | ||||
|         ) | ||||
|  | ||||
|         check_element( | ||||
|             self.fexml.xpath_from_root('/Devengados/Basico'), | ||||
|             'se requiere DevengadoBasico' | ||||
|         ) | ||||
|          | ||||
|         check_element( | ||||
|             self.fexml.xpath_from_root('/Deducciones/Salud'), | ||||
|             'se requiere DeduccionSalud' | ||||
|         ) | ||||
|  | ||||
|         check_element( | ||||
|             self.fexml.xpath_from_root('/Deducciones/FondoPension'), | ||||
|             'se requiere DeduccionFondoPension' | ||||
|         ) | ||||
|  | ||||
|         return errors | ||||
|  | ||||
|     def informacion_general(self): | ||||
|         xpath = self.root_fragment.xpath_from_root('/InformacionGeneral') | ||||
|         return { | ||||
|             'cune': self.fexml.get_element_attribute(cune_xpath, 'CUNE'), | ||||
|             'fecha_generacion': self.fexml.get_element_attribute(xpath, 'FechaGen'), | ||||
|             'numero': self.fexml.get_element_attribute(self.root_fragment('/NumeroSecuenciaXML', 'Numero')) | ||||
|         } | ||||
|  | ||||
|     def toFachoXML(self): | ||||
|         self._devengados_total() | ||||
|         self._deducciones_total() | ||||
|         self._comprobante_total() | ||||
|  | ||||
|         if self.informacion_general is not None: | ||||
|             #TODO(bit4bit) acoplamiento temporal | ||||
|             # es importante el orden de ejecucion | ||||
|  | ||||
|             self.informacion_general.post_apply(self.fexml, self.root_fragment, self.informacion_general_xml) | ||||
|  | ||||
|         if self.metadata is not None: | ||||
|             self.metadata.post_apply(self.fexml, self.root_fragment, self.novedad, self.numero_secuencia_xml, self.lugar_generacion_xml, self.proveedor_xml) | ||||
|  | ||||
|         return self.fexml | ||||
|  | ||||
|     def _comprobante_total(self): | ||||
|         devengados_total = self.root_fragment.get_element_text_or_attribute('./DevengadosTotal', '0.0') | ||||
|         deducciones_total = self.root_fragment.get_element_text_or_attribute('./DeduccionesTotal', '0.0') | ||||
|  | ||||
|         comprobante_total = Amount(devengados_total) - Amount(deducciones_total) | ||||
|  | ||||
|         self.root_fragment.set_element('./ComprobanteTotal', str(round(comprobante_total, 2))) | ||||
|  | ||||
|     def _deducciones_total(self): | ||||
|         xpaths = [ | ||||
|             self.root_fragment.xpath_from_root('/Deducciones/Salud/@Deduccion'), | ||||
|             self.root_fragment.xpath_from_root('/Deducciones/FondoPension/@Deduccion') | ||||
|         ] | ||||
|         deducciones = map(lambda valor: Amount(valor), | ||||
|                           self._values_of_xpaths(xpaths)) | ||||
|  | ||||
|         deducciones_total = Amount(0.0) | ||||
|          | ||||
|         for deduccion in deducciones: | ||||
|             deducciones_total += deduccion | ||||
|  | ||||
|         self.root_fragment.set_element('./DeduccionesTotal', str(round(deducciones_total, 2))) | ||||
|  | ||||
|     def _devengados_total(self): | ||||
|         xpaths = [ | ||||
|             self.root_fragment.xpath_from_root('/Devengados/Basico/@SueldoTrabajado'), | ||||
|             self.root_fragment.xpath_from_root('/Devengados/Transporte/@AuxilioTransporte'), | ||||
|             self.root_fragment.xpath_from_root('/Devengados/Transporte/@ViaticoManuAlojS'), | ||||
|             self.root_fragment.xpath_from_root('/Devengados/Transporte/@ViaticoManuAlojNS') | ||||
|         ] | ||||
|         devengados = map(lambda valor: Amount(valor), | ||||
|                          self._values_of_xpaths(xpaths)) | ||||
|          | ||||
|         devengados_total = Amount(0.0) | ||||
|         for devengado in devengados: | ||||
|             devengados_total += devengado | ||||
|         # TODO(bit4bit) nque valor va redondeado? | ||||
|         # NIE186 | ||||
|         self.root_fragment.set_element('./Redondeo', str(round(0,2)))           | ||||
|         self.root_fragment.set_element('./DevengadosTotal', str(round(devengados_total,2))) | ||||
|  | ||||
|     def _values_of_xpaths(self, xpaths): | ||||
|         xpaths_values_of_values = map(lambda val: self.fexml.get_element_text_or_attribute(val, multiple=True), xpaths) | ||||
|         xpaths_values = [] | ||||
|         # toda esta carreta para hacer un aplano de lista | ||||
|         for xpath_values in xpaths_values_of_values: | ||||
|             if xpath_values is None: | ||||
|                 continue | ||||
|  | ||||
|             for xpath_value in xpath_values: | ||||
|                 xpaths_values.append(xpath_value) | ||||
|  | ||||
|         return filter(lambda val: val is not None, xpaths_values) | ||||
|  | ||||
| class DIANNominaIndividual(DIANNominaXML): | ||||
|  | ||||
|     def __init__(self): | ||||
|         schema = "dian:gov:co:facturaelectronica:NominaIndividual" | ||||
|  | ||||
|         super().__init__('NominaIndividual', schemaLocation=schema) | ||||
|         self.informacion_general_version = 'V1.0: Documento Soporte de Pago de Nómina Electrónica' | ||||
|  | ||||
| # TODO(bit4bit) confirmar que no tienen en comun con NominaIndividual | ||||
| class DIANNominaIndividualDeAjuste(DIANNominaXML): | ||||
|  | ||||
|     class Reemplazar(DIANNominaXML): | ||||
|         @dataclass | ||||
|         class Predecesor: | ||||
|             numero: str | ||||
|             cune: str | ||||
|             fecha_generacion: str | ||||
|  | ||||
|             def apply(self, fragment): | ||||
|                 fragment.set_element('./Reemplazar/ReemplazandoPredecesor', None, | ||||
|                                      # NIAE090 | ||||
|                                      NumeroPred = self.numero, | ||||
|                                      # NIAE191 | ||||
|                                      CUNEPred = self.cune, | ||||
|                                      # NIAE192 | ||||
|                                      FechaGenPred = self.fecha_generacion | ||||
|                                      ) | ||||
|  | ||||
|         def __init__(self): | ||||
|             super().__init__('NominaIndividualDeAjuste', './Reemplazar') | ||||
|             # NIAE214 | ||||
|             self.root_fragment.set_element('./TipoNota', '1') | ||||
|  | ||||
|         def asignar_predecesor(self, predecesor): | ||||
|             if not isinstance(predecesor, self.Predecesor): | ||||
|                 raise ValueError("se espera tipo Predecesor") | ||||
|             predecesor.apply(self.fexml) | ||||
|  | ||||
|          | ||||
|     class Eliminar(DIANNominaXML): | ||||
|          | ||||
|         @dataclass | ||||
|         class Predecesor: | ||||
|             numero: str | ||||
|             cune: str | ||||
|             fecha_generacion: str | ||||
|  | ||||
|             def apply(self, fragment): | ||||
|                 fragment.set_element('./Eliminar/EliminandoPredecesor', None, | ||||
|                                      # NIAE090 | ||||
|                                      NumeroPred = self.numero, | ||||
|                                      # NIAE191 | ||||
|                                      CUNEPred = self.cune, | ||||
|                                      # NIAE192 | ||||
|                                      FechaGenPred = self.fecha_generacion | ||||
|                                      ) | ||||
|  | ||||
|         def __init__(self): | ||||
|             super().__init__('NominaIndividualDeAjuste', './Eliminar') | ||||
|  | ||||
|             self.root_fragment.set_element('./TipoNota', '2') | ||||
|             self.informacion_general_version = "V1.0: Nota de Ajuste de Documento Soporte de Pago de Nómina Electrónica" | ||||
|  | ||||
|         def asignar_predecesor(self, predecesor): | ||||
|             if not isinstance(predecesor, self.Predecesor): | ||||
|                 raise ValueError("se espera tipo Eliminar.Predecesor") | ||||
|             predecesor.apply(self.fexml) | ||||
|              | ||||
|     def __init__(self): | ||||
|         super().__init__('NominaIndividualDeAjuste') | ||||
|  | ||||
| @@ -1,4 +0,0 @@ | ||||
| from .. import form | ||||
|  | ||||
| class Amount(form.Amount): | ||||
|     pass | ||||
| @@ -1,3 +0,0 @@ | ||||
| # contributing | ||||
|  | ||||
| crear nuevo objeto de valor y exportar en **__init__.py** atributo **__all__**. | ||||
| @@ -1,13 +0,0 @@ | ||||
| # | ||||
| # al crear objetos de valor | ||||
| # se debe exportar en __all__ | ||||
|  | ||||
| from .deduccion import * | ||||
| from .salud import * | ||||
| from .fondo_pension import * | ||||
|  | ||||
| __all__ = [ | ||||
|     'Deduccion', | ||||
|     'DeduccionSalud', | ||||
|     'DeduccionFondoPension' | ||||
| ] | ||||
| @@ -1,2 +0,0 @@ | ||||
| class Deduccion: | ||||
|     pass | ||||
| @@ -1,18 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from ..amount import Amount | ||||
| from .deduccion import Deduccion | ||||
|  | ||||
| @dataclass | ||||
| class DeduccionFondoPension(Deduccion): | ||||
|     porcentaje: Amount | ||||
|     deduccion: Amount | ||||
|  | ||||
|     def apply(self, fragment): | ||||
|         fragment.set_element('./FondoPension', None, | ||||
|                              append_ = True, | ||||
|                              # NIE164 | ||||
|                              Porcentaje = str(round(self.porcentaje, 2)), | ||||
|                              #  NIE166 | ||||
|                              Deduccion = self.deduccion | ||||
|                              ) | ||||
| @@ -1,19 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from ..amount import Amount | ||||
| from .deduccion import Deduccion | ||||
|  | ||||
| @dataclass | ||||
| class DeduccionSalud(Deduccion): | ||||
|     porcentaje: Amount | ||||
|     deduccion: Amount | ||||
|  | ||||
|     def apply(self, fragment): | ||||
|         fragment.set_element('./Salud', None, | ||||
|                              append_ = True, | ||||
|                              # NIE161 | ||||
|                              Porcentaje = str(round(self.porcentaje, 2)), | ||||
|                              #  NIE163 | ||||
|                              Deduccion = self.deduccion | ||||
|                              ) | ||||
|  | ||||
| @@ -1,4 +0,0 @@ | ||||
| from .. import form | ||||
|  | ||||
| class Departamento(form.CountrySubentity): | ||||
|     pass | ||||
| @@ -1,3 +0,0 @@ | ||||
| # contributing | ||||
|  | ||||
| crear nuevo objeto de valor y exportar en **__init__.py** atributo **__all__**. | ||||
| @@ -1,19 +0,0 @@ | ||||
|  | ||||
| from .basico import * | ||||
| from .transporte import * | ||||
| from .devengado import * | ||||
| from .horas_extras import * | ||||
|  | ||||
| __all__ = [ | ||||
|     'Devengado', | ||||
|     'DevengadoBasico', | ||||
|     'DevengadoTransporte', | ||||
|     'DevengadoHoraExtra', | ||||
|     'DevengadoHorasExtrasDiarias', | ||||
|     'DevengadoHorasExtrasNocturnas', | ||||
|     'DevengadoHorasRecargoNocturno', | ||||
|     'DevengadoHorasExtrasDiariasDominicalesYFestivos', | ||||
|     'DevengadoHorasRecargoDiariasDominicalesYFestivos', | ||||
|     'DevengadoHorasExtrasNocturnasDominicalesYFestivos', | ||||
|     'DevengadoHorasRecargoNocturnoDominicalesYFestivos' | ||||
| ] | ||||
| @@ -1,20 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from ..amount import Amount | ||||
| from .devengado import Devengado | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class DevengadoBasico(Devengado): | ||||
|     dias_trabajados: int | ||||
|     sueldo_trabajado: Amount | ||||
|  | ||||
|     def apply(self, fragment): | ||||
|         fragment.find_or_create_element('./Basico') | ||||
|          | ||||
|         fragment.set_attributes('/Basico', | ||||
|                                 # NIE069 | ||||
|                                 DiasTrabajados = str(self.dias_trabajados), | ||||
|                                 # NIE070 | ||||
|                                 SueldoTrabajado = round(self.sueldo_trabajado, 2) | ||||
|                                 ) | ||||
| @@ -1,2 +0,0 @@ | ||||
| class Devengado: | ||||
|     pass | ||||
| @@ -1,93 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
| from typing import List | ||||
|  | ||||
| from ..amount import Amount | ||||
| from .devengado import Devengado | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class DevengadoHoraExtra: | ||||
|     hora_inicio: str | ||||
|     hora_fin: str | ||||
|     cantidad: int | ||||
|     porcentaje: Amount | ||||
|     pago: Amount | ||||
|  | ||||
|     def apply(self, child_path, fragment): | ||||
|         fragment.set_element(child_path, None, | ||||
|                              append_=True, | ||||
|                              # NIE074 | ||||
|                              HoraInicio=self.hora_inicio, | ||||
|                              # NIE075 | ||||
|                              HoraFin=self.hora_fin, | ||||
|                              # NIE076 | ||||
|                              Cantidad=self.cantidad, | ||||
|                              # NIE077 | ||||
|                              Porcentaje=str(round(self.porcentaje, 2)), | ||||
|                              # NIE078 | ||||
|                              Pago=str(round(self.pago, 2))) | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class DevengadoHorasExtrasDiarias(Devengado): | ||||
|     horas_extras: List[DevengadoHoraExtra] | ||||
|      | ||||
|     def apply(self, fragment): | ||||
|         hora_extra_xml = fragment.fragment('./HEDs') | ||||
|         for hora_extra in self.horas_extras: | ||||
|             hora_extra.apply('./HED', hora_extra_xml) | ||||
|  | ||||
| @dataclass | ||||
| class DevengadoHorasExtrasNocturnas(Devengado): | ||||
|     horas_extras: List[DevengadoHoraExtra] | ||||
|      | ||||
|     def apply(self, fragment): | ||||
|         hora_extra_xml = fragment.fragment('./HENs') | ||||
|         for hora_extra in self.horas_extras: | ||||
|             hora_extra.apply('./HEN', hora_extra_xml) | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class DevengadoHorasRecargoNocturno(Devengado): | ||||
|     horas_extras: List[DevengadoHoraExtra] | ||||
|      | ||||
|     def apply(self, fragment): | ||||
|         hora_extra_xml = fragment.fragment('./HRNs') | ||||
|         for hora_extra in self.horas_extras: | ||||
|             hora_extra.apply('./HRN', hora_extra_xml) | ||||
|  | ||||
| @dataclass | ||||
| class DevengadoHorasExtrasDiariasDominicalesYFestivos(Devengado): | ||||
|     horas_extras: List[DevengadoHoraExtra] | ||||
|      | ||||
|     def apply(self, fragment): | ||||
|         hora_extra_xml = fragment.fragment('./HEDDFs') | ||||
|         for hora_extra in self.horas_extras: | ||||
|             hora_extra.apply('./HEDDF', hora_extra_xml) | ||||
|  | ||||
| @dataclass | ||||
| class DevengadoHorasRecargoDiariasDominicalesYFestivos(Devengado): | ||||
|     horas_extras: List[DevengadoHoraExtra] | ||||
|      | ||||
|     def apply(self, fragment): | ||||
|         hora_extra_xml = fragment.fragment('./HRDDFs') | ||||
|         for hora_extra in self.horas_extras: | ||||
|             hora_extra.apply('./HRDDF', hora_extra_xml) | ||||
|  | ||||
| @dataclass | ||||
| class DevengadoHorasExtrasNocturnasDominicalesYFestivos(Devengado): | ||||
|     horas_extras: List[DevengadoHoraExtra] | ||||
|      | ||||
|     def apply(self, fragment): | ||||
|         hora_extra_xml = fragment.fragment('./HENDFs') | ||||
|         for hora_extra in self.horas_extras: | ||||
|             hora_extra.apply('./HENDF', hora_extra_xml) | ||||
|  | ||||
| @dataclass | ||||
| class DevengadoHorasRecargoNocturnoDominicalesYFestivos(Devengado): | ||||
|     horas_extras: List[DevengadoHoraExtra] | ||||
|      | ||||
|     def apply(self, fragment): | ||||
|         hora_extra_xml = fragment.fragment('./HRNDFs') | ||||
|         for hora_extra in self.horas_extras: | ||||
|             hora_extra.apply('./HRNDF', hora_extra_xml) | ||||
| @@ -1,21 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from ..amount import Amount | ||||
| from .devengado import Devengado | ||||
|  | ||||
| @dataclass | ||||
| class DevengadoTransporte(Devengado): | ||||
|     auxilio_transporte: Amount = None | ||||
|     viatico_manutencion: Amount = None | ||||
|     viatico_manutencion_no_salarial: Amount = None | ||||
|  | ||||
|     def apply(self, fragment): | ||||
|         fragment.set_element('./Transporte', None, | ||||
|                              append_ = True, | ||||
|                              # NIE071 | ||||
|                              AuxilioTransporte = self.auxilio_transporte, | ||||
|                              # NIE072 | ||||
|                              ViaticoManuAlojS = self.viatico_manutencion, | ||||
|                              # NIE073 | ||||
|                              ViaticoManuAlojNS = self.viatico_manutencion_no_salarial | ||||
|                              ) | ||||
| @@ -1,35 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from ..pais import Pais | ||||
| from ..departamento import Departamento | ||||
| from ..municipio import Municipio | ||||
|  | ||||
| @dataclass | ||||
| class Empleador: | ||||
|     razon_social: str | ||||
|     nit: str | ||||
|     dv: str | ||||
|     pais: Pais | ||||
|     departamento: Departamento | ||||
|     municipio: Municipio | ||||
|     direccion: str | ||||
|  | ||||
|     def apply(self, fragment): | ||||
|         fragment.set_attributes('./Empleador', | ||||
|                                 # NIE033 | ||||
|                                 NIT = self.nit, | ||||
|                                 # NIE034 | ||||
|                                 DV = self.dv, | ||||
|                                 # NIE035 | ||||
|                                 Pais = self.pais.code, | ||||
|                                 # NIE036 | ||||
|                                 DepartamentoEstado = self.departamento.code, | ||||
|                                 # NIE037 | ||||
|                                 MunicipioCiudad = self.municipio.code, | ||||
|                                 # NIE038 | ||||
|                                 Direccion = self.direccion, | ||||
|  | ||||
|                                 RazonSocial=self.razon_social | ||||
|                                 ) | ||||
|  | ||||
|  | ||||
| @@ -1,2 +0,0 @@ | ||||
| class DIANNominaIndividualError(Exception): | ||||
|     pass | ||||
| @@ -1,155 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
| import datetime | ||||
|  | ||||
| from facho import fe | ||||
|  | ||||
| class Habilitacion: | ||||
|  | ||||
|     @dataclass | ||||
|     class Metadata: | ||||
|         software_pin: str | ||||
|         software_id: str | ||||
|         nit: str | ||||
|         dv: str | ||||
|  | ||||
|     def __init__(self, metadata): | ||||
|         self.metadata = metadata | ||||
|  | ||||
|     def generar(self, zipname, fecha): | ||||
|         nominas = [] | ||||
|         dianzip = fe.DianZIP(open(zipname, 'w')) | ||||
|  | ||||
|         fechabase = datetime.datetime.now() | ||||
|         consecutivo = 0 | ||||
|         for _ in range(1, 11): | ||||
|             consecutivo += 1 | ||||
|             fechabase += datetime.timedelta(days=1) | ||||
|             nomina = self._crear_nomina_individual() | ||||
|  | ||||
|             # pag 96 | ||||
|             nombre = "nie%010d%s%08x.xml" % (int(self.nit), fecha.strftime('%s'), consecutivo) | ||||
|          | ||||
|     def _crear_nomina_individual_reemplazar(self, nomina, fechabase): | ||||
|         metadata = self.metadata | ||||
|  | ||||
|         fecha = fechabase.strftime('%Y-%m-%d') | ||||
|  | ||||
|         nomina_ajuste = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar() | ||||
|         self._poblar_nomina(nomina_ajuste, metadata, fecha, prefijo='R') | ||||
|         informacion_general = nomina.informacion_general() | ||||
|          | ||||
|          | ||||
|     def _poblar_nomina(self, nomina, metadata, fecha, prefijo='N', consecutivo='0001'): | ||||
|         nomina.asignar_fecha_pago(fecha) | ||||
|  | ||||
|         nomina.asignar_metadata(fe.nomina.Metadata( | ||||
|             secuencia=fe.nomina.NumeroSecuencia( | ||||
|                 prefijo=prefijo, | ||||
|                 consecutivo=consecutivo | ||||
|             ), | ||||
|             lugar_generacion=fe.nomina.Lugar( | ||||
|                 pais = fe.nomina.Pais( | ||||
|                     code = 'CO' | ||||
|                 ), | ||||
|                 departamento = fe.nomina.Departamento( | ||||
|                     code = '05' | ||||
|                 ), | ||||
|                 municipio = fe.nomina.Municipio( | ||||
|                     code = '05001' | ||||
|                 ), | ||||
|             ), | ||||
|             proveedor=fe.nomina.Proveedor( | ||||
|                 nit=metadata.nit, | ||||
|                 dv=metadata.dv, | ||||
|                 software_id=metadata.software_id, | ||||
|                 software_pin=metadata.software_pin | ||||
|             ) | ||||
|         )) | ||||
|  | ||||
|         nomina.asignar_periodo(fe.nomina.Periodo( | ||||
|             fecha_ingreso=fecha, | ||||
|             fecha_liquidacion_inicio=fecha, | ||||
|             fecha_liquidacion_fin=fecha, | ||||
|             fecha_generacion=fecha, | ||||
|         )) | ||||
|          | ||||
|         nomina.asignar_informacion_general(fe.nomina.InformacionGeneral( | ||||
|             fecha_generacion = fecha, | ||||
|             hora_generacion = '20:09:00-05:00', | ||||
|             tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRUEBAS, | ||||
|             software_pin = metadata.software_pin, | ||||
|             periodo_nomina = fe.nomina.PeriodoNomina(code='1'), | ||||
|             tipo_moneda = fe.nomina.TipoMoneda(code='COP') | ||||
|         )) | ||||
|  | ||||
|         nomina.asignar_pago(fe.nomina.Pago( | ||||
|             forma=fe.nomina.FormaPago( | ||||
|                 code='1', | ||||
|             ), | ||||
|             metodo=fe.nomina.MetodoPago( | ||||
|                 code='10' | ||||
|             ) | ||||
|         )) | ||||
|         nomina.asignar_empleador(fe.nomina.Empleador( | ||||
|             nit = metadata.nit, | ||||
|             dv = '0', | ||||
|             pais = fe.nomina.Pais( | ||||
|                 code = 'CO' | ||||
|             ), | ||||
|             departamento = fe.nomina.Departamento( | ||||
|                 code = '05' | ||||
|             ), | ||||
|             municipio = fe.nomina.Municipio( | ||||
|                 code = '05001' | ||||
|             ), | ||||
|             direccion = 'calle etrivial' | ||||
|         )) | ||||
|  | ||||
|         nomina.asignar_trabajador(fe.nomina.Trabajador( | ||||
|             tipo_contrato = fe.nomina.TipoContrato( | ||||
|                 code = '1' | ||||
|             ), | ||||
|             alto_riesgo = False, | ||||
|             tipo_documento = fe.nomina.TipoDocumento( | ||||
|                 code = '11' | ||||
|             ), | ||||
|             primer_apellido = 'gnu', | ||||
|             segundo_apellido = 'emacs', | ||||
|             primer_nombre = 'facho', | ||||
|             lugar_trabajo = fe.nomina.LugarTrabajo( | ||||
|                 pais = fe.nomina.Pais(code='CO'), | ||||
|                 departamento = fe.nomina.Departamento(code='05'), | ||||
|                 municipio = fe.nomina.Municipio(code='05001'), | ||||
|                 direccion = 'calle facho' | ||||
|             ), | ||||
|             numero_documento = metadata.nit, | ||||
|             tipo = fe.nomina.TipoTrabajador( | ||||
|                 code = '01' | ||||
|             ), | ||||
|             salario_integral = True, | ||||
|             sueldo = fe.nomina.Amount(1_500_000) | ||||
|         )) | ||||
|          | ||||
|         nomina.adicionar_devengado(fe.nomina.DevengadoBasico( | ||||
|             dias_trabajados = 60, | ||||
|             sueldo_trabajado = fe.nomina.Amount(3_500_000) | ||||
|         )) | ||||
|  | ||||
|         nomina.adicionar_deduccion(fe.nomina.DeduccionSalud( | ||||
|             porcentaje = fe.nomina.Amount(19), | ||||
|             deduccion = fe.nomina.Amount(1_000_000) | ||||
|         )) | ||||
|  | ||||
|         nomina.adicionar_deduccion(fe.nomina.DeduccionFondoPension( | ||||
|             porcentaje=fe.nomina.Amount(1), | ||||
|             deduccion=fe.nomina.Amount(10) | ||||
|         )) | ||||
|  | ||||
|     def _crear_nomina_individual(self, fechabase): | ||||
|         metadata = self.metadata | ||||
|  | ||||
|         fecha = fechabase.strftime('%Y-%m-%d') | ||||
|  | ||||
|         nomina = fe.nomina.DIANNominaIndividual() | ||||
|         self._poblar_nomina(nomina, metadata, fecha) | ||||
|                  | ||||
| @@ -1,25 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from .pais import Pais | ||||
| from .departamento import Departamento | ||||
| from .municipio import Municipio | ||||
| from facho.fe.data.dian import codelist | ||||
|  | ||||
| @dataclass | ||||
| class Lugar: | ||||
|     pais: Pais | ||||
|     departamento: Departamento | ||||
|     municipio: Municipio | ||||
|     idioma: str = 'es' | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         if self.idioma not in codelist.IdiomaISO6391: | ||||
|             raise ValueError("idioma [%s] not found" % (self.code)) | ||||
|         codelist.IdiomaISO6391[self.idioma]['iso-639-1'] | ||||
|  | ||||
|     def apply(self, fragment, root): | ||||
|         fragment.set_attributes(root, | ||||
|                                 Pais=self.pais.code, | ||||
|                                 DepartamentoEstado=self.departamento.code, | ||||
|                                 MunicipioCiudad=self.municipio.code, | ||||
|                                 Idioma=self.idioma) | ||||
| @@ -1,5 +0,0 @@ | ||||
| from .. import form | ||||
|  | ||||
| class Municipio(form.City): | ||||
|     pass | ||||
|  | ||||
| @@ -1,16 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from .forma_pago import FormaPago | ||||
| from .metodo_pago import MetodoPago | ||||
|  | ||||
| @dataclass | ||||
| class Pago: | ||||
|     forma: FormaPago | ||||
|     metodo: MetodoPago | ||||
|  | ||||
|     def apply(self, fragment): | ||||
|         fragment.set_attributes('./Pago', | ||||
|                                 # NIE064 | ||||
|                                 Forma = self.forma.code, | ||||
|                                 # NIE065 | ||||
|                                 Metodo = self.metodo.code) | ||||
| @@ -1,13 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from facho.fe.data.dian import codelist | ||||
|  | ||||
| @dataclass | ||||
| class FormaPago: | ||||
|     code: str | ||||
|     name: str = '' | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         if self.code not in codelist.FormasPago: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.FormasPago[self.code]['name'] | ||||
| @@ -1,14 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from facho.fe.data.dian import codelist | ||||
|  | ||||
| @dataclass | ||||
| class MetodoPago: | ||||
|     code: str | ||||
|     name: str = '' | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         if self.code not in codelist.MediosPago: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.MediosPago[self.code]['name'] | ||||
|  | ||||
| @@ -1,4 +0,0 @@ | ||||
| from .. import form | ||||
|  | ||||
| class Pais(form.Country): | ||||
|     pass | ||||
| @@ -1,73 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from ..amount import Amount | ||||
|  | ||||
| from .tipo_contrato import * | ||||
| from .tipo_documento import * | ||||
| from .lugar_trabajo import * | ||||
| from .tipo_trabajador import * | ||||
| from .sub_tipo_trabajador import * | ||||
|  | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Trabajador: | ||||
|     tipo_contrato: TipoContrato | ||||
|     tipo_documento: TipoDocumento | ||||
|     numero_documento: str | ||||
|  | ||||
|     primer_apellido: str | ||||
|     segundo_apellido: str | ||||
|     primer_nombre: str | ||||
|  | ||||
|     lugar_trabajo: LugarTrabajo | ||||
|     alto_riesgo: bool | ||||
|     salario_integral: bool | ||||
|     sueldo: Amount | ||||
|  | ||||
|     tipo: TipoTrabajador | ||||
|  | ||||
|     codigo_trabajador: str = None | ||||
|     otros_nombres: str = None | ||||
|     sub_tipo: SubTipoTrabajador = SubTipoTrabajador(code='00') | ||||
|  | ||||
|     def apply(self, fragment): | ||||
|         fragment.set_attributes('./Trabajador', | ||||
|                                 # NIE041 | ||||
|                                 TipoTrabajador = self.tipo.code, | ||||
|                                 # NIE042 | ||||
|                                 SubTipoTrabajador = self.sub_tipo.code, | ||||
|                                 # NIE043 | ||||
|                                 AltoRiesgoPension = str(self.alto_riesgo).lower(), | ||||
|                                 # NIE044 | ||||
|                                 TipoDocumento = self.tipo_documento.code, | ||||
|                                 # NIE045 | ||||
|                                 NumeroDocumento = self.numero_documento, | ||||
|                                 # NIE046 | ||||
|                                 PrimerApellido = self.primer_apellido, | ||||
|                                 # NIE047 | ||||
|                                 SegundoApellido = self.segundo_apellido, | ||||
|                                 # NIE048 | ||||
|                                 PrimerNombre = self.primer_nombre, | ||||
|                                 # NIE049 | ||||
|                                 OtrosNombres = self.otros_nombres, | ||||
|                                 # NIE050 | ||||
|                                 LugarTrabajoPais = self.lugar_trabajo.pais.code, | ||||
|  | ||||
|                                 # NIE051 | ||||
|                                 LugarTrabajoDepartamentoEstado = self.lugar_trabajo.departamento.code, | ||||
|  | ||||
|                                 # NIE052 | ||||
|                                 LugarTrabajoMunicipioCiudad = self.lugar_trabajo.municipio.code, | ||||
|  | ||||
|                                 # NIE053 | ||||
|                                 LugarTrabajoDireccion = self.lugar_trabajo.direccion, | ||||
|                                 # NIE056 | ||||
|                                 SalarioIntegral = str(self.salario_integral).lower(), | ||||
|                                 # NIE061 | ||||
|                                 TipoContrato = self.tipo_contrato.code, | ||||
|                                 # NIE062 | ||||
|                                 Sueldo = str(self.sueldo), | ||||
|                                 # NIE063 | ||||
|                                 CodigoTrabajador = self.codigo_trabajador | ||||
|                                 ) | ||||
| @@ -1,13 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from . import * | ||||
| from ..pais import Pais | ||||
| from ..departamento import Departamento | ||||
| from ..municipio import Municipio | ||||
|  | ||||
| @dataclass | ||||
| class LugarTrabajo: | ||||
|     pais: Pais | ||||
|     departamento: Departamento | ||||
|     municipio: Municipio | ||||
|     direccion: str | ||||
| @@ -1,13 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from facho.fe.data.dian import codelist | ||||
|  | ||||
| @dataclass | ||||
| class SubTipoTrabajador: | ||||
|     code: str | ||||
|     name: str = '' | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         if self.code not in codelist.SubTipoTrabajador: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.SubTipoTrabajador[self.code]['name'] | ||||
| @@ -1,15 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from facho.fe.data.dian import codelist | ||||
|  | ||||
| @dataclass | ||||
| class TipoContrato: | ||||
|     code: str | ||||
|     name: str = '' | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         if self.code not in codelist.TipoContrato: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.TipoContrato[self.code]['name'] | ||||
|  | ||||
|  | ||||
| @@ -1,13 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from facho.fe.data.dian import codelist | ||||
|  | ||||
| @dataclass | ||||
| class TipoDocumento: | ||||
|     code: str | ||||
|     name: str = '' | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         if self.code not in codelist.TipoIdFiscal: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.TipoIdFiscal[self.code]['name'] | ||||
| @@ -1,13 +0,0 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from facho.fe.data.dian import codelist | ||||
|  | ||||
| @dataclass | ||||
| class TipoTrabajador: | ||||
|     code: str | ||||
|     name: str = '' | ||||
|  | ||||
|     def __post_init__(self): | ||||
|         if self.code not in codelist.TipoTrabajador: | ||||
|             raise ValueError("code [%s] not found" % (self.code)) | ||||
|         self.name = codelist.TipoTrabajador[self.code]['name'] | ||||
							
								
								
									
										175
									
								
								facho/model/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								facho/model/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| from .fields import Field | ||||
| from collections import defaultdict | ||||
|  | ||||
| class ModelMeta(type): | ||||
|     def __new__(cls, name, bases, ns): | ||||
|         new = type.__new__(cls, name, bases, ns) | ||||
|  | ||||
|         # mapeamos asignacion en declaracion de clase | ||||
|         # a attributo de objeto | ||||
|         if '__name__' in ns: | ||||
|             new.__name__ = ns['__name__'] | ||||
|         if '__namespace__' in ns: | ||||
|             new.__namespace__ = ns['__namespace__'] | ||||
|         else: | ||||
|             new.__namespace__ = {} | ||||
|              | ||||
|         return new | ||||
|  | ||||
| class ModelBase(object, metaclass=ModelMeta): | ||||
|  | ||||
|     def __new__(cls, *args, **kwargs): | ||||
|         obj = super().__new__(cls, *args, **kwargs) | ||||
|         obj._xml_attributes = {} | ||||
|         obj._fields = {} | ||||
|         obj._value = None | ||||
|         obj._namespace_prefix = None | ||||
|         obj._on_change_fields = defaultdict(list) | ||||
|         obj._order_fields = [] | ||||
|          | ||||
|         def on_change_fields_for_function(): | ||||
|             # se recorre arbol de herencia buscando attributo on_changes | ||||
|             for parent_cls in type(obj).__mro__: | ||||
|                 for parent_attr in dir(parent_cls): | ||||
|                     parent_meth = getattr(parent_cls, parent_attr, None) | ||||
|                     if not callable(parent_meth): | ||||
|                         continue | ||||
|                     on_changes = getattr(parent_meth, 'on_changes', None) | ||||
|                     if on_changes: | ||||
|                         return (parent_meth, on_changes) | ||||
|             return (None, []) | ||||
|  | ||||
|         # forzamos registros de campos al modelo | ||||
|         # al instanciar | ||||
|         for (key, v) in type(obj).__dict__.items(): | ||||
|             if isinstance(v, fields.Field): | ||||
|                 obj._order_fields.append(key) | ||||
|  | ||||
|             if isinstance(v, fields.Attribute) or isinstance(v, fields.Many2One) or isinstance(v, fields.Function) or isinstance(v, fields.Amount): | ||||
|                 if hasattr(v, 'default') and v.default is not None: | ||||
|                     setattr(obj, key, v.default) | ||||
|                 if hasattr(v, 'create') and v.create == True: | ||||
|                     setattr(obj, key, '') | ||||
|  | ||||
|                 # register callbacks for changes | ||||
|                 (fun, on_change_fields) = on_change_fields_for_function() | ||||
|                 for field in on_change_fields: | ||||
|                     obj._on_change_fields[field].append(fun) | ||||
|  | ||||
|  | ||||
|         # post inicializacion del objeto | ||||
|         obj.__setup__() | ||||
|         return obj | ||||
|  | ||||
|     def _set_attribute(self, field, name, value): | ||||
|         self._xml_attributes[field] = (name, value) | ||||
|  | ||||
|     def __setitem__(self, key, val): | ||||
|         self._xml_attributes[key] = val | ||||
|  | ||||
|     def __getitem__(self, key): | ||||
|         return self._xml_attributes[key] | ||||
|  | ||||
|     def _get_field(self, name): | ||||
|         return self._fields[name] | ||||
|  | ||||
|     def _set_field(self, name, field): | ||||
|         field.name = name | ||||
|         self._fields[name] = field | ||||
|  | ||||
|     def _set_content(self, value): | ||||
|         default = self.__default_set__(value) | ||||
|         if default is not None: | ||||
|             self._value = default | ||||
|  | ||||
|     def to_xml(self): | ||||
|         """ | ||||
|         Genera xml del modelo y sus relaciones | ||||
|         """ | ||||
|         def _hook_before_xml(): | ||||
|             self.__before_xml__() | ||||
|             for field in self._fields.values(): | ||||
|                 if hasattr(field, '__before_xml__'): | ||||
|                     field.__before_xml__() | ||||
|                      | ||||
|         _hook_before_xml() | ||||
|  | ||||
|         tag = self.__name__ | ||||
|         ns = '' | ||||
|         if self._namespace_prefix is not None: | ||||
|             ns = "%s:" % (self._namespace_prefix) | ||||
|  | ||||
|         pair_attributes = ["%s=\"%s\"" % (k, v) for (k, v) in self._xml_attributes.values()] | ||||
|  | ||||
|         for (prefix, url) in self.__namespace__.items(): | ||||
|             pair_attributes.append("xmlns:%s=\"%s\"" % (prefix, url)) | ||||
|         attributes = "" | ||||
|         if pair_attributes: | ||||
|             attributes = " " + " ".join(pair_attributes) | ||||
|  | ||||
|         content = "" | ||||
|  | ||||
|         ordered_fields = {} | ||||
|         for name in self._order_fields: | ||||
|             if name in self._fields: | ||||
|                 ordered_fields[name] = True | ||||
|             else: | ||||
|                 for key in self._fields.keys(): | ||||
|                     if key.startswith(name): | ||||
|                         ordered_fields[key] = True | ||||
|  | ||||
|         for name in ordered_fields.keys(): | ||||
|             value = self._fields[name] | ||||
|             # al ser virtual no adicinamos al arbol xml | ||||
|             if hasattr(value, 'virtual') and value.virtual: | ||||
|                 continue | ||||
|  | ||||
|             if hasattr(value, 'to_xml'): | ||||
|                 content += value.to_xml() | ||||
|             elif isinstance(value, str): | ||||
|                 content += value | ||||
|  | ||||
|         if self._value is not None: | ||||
|             content += str(self._value) | ||||
|  | ||||
|         if content == "": | ||||
|             return "<%s%s%s/>" % (ns, tag, attributes) | ||||
|         else: | ||||
|             return "<%s%s%s>%s</%s%s>" % (ns, tag, attributes, content, ns, tag) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.to_xml() | ||||
|  | ||||
|  | ||||
| class Model(ModelBase): | ||||
|     """ | ||||
|     Model clase que representa el modelo | ||||
|     """ | ||||
|  | ||||
|     def __before_xml__(self): | ||||
|         """ | ||||
|         Ejecuta antes de generar el xml, este | ||||
|         metodo sirve para realizar actualizaciones | ||||
|         en los campos en el ultimo momento | ||||
|         """ | ||||
|         pass | ||||
|  | ||||
|     def __default_set__(self, value): | ||||
|         """ | ||||
|         Al asignar un valor al modelo atraves de una relacion (person.relation = '33') | ||||
|         se puede personalizar como hacer esta asignacion. | ||||
|         """ | ||||
|         return value | ||||
|  | ||||
|     def __default_get__(self, name, value): | ||||
|         """ | ||||
|         Al obtener el valor atraves de una relacion (age = person.age) | ||||
|         Retorno de valor por defecto | ||||
|         """ | ||||
|         return value | ||||
|  | ||||
|     def __setup__(self): | ||||
|         """ | ||||
|         Inicializar modelo | ||||
|         """ | ||||
|          | ||||
							
								
								
									
										21
									
								
								facho/model/fields/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								facho/model/fields/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| from .attribute import Attribute | ||||
| from .many2one import Many2One | ||||
| from .one2many import One2Many | ||||
| from .function import Function | ||||
| from .virtual import Virtual | ||||
| from .field import Field | ||||
| from .amount import Amount | ||||
|  | ||||
| __all__ = [Attribute, One2Many, Many2One, Virtual, Field, Amount] | ||||
|  | ||||
| def on_change(fields): | ||||
|     from functools import wraps | ||||
|      | ||||
|     def decorator(func): | ||||
|         setattr(func, 'on_changes', fields) | ||||
|  | ||||
|         @wraps(func) | ||||
|         def wrapper(self, *arg, **kwargs): | ||||
|             return func(self, *arg, **kwargs) | ||||
|         return wrapper | ||||
|     return decorator | ||||
							
								
								
									
										35
									
								
								facho/model/fields/amount.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								facho/model/fields/amount.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| from .field import Field | ||||
| from collections import defaultdict | ||||
| import facho.fe.form as form | ||||
|  | ||||
| class Amount(Field): | ||||
|     """ | ||||
|     Amount representa un campo moneda usando form.Amount | ||||
|     """ | ||||
|  | ||||
|     def __init__(self, name=None, default=None, precision=6): | ||||
|         self.field_name = name | ||||
|         self.values = {} | ||||
|         self.default = default | ||||
|         self.precision = precision | ||||
|          | ||||
|     def __get__(self, model, cls): | ||||
|         if model is None: | ||||
|             return self | ||||
|         assert self.name is not None | ||||
|   | ||||
|         self.__init_value(model) | ||||
|         model._set_field(self.name, self) | ||||
|         return self.values[model] | ||||
|  | ||||
|     def __set__(self, model, value): | ||||
|         assert self.name is not None | ||||
|         self.__init_value(model) | ||||
|         model._set_field(self.name, self) | ||||
|         self.values[model] = form.Amount(value, precision=self.precision) | ||||
|  | ||||
|         self._changed_field(model, self.name, value) | ||||
|  | ||||
|     def __init_value(self, model): | ||||
|         if model not in self.values: | ||||
|             self.values[model] = form.Amount(self.default or 0) | ||||
							
								
								
									
										29
									
								
								facho/model/fields/attribute.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								facho/model/fields/attribute.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| from .field import Field | ||||
|  | ||||
| class Attribute(Field): | ||||
|     """ | ||||
|     Attribute es un atributo del elemento actual. | ||||
|     """ | ||||
|      | ||||
|     def __init__(self, name, default=None): | ||||
|         """ | ||||
|         :param name: nombre del atribute | ||||
|         :param default: valor por defecto del attributo | ||||
|         """ | ||||
|         self.attribute = name | ||||
|         self.value = default | ||||
|         self.default = default | ||||
|  | ||||
|     def __get__(self, inst, cls): | ||||
|         if inst is None: | ||||
|             return self | ||||
|  | ||||
|         assert self.name is not None | ||||
|         return self.value | ||||
|  | ||||
|     def __set__(self, inst, value): | ||||
|         assert self.name is not None | ||||
|         self.value = value | ||||
|          | ||||
|         self._changed_field(inst, self.name, value) | ||||
|         inst._set_attribute(self.name, self.attribute, value) | ||||
							
								
								
									
										60
									
								
								facho/model/fields/field.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								facho/model/fields/field.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| import warnings | ||||
|  | ||||
| class Field: | ||||
|     def __set_name__(self, owner, name, virtual=False): | ||||
|         self.name = name | ||||
|         self.virtual = virtual | ||||
|  | ||||
|     def __get__(self, inst, cls): | ||||
|         if inst is None: | ||||
|             return self | ||||
|         assert self.name is not None | ||||
|         return inst._fields[self.name] | ||||
|  | ||||
|     def __set__(self, inst, value): | ||||
|         assert self.name is not None | ||||
|         inst._fields[self.name] = value | ||||
|  | ||||
|     def _set_namespace(self, inst, name, namespaces): | ||||
|         if name is None: | ||||
|             return | ||||
|  | ||||
|         #TODO(bit4bit) aunque las pruebas confirmar | ||||
|         #que si se escribe el namespace que es | ||||
|         #no ahi confirmacion de declaracion previa del namespace | ||||
|  | ||||
|         inst._namespace_prefix = name | ||||
|  | ||||
|     def _call(self, inst, method, *args): | ||||
|         call = getattr(inst, method or '', None) | ||||
|  | ||||
|         if callable(call): | ||||
|             return call(*args) | ||||
|  | ||||
|     def _create_model(self, inst, name=None, model=None, attribute=None, namespace=None): | ||||
|         try: | ||||
|             return inst._fields[self.name] | ||||
|         except KeyError: | ||||
|             if model is not None: | ||||
|                 obj = model() | ||||
|             else: | ||||
|                 obj = self.model() | ||||
|             if name is not None: | ||||
|                 obj.__name__ = name | ||||
|  | ||||
|             if namespace: | ||||
|                 self._set_namespace(obj, namespace, inst.__namespace__) | ||||
|             else: | ||||
|                 self._set_namespace(obj, self.namespace, inst.__namespace__) | ||||
|  | ||||
|             if attribute: | ||||
|                 inst._fields[attribute] = obj | ||||
|             else: | ||||
|                 inst._fields[self.name] = obj | ||||
|  | ||||
|             return obj | ||||
|  | ||||
|     def _changed_field(self, inst, name, value): | ||||
|         for fun in inst._on_change_fields[name]: | ||||
|             fun(inst, name, value) | ||||
|              | ||||
							
								
								
									
										36
									
								
								facho/model/fields/function.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								facho/model/fields/function.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| from .field import Field | ||||
|  | ||||
| class Function(Field): | ||||
|     """ | ||||
|     Permite modificar el modelo cuando se intenta, | ||||
|     obtener el valor de este campo. | ||||
|  | ||||
|     DEPRECATED usar Virtual | ||||
|     """ | ||||
|     def __init__(self, field, getter=None, default=None): | ||||
|         self.field = field | ||||
|         self.getter = getter | ||||
|         self.default = default | ||||
|  | ||||
|     def __get__(self, inst, cls): | ||||
|         if inst is None: | ||||
|             return self | ||||
|         assert self.name is not None | ||||
|  | ||||
|         # si se indica `field` se adiciona | ||||
|         # como campo del modelo, esto es | ||||
|         # que se serializa a xml | ||||
|         inst._set_field(self.name, self.field) | ||||
|  | ||||
|         if self.getter is not None: | ||||
|             value = self._call(inst, self.getter, self.name, self.field) | ||||
|  | ||||
|             if value is not None: | ||||
|                 self.field.__set__(inst, value) | ||||
|  | ||||
|         return self.field | ||||
|  | ||||
|     def __set__(self, inst, value): | ||||
|         inst._set_field(self.name, self.field) | ||||
|         self._changed_field(inst, self.name, value) | ||||
|         self.field.__set__(inst, value) | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user