summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-11-13 15:01:09 +0100
committerChristian Grothoff <christian@grothoff.org>2019-11-13 15:01:09 +0100
commitc8047726772c2f4a18a6b0ebc7ce879bf260860a (patch)
treea6bab2e9a42c72a720c893b9c2505077067e6bfc
downloadsync-c8047726772c2f4a18a6b0ebc7ce879bf260860a.tar.gz
sync-c8047726772c2f4a18a6b0ebc7ce879bf260860a.tar.bz2
sync-c8047726772c2f4a18a6b0ebc7ce879bf260860a.zip
skeleton
-rw-r--r--.gitignore63
-rw-r--r--AUTHORS1
-rw-r--r--COPYING661
-rw-r--r--COPYING.AGPL661
-rw-r--r--ChangeLog2
-rw-r--r--INSTALL368
-rw-r--r--Makefile.am26
-rw-r--r--NEWS0
-rw-r--r--README36
-rwxr-xr-xbootstrap31
-rw-r--r--configure.ac309
-rw-r--r--contrib/gnunet.tag55
-rw-r--r--contrib/uncrustify.cfg78
-rwxr-xr-xcontrib/uncrustify_precommit35
-rw-r--r--m4/ax_lib_postgresql.m4155
-rw-r--r--m4/ax_prog_doxygen.m4586
-rw-r--r--m4/libcurl.m4251
-rw-r--r--m4/libgnurl.m4250
-rw-r--r--src/Makefile.am3
-rw-r--r--src/include/Makefile.am10
-rw-r--r--src/include/platform.h60
-rw-r--r--src/include/sync_database_lib.h46
-rw-r--r--src/include/sync_database_plugin.h117
-rw-r--r--src/include/sync_service.h64
-rw-r--r--src/lib/Makefile.am32
-rw-r--r--src/lib/sync_api_upload.c57
-rw-r--r--src/sync/Makefile.am28
-rw-r--r--src/sync/sync-httpd.c744
-rw-r--r--src/sync/sync-httpd.h148
-rw-r--r--src/sync/sync-httpd_backup.c56
-rw-r--r--src/sync/sync-httpd_backup.h53
-rw-r--r--src/sync/sync-httpd_mhd.c156
-rw-r--r--src/sync/sync-httpd_mhd.h113
-rw-r--r--src/sync/sync-httpd_parsing.c272
-rw-r--r--src/sync/sync-httpd_parsing.h93
-rw-r--r--src/sync/sync-httpd_responses.c408
-rw-r--r--src/sync/sync-httpd_responses.h244
-rw-r--r--src/sync/sync.conf31
-rw-r--r--src/syncdb/Makefile.am62
-rw-r--r--src/syncdb/plugin_sync_postgres.c284
-rw-r--r--src/syncdb/sync_db_plugin.c149
-rw-r--r--src/syncdb/sync_db_postgres.conf7
-rw-r--r--src/syncdb/test_sync_db.c200
-rw-r--r--src/syncdb/test_sync_db_postgres.conf7
44 files changed, 7012 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1ecf3bd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,63 @@
+Makefile
+Makefile.in
+aclocal.m4
+anastasis_config.h
+anastasis_config.h.in
+anastasis_config.h.in~
+autom4te.cache/
+compile
+config.guess
+config.log
+config.status
+config.sub
+configure
+contrib/uncrustify.sh
+depcomp
+doc/Makefile
+install-sh
+libtool
+ltmain.sh
+missing
+src/Makefile
+src/Makefile.in
+src/util/.deps/
+src/util/.libs/
+src/stasis/Makefile
+src/stasis/Makefile.in
+src/stasis/libanastasis_plugin_db_postgres.la
+src/stasis/plugin_anastasis_postgres.lo
+src/stasis/plugin_anastasis_postgres.o
+src/stasis/.deps/
+src/backend/Makefile
+src/backend/Makefile.in
+src/include/Makefile
+src/include/Makefile.in
+src/lib/.deps/
+src/lib/Makefile
+src/lib/Makefile.in
+stamp-h1
+test-driver
+uncrustify.cfg
+doc/Makefile.in
+m4/libtool.m4
+m4/ltoptions.m4
+m4/ltsugar.m4
+m4/ltversion.m4
+m4/lt~obsolete.m4
+*.swp
+src/lib/.libs
+*.lo
+*.o
+*.la
+src/util/.deps/
+src/backend/.deps/
+src/backend/.idea/
+src/backend/.libs/
+src/stasis/.libs/
+src/backend/anastasis-httpd
+doc/Makefile.in
+src/include/Makefile.in
+
+A
+A
+
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..eb41b69
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Christian Grothoff
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..dba13ed
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,661 @@
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are 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.
+
+ 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.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ 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 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 work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ 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 AGPL, see
+<http://www.gnu.org/licenses/>.
diff --git a/COPYING.AGPL b/COPYING.AGPL
new file mode 100644
index 0000000..dba13ed
--- /dev/null
+++ b/COPYING.AGPL
@@ -0,0 +1,661 @@
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are 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.
+
+ 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.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ 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 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 work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ 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 AGPL, see
+<http://www.gnu.org/licenses/>.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..823d0fa
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,2 @@
+Tue 18 Jun 2019 04:19:29 PM CEST
+ Initial project setup. -CG
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..8865734
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,368 @@
+Installation Instructions
+*************************
+
+ Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
+Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved. This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+ Briefly, the shell command './configure && make && make install'
+should configure, build, and install this package. The following
+more-detailed instructions are generic; see the 'README' file for
+instructions specific to this package. Some packages provide this
+'INSTALL' file but do not implement all of the features documented
+below. The lack of an optional feature in a given package is not
+necessarily a bug. More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+ The 'configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a 'Makefile' in each directory of the package.
+It may also create one or more '.h' files containing system-dependent
+definitions. Finally, it creates a shell script 'config.status' that
+you can run in the future to recreate the current configuration, and a
+file 'config.log' containing compiler output (useful mainly for
+debugging 'configure').
+
+ It can also use an optional file (typically called 'config.cache' and
+enabled with '--cache-file=config.cache' or simply '-C') that saves the
+results of its tests to speed up reconfiguring. Caching is disabled by
+default to prevent problems with accidental use of stale cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how 'configure' could check whether to do them, and mail
+diffs or instructions to the address given in the 'README' so they can
+be considered for the next release. If you are using the cache, and at
+some point 'config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file 'configure.ac' (or 'configure.in') is used to create
+'configure' by a program called 'autoconf'. You need 'configure.ac' if
+you want to change it or regenerate 'configure' using a newer version of
+'autoconf'.
+
+ The simplest way to compile this package is:
+
+ 1. 'cd' to the directory containing the package's source code and type
+ './configure' to configure the package for your system.
+
+ Running 'configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type 'make' to compile the package.
+
+ 3. Optionally, type 'make check' to run any self-tests that come with
+ the package, generally using the just-built uninstalled binaries.
+
+ 4. Type 'make install' to install the programs and any data files and
+ documentation. When installing into a prefix owned by root, it is
+ recommended that the package be configured and built as a regular
+ user, and only the 'make install' phase executed with root
+ privileges.
+
+ 5. Optionally, type 'make installcheck' to repeat any self-tests, but
+ this time using the binaries in their final installed location.
+ This target does not install anything. Running this target as a
+ regular user, particularly if the prior 'make install' required
+ root privileges, verifies that the installation completed
+ correctly.
+
+ 6. You can remove the program binaries and object files from the
+ source code directory by typing 'make clean'. To also remove the
+ files that 'configure' created (so you can compile the package for
+ a different kind of computer), type 'make distclean'. There is
+ also a 'make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 7. Often, you can also type 'make uninstall' to remove the installed
+ files again. In practice, not all packages have tested that
+ uninstallation works correctly, even though it is required by the
+ GNU Coding Standards.
+
+ 8. Some packages, particularly those that use Automake, provide 'make
+ distcheck', which can by used by developers to test that all other
+ targets like 'make install' and 'make uninstall' work correctly.
+ This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the 'configure' script does not know about. Run './configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give 'configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here is
+an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU 'make'. 'cd' to the
+directory where you want the object files and executables to go and run
+the 'configure' script. 'configure' automatically checks for the source
+code in the directory that 'configure' is in and in '..'. This is known
+as a "VPATH" build.
+
+ With a non-GNU 'make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use 'make distclean' before
+reconfiguring for another architecture.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple '-arch' options to the
+compiler but only a single '-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the 'lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, 'make install' installs the package's commands under
+'/usr/local/bin', include files under '/usr/local/include', etc. You
+can specify an installation prefix other than '/usr/local' by giving
+'configure' the option '--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like '--bindir=DIR' to specify different values for particular
+kinds of files. Run 'configure --help' for a list of the directories
+you can set and what kinds of files go in them. In general, the default
+for these options is expressed in terms of '${prefix}', so that
+specifying just '--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+ The most portable way to affect installation locations is to pass the
+correct locations to 'configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+'make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+ The first method involves providing an override variable for each
+affected directory. For example, 'make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+'${prefix}'. Any directories that were specified during 'configure',
+but not in terms of '${prefix}', must each be overridden at install time
+for the entire installation to be relocated. The approach of makefile
+variable overrides for each directory variable is required by the GNU
+Coding Standards, and ideally causes no recompilation. However, some
+platforms have known limitations with the semantics of shared libraries
+that end up requiring recompilation when using this method, particularly
+noticeable in packages that use GNU Libtool.
+
+ The second method involves providing the 'DESTDIR' variable. For
+example, 'make install DESTDIR=/alternate/directory' will prepend
+'/alternate/directory' before all installation names. The approach of
+'DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters. On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of '${prefix}'
+at 'configure' time.
+
+Optional Features
+=================
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving 'configure' the
+option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
+
+ Some packages pay attention to '--enable-FEATURE' options to
+'configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to '--with-PACKAGE' options, where PACKAGE
+is something like 'gnu-as' or 'x' (for the X Window System). The
+'README' should mention any '--enable-' and '--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, 'configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the 'configure' options '--x-includes=DIR' and
+'--x-libraries=DIR' to specify their locations.
+
+ Some packages offer the ability to configure how verbose the
+execution of 'make' will be. For these packages, running './configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with 'make V=1'; while running './configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with 'make V=0'.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
+is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ HP-UX 'make' updates targets which have the same time stamps as their
+prerequisites, which makes it generally unusable when shipped generated
+files such as 'configure' are involved. Use GNU 'make' instead.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
+workaround. If GNU CC is not installed, it is therefore recommended to
+try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+ On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
+directory contains several dysfunctional programs; working variants of
+these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
+in your 'PATH', put it _after_ '/usr/bin'.
+
+ On Haiku, software installed for all users goes in '/boot/common',
+not '/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+ There may be some features 'configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, 'configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+'--build=TYPE' option. TYPE can either be a short name for the system
+type, such as 'sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file 'config.sub' for the possible values of each field. If
+'config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option '--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with '--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for 'configure' scripts to share,
+you can create a site shell script called 'config.site' that gives
+default values for variables like 'CC', 'cache_file', and 'prefix'.
+'configure' looks for 'PREFIX/share/config.site' if it exists, then
+'PREFIX/etc/config.site' if it exists. Or, you can set the
+'CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all 'configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to 'configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the 'configure' command line, using 'VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified 'gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
+Autoconf limitation. Until the limitation is lifted, you can use this
+workaround:
+
+ CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+'configure' Invocation
+======================
+
+ 'configure' recognizes the following options to control how it
+operates.
+
+'--help'
+'-h'
+ Print a summary of all of the options to 'configure', and exit.
+
+'--help=short'
+'--help=recursive'
+ Print a summary of the options unique to this package's
+ 'configure', and exit. The 'short' variant lists options used only
+ in the top level, while the 'recursive' variant lists options also
+ present in any nested packages.
+
+'--version'
+'-V'
+ Print the version of Autoconf used to generate the 'configure'
+ script, and exit.
+
+'--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally 'config.cache'. FILE defaults to '/dev/null' to
+ disable caching.
+
+'--config-cache'
+'-C'
+ Alias for '--cache-file=config.cache'.
+
+'--quiet'
+'--silent'
+'-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to '/dev/null' (any error
+ messages will still be shown).
+
+'--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ 'configure' can determine that directory automatically.
+
+'--prefix=DIR'
+ Use DIR as the installation prefix. *note Installation Names:: for
+ more details, including other options available for fine-tuning the
+ installation locations.
+
+'--no-create'
+'-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+'configure' also accepts some other, not widely useful, options. Run
+'configure --help' for more details.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..3227908
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,26 @@
+# This Makefile is in the public domain
+
+if DOC_ONLY
+if ENABLE_DOC
+ SUBDIRS = . doc
+else
+ SUBDIRS = .
+endif
+else
+if ENABLE_DOC
+ SUBDIRS = . src doc
+else
+ SUBDIRS = . src doc
+endif
+endif
+
+@DX_RULES@
+
+ACLOCAL_AMFLAGS = -I m4
+EXTRA_DIST = \
+ AUTHORS \
+ COPYING.AGPL \
+ contrib/gnunet.tag \
+ contrib/uncrustify.cfg \
+ contrib/uncrustify_precommit \
+ Doxyfile
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..326a1d9
--- /dev/null
+++ b/README
@@ -0,0 +1,36 @@
+TALER MERCHANT
+
+1. DESCRIPTION
+
+Under the name 'Taler merchant' there are two main objectives: one is to
+implement a common helper (called 'backend') for all the existing merchants
+willing to integrate Taler in their existing online shops, whereas the other
+objective is implementing some demonstrator shops which use that backend.
+
+2. INNOVATIVE ASPECTS
+
+This component allows merchants to receive payments without invading the
+customers' privacy. Of course, this applies mostly for digital goods, as the
+merchant does not need to know the customer's physical address.
+
+3. PLANNING/PERSPECTIVES
+
+Since the main component's part is the backend, and it is supposed to work with
+preexisting shops, a massive backend's testing with existing shop portals should
+be accomplished.
+
+
+4. DEPENDENCIES
+
+libjansson: MIT License, AGPL- and LGPL-Compatible, owned by Petri Lehtinen and other individuals
+libgcrypt: LGPL, owned by Free Software Foundation
+postgresql: PostgreSQL License, AGPL- and LGPL-Compatible, owned by The PostgreSQL
+Global Development Group
+libgnunetutil (in all of its variants): GPLv3+, owned by GNUnet e.V.
+PHP: PHP License, AGPL- and LGPL-Compatible, owned by The PHP Group
+
+5. DIRECTORY STRUCTURE
+
+- 'src/' contains the "backend", a C piece of software which implements cryto routines
+ and communication with the 'exchange'
+ 'doc/' contains documentation files, like TeXinfo
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..65d653e
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+if ! git --version >/dev/null; then
+ echo "git not installed"
+ exit 1
+fi
+
+echo "$0: Updating submodules"
+echo | git submodule update --init
+
+# This is more portable than `which' but comes with
+# the caveat of not(?) properly working on busybox's ash:
+existence()
+{
+ command -v "$1" >/dev/null 2>&1
+}
+
+
+if existence uncrustify; then
+ echo "Installing uncrustify hook and configuration"
+ # Install uncrustify format symlink (if possible)
+ ln -s contrib/uncrustify.cfg uncrustify.cfg 2> /dev/null
+ # Install pre-commit hook (if possible)
+ ln -s ../../contrib/uncrustify_precommit .git/hooks/pre-commit 2> /dev/null
+else
+ echo "Uncrustify not detected, hook not installed. Please install uncrustify if you plan on doing development"
+fi
+
+
+echo "$0: Running autoreconf"
+autoreconf -if
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..1250b6d
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,309 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+#
+# This configure file is in the public domain
+
+AC_PREREQ([2.69])
+AC_INIT([anastasis], [0.5.0], [taler-bug@gnu.org])
+AC_CONFIG_SRCDIR([src/backend/anastasis-httpd.c])
+AC_CONFIG_HEADERS([anastasis_config.h])
+# support for non-recursive builds
+AM_INIT_AUTOMAKE([subdir-objects 1.9 tar-pax])
+
+# pretty build rules
+AM_SILENT_RULES([yes])
+
+AC_CONFIG_MACRO_DIR([m4])
+
+LT_INIT
+
+DX_INIT_DOXYGEN([anastasis],,,
+DX_PS_FEATURE(OFF),
+DX_PDF_FEATURE(OFF),
+DX_RTF_FEATURE(OFF),
+DX_CHI_FEATURE(OFF),
+DX_XML_FEATURE(OFF))
+
+AC_MSG_CHECKING([whether to compile documentation ONLY])
+AC_ARG_ENABLE([only-doc],
+ [AS_HELP_STRING([--enable-only-doc], [only compile Taler documentation])],
+ [doc_only=${enableval}],
+ [doc_only=no])
+AC_MSG_RESULT($doc_only)
+AM_CONDITIONAL([DOC_ONLY], [test "$doc_only" = "yes"])
+
+
+# Not indented as it covers most of the file...
+AS_IF([test "x$doc_only" != xyes],[
+
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_CC_C99
+
+CFLAGS="-Wall $CFLAGS"
+
+# Checks for header files.
+AC_CHECK_HEADERS([stdint.h stdlib.h string.h unistd.h])
+
+# Check for GNUnet's libgnunetutil.
+libgnunetutil=0
+AC_MSG_CHECKING([for libgnunetutil])
+AC_ARG_WITH(gnunet,
+ [AS_HELP_STRING([--with-gnunet=PFX], [base of GNUnet installation])],
+ [AC_MSG_RESULT([given as $with_gnunet])],
+ [AC_MSG_RESULT(not given)
+ with_gnunet=yes])
+AS_CASE([$with_gnunet],
+ [yes], [],
+ [no], [AC_MSG_ERROR([--with-gnunet is required])],
+ [LDFLAGS="-L$with_gnunet/lib $LDFLAGS"
+ CPPFLAGS="-I$with_gnunet/include $CPPFLAGS"])
+AC_CHECK_HEADERS([gnunet/platform.h gnunet/gnunet_util_lib.h],
+ [AC_CHECK_LIB([gnunetutil], [GNUNET_SCHEDULER_run], libgnunetutil=1)],
+ [], [#ifdef HAVE_GNUNET_PLATFORM_H
+ #include <gnunet/platform.h>
+ #endif])
+AS_IF([test $libgnunetutil != 1],
+ [AC_MSG_ERROR([[
+***
+*** You need libgnunetutil to build this program.
+*** This library is part of GNUnet, available at
+*** https://gnunet.org
+*** ]])])
+
+
+# test for postgres
+AX_LIB_POSTGRESQL([9.3])
+AS_IF([test "x$found_postgresql" = "xyes"],[postgres=true])
+AM_CONDITIONAL(HAVE_POSTGRESQL, test x$postgres = xtrue)
+
+# Check for Taler's libtalerpq
+libtalerpq=0
+AC_MSG_CHECKING([for libtalerpq])
+AC_ARG_WITH(exchange,
+ [AS_HELP_STRING([--with-exchange=PFX], [base of Taler EXCHANGE installation])],
+ [AC_MSG_RESULT([given as $with_exchange])],
+ [AC_MSG_RESULT(not given)
+ with_exchange=yes])
+AS_CASE([$with_exchange],
+ [yes], [],
+ [no], [AC_MSG_ERROR([--with-exchange is required])],
+ [LDFLAGS="-L$with_exchange/lib $LDFLAGS"
+ CPPFLAGS="-I$with_exchange/include $CPPFLAGS $POSTGRESQL_CPPFLAGS"])
+
+CPPFLAGS="$CPPFLAGS $POSTGRESQL_CPPFLAGS"
+LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+AC_CHECK_HEADERS([gnunet/gnunet_pq_lib.h],
+ [AC_CHECK_LIB([gnunetpq], [GNUNET_PQ_connect_with_cfg], libgnunetpq=1)],
+ [], [#ifdef HAVE_GNUNET_PLATFORM_H
+ #include <gnunet/platform.h>
+ #endif])
+AM_CONDITIONAL(HAVE_GNUNETPQ, test x$libgnunetpq = x1)
+
+# check for libmicrohttpd
+microhttpd=0
+AC_MSG_CHECKING([for microhttpd])
+AC_ARG_WITH([microhttpd],
+ [AS_HELP_STRING([--with-microhttpd=PFX], [base of microhttpd installation])],
+ [AC_MSG_RESULT([given as $with_microhttpd])],
+ [AC_MSG_RESULT([not given])
+ with_microhttpd=yes])
+AS_CASE([$with_microhttpd],
+ [yes], [],
+ [no], [AC_MSG_ERROR([--with-microhttpd is required])],
+ [LDFLAGS="-L$with_microhttpd/lib $LDFLAGS"
+ CPPFLAGS="-I$with_microhttpd/include $CPPFLAGS"])
+AC_CHECK_LIB(microhttpd,MHD_start_daemon,
+ [AC_CHECK_HEADER([microhttpd.h],[microhttpd=1])])
+AS_IF([test $microhttpd = 0],
+ [AC_MSG_ERROR([[
+***
+*** You need libmicrohttpd to build this program.
+*** ]])])
+
+jansson=0
+PKG_CHECK_MODULES([JANSSON], [jansson >= 2.3],
+ [LDFLAGS="$JANSSON_LIBS $LDFLAGS"
+ CPPFLAGS="$JANSSON_CFLAGS $CPPFLAGS"],
+ [AC_MSG_ERROR([[
+***
+*** You need libjansson to build this program.
+***]])])
+
+# check for libgnurl
+# libgnurl
+LIBGNURL_CHECK_CONFIG(,7.34.0,gnurl=1,gnurl=0)
+AS_IF([test "x$gnurl" = x1],[
+ AM_CONDITIONAL(HAVE_LIBGNURL, true)
+ AC_DEFINE([HAVE_LIBGNURL],[1],[Have libgnurl])
+],[
+ AM_CONDITIONAL(HAVE_LIBGNURL, false)
+])
+
+# libcurl-gnutls
+LIBCURL_CHECK_CONFIG(,7.34.0,[curl=true],[curl=false])
+AS_IF([test "x$curl" = xtrue],
+ [LDFLAGS="-L$with_libcurl/lib $LDFLAGS"
+ CPPFLAGS="-I$with_libcurl/include $CPPFLAGS"
+ AC_CHECK_HEADERS([curl/curl.h],
+ [AC_CHECK_DECLS(CURLINFO_TLS_SESSION,
+ [curl=true],
+ [curl=false],
+ [[#include <curl/curl.h>]])],
+ [curl=false])
+ # need libcurl-gnutls.so, everything else is not acceptable
+ AC_CHECK_LIB([curl-gnutls],
+ [curl_easy_getinfo],,
+ [curl=false])])
+ # cURL must support CURLINFO_TLS_SESSION, version >= 7.34
+
+# Check for curl/curl.h and gnurl/curl.h so we can use #ifdef
+# HAVE_CURL_CURL_H later (the above LIBCURL_CHECK_CONFIG accepted
+# *either* header set).
+AC_CHECK_HEADERS([curl/curl.h],,
+ curl=false
+ AC_CHECK_HEADERS([gnurl/curl.h],,
+ gnurl=false))
+
+# libgnurl
+AS_IF([test "x$gnurl" = "x0"],
+ [AS_IF([test "x$curl" = "x0"],
+ [AC_MSG_NOTICE([NOTICE: libgnurl not found. taler-bank support will not be compiled.])],
+ [AC_MSG_NOTICE([WARNING: libgnurl not found, trying to use libcurl-gnutls instead.])])])
+
+AS_IF([test x$curl = xfalse],
+ [AM_CONDITIONAL(HAVE_LIBCURL, false)
+ AS_IF([test "x$gnurl" = "x0"],
+ [AC_MSG_WARN([GNU Taler requires libcurl-gnutls >= 7.34])])],
+ [AM_CONDITIONAL(HAVE_LIBCURL, true)
+ AC_DEFINE([HAVE_LIBCURL],[1],[Have CURL])])
+
+# check for libtalertwistertesting
+twistertesting=0
+AC_MSG_CHECKING([for talerwtistertesting])
+AC_ARG_WITH([twister],
+ [AS_HELP_STRING([--with-twister=PFX], [base of libtalertwistertesting])],
+ [AC_MSG_RESULT([given as $with_twister])],
+ [AC_MSG_RESULT([not given])
+ with_twister=yes])
+AS_CASE([$with_twister],
+ [yes], [],
+ [no], [AC_MSG_WARN([no twister-testing will be compiled])],
+ [LDFLAGS="-L$with_twister/lib $LDFLAGS"
+ CPPFLAGS="-I$with_twister/include $CPPFLAGS"])
+
+AC_CHECK_HEADERS([taler/taler_twister_testing_lib.h],
+ [AC_CHECK_LIB([talertwistertesting], [TALER_TESTING_run_twister], twistertesting=1,, [-ltalerexchange -ltalerbank])],
+ [], [#ifdef HAVE_GNUNET_PLATFORM_H
+ #include <gnunet/platform.h>
+ #endif])
+AM_CONDITIONAL(HAVE_TWISTER, test x$twistertesting = x1)
+
+# gcov compilation
+AC_MSG_CHECKING(whether to compile with support for code coverage analysis)
+AC_ARG_ENABLE([coverage],
+ AS_HELP_STRING([--enable-coverage],
+ [compile the library with code coverage support]),
+ [use_gcov=${enableval}],
+ [use_gcov=no])
+AC_MSG_RESULT($use_gcov)
+AM_CONDITIONAL([USE_COVERAGE], [test "x$use_gcov" = "xyes"])
+
+# Require minimum libgcrypt version
+need_libgcrypt_version=1.6.1
+AC_DEFINE_UNQUOTED([NEED_LIBGCRYPT_VERSION], ["$need_libgcrypt_version"],
+ [minimum version of libgcrypt required])
+AM_PATH_LIBGCRYPT([$need_libgcrypt_version])
+
+# logging
+extra_logging=0
+AC_ARG_ENABLE([logging],
+ AS_HELP_STRING([--enable-logging@<:@=value@:>@],[Enable logging calls. Possible values: yes,no,verbose ('yes' is the default)]),
+ [AS_IF([test "x$enableval" = "xyes"], [],
+ [test "x$enableval" = "xno"], [AC_DEFINE([GNUNET_CULL_LOGGING],[],[Define to cull all logging calls])],
+ [test "x$enableval" = "xverbose"], [extra_logging=1]
+ [test "x$enableval" = "xveryverbose"], [extra_logging=2])
+ ], [])
+AC_DEFINE_UNQUOTED([GNUNET_EXTRA_LOGGING],[$extra_logging],[1 if extra logging is enabled, 2 for very verbose extra logging, 0 otherwise])
+
+# version info
+AC_PATH_PROG(gitcommand, git)
+AC_MSG_CHECKING(for source being under a VCS)
+git_version=
+AS_IF([test ! "X$gitcommand" = "X"],
+[
+ git_version=$(cd $srcdir ; git rev-list --full-history --all --abbrev-commit | head -n 1 2>/dev/null)
+])
+AS_IF([test "X$git_version" = "X"],
+ [
+ vcs_name="no"
+ vcs_version="\"release\""
+ ],
+ [
+ vcs_name="yes, git-svn"
+ vcs_version="\"git-$git_version\""
+ ])
+AC_MSG_RESULT($vcs_name)
+
+AC_MSG_CHECKING(VCS version)
+AC_MSG_RESULT($vcs_version)
+AC_DEFINE_UNQUOTED(VCS_VERSION, [$vcs_version], [VCS revision/hash or tarball version])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT64_T
+AC_TYPE_INTMAX_T
+AC_TYPE_UINTMAX_T
+
+# Checks for library functions.
+AC_CHECK_FUNCS([strdup])
+
+
+AC_ARG_ENABLE([[doc]],
+ [AS_HELP_STRING([[--disable-doc]], [do not build any documentation])], ,
+ [enable_doc=yes])
+test "x$enable_doc" = "xno" || enable_doc=yes
+AM_CONDITIONAL([ENABLE_DOC], [test "x$enable_doc" = "xyes"])
+
+
+],[ # this is about the doc-only if on top of the file
+
+# logic if doc_only is set, make sure conditionals are still defined
+AM_CONDITIONAL([HAVE_GNUNETPQ], [false])
+AM_CONDITIONAL([HAVE_POSTGRESQL], [false])
+AM_CONDITIONAL([HAVE_LIBCURL], [false])
+AM_CONDITIONAL([HAVE_LIBGNURL], [false])
+AM_CONDITIONAL([USE_COVERAGE], [false])
+AM_CONDITIONAL([ENABLE_DOC], [true])
+AM_CONDITIONAL([HAVE_TWISTER], [true])
+
+
+# end of 'doc_only'
+])
+
+
+# should experimental code be compiled (code that may not yet compile / have passing test cases)?
+AC_MSG_CHECKING(whether to compile experimental code)
+AC_ARG_ENABLE([experimental],
+ [AS_HELP_STRING([--enable-experimental], [enable compiling experimental code])],
+ [enable_experimental=${enableval}],
+ [enable_experimental=no])
+AC_MSG_RESULT($enable_experimental)
+AM_CONDITIONAL([HAVE_EXPERIMENTAL], [test "x$enable_experimental" = "xyes"])
+
+
+AC_CONFIG_FILES([Makefile
+doc/Makefile
+src/Makefile
+src/util/Makefile
+src/stasis/Makefile
+src/backend/Makefile
+src/include/Makefile
+src/lib/Makefile
+])
+AC_OUTPUT
diff --git a/contrib/gnunet.tag b/contrib/gnunet.tag
new file mode 100644
index 0000000..1cf4f0d
--- /dev/null
+++ b/contrib/gnunet.tag
@@ -0,0 +1,55 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
+<tagfile>
+ <compound kind="file">
+ <name>gnunet_util_lib.h</name>
+ <path></path>
+ <filename>gnunet_util_lib.h</filename>
+ <member kind="define">
+ <type>#define</type>
+ <name>GNUNET_YES</name>
+ <anchorfile>gnunet_util_lib.h</anchorfile>
+ <arglist></arglist>
+ </member>
+ <member kind="define">
+ <type>#define</type>
+ <name>GNUNET_OK</name>
+ <anchorfile>gnunet_util_lib.h</anchorfile>
+ <arglist></arglist>
+ </member>
+ <member kind="define">
+ <type>#define</type>
+ <name>GNUNET_NO</name>
+ <anchorfile>gnunet_util_lib.h</anchorfile>
+ <arglist></arglist>
+ </member>
+ <member kind="define">
+ <type>#define</type>
+ <name>GNUNET_SYSERR</name>
+ <anchorfile>gnunet_util_lib.h</anchorfile>
+ <arglist></arglist>
+ </member>
+ <member kind="define">
+ <type>#define</type>
+ <name>GNUNET_TIME_UNIT_FOREVER_ABS</name>
+ <anchorfile>gnunet_util_lib.h</anchorfile>
+ <arglist></arglist>
+ </member>
+ </compound>
+ <compound kind="file">
+ <name>gnunet_pq_lib.h</name>
+ <path></path>
+ <filename>gnunet_pq_lib.h</filename>
+ <member kind="define">
+ <type>#define</type>
+ <name>GNUNET_PQ_query_param_end</name>
+ <anchorfile>gnunet_pq_lib.h</anchorfile>
+ <arglist></arglist>
+ </member>
+ <member kind="typedef">
+ <type>int</type>
+ <name>GNUNET_PQ_ResultConverter</name>
+ <anchorfile>gnunet_pq_lib.h</anchorfile>
+ <arglist>)(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)</arglist>
+ </member>
+ </compound>
+</tagfile>
diff --git a/contrib/uncrustify.cfg b/contrib/uncrustify.cfg
new file mode 100644
index 0000000..f56c8e7
--- /dev/null
+++ b/contrib/uncrustify.cfg
@@ -0,0 +1,78 @@
+input_tab_size = 2
+output_tab_size = 2
+
+indent_columns = 2
+indent_with_tabs = 0
+indent_case_brace = 2
+indent_label=-16
+
+code_width=80
+#cmd_width=80
+
+# Leave most comments alone for now
+cmt_indent_multi=false
+sp_cmt_cpp_start=add
+
+sp_not=add
+
+sp_func_call_user_paren_paren=remove
+sp_inside_fparen=remove
+sp_after_cast=add
+
+ls_for_split_full=true
+ls_func_split_full=true
+ls_code_width=true
+
+# Arithmetic operations in wrapped expressions should be at the start
+# of the line.
+pos_arith=lead
+
+# Fully parenthesize boolean exprs
+mod_full_paren_if_bool=true
+
+# Braces should be on their own line
+nl_fdef_brace=add
+nl_enum_brace=add
+nl_struct_brace=add
+nl_union_brace=add
+nl_if_brace=add
+nl_brace_else=add
+nl_elseif_brace=add
+nl_while_brace=add
+nl_switch_brace=add
+
+# no newline between "else" and "if"
+nl_else_if=remove
+
+nl_func_paren=remove
+nl_assign_brace=remove
+
+# No extra newlines that cause noisy diffs
+nl_start_of_file=remove
+# If there's no new line, it's not a text file!
+nl_end_of_file=add
+
+sp_inside_paren = remove
+
+sp_arith = add
+sp_arith_additive = add
+
+# We want spaces before and after "="
+sp_before_assign = add
+sp_after_assign = add
+
+# we want "char *foo;"
+sp_after_ptr_star = remove
+sp_between_ptr_star = remove
+
+# we want "if (foo) { ... }"
+sp_before_sparen = add
+
+sp_inside_fparen = remove
+
+# add space before function call and decl: "foo (x)"
+sp_func_call_paren = add
+sp_func_proto_paren = add
+sp_func_proto_paren_empty = add
+sp_func_def_paren = add
+sp_func_def_paren_empty = add
diff --git a/contrib/uncrustify_precommit b/contrib/uncrustify_precommit
new file mode 100755
index 0000000..fd29998
--- /dev/null
+++ b/contrib/uncrustify_precommit
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# use as .git/hooks/pre-commit
+
+exec 1>&2
+
+RET=0
+changed=$(git diff --cached --name-only)
+crustified=""
+
+for f in $changed;
+do
+ if echo $f | grep \\.[c,h]\$ > /dev/null
+ then
+ # compare result of uncrustify with changes
+ #
+ # only change any of the invocations here if
+ # they are portable across all cmp and shell
+ # implementations !
+ uncrustify -q -c uncrustify.cfg -f $f | cmp -s $f -
+ if test $? = 1 ;
+ then
+ crustified=" $crustified $f"
+ RET=1
+ fi
+ fi
+done
+
+if [ $RET = 1 ];
+then
+ echo "Run"
+ echo "uncrustify --no-backup -c uncrustify.cfg ${crustified}"
+ echo "before commiting."
+fi
+exit $RET
diff --git a/m4/ax_lib_postgresql.m4 b/m4/ax_lib_postgresql.m4
new file mode 100644
index 0000000..11b6991
--- /dev/null
+++ b/m4/ax_lib_postgresql.m4
@@ -0,0 +1,155 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_lib_postgresql.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_LIB_POSTGRESQL([MINIMUM-VERSION])
+#
+# DESCRIPTION
+#
+# This macro provides tests of availability of PostgreSQL 'libpq' library
+# of particular version or newer.
+#
+# AX_LIB_POSTGRESQL macro takes only one argument which is optional. If
+# there is no required version passed, then macro does not run version
+# test.
+#
+# The --with-postgresql option takes one of three possible values:
+#
+# no - do not check for PostgreSQL client library
+#
+# yes - do check for PostgreSQL library in standard locations (pg_config
+# should be in the PATH)
+#
+# path - complete path to pg_config utility, use this option if pg_config
+# can't be found in the PATH
+#
+# This macro calls:
+#
+# AC_SUBST(POSTGRESQL_CPPFLAGS)
+# AC_SUBST(POSTGRESQL_LDFLAGS)
+# AC_SUBST(POSTGRESQL_VERSION)
+#
+# And sets:
+#
+# HAVE_POSTGRESQL
+#
+# LICENSE
+#
+# Copyright (c) 2008 Mateusz Loskot <mateusz@loskot.net>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 9
+
+AC_DEFUN([AX_LIB_POSTGRESQL],
+[
+ AC_ARG_WITH([postgresql],
+ AS_HELP_STRING([--with-postgresql=@<:@ARG@:>@],
+ [use PostgreSQL library @<:@default=yes@:>@, optionally specify path to pg_config]
+ ),
+ [
+ if test "$withval" = "no"; then
+ want_postgresql="no"
+ elif test "$withval" = "yes"; then
+ want_postgresql="yes"
+ else
+ want_postgresql="yes"
+ PG_CONFIG="$withval"
+ fi
+ ],
+ [want_postgresql="yes"]
+ )
+
+ POSTGRESQL_CPPFLAGS=""
+ POSTGRESQL_LDFLAGS=""
+ POSTGRESQL_VERSION=""
+
+ dnl
+ dnl Check PostgreSQL libraries (libpq)
+ dnl
+
+ if test "$want_postgresql" = "yes"; then
+
+ if test -z "$PG_CONFIG" -o test; then
+ AC_PATH_PROG([PG_CONFIG], [pg_config], [])
+ fi
+
+ if test ! -x "$PG_CONFIG"; then
+ dnl AC_MSG_ERROR([$PG_CONFIG does not exist or it is not an exectuable file])
+ PG_CONFIG="no"
+ found_postgresql="no"
+ fi
+
+ if test "$PG_CONFIG" != "no"; then
+ AC_MSG_CHECKING([for PostgreSQL libraries])
+
+ POSTGRESQL_CPPFLAGS="-I`$PG_CONFIG --includedir`"
+ POSTGRESQL_LDFLAGS="-L`$PG_CONFIG --libdir`"
+
+ POSTGRESQL_VERSION=`$PG_CONFIG --version | sed -e 's#PostgreSQL ##' | awk '{print $1}'`
+
+ AC_DEFINE([HAVE_POSTGRESQL], [1],
+ [Define to 1 if PostgreSQL libraries are available])
+
+ found_postgresql="yes"
+ AC_MSG_RESULT([yes])
+ else
+ found_postgresql="no"
+ AC_MSG_RESULT([no])
+ fi
+ fi
+
+ dnl
+ dnl Check if required version of PostgreSQL is available
+ dnl
+
+
+ postgresql_version_req=ifelse([$1], [], [], [$1])
+
+ if test "$found_postgresql" = "yes" -a -n "$postgresql_version_req"; then
+
+ AC_MSG_CHECKING([if PostgreSQL version $POSTGRESQL_VERSION is >= $postgresql_version_req])
+
+ dnl Decompose required version string of PostgreSQL
+ dnl and calculate its number representation
+ postgresql_version_req_major=`expr $postgresql_version_req : '\([[0-9]]*\)'`
+ postgresql_version_req_minor=`expr $postgresql_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
+ postgresql_version_req_micro=`expr $postgresql_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+ if test "x$postgresql_version_req_micro" = "x"; then
+ postgresql_version_req_micro="0"
+ fi
+
+ postgresql_version_req_number=`expr $postgresql_version_req_major \* 1000000 \
+ \+ $postgresql_version_req_minor \* 1000 \
+ \+ $postgresql_version_req_micro`
+
+ dnl Decompose version string of installed PostgreSQL
+ dnl and calculate its number representation
+ postgresql_version_major=`expr $POSTGRESQL_VERSION : '\([[0-9]]*\)'`
+ postgresql_version_minor=`expr $POSTGRESQL_VERSION : '[[0-9]]*\.\([[0-9]]*\)'`
+ postgresql_version_micro=`expr $POSTGRESQL_VERSION : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+ if test "x$postgresql_version_micro" = "x"; then
+ postgresql_version_micro="0"
+ fi
+
+ postgresql_version_number=`expr $postgresql_version_major \* 1000000 \
+ \+ $postgresql_version_minor \* 1000 \
+ \+ $postgresql_version_micro`
+
+ postgresql_version_check=`expr $postgresql_version_number \>\= $postgresql_version_req_number`
+ if test "$postgresql_version_check" = "1"; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+
+ AC_SUBST([POSTGRESQL_VERSION])
+ AC_SUBST([POSTGRESQL_CPPFLAGS])
+ AC_SUBST([POSTGRESQL_LDFLAGS])
+])
diff --git a/m4/ax_prog_doxygen.m4 b/m4/ax_prog_doxygen.m4
new file mode 100644
index 0000000..a371f7f
--- /dev/null
+++ b/m4/ax_prog_doxygen.m4
@@ -0,0 +1,586 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# DX_INIT_DOXYGEN(PROJECT-NAME, [DOXYFILE-PATH], [OUTPUT-DIR], ...)
+# DX_DOXYGEN_FEATURE(ON|OFF)
+# DX_DOT_FEATURE(ON|OFF)
+# DX_HTML_FEATURE(ON|OFF)
+# DX_CHM_FEATURE(ON|OFF)
+# DX_CHI_FEATURE(ON|OFF)
+# DX_MAN_FEATURE(ON|OFF)
+# DX_RTF_FEATURE(ON|OFF)
+# DX_XML_FEATURE(ON|OFF)
+# DX_PDF_FEATURE(ON|OFF)
+# DX_PS_FEATURE(ON|OFF)
+#
+# DESCRIPTION
+#
+# The DX_*_FEATURE macros control the default setting for the given
+# Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
+# generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
+# help (for MS users), 'CHI' for generating a separate .chi file by the
+# .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
+# output formats. The environment variable DOXYGEN_PAPER_SIZE may be
+# specified to override the default 'a4wide' paper size.
+#
+# By default, HTML, PDF and PS documentation is generated as this seems to
+# be the most popular and portable combination. MAN pages created by
+# Doxygen are usually problematic, though by picking an appropriate subset
+# and doing some massaging they might be better than nothing. CHM and RTF
+# are specific for MS (note that you can't generate both HTML and CHM at
+# the same time). The XML is rather useless unless you apply specialized
+# post-processing to it.
+#
+# The macros mainly control the default state of the feature. The use can
+# override the default by specifying --enable or --disable. The macros
+# ensure that contradictory flags are not given (e.g.,
+# --enable-doxygen-html and --enable-doxygen-chm,
+# --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
+# feature will be automatically disabled (with a warning) if the required
+# programs are missing.
+#
+# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
+# with the following parameters: a one-word name for the project for use
+# as a filename base etc., an optional configuration file name (the
+# default is '$(srcdir)/Doxyfile', the same as Doxygen's default), and an
+# optional output directory name (the default is 'doxygen-doc'). To run
+# doxygen multiple times for different configuration files and output
+# directories provide more parameters: the second, forth, sixth, etc
+# parameter are configuration file names and the third, fifth, seventh,
+# etc parameter are output directories. No checking is done to catch
+# duplicates.
+#
+# Automake Support
+#
+# The DX_RULES substitution can be used to add all needed rules to the
+# Makefile. Note that this is a substitution without being a variable:
+# only the @DX_RULES@ syntax will work.
+#
+# The provided targets are:
+#
+# doxygen-doc: Generate all doxygen documentation.
+#
+# doxygen-run: Run doxygen, which will generate some of the
+# documentation (HTML, CHM, CHI, MAN, RTF, XML)
+# but will not do the post processing required
+# for the rest of it (PS, PDF).
+#
+# doxygen-ps: Generate doxygen PostScript documentation.
+#
+# doxygen-pdf: Generate doxygen PDF documentation.
+#
+# Note that by default these are not integrated into the automake targets.
+# If doxygen is used to generate man pages, you can achieve this
+# integration by setting man3_MANS to the list of man pages generated and
+# then adding the dependency:
+#
+# $(man3_MANS): doxygen-doc
+#
+# This will cause make to run doxygen and generate all the documentation.
+#
+# The following variable is intended for use in Makefile.am:
+#
+# DX_CLEANFILES = everything to clean.
+#
+# Then add this variable to MOSTLYCLEANFILES.
+#
+# LICENSE
+#
+# Copyright (c) 2009 Oren Ben-Kiki <oren@ben-kiki.org>
+# Copyright (c) 2015 Olaf Mandel <olaf@mandel.name>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 23
+
+## ----------##
+## Defaults. ##
+## ----------##
+
+DX_ENV=""
+AC_DEFUN([DX_FEATURE_doc], ON)
+AC_DEFUN([DX_FEATURE_dot], OFF)
+AC_DEFUN([DX_FEATURE_man], OFF)
+AC_DEFUN([DX_FEATURE_html], ON)
+AC_DEFUN([DX_FEATURE_chm], OFF)
+AC_DEFUN([DX_FEATURE_chi], OFF)
+AC_DEFUN([DX_FEATURE_rtf], OFF)
+AC_DEFUN([DX_FEATURE_xml], OFF)
+AC_DEFUN([DX_FEATURE_pdf], ON)
+AC_DEFUN([DX_FEATURE_ps], ON)
+
+## --------------- ##
+## Private macros. ##
+## --------------- ##
+
+# DX_ENV_APPEND(VARIABLE, VALUE)
+# ------------------------------
+# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen and add it
+# as a substitution (but not a Makefile variable). The substitution
+# is skipped if the variable name is VERSION.
+AC_DEFUN([DX_ENV_APPEND],
+[AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])dnl
+m4_if([$1], [VERSION], [], [AC_SUBST([$1], [$2])dnl
+AM_SUBST_NOTMAKE([$1])])dnl
+])
+
+# DX_DIRNAME_EXPR
+# ---------------
+# Expand into a shell expression prints the directory part of a path.
+AC_DEFUN([DX_DIRNAME_EXPR],
+ [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
+
+# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
+# -------------------------------------
+# Expands according to the M4 (static) status of the feature.
+AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
+
+# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
+# ----------------------------------
+# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
+AC_DEFUN([DX_REQUIRE_PROG], [
+AC_PATH_TOOL([$1], [$2])
+if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
+ AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
+ AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
+fi
+])
+
+# DX_TEST_FEATURE(FEATURE)
+# ------------------------
+# Expand to a shell expression testing whether the feature is active.
+AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
+
+# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
+# -------------------------------------------------
+# Verify that a required features has the right state before trying to turn on
+# the DX_CURRENT_FEATURE.
+AC_DEFUN([DX_CHECK_DEPEND], [
+test "$DX_FLAG_$1" = "$2" \
+|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
+ requires, contradicts) doxygen-DX_CURRENT_FEATURE])
+])
+
+# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
+# ----------------------------------------------------------
+# Turn off the DX_CURRENT_FEATURE if the required feature is off.
+AC_DEFUN([DX_CLEAR_DEPEND], [
+test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
+])
+
+# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
+# CHECK_DEPEND, CLEAR_DEPEND,
+# REQUIRE, DO-IF-ON, DO-IF-OFF)
+# --------------------------------------------
+# Parse the command-line option controlling a feature. CHECK_DEPEND is called
+# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
+# otherwise CLEAR_DEPEND is called to turn off the default state if a required
+# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
+# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
+# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
+AC_DEFUN([DX_ARG_ABLE], [
+ AC_DEFUN([DX_CURRENT_FEATURE], [$1])
+ AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
+ AC_ARG_ENABLE(doxygen-$1,
+ [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
+ [--enable-doxygen-$1]),
+ DX_IF_FEATURE([$1], [don't $2], [$2]))],
+ [
+case "$enableval" in
+#(
+y|Y|yes|Yes|YES)
+ AC_SUBST([DX_FLAG_$1], 1)
+ $3
+;; #(
+n|N|no|No|NO)
+ AC_SUBST([DX_FLAG_$1], 0)
+;; #(
+*)
+ AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
+;;
+esac
+], [
+AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
+$4
+])
+if DX_TEST_FEATURE([$1]); then
+ $5
+ :
+fi
+if DX_TEST_FEATURE([$1]); then
+ $6
+ :
+else
+ $7
+ :
+fi
+])
+
+## -------------- ##
+## Public macros. ##
+## -------------- ##
+
+# DX_XXX_FEATURE(DEFAULT_STATE)
+# -----------------------------
+AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
+AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])])
+AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
+AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
+AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
+AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
+AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
+AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
+
+# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR], ...)
+# --------------------------------------------------------------
+# PROJECT also serves as the base name for the documentation files.
+# The default CONFIG-FILE is "$(srcdir)/Doxyfile" and OUTPUT-DOC-DIR is
+# "doxygen-doc".
+# More arguments are interpreted as interleaved CONFIG-FILE and
+# OUTPUT-DOC-DIR values.
+AC_DEFUN([DX_INIT_DOXYGEN], [
+
+# Files:
+AC_SUBST([DX_PROJECT], [$1])
+AC_SUBST([DX_CONFIG], ['ifelse([$2], [], [$(srcdir)/Doxyfile], [$2])'])
+AC_SUBST([DX_DOCDIR], ['ifelse([$3], [], [doxygen-doc], [$3])'])
+m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 4, m4_count($@), 2,
+ [AC_SUBST([DX_CONFIG]m4_eval(DX_i[/2]),
+ 'm4_default_nblank_quoted(m4_argn(DX_i, $@),
+ [$(srcdir)/Doxyfile])')])])dnl
+m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 5, m4_count($@,), 2,
+ [AC_SUBST([DX_DOCDIR]m4_eval([(]DX_i[-1)/2]),
+ 'm4_default_nblank_quoted(m4_argn(DX_i, $@),
+ [doxygen-doc])')])])dnl
+m4_define([DX_loop], m4_dquote(m4_if(m4_eval(3 < m4_count($@)), 1,
+ [m4_for([DX_i], 4, m4_count($@), 2, [, m4_eval(DX_i[/2])])],
+ [])))dnl
+
+# Environment variables used inside doxygen.cfg:
+DX_ENV_APPEND(SRCDIR, $srcdir)
+DX_ENV_APPEND(PROJECT, $DX_PROJECT)
+DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
+
+# Doxygen itself:
+DX_ARG_ABLE(doc, [generate any doxygen documentation],
+ [],
+ [],
+ [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
+ DX_REQUIRE_PROG([DX_PERL], perl)],
+ [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
+
+# Dot for graphics:
+DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_DOT], dot)],
+ [DX_ENV_APPEND(HAVE_DOT, YES)
+ DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
+ [DX_ENV_APPEND(HAVE_DOT, NO)])
+
+# Man pages generation:
+DX_ARG_ABLE(man, [generate doxygen manual pages],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_MAN, YES)],
+ [DX_ENV_APPEND(GENERATE_MAN, NO)])
+
+# RTF file generation:
+DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_RTF, YES)],
+ [DX_ENV_APPEND(GENERATE_RTF, NO)])
+
+# XML file generation:
+DX_ARG_ABLE(xml, [generate doxygen XML documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_XML, YES)],
+ [DX_ENV_APPEND(GENERATE_XML, NO)])
+
+# (Compressed) HTML help generation:
+DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_HHC], hhc)],
+ [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
+ DX_ENV_APPEND(GENERATE_HTML, YES)
+ DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
+ [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
+
+# Separate CHI file generation.
+DX_ARG_ABLE(chi, [generate doxygen separate compressed HTML help index file],
+ [DX_CHECK_DEPEND(chm, 1)],
+ [DX_CLEAR_DEPEND(chm, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_CHI, YES)],
+ [DX_ENV_APPEND(GENERATE_CHI, NO)])
+
+# Plain HTML pages generation:
+DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
+ [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
+ [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
+ [],
+ [DX_ENV_APPEND(GENERATE_HTML, YES)],
+ [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
+
+# PostScript file generation:
+DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_LATEX], latex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_DVIPS], dvips)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# PDF file generation:
+DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# LaTeX generation for PS and/or PDF:
+if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
+ DX_ENV_APPEND(GENERATE_LATEX, YES)
+else
+ DX_ENV_APPEND(GENERATE_LATEX, NO)
+fi
+
+# Paper size for PS and/or PDF:
+AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
+ [a4wide (default), a4, letter, legal or executive])
+case "$DOXYGEN_PAPER_SIZE" in
+#(
+"")
+ AC_SUBST(DOXYGEN_PAPER_SIZE, "")
+;; #(
+a4wide|a4|letter|legal|executive)
+ DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
+;; #(
+*)
+ AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
+;;
+esac
+
+# Rules:
+AS_IF([[test $DX_FLAG_html -eq 1]],
+[[DX_SNIPPET_html="## ------------------------------- ##
+## Rules specific for HTML output. ##
+## ------------------------------- ##
+
+DX_CLEAN_HTML = \$(DX_DOCDIR)/html]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+ \$(DX_DOCDIR]DX_i[)/html]])[
+
+"]],
+[[DX_SNIPPET_html=""]])
+AS_IF([[test $DX_FLAG_chi -eq 1]],
+[[DX_SNIPPET_chi="
+DX_CLEAN_CHI = \$(DX_DOCDIR)/\$(PACKAGE).chi]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).chi]])["]],
+[[DX_SNIPPET_chi=""]])
+AS_IF([[test $DX_FLAG_chm -eq 1]],
+[[DX_SNIPPET_chm="## ------------------------------ ##
+## Rules specific for CHM output. ##
+## ------------------------------ ##
+
+DX_CLEAN_CHM = \$(DX_DOCDIR)/chm]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+ \$(DX_DOCDIR]DX_i[)/chm]])[\
+${DX_SNIPPET_chi}
+
+"]],
+[[DX_SNIPPET_chm=""]])
+AS_IF([[test $DX_FLAG_man -eq 1]],
+[[DX_SNIPPET_man="## ------------------------------ ##
+## Rules specific for MAN output. ##
+## ------------------------------ ##
+
+DX_CLEAN_MAN = \$(DX_DOCDIR)/man]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+ \$(DX_DOCDIR]DX_i[)/man]])[
+
+"]],
+[[DX_SNIPPET_man=""]])
+AS_IF([[test $DX_FLAG_rtf -eq 1]],
+[[DX_SNIPPET_rtf="## ------------------------------ ##
+## Rules specific for RTF output. ##
+## ------------------------------ ##
+
+DX_CLEAN_RTF = \$(DX_DOCDIR)/rtf]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+ \$(DX_DOCDIR]DX_i[)/rtf]])[
+
+"]],
+[[DX_SNIPPET_rtf=""]])
+AS_IF([[test $DX_FLAG_xml -eq 1]],
+[[DX_SNIPPET_xml="## ------------------------------ ##
+## Rules specific for XML output. ##
+## ------------------------------ ##
+
+DX_CLEAN_XML = \$(DX_DOCDIR)/xml]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+ \$(DX_DOCDIR]DX_i[)/xml]])[
+
+"]],
+[[DX_SNIPPET_xml=""]])
+AS_IF([[test $DX_FLAG_ps -eq 1]],
+[[DX_SNIPPET_ps="## ----------------------------- ##
+## Rules specific for PS output. ##
+## ----------------------------- ##
+
+DX_CLEAN_PS = \$(DX_DOCDIR)/\$(PACKAGE).ps]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps]])[
+
+DX_PS_GOAL = doxygen-ps
+
+doxygen-ps: \$(DX_CLEAN_PS)
+
+]m4_foreach([DX_i], [DX_loop],
+[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
+ \$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
+ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
+ \$(DX_LATEX) refman.tex; \\
+ \$(DX_MAKEINDEX) refman.idx; \\
+ \$(DX_LATEX) refman.tex; \\
+ countdown=5; \\
+ while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
+ refman.log > /dev/null 2>&1 \\
+ && test \$\$countdown -gt 0; do \\
+ \$(DX_LATEX) refman.tex; \\
+ countdown=\`expr \$\$countdown - 1\`; \\
+ done; \\
+ \$(DX_DVIPS) -o ../\$(PACKAGE).ps refman.dvi
+
+]])["]],
+[[DX_SNIPPET_ps=""]])
+AS_IF([[test $DX_FLAG_pdf -eq 1]],
+[[DX_SNIPPET_pdf="## ------------------------------ ##
+## Rules specific for PDF output. ##
+## ------------------------------ ##
+
+DX_CLEAN_PDF = \$(DX_DOCDIR)/\$(PACKAGE).pdf]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf]])[
+
+DX_PDF_GOAL = doxygen-pdf
+
+doxygen-pdf: \$(DX_CLEAN_PDF)
+
+]m4_foreach([DX_i], [DX_loop],
+[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
+ \$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
+ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
+ \$(DX_PDFLATEX) refman.tex; \\
+ \$(DX_MAKEINDEX) refman.idx; \\
+ \$(DX_PDFLATEX) refman.tex; \\
+ countdown=5; \\
+ while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
+ refman.log > /dev/null 2>&1 \\
+ && test \$\$countdown -gt 0; do \\
+ \$(DX_PDFLATEX) refman.tex; \\
+ countdown=\`expr \$\$countdown - 1\`; \\
+ done; \\
+ mv refman.pdf ../\$(PACKAGE).pdf
+
+]])["]],
+[[DX_SNIPPET_pdf=""]])
+AS_IF([[test $DX_FLAG_ps -eq 1 -o $DX_FLAG_pdf -eq 1]],
+[[DX_SNIPPET_latex="## ------------------------------------------------- ##
+## Rules specific for LaTeX (shared for PS and PDF). ##
+## ------------------------------------------------- ##
+
+DX_V_LATEX = \$(_DX_v_LATEX_\$(V))
+_DX_v_LATEX_ = \$(_DX_v_LATEX_\$(AM_DEFAULT_VERBOSITY))
+_DX_v_LATEX_0 = @echo \" LATEX \" \$][@;
+
+DX_CLEAN_LATEX = \$(DX_DOCDIR)/latex]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+ \$(DX_DOCDIR]DX_i[)/latex]])[
+
+"]],
+[[DX_SNIPPET_latex=""]])
+
+AS_IF([[test $DX_FLAG_doc -eq 1]],
+[[DX_SNIPPET_doc="## --------------------------------- ##
+## Format-independent Doxygen rules. ##
+## --------------------------------- ##
+
+${DX_SNIPPET_html}\
+${DX_SNIPPET_chm}\
+${DX_SNIPPET_man}\
+${DX_SNIPPET_rtf}\
+${DX_SNIPPET_xml}\
+${DX_SNIPPET_ps}\
+${DX_SNIPPET_pdf}\
+${DX_SNIPPET_latex}\
+DX_V_DXGEN = \$(_DX_v_DXGEN_\$(V))
+_DX_v_DXGEN_ = \$(_DX_v_DXGEN_\$(AM_DEFAULT_VERBOSITY))
+_DX_v_DXGEN_0 = @echo \" DXGEN \" \$<;
+
+.PHONY: doxygen-run doxygen-doc \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
+
+.INTERMEDIATE: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
+
+doxygen-run:]m4_foreach([DX_i], [DX_loop],
+ [[ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag]])[
+
+doxygen-doc: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
+
+]m4_foreach([DX_i], [DX_loop],
+[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag: \$(DX_CONFIG]DX_i[) \$(pkginclude_HEADERS)
+ \$(A""M_V_at)rm -rf \$(DX_DOCDIR]DX_i[)
+ \$(DX_V_DXGEN)\$(DX_ENV) DOCDIR=\$(DX_DOCDIR]DX_i[) \$(DX_DOXYGEN) \$(DX_CONFIG]DX_i[)
+ \$(A""M_V_at)echo Timestamp >\$][@
+
+]])dnl
+[DX_CLEANFILES = \\]
+m4_foreach([DX_i], [DX_loop],
+[[ \$(DX_DOCDIR]DX_i[)/doxygen_sqlite3.db \\
+ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag \\
+]])dnl
+[ -r \\
+ \$(DX_CLEAN_HTML) \\
+ \$(DX_CLEAN_CHM) \\
+ \$(DX_CLEAN_CHI) \\
+ \$(DX_CLEAN_MAN) \\
+ \$(DX_CLEAN_RTF) \\
+ \$(DX_CLEAN_XML) \\
+ \$(DX_CLEAN_PS) \\
+ \$(DX_CLEAN_PDF) \\
+ \$(DX_CLEAN_LATEX)"]],
+[[DX_SNIPPET_doc=""]])
+AC_SUBST([DX_RULES],
+["${DX_SNIPPET_doc}"])dnl
+AM_SUBST_NOTMAKE([DX_RULES])
+
+#For debugging:
+#echo DX_FLAG_doc=$DX_FLAG_doc
+#echo DX_FLAG_dot=$DX_FLAG_dot
+#echo DX_FLAG_man=$DX_FLAG_man
+#echo DX_FLAG_html=$DX_FLAG_html
+#echo DX_FLAG_chm=$DX_FLAG_chm
+#echo DX_FLAG_chi=$DX_FLAG_chi
+#echo DX_FLAG_rtf=$DX_FLAG_rtf
+#echo DX_FLAG_xml=$DX_FLAG_xml
+#echo DX_FLAG_pdf=$DX_FLAG_pdf
+#echo DX_FLAG_ps=$DX_FLAG_ps
+#echo DX_ENV=$DX_ENV
+])
diff --git a/m4/libcurl.m4 b/m4/libcurl.m4
new file mode 100644
index 0000000..a84077a
--- /dev/null
+++ b/m4/libcurl.m4
@@ -0,0 +1,251 @@
+# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION],
+# [ACTION-IF-YES], [ACTION-IF-NO])
+# ----------------------------------------------------------
+# David Shaw <dshaw@jabberwocky.com> May-09-2006
+#
+# Checks for libcurl. DEFAULT-ACTION is the string yes or no to
+# specify whether to default to --with-libcurl or --without-libcurl.
+# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the
+# minimum version of libcurl to accept. Pass the version as a regular
+# version number like 7.10.1. If not supplied, any version is
+# accepted. ACTION-IF-YES is a list of shell commands to run if
+# libcurl was successfully found and passed the various tests.
+# ACTION-IF-NO is a list of shell commands that are run otherwise.
+# Note that using --without-libcurl does run ACTION-IF-NO.
+#
+# This macro #defines HAVE_LIBCURL if a working libcurl setup is
+# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary
+# values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are
+# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy
+# where yyy are the various protocols supported by libcurl. Both xxx
+# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of
+# the macro for the complete list of possible defines. Shell
+# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also
+# defined to 'yes' for those features and protocols that were found.
+# Note that xxx and yyy keep the same capitalization as in the
+# curl-config list (e.g. it's "HTTP" and not "http").
+#
+# Users may override the detected values by doing something like:
+# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure
+#
+# For the sake of sanity, this macro assumes that any libcurl that is
+# found is after version 7.7.2, the first version that included the
+# curl-config script. Note that it is very important for people
+# packaging binary versions of libcurl to include this script!
+# Without curl-config, we can only guess what protocols are available,
+# or use curl_version_info to figure it out at runtime.
+
+AC_DEFUN([LIBCURL_CHECK_CONFIG],
+[
+ AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL])
+ AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4])
+ AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6])
+ AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz])
+ AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS])
+ AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN])
+ AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI])
+ AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM])
+
+ AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP])
+ AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP])
+
+ AC_ARG_WITH(libcurl,
+ AC_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]),
+ [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])])
+
+ if test "$_libcurl_with" != "no" ; then
+
+ AC_PROG_AWK
+
+ _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'"
+
+ _libcurl_try_link=yes
+
+ if test -d "$_libcurl_with" ; then
+ LIBCURL_CPPFLAGS="-I$withval/include"
+ _libcurl_ldflags="-L$withval/lib"
+ AC_PATH_PROG([_libcurl_config],[curl-config],[],
+ ["$withval/bin"])
+ else
+ AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH])
+ fi
+
+ if test x$_libcurl_config != "x" ; then
+ AC_CACHE_CHECK([for the version of libcurl],
+ [libcurl_cv_lib_curl_version],
+ [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`])
+
+ _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse`
+ _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse`
+
+ if test $_libcurl_wanted -gt 0 ; then
+ AC_CACHE_CHECK([for libcurl >= version $2],
+ [libcurl_cv_lib_version_ok],
+ [
+ if test $_libcurl_version -ge $_libcurl_wanted ; then
+ libcurl_cv_lib_version_ok=yes
+ else
+ libcurl_cv_lib_version_ok=no
+ fi
+ ])
+ fi
+
+ if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then
+ if test x"$LIBCURL_CPPFLAGS" = "x" ; then
+ LIBCURL_CPPFLAGS=`$_libcurl_config --cflags`
+ fi
+ if test x"$LIBCURL" = "x" ; then
+ LIBCURL=`$_libcurl_config --libs`
+
+ # This is so silly, but Apple actually has a bug in their
+ # curl-config script. Fixed in Tiger, but there are still
+ # lots of Panther installs around.
+ case "${host}" in
+ powerpc-apple-darwin7*)
+ LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'`
+ ;;
+ esac
+ fi
+
+ # All curl-config scripts support --feature
+ _libcurl_features=`$_libcurl_config --feature`
+
+ # Is it modern enough to have --protocols? (7.12.4)
+ if test $_libcurl_version -ge 461828 ; then
+ _libcurl_protocols=`$_libcurl_config --protocols`
+ fi
+ else
+ _libcurl_try_link=no
+ fi
+
+ unset _libcurl_wanted
+ fi
+
+ if test $_libcurl_try_link = yes ; then
+
+ # we didn't find curl-config, so let's see if the user-supplied
+ # link line (or failing that, "-lcurl") is enough.
+ LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"}
+
+ AC_CACHE_CHECK([whether libcurl is usable],
+ [libcurl_cv_lib_curl_usable],
+ [
+ _libcurl_save_cppflags=$CPPFLAGS
+ CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS"
+ _libcurl_save_libs=$LIBS
+ LIBS="$LIBCURL $LIBS"
+
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <curl/curl.h>]],[[
+/* Try and use a few common options to force a failure if we are
+ missing symbols or can't link. */
+int x;
+curl_easy_setopt(NULL,CURLOPT_URL,NULL);
+x=CURL_ERROR_SIZE;
+x=CURLOPT_WRITEFUNCTION;
+x=CURLOPT_WRITEDATA;
+x=CURLOPT_ERRORBUFFER;
+x=CURLOPT_STDERR;
+x=CURLOPT_VERBOSE;
+if (x) ;
+]])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no)
+
+ CPPFLAGS=$_libcurl_save_cppflags
+ LIBS=$_libcurl_save_libs
+ unset _libcurl_save_cppflags
+ unset _libcurl_save_libs
+ ])
+
+ if test $libcurl_cv_lib_curl_usable = yes ; then
+
+ # Does curl_free() exist in this version of libcurl?
+ # If not, fake it with free()
+
+ _libcurl_save_cppflags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS"
+ _libcurl_save_libs=$LIBS
+ LIBS="$LIBS $LIBCURL"
+
+ AC_CHECK_FUNC(curl_free,,
+ AC_DEFINE(curl_free,free,
+ [Define curl_free() as free() if our version of curl lacks curl_free.]))
+
+ CPPFLAGS=$_libcurl_save_cppflags
+ LIBS=$_libcurl_save_libs
+ unset _libcurl_save_cppflags
+ unset _libcurl_save_libs
+
+ AC_DEFINE(HAVE_LIBCURL,1,
+ [Define to 1 if you have a functional curl library.])
+ AC_SUBST(LIBCURL_CPPFLAGS)
+ AC_SUBST(LIBCURL)
+
+ for _libcurl_feature in $_libcurl_features ; do
+ AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1])
+ eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes
+ done
+
+ if test "x$_libcurl_protocols" = "x" ; then
+
+ # We don't have --protocols, so just assume that all
+ # protocols are available
+ _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP"
+
+ if test x$libcurl_feature_SSL = xyes ; then
+ _libcurl_protocols="$_libcurl_protocols HTTPS"
+
+ # FTPS wasn't standards-compliant until version
+ # 7.11.0 (0x070b00 == 461568)
+ if test $_libcurl_version -ge 461568; then
+ _libcurl_protocols="$_libcurl_protocols FTPS"
+ fi
+ fi
+
+ # RTSP, IMAP, POP3 and SMTP were added in
+ # 7.20.0 (0x071400 == 463872)
+ if test $_libcurl_version -ge 463872; then
+ _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP"
+ fi
+ fi
+
+ for _libcurl_protocol in $_libcurl_protocols ; do
+ AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1])
+ eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes
+ done
+ else
+ unset LIBCURL
+ unset LIBCURL_CPPFLAGS
+ fi
+ fi
+
+ unset _libcurl_try_link
+ unset _libcurl_version_parse
+ unset _libcurl_config
+ unset _libcurl_feature
+ unset _libcurl_features
+ unset _libcurl_protocol
+ unset _libcurl_protocols
+ unset _libcurl_version
+ unset _libcurl_ldflags
+ fi
+
+ if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then
+ # This is the IF-NO path
+ ifelse([$4],,:,[$4])
+ else
+ # This is the IF-YES path
+ ifelse([$3],,:,[$3])
+ fi
+
+ unset _libcurl_with
+])dnl
diff --git a/m4/libgnurl.m4 b/m4/libgnurl.m4
new file mode 100644
index 0000000..69aa166
--- /dev/null
+++ b/m4/libgnurl.m4
@@ -0,0 +1,250 @@
+# LIBGNURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION],
+# [ACTION-IF-YES], [ACTION-IF-NO])
+# ----------------------------------------------------------
+# David Shaw <dshaw@jabberwocky.com> May-09-2006
+#
+# Checks for libgnurl. DEFAULT-ACTION is the string yes or no to
+# specify whether to default to --with-libgnurl or --without-libgnurl.
+# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the
+# minimum version of libgnurl to accept. Pass the version as a regular
+# version number like 7.10.1. If not supplied, any version is
+# accepted. ACTION-IF-YES is a list of shell commands to run if
+# libgnurl was successfully found and passed the various tests.
+# ACTION-IF-NO is a list of shell commands that are run otherwise.
+# Note that using --without-libgnurl does run ACTION-IF-NO.
+#
+# This macro #defines HAVE_LIBGNURL if a working libgnurl setup is
+# found, and sets @LIBGNURL@ and @LIBGNURL_CPPFLAGS@ to the necessary
+# values. Other useful defines are LIBGNURL_FEATURE_xxx where xxx are
+# the various features supported by libgnurl, and LIBGNURL_PROTOCOL_yyy
+# where yyy are the various protocols supported by libgnurl. Both xxx
+# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of
+# the macro for the complete list of possible defines. Shell
+# variables $libgnurl_feature_xxx and $libgnurl_protocol_yyy are also
+# defined to 'yes' for those features and protocols that were found.
+# Note that xxx and yyy keep the same capitalization as in the
+# gnurl-config list (e.g. it's "HTTP" and not "http").
+#
+# Users may override the detected values by doing something like:
+# LIBGNURL="-lgnurl" LIBGNURL_CPPFLAGS="-I/usr/myinclude" ./configure
+#
+# For the sake of sanity, this macro assumes that any libgnurl that is
+# found is after version 7.7.2, the first version that included the
+# gnurl-config script. Note that it is very important for people
+# packaging binary versions of libgnurl to include this script!
+# Without gnurl-config, we can only guess what protocols are available,
+# or use gnurl_version_info to figure it out at runtime.
+
+AC_DEFUN([LIBGNURL_CHECK_CONFIG],
+[
+ AH_TEMPLATE([LIBGNURL_FEATURE_SSL],[Defined if libgnurl supports SSL])
+ AH_TEMPLATE([LIBGNURL_FEATURE_KRB4],[Defined if libgnurl supports KRB4])
+ AH_TEMPLATE([LIBGNURL_FEATURE_IPV6],[Defined if libgnurl supports IPv6])
+ AH_TEMPLATE([LIBGNURL_FEATURE_LIBZ],[Defined if libgnurl supports libz])
+ AH_TEMPLATE([LIBGNURL_FEATURE_ASYNCHDNS],[Defined if libgnurl supports AsynchDNS])
+ AH_TEMPLATE([LIBGNURL_FEATURE_IDN],[Defined if libgnurl supports IDN])
+ AH_TEMPLATE([LIBGNURL_FEATURE_SSPI],[Defined if libgnurl supports SSPI])
+ AH_TEMPLATE([LIBGNURL_FEATURE_NTLM],[Defined if libgnurl supports NTLM])
+
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_HTTP],[Defined if libgnurl supports HTTP])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_HTTPS],[Defined if libgnurl supports HTTPS])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_FTP],[Defined if libgnurl supports FTP])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_FTPS],[Defined if libgnurl supports FTPS])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_FILE],[Defined if libgnurl supports FILE])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_TELNET],[Defined if libgnurl supports TELNET])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_LDAP],[Defined if libgnurl supports LDAP])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_DICT],[Defined if libgnurl supports DICT])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_TFTP],[Defined if libgnurl supports TFTP])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_RTSP],[Defined if libgnurl supports RTSP])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_POP3],[Defined if libgnurl supports POP3])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_IMAP],[Defined if libgnurl supports IMAP])
+ AH_TEMPLATE([LIBGNURL_PROTOCOL_SMTP],[Defined if libgnurl supports SMTP])
+
+ AC_ARG_WITH(libgnurl,
+ AC_HELP_STRING([--with-libgnurl=PREFIX],[look for the gnurl library in PREFIX/lib and headers in PREFIX/include]),
+ [_libgnurl_with=$withval],[_libgnurl_with=ifelse([$1],,[yes],[$1])])
+
+ if test "$_libgnurl_with" != "no" ; then
+
+ AC_PROG_AWK
+
+ _libgnurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'"
+
+ _libgnurl_try_link=yes
+
+ if test -d "$_libgnurl_with" ; then
+ LIBGNURL_CPPFLAGS="-I$withval/include"
+ _libgnurl_ldflags="-L$withval/lib"
+ AC_PATH_PROG([_libgnurl_config],[gnurl-config],[],
+ ["$withval/bin"])
+ else
+ AC_PATH_PROG([_libgnurl_config],[gnurl-config],[],[$PATH])
+ fi
+
+ if test x$_libgnurl_config != "x" ; then
+ AC_CACHE_CHECK([for the version of libgnurl],
+ [libgnurl_cv_lib_gnurl_version],
+ [libgnurl_cv_lib_gnurl_version=`$_libgnurl_config --version | $AWK '{print $[]2}'`])
+
+ _libgnurl_version=`echo $libgnurl_cv_lib_gnurl_version | $_libgnurl_version_parse`
+ _libgnurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libgnurl_version_parse`
+
+ if test $_libgnurl_wanted -gt 0 ; then
+ AC_CACHE_CHECK([for libgnurl >= version $2],
+ [libgnurl_cv_lib_version_ok],
+ [
+ if test $_libgnurl_version -ge $_libgnurl_wanted ; then
+ libgnurl_cv_lib_version_ok=yes
+ else
+ libgnurl_cv_lib_version_ok=no
+ fi
+ ])
+ fi
+
+ if test $_libgnurl_wanted -eq 0 || test x$libgnurl_cv_lib_version_ok = xyes ; then
+ if test x"$LIBGNURL_CPPFLAGS" = "x" ; then
+ LIBGNURL_CPPFLAGS=`$_libgnurl_config --cflags`
+ fi
+ if test x"$LIBGNURL" = "x" ; then
+ LIBGNURL=`$_libgnurl_config --libs`
+
+ # This is so silly, but Apple actually has a bug in their
+ # gnurl-config script. Fixed in Tiger, but there are still
+ # lots of Panther installs around.
+ case "${host}" in
+ powerpc-apple-darwin7*)
+ LIBGNURL=`echo $LIBGNURL | sed -e 's|-arch i386||g'`
+ ;;
+ esac
+ fi
+
+ # All gnurl-config scripts support --feature
+ _libgnurl_features=`$_libgnurl_config --feature`
+
+ # Is it modern enough to have --protocols? (7.12.4)
+ if test $_libgnurl_version -ge 461828 ; then
+ _libgnurl_protocols=`$_libgnurl_config --protocols`
+ fi
+ else
+ _libgnurl_try_link=no
+ fi
+
+ unset _libgnurl_wanted
+ fi
+
+ if test $_libgnurl_try_link = yes ; then
+
+ # we didn't find gnurl-config, so let's see if the user-supplied
+ # link line (or failing that, "-lgnurl") is enough.
+ LIBGNURL=${LIBGNURL-"$_libgnurl_ldflags -lgnurl"}
+
+ AC_CACHE_CHECK([whether libgnurl is usable],
+ [libgnurl_cv_lib_gnurl_usable],
+ [
+ _libgnurl_save_cppflags=$CPPFLAGS
+ CPPFLAGS="$LIBGNURL_CPPFLAGS $CPPFLAGS"
+ _libgnurl_save_libs=$LIBS
+ LIBS="$LIBGNURL $LIBS"
+
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <curl/curl.h>],[
+/* Try and use a few common options to force a failure if we are
+ missing symbols or can't link. */
+int x;
+curl_easy_setopt(NULL,CURLOPT_URL,NULL);
+x=CURL_ERROR_SIZE;
+x=CURLOPT_WRITEFUNCTION;
+x=CURLOPT_FILE;
+x=CURLOPT_ERRORBUFFER;
+x=CURLOPT_STDERR;
+x=CURLOPT_VERBOSE;
+])],libgnurl_cv_lib_gnurl_usable=yes,libgnurl_cv_lib_gnurl_usable=no)
+
+ CPPFLAGS=$_libgnurl_save_cppflags
+ LIBS=$_libgnurl_save_libs
+ unset _libgnurl_save_cppflags
+ unset _libgnurl_save_libs
+ ])
+
+ if test $libgnurl_cv_lib_gnurl_usable = yes ; then
+
+ # Does gnurl_free() exist in this version of libgnurl?
+ # If not, fake it with free()
+
+ _libgnurl_save_cppflags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $LIBGNURL_CPPFLAGS"
+ _libgnurl_save_libs=$LIBS
+ LIBS="$LIBS $LIBGNURL"
+
+ AC_CHECK_FUNC(curl_free,,
+ AC_DEFINE(curl_free,free,
+ [Define curl_free() as free() if our version of gnurl lacks curl_free.]))
+
+ CPPFLAGS=$_libgnurl_save_cppflags
+ LIBS=$_libgnurl_save_libs
+ unset _libgnurl_save_cppflags
+ unset _libgnurl_save_libs
+
+ AC_DEFINE(HAVE_LIBGNURL,1,
+ [Define to 1 if you have a functional gnurl library.])
+ AC_SUBST(LIBGNURL_CPPFLAGS)
+ AC_SUBST(LIBGNURL)
+
+ for _libgnurl_feature in $_libgnurl_features ; do
+ AC_DEFINE_UNQUOTED(AS_TR_CPP(libgnurl_feature_$_libgnurl_feature),[1])
+ eval AS_TR_SH(libgnurl_feature_$_libgnurl_feature)=yes
+ done
+
+ if test "x$_libgnurl_protocols" = "x" ; then
+
+ # We don't have --protocols, so just assume that all
+ # protocols are available
+ _libgnurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP"
+
+ if test x$libgnurl_feature_SSL = xyes ; then
+ _libgnurl_protocols="$_libgnurl_protocols HTTPS"
+
+ # FTPS wasn't standards-compliant until version
+ # 7.11.0 (0x070b00 == 461568)
+ if test $_libgnurl_version -ge 461568; then
+ _libgnurl_protocols="$_libgnurl_protocols FTPS"
+ fi
+ fi
+
+ # RTSP, IMAP, POP3 and SMTP were added in
+ # 7.20.0 (0x071400 == 463872)
+ if test $_libgnurl_version -ge 463872; then
+ _libgnurl_protocols="$_libgnurl_protocols RTSP IMAP POP3 SMTP"
+ fi
+ fi
+
+ for _libgnurl_protocol in $_libgnurl_protocols ; do
+ AC_DEFINE_UNQUOTED(AS_TR_CPP(libgnurl_protocol_$_libgnurl_protocol),[1])
+ eval AS_TR_SH(libgnurl_protocol_$_libgnurl_protocol)=yes
+ done
+ else
+ unset LIBGNURL
+ unset LIBGNURL_CPPFLAGS
+ fi
+ fi
+
+ unset _libgnurl_try_link
+ unset _libgnurl_version_parse
+ unset _libgnurl_config
+ unset _libgnurl_feature
+ unset _libgnurl_features
+ unset _libgnurl_protocol
+ unset _libgnurl_protocols
+ unset _libgnurl_version
+ unset _libgnurl_ldflags
+ fi
+
+ if test x$_libgnurl_with = xno || test x$libgnurl_cv_lib_gnurl_usable != xyes ; then
+ # This is the IF-NO path
+ ifelse([$4],,:,[$4])
+ else
+ # This is the IF-YES path
+ ifelse([$3],,:,[$3])
+ fi
+
+ unset _libgnurl_with
+])dnl
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..0746ad4
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,3 @@
+# This Makefile is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+SUBDIRS = include syncdb sync lib
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
new file mode 100644
index 0000000..abcbfe9
--- /dev/null
+++ b/src/include/Makefile.am
@@ -0,0 +1,10 @@
+# This Makefile.am is in the public domain
+EXTRA_DIST = \
+ platform.h
+
+talerincludedir = $(includedir)/taler
+
+talerinclude_HEADERS = \
+ sync_database_plugin.h \
+ sync_service.h \
+ sync_database_lib.h
diff --git a/src/include/platform.h b/src/include/platform.h
new file mode 100644
index 0000000..b17c64f
--- /dev/null
+++ b/src/include/platform.h
@@ -0,0 +1,60 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file include/platform.h
+ * @brief This file contains the includes and definitions which are used by the
+ * rest of the modules
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ */
+
+#ifndef PLATFORM_H_
+#define PLATFORM_H_
+
+/* Include our configuration header */
+#ifndef HAVE_USED_CONFIG_H
+# define HAVE_USED_CONFIG_H
+# ifdef HAVE_CONFIG_H
+# include "sync_config.h"
+# endif
+#endif
+
+
+#if (GNUNET_EXTRA_LOGGING >= 1)
+#define VERBOSE(cmd) cmd
+#else
+#define VERBOSE(cmd) do { break; } while (0)
+#endif
+
+/* Include the features available for GNU source */
+#define _GNU_SOURCE
+
+/* Include GNUnet's platform file */
+#include <gnunet/platform.h>
+
+/* Do not use shortcuts for gcrypt mpi */
+#define GCRYPT_NO_MPI_MACROS 1
+
+/* Do not use deprecated functions from gcrypt */
+#define GCRYPT_NO_DEPRECATED 1
+
+/* Ignore MHD deprecations for now as we want to be compatible
+ to "ancient" MHD releases. */
+#define MHD_NO_DEPRECATION 1
+
+#endif /* PLATFORM_H_ */
+
+/* end of platform.h */
diff --git a/src/include/sync_database_lib.h b/src/include/sync_database_lib.h
new file mode 100644
index 0000000..2a67ec3
--- /dev/null
+++ b/src/include/sync_database_lib.h
@@ -0,0 +1,46 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2017 Inria & GNUnet e.V.
+
+ TALER 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, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ *
+ */
+#ifndef SYNC_DB_LIB_H
+#define SYNC_DB_LIB_H
+
+#include <taler/taler_util.h>
+#include "sync_database_plugin.h"
+
+/**
+ * Initialize the plugin.
+ *
+ * @param cfg configuration to use
+ * @return NULL on failure
+ */
+struct SYNC_DatabasePlugin *
+SYNC_DB_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg);
+
+
+/**
+ * Shutdown the plugin.
+ *
+ * @param plugin plugin to unload
+ */
+void
+SYNC_DB_plugin_unload (struct SYNC_DatabasePlugin *plugin);
+
+
+#endif /* SYNC_DB_LIB_H */
+
+/* end of sync_database_lib.h */
diff --git a/src/include/sync_database_plugin.h b/src/include/sync_database_plugin.h
new file mode 100644
index 0000000..5563cf3
--- /dev/null
+++ b/src/include/sync_database_plugin.h
@@ -0,0 +1,117 @@
+/*
+ This file is part of Sync
+ Copyright (C) 2019 Taler Systems SA
+
+ Sync is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ Sync 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
+ Sync; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_database_plugin.h
+ * @brief database access for Sync
+ * @author Christian Grothoff
+ */
+#ifndef TALER_SYNC_DATABASE_PLUGIN_H
+#define TALER_SYNC_DATABASE_PLUGIN_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include <sync_error_codes.h>
+#include "sync_service.h"
+#include <jansson.h>
+#include <taler/taler_util.h>
+
+/**
+ * Handle to interact with the database.
+ *
+ * Functions ending with "_TR" run their OWN transaction scope
+ * and MUST NOT be called from within a transaction setup by the
+ * caller. Functions ending with "_NT" require the caller to
+ * setup a transaction scope. Functions without a suffix are
+ * simple, single SQL queries that MAY be used either way.
+ */
+struct SYNC_DatabasePlugin
+{
+
+ /**
+ * Closure for all callbacks.
+ */
+ void *cls;
+
+ /**
+ * Name of the library which generated this plugin. Set by the
+ * plugin loader.
+ */
+ char *library_name;
+
+ /**
+ * Drop sync tables. Used for testcases.
+ *
+ * @param cls closure
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+ int
+ (*drop_tables) (void *cls);
+
+ /**
+ * Function called to perform "garbage collection" on the
+ * database, expiring records we no longer require. Deletes
+ * all user records that are not paid up (and by cascade deletes
+ * the associated recovery documents). Also deletes expired
+ * truth and financial records older than @a fin_expire.
+ *
+ * @param cls closure
+ * @param fin_expire financial records older than the given
+ * time stamp should be garbage collected (usual
+ * values might be something like 6-10 years in the past)
+ * @return transaction status
+ */
+ enum SYNC_DB_QueryStatus
+ (*gc)(void *cls,
+ struct GNUNET_TIME_Absolute fin_expire);
+
+ /**
+ * Do a pre-flight check that we are not in an uncommitted transaction.
+ * If we are, try to commit the previous transaction and output a warning.
+ * Does not return anything, as we will continue regardless of the outcome.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ */
+ void
+ (*preflight) (void *cls);
+
+ /**
+ * Check that the database connection is still up.
+ *
+ * @param pg connection to check
+ */
+ void
+ (*check_connection) (void *cls);
+
+ /**
+ * Store backup.
+ *
+ * @param cls closure
+ * @return transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*store_backup)(void *cls,
+ ...);
+
+ /**
+ * Obtain backup.
+ *
+ * @param cls closure
+ */
+ enum GNUNET_DB_QueryStatus
+ (*lookup_backup)(void *cls,
+ ...);
+
+};
+#endif
diff --git a/src/include/sync_service.h b/src/include/sync_service.h
new file mode 100644
index 0000000..efe46fe
--- /dev/null
+++ b/src/include/sync_service.h
@@ -0,0 +1,64 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2019 Taler Systems SA
+
+ Anastasis is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ Anastasis 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along with
+ Anastasis; see the file COPYING.LIB. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/sync_service.h
+ * @brief C interface of libsync, a C library to use sync's HTTP API
+ * @author Christian Grothoff
+ */
+#ifndef _SYNC_SERVICE_H
+#define _SYNC_SERVICE_H
+
+#include <gnunet/gnunet_curl_lib.h>
+#include <jansson.h>
+
+
+/**
+ * An EdDSA public key that is used to identify a user's account.
+ */
+struct SYNC_AccountPubP
+{
+ struct GNUNET_CRYPTO_EddsaPublicKey pub;
+};
+
+
+struct SYNC_UploadOperation;
+
+struct SYNC_UploadOperation *
+SYNC_upload (struct GNUNET_CURL_Context *ctx,
+ const char *base_url,
+ ...);
+
+
+void
+SYNC_upload_cancel (struct SYNC_UploadOperation *uo);
+
+
+
+struct SYNC_DownloadOperation;
+
+struct SYNC_DownloadOperation *
+SYNC_download (struct GNUNET_CURL_Context *ctx,
+ const char *base_url,
+ ...);
+
+
+void
+SYNC_download_cancel (struct SYNC_DownloadOperation *uo);
+
+
+
+
+#endif /* _SYNC_SERVICE_H */
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
new file mode 100644
index 0000000..5f05c26
--- /dev/null
+++ b/src/lib/Makefile.am
@@ -0,0 +1,32 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage -O0
+ XLIB = -lgcov
+endif
+
+lib_LTLIBRARIES = \
+ libsync.la
+
+libsync_la_LDFLAGS = \
+ -version-info 0:0:0 \
+ -no-undefined
+
+libsync_la_SOURCES = \
+ sync_api_upload.c
+
+libsync_la_LIBADD = \
+ -lgnunetcurl \
+ -lgnunetjson \
+ -lgnunetutil \
+ -ljansson \
+ $(XLIB)
+
+if HAVE_LIBCURL
+libsync_la_LIBADD += -lcurl
+else
+if HAVE_LIBGNURL
+libsync_la_LIBADD += -lgnurl
+endif
+endif
diff --git a/src/lib/sync_api_upload.c b/src/lib/sync_api_upload.c
new file mode 100644
index 0000000..353db1a
--- /dev/null
+++ b/src/lib/sync_api_upload.c
@@ -0,0 +1,57 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2017 GNUnet e.V. and INRIA
+
+ TALER is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1,
+ or (at your option) any later version.
+
+ TALER 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with TALER; see the file COPYING.LGPL. If not,
+ see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file lib/sync_api_upload.c
+ * @brief Implementation of the upload POST
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <curl/curl.h>
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "anastasis_service.h"
+
+
+/**
+ * @brief
+ */
+struct SYNC_UploadOperation
+{
+
+ /**
+ * The url for this request.
+ */
+ char *url;
+
+ /**
+ * Handle for the request.
+ */
+ struct GNUNET_CURL_Job *job;
+
+ /**
+ * Reference to the execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+};
+
+/* end of sync_api_upload.c */
diff --git a/src/sync/Makefile.am b/src/sync/Makefile.am
new file mode 100644
index 0000000..c703348
--- /dev/null
+++ b/src/sync/Makefile.am
@@ -0,0 +1,28 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+pkgcfgdir = $(prefix)/share/taler/config.d/
+
+pkgcfg_DATA = \
+ sync.conf
+
+bin_PROGRAMS = \
+ sync-httpd
+
+sync_httpd_SOURCES = \
+ sync-httpd.c sync-httpd.h \
+ sync-httpd_parsing.c sync-httpd_parsing.h \
+ sync-httpd_responses.c sync-httpd_responses.h \
+ sync-httpd_mhd.c sync-httpd_mhd.h \
+ sync-httpd_policy.c sync-httpd_policy.h
+
+sync_httpd_LDADD = \
+ $(top_builddir)/src/stasis/libsyncdb.la \
+ -lmicrohttpd \
+ -ljansson \
+ -lgnunetcurl \
+ -lgnunetjson \
+ -lgnunetutil
+
+EXTRA_DIST = \
+ $(pkgcfg_DATA)
diff --git a/src/sync/sync-httpd.c b/src/sync/sync-httpd.c
new file mode 100644
index 0000000..d4f3830
--- /dev/null
+++ b/src/sync/sync-httpd.c
@@ -0,0 +1,744 @@
+/*
+ This file is part of TALER
+ (C) 2019 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file backup/sync-httpd.c
+ * @brief HTTP serving layer intended to provide basic backup operations
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <microhttpd.h>
+#include <gnunet/gnunet_util_lib.h>
+#include "sync-httpd_responses.h"
+#include "sync-httpd.h"
+#include "sync-httpd_parsing.h"
+#include "sync-httpd_mhd.h"
+#include "sync_database_lib.h"
+#include "sync-httpd_policy.h"
+
+/**
+ * Backlog for listen operation on unix-domain sockets.
+ */
+#define UNIX_BACKLOG 500
+
+/**
+ * The port we are running on
+ */
+static long long unsigned port;
+
+/**
+ * Should a "Connection: close" header be added to each HTTP response?
+ */
+int TMH_sync_connection_close;
+
+/**
+ * Task running the HTTP server.
+ */
+static struct GNUNET_SCHEDULER_Task *mhd_task;
+
+/**
+ * Global return code
+ */
+static int result;
+
+/**
+ * The MHD Daemon
+ */
+static struct MHD_Daemon *mhd;
+
+/**
+ * Path for the unix domain-socket
+ * to run the daemon on.
+ */
+static char *serve_unixpath;
+
+/**
+ * File mode for unix-domain socket.
+ */
+static mode_t unixpath_mode;
+
+/**
+ * Connection handle to the our database
+ */
+struct sync_DatabasePlugin *db;
+
+
+/**
+ * Return GNUNET_YES if given a valid correlation ID and
+ * GNUNET_NO otherwise.
+ *
+ * @returns GNUNET_YES iff given a valid correlation ID
+ */
+static int
+is_valid_correlation_id (const char *correlation_id)
+{
+ if (strlen (correlation_id) >= 64)
+ return GNUNET_NO;
+ for (int i = 0; i < strlen (correlation_id); i++)
+ if (! (isalnum (correlation_id[i]) ||(correlation_id[i] == '-')))
+ return GNUNET_NO;
+ return GNUNET_YES;
+}
+
+
+/**
+ * A client has requested the given url using the given method
+ * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT,
+ * #MHD_HTTP_METHOD_DELETE, #MHD_HTTP_METHOD_POST, etc). The callback
+ * must call MHD callbacks to provide content to give back to the
+ * client and return an HTTP status code (i.e. #MHD_HTTP_OK,
+ * #MHD_HTTP_NOT_FOUND, etc.).
+ *
+ * @param cls argument given together with the function
+ * pointer when the handler was registered with MHD
+ * @param url the requested url
+ * @param method the HTTP method used (#MHD_HTTP_METHOD_GET,
+ * #MHD_HTTP_METHOD_PUT, etc.)
+ * @param version the HTTP version string (i.e.
+ * #MHD_HTTP_VERSION_1_1)
+ * @param upload_data the data being uploaded (excluding HEADERS,
+ * for a POST that fits into memory and that is encoded
+ * with a supported encoding, the POST data will NOT be
+ * given in upload_data and is instead available as
+ * part of #MHD_get_connection_values; very large POST
+ * data *will* be made available incrementally in
+ * @a upload_data)
+ * @param upload_data_size set initially to the size of the
+ * @a upload_data provided; the method must update this
+ * value to the number of bytes NOT processed;
+ * @param con_cls pointer that the callback can set to some
+ * address and that will be preserved by MHD for future
+ * calls for this request; since the access handler may
+ * be called many times (i.e., for a PUT/POST operation
+ * with plenty of upload data) this allows the application
+ * to easily associate some request-specific state.
+ * If necessary, this state can be cleaned up in the
+ * global #MHD_RequestCompletedCallback (which
+ * can be set with the #MHD_OPTION_NOTIFY_COMPLETED).
+ * Initially, `*con_cls` will be NULL.
+ * @return #MHD_YES if the connection was handled successfully,
+ * #MHD_NO if the socket must be closed due to a serios
+ * error while handling the request
+ */
+static int
+url_handler (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **con_cls)
+{
+ static struct TMH_RequestHandler handlers[] = {
+ /* Landing page, tell humans to go away. */
+ { "/", MHD_HTTP_METHOD_GET, "text/plain",
+ "Hello, I'm sync. This HTTP server is not for humans.\n", 0,
+ &TMH_MHD_handler_static_response, MHD_HTTP_OK },
+ { "/agpl", MHD_HTTP_METHOD_GET, "text/plain",
+ NULL, 0,
+ &TMH_MHD_handler_agpl_redirect, MHD_HTTP_FOUND },
+ {NULL, NULL, NULL, NULL, 0, 0 }
+ };
+ static struct TMH_RequestHandler h404 = {
+ "", NULL, "text/html",
+ "<html><title>404: not found</title></html>", 0,
+ &TMH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND
+ };
+
+ struct TM_HandlerContext *hc;
+ struct GNUNET_AsyncScopeId aid;
+ const char *correlation_id = NULL;
+
+ hc = *con_cls;
+
+ if (NULL == hc)
+ {
+ GNUNET_async_scope_fresh (&aid);
+ /* We only read the correlation ID on the first callback for every client */
+ correlation_id = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ "sync-Correlation-Id");
+ if ((NULL != correlation_id) &&
+ (GNUNET_YES != is_valid_correlation_id (correlation_id)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "illegal incoming correlation ID\n");
+ correlation_id = NULL;
+ }
+ }
+ else
+ {
+ aid = hc->async_scope_id;
+ }
+
+ GNUNET_SCHEDULER_begin_async_scope (&aid);
+
+ if (NULL != correlation_id)
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Handling request for (%s) URL '%s', correlation_id=%s\n",
+ method,
+ url,
+ correlation_id);
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Handling request (%s) for URL '%s'\n",
+ method,
+ url);
+ if (0 == strncmp (url,
+ "/backup/",
+ strlen ("/backup/")))
+ {
+ // return handle_policy (...);
+ if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
+ {
+ return sync_handler_backup_get (connection,
+ url,
+ con_cls);
+ }
+ if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
+ {
+ return sync_handler_backup_post (connection,
+ con_cls,
+ url,
+ upload_data,
+ upload_data_size);
+ }
+ }
+ for (unsigned int i = 0; NULL != handlers[i].url; i++)
+ {
+ struct TMH_RequestHandler *rh = &handlers[i];
+
+ if ( (0 == strcmp (url,
+ rh->url)) &&
+ ( (NULL == rh->method) ||
+ (0 == strcmp (method,
+ rh->method)) ) )
+ {
+ int ret;
+
+ ret = rh->handler (rh,
+ connection,
+ con_cls,
+ upload_data,
+ upload_data_size);
+ hc = *con_cls;
+ if (NULL != hc)
+ {
+ hc->rh = rh;
+ /* Store the async context ID, so we can restore it if
+ * we get another callack for this request. */
+ hc->async_scope_id = aid;
+ }
+ return ret;
+ }
+ }
+ return TMH_MHD_handler_static_response (&h404,
+ connection,
+ con_cls,
+ upload_data,
+ upload_data_size);
+}
+
+
+/**
+ * Shutdown task (magically invoked when the application is being
+ * quit)
+ *
+ * @param cls NULL
+ */
+static void
+do_shutdown (void *cls)
+{
+ if (NULL != mhd_task)
+ {
+ GNUNET_SCHEDULER_cancel (mhd_task);
+ mhd_task = NULL;
+ }
+ if (NULL != mhd)
+ {
+ MHD_stop_daemon (mhd);
+ mhd = NULL;
+ }
+ if (NULL != db)
+ {
+ sync_DB_plugin_unload (db);
+ db = NULL;
+ }
+}
+
+
+/**
+ * Function called whenever MHD is done with a request. If the
+ * request was a POST, we may have stored a `struct Buffer *` in the
+ * @a con_cls that might still need to be cleaned up. Call the
+ * respective function to free the memory.
+ *
+ * @param cls client-defined closure
+ * @param connection connection handle
+ * @param con_cls value as set by the last call to
+ * the #MHD_AccessHandlerCallback
+ * @param toe reason for request termination
+ * @see #MHD_OPTION_NOTIFY_COMPLETED
+ * @ingroup request
+ */
+static void
+handle_mhd_completion_callback (void *cls,
+ struct MHD_Connection *connection,
+ void **con_cls,
+ enum MHD_RequestTerminationCode toe)
+{
+ struct TM_HandlerContext *hc = *con_cls;
+
+ if (NULL == hc)
+ return;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Finished handling request for `%s' with status %d\n",
+ hc->rh->url,
+ (int) toe);
+ hc->cc (hc);
+ *con_cls = NULL;
+}
+
+
+/**
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
+ */
+static struct GNUNET_SCHEDULER_Task *
+prepare_daemon (void);
+
+
+/**
+ * Set if we should immediately #MHD_run again.
+ */
+static int triggered;
+
+
+/**
+ * Call MHD to process pending requests and then go back
+ * and schedule the next run.
+ *
+ * @param cls the `struct MHD_Daemon` of the HTTP server to run
+ */
+static void
+run_daemon (void *cls)
+{
+ mhd_task = NULL;
+ do {
+ triggered = 0;
+ GNUNET_assert (MHD_YES == MHD_run (mhd));
+ } while (0 != triggered);
+ mhd_task = prepare_daemon ();
+}
+
+
+/**
+ * Kick MHD to run now, to be called after MHD_resume_connection().
+ * Basically, we need to explicitly resume MHD's event loop whenever
+ * we made progress serving a request. This function re-schedules
+ * the task processing MHD's activities to run immediately.
+ */
+void
+TMH_trigger_daemon ()
+{
+ if (NULL != mhd_task)
+ {
+ GNUNET_SCHEDULER_cancel (mhd_task);
+ mhd_task = NULL;
+ run_daemon (NULL);
+ }
+ else
+ {
+ triggered = 1;
+ }
+}
+
+
+/**
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
+ *
+ * @param daemon_handle HTTP server to prepare to run
+ */
+static struct GNUNET_SCHEDULER_Task *
+prepare_daemon ()
+{
+ struct GNUNET_SCHEDULER_Task *ret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ struct GNUNET_NETWORK_FDSet *wrs;
+ struct GNUNET_NETWORK_FDSet *wws;
+ int max;
+ MHD_UNSIGNED_LONG_LONG timeout;
+ int haveto;
+ struct GNUNET_TIME_Relative tv;
+
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ wrs = GNUNET_NETWORK_fdset_create ();
+ wws = GNUNET_NETWORK_fdset_create ();
+ max = -1;
+ GNUNET_assert (MHD_YES ==
+ MHD_get_fdset (mhd,
+ &rs,
+ &ws,
+ &es,
+ &max));
+ haveto = MHD_get_timeout (mhd, &timeout);
+ if (haveto == MHD_YES)
+ tv.rel_value_us = (uint64_t) timeout * 1000LL;
+ else
+ tv = GNUNET_TIME_UNIT_FOREVER_REL;
+ GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
+ GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding run_daemon select task\n");
+ ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
+ tv,
+ wrs,
+ wws,
+ &run_daemon,
+ NULL);
+ GNUNET_NETWORK_fdset_destroy (wrs);
+ GNUNET_NETWORK_fdset_destroy (wws);
+ return ret;
+}
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be
+ * NULL!)
+ * @param config configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *config)
+{
+ int fh;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting sync-httpd\n");
+
+ result = GNUNET_SYSERR;
+ GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+ NULL);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_log_setup ("sync-httpd",
+ "WARNING",
+ NULL));
+ if (NULL ==
+ (db = sync_DB_plugin_load (config)))
+ {
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+ {
+ const char *choices[] = {"tcp",
+ "unix",
+ NULL};
+
+ const char *serve_type;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_choice (config,
+ "sync",
+ "SERVE",
+ choices,
+ &serve_type))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "sync",
+ "SERVE",
+ "serve type required");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+ if (0 == strcmp (serve_type, "unix"))
+ {
+ struct sockaddr_un *un;
+ char *mode;
+ struct GNUNET_NETWORK_Handle *nh;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (config,
+ "sync",
+ "unixpath",
+ &serve_unixpath))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "sync",
+ "unixpath",
+ "unixpath required");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+ if (strlen (serve_unixpath) >= sizeof (un->sun_path))
+ {
+ fprintf (stderr,
+ "Invalid configuration: unix path too long\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (config,
+ "sync",
+ "UNIXPATH_MODE",
+ &mode))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "sync",
+ "UNIXPATH_MODE");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ errno = 0;
+ unixpath_mode = (mode_t) strtoul (mode, NULL, 8);
+ if (0 != errno)
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "sync",
+ "UNIXPATH_MODE",
+ "must be octal number");
+ GNUNET_free (mode);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ GNUNET_free (mode);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Creating listen socket '%s' with mode %o\n",
+ serve_unixpath, unixpath_mode);
+
+ if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (serve_unixpath))
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "mkdir",
+ serve_unixpath);
+ }
+
+ un = GNUNET_new (struct sockaddr_un);
+ un->sun_family = AF_UNIX;
+ strncpy (un->sun_path,
+ serve_unixpath,
+ sizeof (un->sun_path) - 1);
+
+ GNUNET_NETWORK_unix_precheck (un);
+
+ if (NULL == (nh = GNUNET_NETWORK_socket_create (AF_UNIX,
+ SOCK_STREAM,
+ 0)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "socket(AF_UNIX)");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_NETWORK_socket_bind (nh,
+ (void *) un,
+ sizeof (struct sockaddr_un)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "bind(AF_UNIX)");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_NETWORK_socket_listen (nh,
+ UNIX_BACKLOG))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "listen(AF_UNIX)");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+ fh = GNUNET_NETWORK_get_fd (nh);
+ GNUNET_NETWORK_socket_free_memory_only_ (nh);
+ if (0 != chmod (serve_unixpath,
+ unixpath_mode))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "chmod");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ port = 0;
+ }
+ else if (0 == strcmp (serve_type, "tcp"))
+ {
+ char *bind_to;
+
+ if (GNUNET_SYSERR ==
+ GNUNET_CONFIGURATION_get_value_number (config,
+ "sync",
+ "PORT",
+ &port))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "sync",
+ "PORT");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_string (config,
+ "sync",
+ "BIND_TO",
+ &bind_to))
+ {
+ char port_str[6];
+ struct addrinfo hints;
+ struct addrinfo *res;
+ int ec;
+ struct GNUNET_NETWORK_Handle *nh;
+
+ GNUNET_snprintf (port_str,
+ sizeof (port_str),
+ "%u",
+ (uint16_t) port);
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags = AI_PASSIVE
+#ifdef AI_IDN
+ | AI_IDN
+#endif
+ ;
+ if (0 !=
+ (ec = getaddrinfo (bind_to,
+ port_str,
+ &hints,
+ &res)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to resolve BIND_TO address `%s': %s\n",
+ bind_to,
+ gai_strerror (ec));
+ GNUNET_free (bind_to);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ GNUNET_free (bind_to);
+
+ if (NULL == (nh = GNUNET_NETWORK_socket_create (res->ai_family,
+ res->ai_socktype,
+ res->ai_protocol)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "socket");
+ freeaddrinfo (res);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_NETWORK_socket_bind (nh,
+ res->ai_addr,
+ res->ai_addrlen))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "bind");
+ freeaddrinfo (res);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ freeaddrinfo (res);
+ if (GNUNET_OK !=
+ GNUNET_NETWORK_socket_listen (nh,
+ UNIX_BACKLOG))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "listen");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ fh = GNUNET_NETWORK_get_fd (nh);
+ GNUNET_NETWORK_socket_free_memory_only_ (nh);
+ }
+ else
+ {
+ fh = -1;
+ }
+ }
+ else
+ {
+ // not reached
+ GNUNET_assert (0);
+ }
+ }
+ mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME | MHD_USE_DUAL_STACK,
+ port,
+ NULL, NULL,
+ &url_handler, NULL,
+ MHD_OPTION_LISTEN_SOCKET, fh,
+ MHD_OPTION_NOTIFY_COMPLETED,
+ &handle_mhd_completion_callback, NULL,
+ MHD_OPTION_CONNECTION_TIMEOUT, (unsigned
+ int) 10 /* 10s */,
+ MHD_OPTION_END);
+ if (NULL == mhd)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to launch HTTP service, exiting.\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ result = GNUNET_OK;
+ mhd_task = prepare_daemon ();
+}
+
+
+/**
+ * The main function of the serve tool
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc,
+ char *const *argv)
+{
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_option_flag ('C',
+ "connection-close",
+ "force HTTP connections to be closed after each request",
+ &TMH_sync_connection_close),
+
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PROGRAM_run (argc, argv,
+ "sync-httpd",
+ "sync HTTP interface",
+ options, &run, NULL))
+ return 3;
+ return (GNUNET_OK == result) ? 0 : 1;
+}
diff --git a/src/sync/sync-httpd.h b/src/sync/sync-httpd.h
new file mode 100644
index 0000000..56ad155
--- /dev/null
+++ b/src/sync/sync-httpd.h
@@ -0,0 +1,148 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2019 Taler Systems SA
+
+ TALER 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, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sync/sync-httpd.h
+ * @brief HTTP serving layer
+ * @author Christian Grothoff
+ */
+#ifndef sync_HTTPD_H
+#define sync_HTTPD_H
+
+#include "platform.h"
+#include <microhttpd.h>
+#include "sync_database_lib.h"
+
+/**
+ * @brief Struct describing an URL and the handler for it.
+ */
+struct TMH_RequestHandler
+{
+
+ /**
+ * URL the handler is for.
+ */
+ const char *url;
+
+ /**
+ * Method the handler is for, NULL for "all".
+ */
+ const char *method;
+
+ /**
+ * Mime type to use in reply (hint, can be NULL).
+ */
+ const char *mime_type;
+
+ /**
+ * Raw data for the @e handler
+ */
+ const void *data;
+
+ /**
+ * Number of bytes in @e data, 0 for 0-terminated.
+ */
+ size_t data_size;
+
+ /**
+ * Function to call to handle the request.
+ *
+ * @param rh this struct
+ * @param mime_type the @e mime_type for the reply (hint, can be NULL)
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+ int (*handler)(struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+ /**
+ * Default response code.
+ */
+ int response_code;
+};
+
+
+/**
+ * Each MHD response handler that sets the "connection_cls" to a
+ * non-NULL value must use a struct that has this struct as its first
+ * member. This struct contains a single callback, which will be
+ * invoked to clean up the memory when the contection is completed.
+ */
+struct TM_HandlerContext;
+
+/**
+ * Signature of a function used to clean up the context
+ * we keep in the "connection_cls" of MHD when handling
+ * a request.
+ *
+ * @param hc header of the context to clean up.
+ */
+typedef void
+(*TM_ContextCleanup)(struct TM_HandlerContext *hc);
+
+
+/**
+ * Each MHD response handler that sets the "connection_cls" to a
+ * non-NULL value must use a struct that has this struct as its first
+ * member. This struct contains a single callback, which will be
+ * invoked to clean up the memory when the connection is completed.
+ */
+struct TM_HandlerContext
+{
+
+ /**
+ * Function to execute the handler-specific cleanup of the
+ * (typically larger) context.
+ */
+ TM_ContextCleanup cc;
+
+ /**
+ * Which request handler is handling this request?
+ */
+ const struct TMH_RequestHandler *rh;
+
+ /**
+ * Asynchronous request context id.
+ */
+ struct GNUNET_AsyncScopeId async_scope_id;
+};
+
+
+/**
+ * Should a "Connection: close" header be added to each HTTP response?
+ */
+extern int TMH_sync_connection_close;
+
+/**
+ * Handle to the database backend.
+ */
+extern struct sync_DatabasePlugin *db;
+
+/**
+ * Kick MHD to run now, to be called after MHD_resume_connection().
+ * Basically, we need to explicitly resume MHD's event loop whenever
+ * we made progress serving a request. This function re-schedules
+ * the task processing MHD's activities to run immediately.
+ */
+void
+TMH_trigger_daemon (void);
+
+#endif
diff --git a/src/sync/sync-httpd_backup.c b/src/sync/sync-httpd_backup.c
new file mode 100644
index 0000000..86ba955
--- /dev/null
+++ b/src/sync/sync-httpd_backup.c
@@ -0,0 +1,56 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2019 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sync-httpd_backup.c
+ * @brief functions to handle incoming requests for backups
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "sync-httpd.h"
+#include <gnunet/gnunet_util_lib.h>
+
+/**
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+sync_handler_backup_get (struct MHD_Connection *connection,
+ const char *url,
+ void **con_cls)
+{
+ return MHD_NO;
+}
+
+
+/**
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+sync_handler_backup_post (struct MHD_Connection *connection,
+ void **con_cls,
+ const char *url,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ return MHD_NO;
+}
diff --git a/src/sync/sync-httpd_backup.h b/src/sync/sync-httpd_backup.h
new file mode 100644
index 0000000..1ba7408
--- /dev/null
+++ b/src/sync/sync-httpd_backup.h
@@ -0,0 +1,53 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sync-httpd_policy.h
+ * @brief functions to handle incoming requests on /backup/
+ * @author Christian Grothoff
+ */
+#ifndef SYNC_HTTPD_BACKUP_H
+#define SYNC_HTTPD_BACKUP_H
+#include <microhttpd.h>
+
+/**
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+sync_handler_backup_get (struct MHD_Connection *connection,
+ const char *url,
+ void **con_cls);
+
+
+/**
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+sync_handler_backup_post (struct MHD_Connection *connection,
+ void **con_cls,
+ const char *url,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+
+#endif
diff --git a/src/sync/sync-httpd_mhd.c b/src/sync/sync-httpd_mhd.c
new file mode 100644
index 0000000..269316d
--- /dev/null
+++ b/src/sync/sync-httpd_mhd.c
@@ -0,0 +1,156 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sync-httpd_mhd.c
+ * @brief helpers for MHD interaction; these are TALER_EXCHANGE_handler_ functions
+ * that generate simple MHD replies that do not require any real operations
+ * to be performed (error handling, static pages, etc.)
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <jansson.h>
+#include "sync-httpd_mhd.h"
+#include "sync-httpd_responses.h"
+
+
+/**
+ * Function to call to handle the request by sending
+ * back static data from the @a rh.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+TMH_MHD_handler_static_response (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 == rh->data_size)
+ rh->data_size = strlen ((const char *) rh->data);
+ response = MHD_create_response_from_buffer (rh->data_size,
+ (void *) rh->data,
+ MHD_RESPMEM_PERSISTENT);
+ if (NULL == response)
+ {
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ TMH_RESPONSE_add_global_headers (response);
+ if (NULL != rh->mime_type)
+ (void) MHD_add_response_header (response,
+ MHD_HTTP_HEADER_CONTENT_TYPE,
+ rh->mime_type);
+ ret = MHD_queue_response (connection,
+ rh->response_code,
+ response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+/**
+ * Function to call to handle the request by sending
+ * back a redirect to the AGPL source code.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+TMH_MHD_handler_agpl_redirect (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ const char *agpl =
+ "This server is licensed under the Affero GPL. You will now be redirected to the source code.";
+ struct MHD_Response *response;
+ int ret;
+
+ response = MHD_create_response_from_buffer (strlen (agpl),
+ (void *) agpl,
+ MHD_RESPMEM_PERSISTENT);
+ if (NULL == response)
+ {
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ TMH_RESPONSE_add_global_headers (response);
+ if (NULL != rh->mime_type)
+ (void) MHD_add_response_header (response,
+ MHD_HTTP_HEADER_CONTENT_TYPE,
+ rh->mime_type);
+ if (MHD_NO ==
+ MHD_add_response_header (response,
+ MHD_HTTP_HEADER_LOCATION,
+ "http://www.git.taler.net/sync.git"))
+ {
+ GNUNET_break (0);
+ ret = MHD_NO;
+ }
+ else
+ {
+ ret = MHD_queue_response (connection,
+ rh->response_code,
+ response);
+ }
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+/**
+ * Function to call to handle the request by building a JSON
+ * reply with an error message from @a rh.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+TMH_MHD_handler_send_json_pack_error (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ return TMH_RESPONSE_reply_json_pack (connection,
+ rh->response_code,
+ "{s:s}",
+ "error",
+ rh->data);
+}
+
+
+/* end of taler-exchange-httpd_mhd.c */
diff --git a/src/sync/sync-httpd_mhd.h b/src/sync/sync-httpd_mhd.h
new file mode 100644
index 0000000..b157baa
--- /dev/null
+++ b/src/sync/sync-httpd_mhd.h
@@ -0,0 +1,113 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015 GNUnet e.V. and INRIA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file sync-httpd_mhd.h
+ * @brief helpers for MHD interaction, used to generate simple responses
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#ifndef sync_HTTPD_MHD_H
+#define sync_HTTPD_MHD_H
+#include <gnunet/gnunet_util_lib.h>
+#include <microhttpd.h>
+#include "sync-httpd.h"
+
+
+/**
+ * Function to call to handle the request by sending
+ * back static data from the @a rh.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param mi merchant backend instance, NULL is allowed in this case!
+ * @return MHD result code
+ */
+int
+TMH_MHD_handler_static_response (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+
+/**
+ * Function to call to handle the request by sending
+ * back a redirect to the AGPL source code.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param mi merchant backend instance, never NULL
+ * @return MHD result code
+ */
+int
+TMH_MHD_handler_agpl_redirect (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+
+/**
+ * Function to call to handle the request by building a JSON
+ * reply from varargs.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param response_code HTTP response code to use
+ * @param do_cache can the response be cached? (0: no, 1: yes)
+ * @param fmt format string for pack
+ * @param ... varargs
+ * @return MHD result code
+ */
+int
+TMH_MHD_helper_send_json_pack (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void *connection_cls,
+ int response_code,
+ int do_cache,
+ const char *fmt,
+ ...);
+
+
+/**
+ * Function to call to handle the request by building a JSON
+ * reply with an error message from @a rh.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+TMH_MHD_handler_send_json_pack_error (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+
+#endif
diff --git a/src/sync/sync-httpd_parsing.c b/src/sync/sync-httpd_parsing.c
new file mode 100644
index 0000000..49d9f97
--- /dev/null
+++ b/src/sync/sync-httpd_parsing.c
@@ -0,0 +1,272 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation; either version 3,
+ or (at your option) any later version.
+
+ TALER 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public
+ License along with TALER; see the file COPYING. If not,
+ see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file sync-httpd_parsing.c
+ * @brief functions to parse incoming requests
+ * (MHD arguments and JSON snippets)
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <taler/taler_json_lib.h>
+#include "sync-httpd_parsing.h"
+#include "sync-httpd_responses.h"
+
+/* FIXME: de-duplicate code with taler-exchange-httpd_parsing.c
+ and taler-exchange-httpd_response.c */
+
+/**
+ * Initial size for POST request buffer.
+ */
+#define REQUEST_BUFFER_INITIAL (2 * 1024)
+
+/**
+ * Maximum POST request size.
+ */
+#define REQUEST_BUFFER_MAX (1024 * 1024)
+
+
+/**
+ * Buffer for POST requests.
+ */
+struct Buffer
+{
+ /**
+ * Allocated memory
+ */
+ char *data;
+
+ /**
+ * Number of valid bytes in buffer.
+ */
+ size_t fill;
+
+ /**
+ * Number of allocated bytes in buffer.
+ */
+ size_t alloc;
+};
+
+
+
+
+/**
+ * Free the data in a buffer. Does *not* free
+ * the buffer object itself.
+ *
+ * @param buf buffer to de-initialize
+ */
+static void
+buffer_deinit (struct Buffer *buf)
+{
+ GNUNET_free_non_null (buf->data);
+ buf->data = NULL;
+}
+
+
+
+/**
+ * Function called whenever we are done with a request
+ * to clean up our state.
+ *
+ * @param con_cls value as it was left by
+ * #TMH_PARSE_post_json(), to be cleaned up
+ */
+void
+TMH_PARSE_post_cleanup_callback (void *con_cls)
+{
+ struct Buffer *r = con_cls;
+
+ if (NULL != r)
+ {
+ buffer_deinit (r);
+ GNUNET_free (r);
+ }
+}
+
+
+/**
+ * Process a POST request containing a JSON object. This function
+ * realizes an MHD POST processor that will (incrementally) process
+ * JSON data uploaded to the HTTP server. It will store the
+ * required state in the @a con_cls, which must be cleaned up
+ * using #TMH_PARSE_post_cleanup_callback().
+ *
+ * @param connection the MHD connection
+ * @param con_cls the closure (points to a `struct Buffer *`)
+ * @param upload_data the POST data
+ * @param upload_data_size number of bytes in @a upload_data
+ * @param json the JSON object for a completed request
+ * @return
+ * #GNUNET_YES if json object was parsed or at least
+ * may be parsed in the future (call again);
+ * `*json` will be NULL if we need to be called again,
+ * and non-NULL if we are done.
+ * #GNUNET_NO if request is incomplete or invalid
+ * (error message was generated)
+ * #GNUNET_SYSERR on internal error
+ * (we could not even queue an error message,
+ * close HTTP session with MHD_NO)
+ */
+int
+TMH_PARSE_post_json (struct MHD_Connection *connection,
+ void **con_cls,
+ const char *upload_data,
+ size_t *upload_data_size,
+ json_t **json)
+{
+ enum GNUNET_JSON_PostResult pr;
+
+ pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
+ connection,
+ con_cls,
+ upload_data,
+ upload_data_size,
+ json);
+ switch (pr)
+ {
+
+ case GNUNET_JSON_PR_OUT_OF_MEMORY:
+ return (MHD_NO == TMH_RESPONSE_reply_internal_error
+ (connection,
+ TALER_EC_PARSER_OUT_OF_MEMORY,
+ "out of memory")) ? GNUNET_SYSERR : GNUNET_NO;
+
+ case GNUNET_JSON_PR_CONTINUE:
+ return GNUNET_YES;
+
+ case GNUNET_JSON_PR_REQUEST_TOO_LARGE:
+ return (MHD_NO == TMH_RESPONSE_reply_request_too_large
+ (connection)) ? GNUNET_SYSERR : GNUNET_NO;
+
+ case GNUNET_JSON_PR_JSON_INVALID:
+ return (MHD_YES ==
+ TMH_RESPONSE_reply_invalid_json (connection))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ case GNUNET_JSON_PR_SUCCESS:
+ GNUNET_break (NULL != *json);
+ return GNUNET_YES;
+ }
+ /* this should never happen */
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Parse JSON object into components based on the given field
+ * specification.
+ *
+ * @param connection the connection to send an error response to
+ * @param root the JSON node to start the navigation at.
+ * @param spec field specification for the parser
+ * @return
+ * #GNUNET_YES if navigation was successful (caller is responsible
+ * for freeing allocated variable-size data using
+ * #GNUNET_JSON_parse_free() when done)
+ * #GNUNET_NO if json is malformed, error response was generated
+ * #GNUNET_SYSERR on internal error
+ */
+int
+TMH_PARSE_json_data (struct MHD_Connection *connection,
+ const json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ int ret;
+ const char *error_json_name;
+ unsigned int error_line;
+
+ ret = GNUNET_JSON_parse (root,
+ spec,
+ &error_json_name,
+ &error_line);
+ if (GNUNET_SYSERR == ret)
+ {
+ if (NULL == error_json_name)
+ error_json_name = "<no field>";
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Parsing failed due to field '%s'\n",
+ error_json_name);
+ ret = (MHD_YES ==
+ TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:s, s:I}",
+ "error", "parse error",
+ "field", error_json_name,
+ "line", (json_int_t) error_line))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ return ret;
+ }
+ return GNUNET_YES;
+}
+
+
+
+/**
+ * Extract base32crockford encoded data from request.
+ *
+ * Queues an error response to the connection if the parameter is
+ * missing or invalid.
+ *
+ * @param connection the MHD connection
+ * @param param_name the name of the parameter with the key
+ * @param[out] out_data pointer to store the result
+ * @param out_size expected size of data
+ * @return
+ * #GNUNET_YES if the the argument is present
+ * #GNUNET_NO if the argument is absent or malformed
+ * #GNUNET_SYSERR on internal error (error response could not be sent)
+ */
+int
+TMH_PARSE_mhd_request_arg_data (struct MHD_Connection *connection,
+ const char *param_name,
+ void *out_data,
+ size_t out_size)
+{
+ const char *str;
+
+ str = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ param_name);
+ if (NULL == str)
+ {
+ return (MHD_NO ==
+ TMH_RESPONSE_reply_arg_missing (connection,
+ TALER_EC_PARAMETER_MISSING,
+ param_name))
+ ? GNUNET_SYSERR : GNUNET_NO;
+ }
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (str,
+ strlen (str),
+ out_data,
+ out_size))
+ return (MHD_NO ==
+ TMH_RESPONSE_reply_arg_invalid (connection,
+ TALER_EC_PARAMETER_MALFORMED,
+ param_name))
+ ? GNUNET_SYSERR : GNUNET_NO;
+ return GNUNET_OK;
+}
+
+
+/* end of taler-merchant-httpd_parsing.c */
diff --git a/src/sync/sync-httpd_parsing.h b/src/sync/sync-httpd_parsing.h
new file mode 100644
index 0000000..b3c11cd
--- /dev/null
+++ b/src/sync/sync-httpd_parsing.h
@@ -0,0 +1,93 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sync-httpd_parsing.h
+ * @brief functions to parse incoming requests
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#ifndef sync_HTTPD_PARSING_H
+#define sync_HTTPD_PARSING_H
+
+#include <microhttpd.h>
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+
+/**
+ * Process a POST request containing a JSON object. This
+ * function realizes an MHD POST processor that will
+ * (incrementally) process JSON data uploaded to the HTTP
+ * server. It will store the required state in the
+ * "connection_cls", which must be cleaned up using
+ * #TMH_PARSE_post_cleanup_callback().
+ *
+ * @param connection the MHD connection
+ * @param con_cls the closure (points to a `struct Buffer *`)
+ * @param upload_data the POST data
+ * @param upload_data_size number of bytes in @a upload_data
+ * @param json the JSON object for a completed request
+ * @return
+ * #GNUNET_YES if json object was parsed or at least
+ * may be parsed in the future (call again);
+ * `*json` will be NULL if we need to be called again,
+ * and non-NULL if we are done.
+ * #GNUNET_NO is request incomplete or invalid
+ * (error message was generated)
+ * #GNUNET_SYSERR on internal error
+ * (we could not even queue an error message,
+ * close HTTP session with MHD_NO)
+ */
+int
+TMH_PARSE_post_json (struct MHD_Connection *connection,
+ void **con_cls,
+ const char *upload_data,
+ size_t *upload_data_size,
+ json_t **json);
+
+
+/**
+ * Function called whenever we are done with a request
+ * to clean up our state.
+ *
+ * @param con_cls value as it was left by
+ * #TMH_PARSE_post_json(), to be cleaned up
+ */
+void
+TMH_PARSE_post_cleanup_callback (void *con_cls);
+
+
+/**
+ * Parse JSON object into components based on the given field
+ * specification.
+ *
+ * @param connection the connection to send an error response to
+ * @param root the JSON node to start the navigation at.
+ * @param spec field specification for the parser
+ * @return
+ * #GNUNET_YES if navigation was successful (caller is responsible
+ * for freeing allocated variable-size data using
+ * #GNUNET_JSON_parse_free() when done)
+ * #GNUNET_NO if json is malformed, error response was generated
+ * #GNUNET_SYSERR on internal error
+ */
+int
+TMH_PARSE_json_data (struct MHD_Connection *connection,
+ const json_t *root,
+ struct GNUNET_JSON_Specification *spec);
+
+
+#endif /* TALER_MERCHANT_HTTPD_PARSING_H */
diff --git a/src/sync/sync-httpd_responses.c b/src/sync/sync-httpd_responses.c
new file mode 100644
index 0000000..6a95555
--- /dev/null
+++ b/src/sync/sync-httpd_responses.c
@@ -0,0 +1,408 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2017 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sync-httpd_responses.c
+ * @brief API for generating the various replies of the exchange; these
+ * functions are called TMH_RESPONSE_reply_ and they generate
+ * and queue MHD response objects for a given connection.
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "sync-httpd.h"
+#include "sync-httpd_responses.h"
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include <gnunet/gnunet_util_lib.h>
+
+
+/**
+ * Make JSON response object.
+ *
+ * @param json the json object
+ * @return MHD response object
+ */
+struct MHD_Response *
+TMH_RESPONSE_make_json (const json_t *json)
+{
+ struct MHD_Response *resp;
+ char *json_str;
+
+ json_str = json_dumps (json,
+ JSON_INDENT (2));
+ if (NULL == json_str)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ resp = MHD_create_response_from_buffer (strlen (json_str),
+ json_str,
+ MHD_RESPMEM_MUST_FREE);
+ if (NULL == resp)
+ {
+ free (json_str);
+ GNUNET_break (0);
+ return NULL;
+ }
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (resp,
+ MHD_HTTP_HEADER_CONTENT_TYPE,
+ "application/json"));
+ return resp;
+}
+
+
+/**
+ * Send JSON object as response.
+ *
+ * @param connection the MHD connection
+ * @param json the json object
+ * @param response_code the http response code
+ * @return MHD result code
+ */
+int
+TMH_RESPONSE_reply_json (struct MHD_Connection *connection,
+ const json_t *json,
+ unsigned int response_code)
+{
+ struct MHD_Response *resp;
+ int ret;
+
+ resp = TMH_RESPONSE_make_json (json);
+ if (NULL == resp)
+ return MHD_NO;
+ ret = MHD_queue_response (connection,
+ response_code,
+ resp);
+ MHD_destroy_response (resp);
+ return ret;
+}
+
+
+/**
+ * Make JSON response object.
+ *
+ * @param fmt format string for pack
+ * @param ... varargs
+ * @return MHD response object
+ */
+struct MHD_Response *
+TMH_RESPONSE_make_json_pack (const char *fmt,
+ ...)
+{
+ json_t *json;
+ va_list argp;
+ struct MHD_Response *ret;
+ json_error_t jerror;
+
+ va_start (argp, fmt);
+ json = json_vpack_ex (&jerror,
+ 0,
+ fmt,
+ argp);
+ va_end (argp);
+ if (NULL == json)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to pack JSON with format `%s': %s\n",
+ fmt,
+ jerror.text);
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ ret = TMH_RESPONSE_make_json (json);
+ json_decref (json);
+ return ret;
+}
+
+
+/**
+ * Function to call to handle the request by building a JSON
+ * reply from a format string and varargs.
+ *
+ * @param connection the MHD connection to handle
+ * @param response_code HTTP response code to use
+ * @param fmt format string for pack
+ * @param ... varargs
+ * @return MHD result code
+ */
+int
+TMH_RESPONSE_reply_json_pack (struct MHD_Connection *connection,
+ unsigned int response_code,
+ const char *fmt,
+ ...)
+{
+ json_t *json;
+ va_list argp;
+ int ret;
+ json_error_t jerror;
+
+ va_start (argp, fmt);
+ json = json_vpack_ex (&jerror,
+ 0,
+ fmt,
+ argp);
+ va_end (argp);
+ if (NULL == json)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to pack JSON with format `%s': %s\n",
+ fmt,
+ jerror.text);
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ ret = TMH_RESPONSE_reply_json (connection,
+ json,
+ response_code);
+ json_decref (json);
+ return ret;
+}
+
+
+/**
+ * Create a response indicating an internal error.
+ *
+ * @param ec error code to return
+ * @param hint hint about the internal error's nature
+ * @return a MHD response object
+ */
+struct MHD_Response *
+TMH_RESPONSE_make_error (enum TALER_ErrorCode ec,
+ const char *hint)
+{
+ return TMH_RESPONSE_make_json_pack ("{s:I, s:s}",
+ "code", (json_int_t) ec,
+ "hint", hint);
+}
+
+
+/**
+ * Send a response indicating an internal error.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param hint hint about the internal error's nature
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_internal_error (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *hint)
+{
+ return TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ "{s:I, s:s}",
+ "code", (json_int_t) ec,
+ "hint", hint);
+}
+
+
+/**
+ * Send a response indicating that the request was too big.
+ *
+ * @param connection the MHD connection to use
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_request_too_large (struct MHD_Connection *connection)
+{
+ struct MHD_Response *resp;
+ int ret;
+
+ resp = MHD_create_response_from_buffer (0,
+ NULL,
+ MHD_RESPMEM_PERSISTENT);
+ if (NULL == resp)
+ return MHD_NO;
+ ret = MHD_queue_response (connection,
+ MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
+ resp);
+ MHD_destroy_response (resp);
+ return ret;
+}
+
+
+/**
+ * Send a response indicating that we did not find the @a object
+ * needed for the reply.
+ *
+ * @param connection the MHD connection to use
+ * @param response_code response code to use
+ * @param ec error code to return
+ * @param msg human-readable diagnostic
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_rc (struct MHD_Connection *connection,
+ unsigned int response_code,
+ enum TALER_ErrorCode ec,
+ const char *msg)
+{
+ return TMH_RESPONSE_reply_json_pack (connection,
+ response_code,
+ "{s:I, s:s}",
+ "code", (json_int_t) ec,
+ "error", msg);
+}
+
+
+/**
+ * Send a response indicating that the JSON was malformed.
+ *
+ * @param connection the MHD connection to use
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection)
+{
+ return TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:I, s:s}",
+ "code",
+ (json_int_t) TALER_EC_JSON_INVALID,
+ "error", "invalid json");
+}
+
+
+/**
+ * Send a response indicating that we did not find the @a object
+ * needed for the reply.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param object name of the object we did not find
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_not_found (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *object)
+{
+ return TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_NOT_FOUND,
+ "{s:I, s:s}",
+ "code", (json_int_t) ec,
+ "error", object);
+}
+
+
+/**
+ * Send a response indicating that the request was malformed.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param issue description of what was wrong with the request
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_bad_request (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *issue)
+{
+ return TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:I, s:s}",
+ "code", (json_int_t) ec,
+ "error", issue);
+}
+
+
+/**
+ * Add headers we want to return in every response.
+ * Useful for testing, like if we want to always close
+ * connections.
+ *
+ * @param response response to modify
+ */
+void
+TMH_RESPONSE_add_global_headers (struct MHD_Response *response)
+{
+ if (TMH_sync_connection_close)
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (response,
+ MHD_HTTP_HEADER_CONNECTION,
+ "close"));
+}
+
+
+/**
+ * Send a response indicating an external error.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param hint hint about the error's nature
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_external_error (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *hint)
+{
+ return TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:I, s:s}",
+ "code", (json_int_t) ec,
+ "hint", hint);
+}
+
+
+/**
+ * Send a response indicating a missing argument.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param param_name the parameter that is missing
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_arg_missing (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *param_name)
+{
+ return TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:I, s:s}",
+ "error", "missing parameter",
+ "code", (json_int_t) ec,
+ "parameter", param_name);
+}
+
+
+/**
+ * Send a response indicating an invalid argument.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param param_name the parameter that is invalid
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *param_name)
+{
+ return TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:I, s:s}",
+ "error", "invalid parameter",
+ "code", (json_int_t) ec,
+ "parameter", param_name);
+}
+
+
+/* end of taler-exchange-httpd_responses.c */
diff --git a/src/sync/sync-httpd_responses.h b/src/sync/sync-httpd_responses.h
new file mode 100644
index 0000000..a98ba0d
--- /dev/null
+++ b/src/sync/sync-httpd_responses.h
@@ -0,0 +1,244 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2017 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sync-httpd_responses.h
+ * @brief API for generating the various replies of the exchange; these
+ * functions are called TMH_RESPONSE_reply_ and they generate
+ * and queue MHD response objects for a given connection.
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#ifndef sync_HTTPD_RESPONSES_H
+#define sync_HTTPD_RESPONSES_H
+#include "sync-httpd.h"
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include <gnunet/gnunet_util_lib.h>
+
+
+
+/**
+ * Make JSON response object.
+ *
+ * @param json the json object
+ * @return MHD response object
+ */
+struct MHD_Response *
+TMH_RESPONSE_make_json (const json_t *json);
+
+
+/**
+ * Send JSON object as response.
+ *
+ * @param connection the MHD connection
+ * @param json the json object
+ * @param response_code the http response code
+ * @return MHD result code
+ */
+int
+TMH_RESPONSE_reply_json (struct MHD_Connection *connection,
+ const json_t *json,
+ unsigned int response_code);
+
+
+/**
+ * Make JSON response object.
+ *
+ * @param fmt format string for pack
+ * @param ... varargs
+ * @return MHD response object
+ */
+struct MHD_Response *
+TMH_RESPONSE_make_json_pack (const char *fmt,
+ ...);
+
+
+
+
+/**
+ * Function to call to handle the request by building a JSON
+ * reply from a format string and varargs.
+ *
+ * @param connection the MHD connection to handle
+ * @param response_code HTTP response code to use
+ * @param fmt format string for pack
+ * @param ... varargs
+ * @return MHD result code
+ */
+int
+TMH_RESPONSE_reply_json_pack (struct MHD_Connection *connection,
+ unsigned int response_code,
+ const char *fmt,
+ ...);
+
+
+/**
+ * Create a response indicating an internal error.
+ *
+ * @param ec error code to return
+ * @param hint hint about the internal error's nature
+ * @return a MHD response object
+ */
+struct MHD_Response *
+TMH_RESPONSE_make_error (enum TALER_ErrorCode ec,
+ const char *hint);
+
+
+/**
+ * Send a response indicating an internal error.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param hint hint about the internal error's nature
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_internal_error (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *hint);
+
+
+
+
+/**
+ * Send a response indicating that the request was too big.
+ *
+ * @param connection the MHD connection to use
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_request_too_large (struct MHD_Connection *connection);
+
+
+
+/**
+ * Send a response indicating that we did not find the @a object
+ * needed for the reply.
+ *
+ * @param connection the MHD connection to use
+ * @param response_code response code to use
+ * @param ec error code to return
+ * @param msg human-readable diagnostic
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_rc (struct MHD_Connection *connection,
+ unsigned int response_code,
+ enum TALER_ErrorCode ec,
+ const char *msg);
+
+
+
+/**
+ * Send a response indicating that the JSON was malformed.
+ *
+ * @param connection the MHD connection to use
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection);
+
+
+
+/**
+ * Send a response indicating that we did not find the @a object
+ * needed for the reply.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param object name of the object we did not find
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_not_found (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *object);
+
+
+
+/**
+ * Send a response indicating that the request was malformed.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param issue description of what was wrong with the request
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_bad_request (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *issue);
+
+
+
+
+/**
+ * Add headers we want to return in every response.
+ * Useful for testing, like if we want to always close
+ * connections.
+ *
+ * @param response response to modify
+ */
+void
+TMH_RESPONSE_add_global_headers (struct MHD_Response *response);
+
+
+
+/**
+ * Send a response indicating an external error.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param hint hint about the error's nature
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_external_error (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *hint);
+
+
+
+
+/**
+ * Send a response indicating a missing argument.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param param_name the parameter that is missing
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_arg_missing (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *param_name);
+
+
+/**
+ * Send a response indicating an invalid argument.
+ *
+ * @param connection the MHD connection to use
+ * @param ec error code to return
+ * @param param_name the parameter that is invalid
+ * @return a MHD result code
+ */
+int
+TMH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection,
+ enum TALER_ErrorCode ec,
+ const char *param_name);
+
+#endif
diff --git a/src/sync/sync.conf b/src/sync/sync.conf
new file mode 100644
index 0000000..9425c22
--- /dev/null
+++ b/src/sync/sync.conf
@@ -0,0 +1,31 @@
+# This file is in the public domain.
+
+# These are default/sample settings for a merchant backend.
+
+
+# General settings for the backend.
+[sync]
+
+# Use TCP or UNIX domain sockets?
+SERVE = tcp
+
+# Which HTTP port does the backend listen on? Only used if "SERVE" is 'tcp'.
+PORT = 9966
+
+# Which IP address should we bind to? i.e. 127.0.0.1 or ::1 for loopback.
+# Can also be given as a hostname. We will bind to the wildcard (dual-stack)
+# if left empty. Only used if "SERVE" is 'tcp'.
+# BIND_TO =
+
+
+# Which unix domain path should we bind to? Only used if "SERVE" is 'unix'.
+UNIXPATH = ${sync_RUNTIME_DIR}/backend.http
+# What should be the file access permissions (see chmod) for "UNIXPATH"?
+UNIXPATH_MODE = 660
+
+# Which database backend do we use?
+DB = postgres
+
+# Configuration for postgres database.
+[syncdb-postgres]
+CONFIG = postgres:///sync
diff --git a/src/syncdb/Makefile.am b/src/syncdb/Makefile.am
new file mode 100644
index 0000000..56db964
--- /dev/null
+++ b/src/syncdb/Makefile.am
@@ -0,0 +1,62 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/taler
+
+if HAVE_POSTGRESQL
+if HAVE_GNUNETPQ
+plugin_LTLIBRARIES = \
+ libsync_plugin_db_postgres.la
+endif
+endif
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage -O0
+ XLIB = -lgcov
+endif
+
+lib_LTLIBRARIES = \
+ libsyncdb.la
+
+libsyncdb_la_SOURCES = \
+ sync_db_plugin.c
+
+libsyncdb_la_LIBADD = \
+ -lgnunetpq \
+ -lpq \
+ -lgnunetutil
+libsyncdb_la_LDFLAGS = \
+ $(POSTGRESQL_LDFLAGS) \
+ -version-info 2:0:0 \
+ -no-undefined
+
+libsync_plugin_db_postgres_la_SOURCES = \
+ plugin_sync_postgres.c
+libsync_plugin_db_postgres_la_LIBADD = \
+ $(LTLIBINTL)
+libsync_plugin_db_postgres_la_LDFLAGS = \
+ $(TALER_PLUGIN_LDFLAGS) \
+ -lgnunetpq \
+ -lpq \
+ -ltalerpq \
+ -lgnunetutil $(XLIB)
+
+check_PROGRAMS = \
+ $(TESTS)
+
+test_sync_db_postgres_SOURCES = \
+ test_sync_db.c
+test_sync_db_postgres_LDFLAGS = \
+ $(top_builddir)/src/util/libsyncutil.la \
+ libsyncdb.la \
+ -lgnunetutil \
+ -lgnunetpq \
+ -ltalerutil \
+ -ltalerpq \
+ -luuid
+
+TESTS = \
+ test_sync_db-postgres
+
+EXTRA_DIST = \
+ test_sync_db_postgres.conf
diff --git a/src/syncdb/plugin_sync_postgres.c b/src/syncdb/plugin_sync_postgres.c
new file mode 100644
index 0000000..4e63198
--- /dev/null
+++ b/src/syncdb/plugin_sync_postgres.c
@@ -0,0 +1,284 @@
+/*
+ This file is part of TALER
+ (C) 2014--2019 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of ANASTASISABILITY 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sync/plugin_syncdb_postgres.c
+ * @brief database helper functions for postgres used by the sync
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_pq_lib.h>
+#include <taler/taler_pq_lib.h>
+#include "sync_database_plugin.h"
+#include "sync_database_lib.h"
+
+/**
+ * How often do we re-try if we run into a DB serialization error?
+ */
+#define MAX_RETRIES 3
+
+
+/**
+ * Type of the "cls" argument given to each of the functions in
+ * our API.
+ */
+struct PostgresClosure
+{
+
+ /**
+ * Postgres connection handle.
+ */
+ struct GNUNET_PQ_Context *conn;
+
+ /**
+ * Underlying configuration.
+ */
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * Name of the currently active transaction, NULL if none is active.
+ */
+ const char *transaction_name;
+
+};
+
+
+/**
+ * Drop sync tables
+ *
+ * @param cls closure our `struct Plugin`
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+static int
+postgres_drop_tables (void *cls)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS backups;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+ return GNUNET_PQ_exec_statements (pg->conn,
+ es);
+}
+
+
+/**
+ * Check that the database connection is still up.
+ *
+ * @param pg connection to check
+ */
+static void
+check_connection (void *cls)
+{
+ struct PostgresClosure *pg = cls;
+ GNUNET_PQ_reconnect_if_down (pg->conn);
+}
+
+
+/**
+ * Do a pre-flight check that we are not in an uncommitted transaction.
+ * If we are, try to commit the previous transaction and output a warning.
+ * Does not return anything, as we will continue regardless of the outcome.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ */
+static void
+postgres_preflight (void *cls)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("COMMIT"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ if (NULL == pg->transaction_name)
+ return; /* all good */
+ if (GNUNET_OK ==
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "BUG: Preflight check committed transaction `%s'!\n",
+ pg->transaction_name);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "BUG: Preflight check failed to commit transaction `%s'!\n",
+ pg->transaction_name);
+ }
+ pg->transaction_name = NULL;
+}
+
+/**
+ * Start a transaction.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param name unique name identifying the transaction (for debugging),
+ * must point to a constant
+ * @return #GNUNET_OK on success
+ */
+static int
+begin_transaction (void *cls,
+ const char *name)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ check_connection (pg);
+ postgres_preflight (pg);
+ pg->transaction_name = name;
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ TALER_LOG_ERROR ("Failed to start transaction\n");
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+/**
+* Roll back the current transaction of a database connection.
+*
+* @param cls the `struct PostgresClosure` with the plugin-specific state
+* @return #GNUNET_OK on success
+*/
+static void
+rollback (void *cls)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("ROLLBACK"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ TALER_LOG_ERROR ("Failed to rollback transaction\n");
+ GNUNET_break (0);
+ }
+ pg->transaction_name = NULL;
+}
+
+/**
+ * Commit the current transaction of a database connection.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @return transaction status code
+ */
+
+static enum SYNC_DB_QueryStatus
+commit_transaction (void *cls)
+{
+ struct PostgresClosure *pg = cls;
+ enum SYNC_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam no_params[] = {
+ GNUNET_PQ_query_param_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "do_commit",
+ no_params);
+ pg->transaction_name = NULL;
+ return qs;
+}
+
+
+
+/**
+ * Initialize Postgres database subsystem.
+ *
+ * @param cls a configuration instance
+ * @return NULL on error, otherwise a `struct TALER_SYNCDB_Plugin`
+ */
+void *
+libsync_plugin_db_postgres_init (void *cls)
+{
+ struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+ struct PostgresClosure *pg;
+ struct SYNC_DatabasePlugin *plugin;
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ /* Orders created by the frontend, not signed or given a nonce yet.
+ The contract terms will change (nonce will be added) when moved to the
+ contract terms table */
+ GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS backups"
+ "("
+ "data BYTEA NOT NULL,"
+ ");"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+ struct GNUNET_PQ_PreparedStatement ps[] = {
+ GNUNET_PQ_make_prepare ("backup_insert",
+ "INSERT INTO backups "
+ "(data"
+ ") VALUES "
+ "($1);",
+ 1),
+ GNUNET_PQ_make_prepare ("do_commit",
+ "COMMIT",
+ 0),
+ GNUNET_PQ_PREPARED_STATEMENT_END
+ };
+
+ pg = GNUNET_new (struct PostgresClosure);
+ pg->cfg = cfg;
+ pg->conn = GNUNET_PQ_connect_with_cfg (cfg,
+ "syncdb-postgres",
+ es,
+ ps);
+ if (NULL == pg->conn)
+ {
+ GNUNET_free (pg);
+ return NULL;
+ }
+ plugin = GNUNET_new (struct SYNC_DatabasePlugin);
+ plugin->cls = pg;
+ plugin->drop_tables = &postgres_drop_tables;
+ plugin->preflight = &postgres_preflight;
+ plugin->rollback = &rollback;
+ plugin->commit = &commit_transaction;
+ return plugin;
+}
+
+
+/**
+ * Shutdown Postgres database subsystem.
+ *
+ * @param cls a `struct SYNC_DB_Plugin`
+ * @return NULL (always)
+ */
+void *
+libsync_plugin_db_postgres_done (void *cls)
+{
+ struct SYNC_DatabasePlugin *plugin = cls;
+ struct PostgresClosure *pg = plugin->cls;
+
+ GNUNET_PQ_disconnect (pg->conn);
+ GNUNET_free (pg);
+ GNUNET_free (plugin);
+ return NULL;
+}
+
+/* end of plugin_syncdb_postgres.c */
diff --git a/src/syncdb/sync_db_plugin.c b/src/syncdb/sync_db_plugin.c
new file mode 100644
index 0000000..6b2c6e0
--- /dev/null
+++ b/src/syncdb/sync_db_plugin.c
@@ -0,0 +1,149 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2015, 2016 GNUnet e.V. and INRIA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file merchantdb/merchantdb_plugin.c
+ * @brief Logic to load database plugin
+ * @author Christian Grothoff
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ */
+#include "platform.h"
+#include "anastasis_database_plugin.h"
+#include <ltdl.h>
+
+
+/**
+ * Initialize the plugin.
+ *
+ * @param cfg configuration to use
+ * @return #GNUNET_OK on success
+ */
+struct ANASTASIS_DatabasePlugin *
+ANASTASIS_DB_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ char *plugin_name;
+ char *lib_name;
+ struct GNUNET_CONFIGURATION_Handle *cfg_dup;
+ struct ANASTASIS_DatabasePlugin *plugin;
+
+ if (GNUNET_SYSERR ==
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "anastasis",
+ "db",
+ &plugin_name))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "anastasis",
+ "db");
+ return NULL;
+ }
+ (void) GNUNET_asprintf (&lib_name,
+ "libanastasis_plugin_db_%s",
+ plugin_name);
+ GNUNET_free (plugin_name);
+ cfg_dup = GNUNET_CONFIGURATION_dup (cfg);
+ plugin = GNUNET_PLUGIN_load (lib_name, cfg_dup);
+ if (NULL != plugin)
+ plugin->library_name = lib_name;
+ else
+ GNUNET_free (lib_name);
+ GNUNET_CONFIGURATION_destroy (cfg_dup);
+ return plugin;
+}
+
+
+/**
+ * Shutdown the plugin.
+ *
+ * @param plugin the plugin to unload
+ */
+void
+ANASTASIS_DB_plugin_unload (struct ANASTASIS_DatabasePlugin *plugin)
+{
+ char *lib_name;
+
+ if (NULL == plugin)
+ return;
+ lib_name = plugin->library_name;
+ GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name,
+ plugin));
+ GNUNET_free (lib_name);
+}
+
+
+/**
+ * Libtool search path before we started.
+ */
+static char *old_dlsearchpath;
+
+
+/**
+ * Setup libtool paths.
+ */
+void __attribute__ ((constructor))
+plugin_init ()
+{
+ int err;
+ const char *opath;
+ char *path;
+ char *cpath;
+
+ err = lt_dlinit ();
+ if (err > 0)
+ {
+ fprintf (stderr,
+ _ ("Initialization of plugin mechanism failed: %s!\n"),
+ lt_dlerror ());
+ return;
+ }
+ opath = lt_dlgetsearchpath ();
+ if (NULL != opath)
+ old_dlsearchpath = GNUNET_strdup (opath);
+ path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR);
+ if (NULL != path)
+ {
+ if (NULL != opath)
+ {
+ GNUNET_asprintf (&cpath, "%s:%s", opath, path);
+ lt_dlsetsearchpath (cpath);
+ GNUNET_free (path);
+ GNUNET_free (cpath);
+ }
+ else
+ {
+ lt_dlsetsearchpath (path);
+ GNUNET_free (path);
+ }
+ }
+}
+
+
+/**
+ * Shutdown libtool.
+ */
+void __attribute__ ((destructor))
+plugin_fini ()
+{
+ lt_dlsetsearchpath (old_dlsearchpath);
+ if (NULL != old_dlsearchpath)
+ {
+ GNUNET_free (old_dlsearchpath);
+ old_dlsearchpath = NULL;
+ }
+ lt_dlexit ();
+}
+
+
+/* end of anastasis_db_plugin.c */
diff --git a/src/syncdb/sync_db_postgres.conf b/src/syncdb/sync_db_postgres.conf
new file mode 100644
index 0000000..0460bd2
--- /dev/null
+++ b/src/syncdb/sync_db_postgres.conf
@@ -0,0 +1,7 @@
+[anastasis]
+#The DB plugin to use
+DB = postgres
+
+[anastasisdb-postgres]
+#The connection string the plugin has to use for connecting to the database
+CONFIG = postgres:///anastasis
diff --git a/src/syncdb/test_sync_db.c b/src/syncdb/test_sync_db.c
new file mode 100644
index 0000000..e57a548
--- /dev/null
+++ b/src/syncdb/test_sync_db.c
@@ -0,0 +1,200 @@
+/*
+ This file is part of
+ (C) 2014-2017 INRIA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sync/test_sync_db.c
+ * @brief testcase for sync postgres db plugin
+ * @author Marcello Stanisci
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <taler/taler_util.h>
+#include "sync_database_plugin.h"
+#include "sync_database_lib.h"
+#include "sync_error_codes.h"
+#include <uuid/uuid.h>
+
+
+#define FAILIF(cond) \
+ do { \
+ if (! (cond)) { break;} \
+ GNUNET_break (0); \
+ goto drop; \
+ } while (0)
+
+#define RND_BLK(ptr) \
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr))
+
+/**
+ * Global return value for the test. Initially -1, set to 0 upon
+ * completion. Other values indicate some kind of error.
+ */
+static int result;
+
+/**
+ * Handle to the plugin we are testing.
+ */
+static struct SYNC_DatabasePlugin *plugin;
+
+/**
+ * Payment Secret for the test, set to a random value
+ */
+static struct SYNC_PaymentSecretP paymentSecretP;
+
+/**
+ * User public key, set to a random value
+ */
+static struct SYNC_AccountPubP accountPubP;
+
+/**
+ * Amount which is deposited, set to random value
+ */
+static struct TALER_Amount amount;
+
+/**
+ * How many posts are paid by the payment
+ */
+static unsigned int post_counter;
+
+/**
+ * Recoverydata which is stored into the Database, set to a random value
+ */
+static void *recovery_data;
+
+/**
+ * Recovery_data for the select test
+ */
+static void *res_recovery_data;
+
+/**
+ * Truthdata which is stored into the Database, set to a random value
+ */
+static void *truth_data;
+
+/**
+ * Truth for the select test
+ */
+static void *truth;
+
+/**
+ * Keyshare which is stored into the Database, set to a random value
+ */
+static void *key_share;
+
+/**
+ * Keyshare for the select test
+ */
+static void *res_key_share;
+
+/**
+ * Mime-type of truth
+ */
+static char *mime_type;
+
+/**
+ * Mime-type of truth for the select test
+ */
+static char *res_mime_type;
+
+/**
+ * Version of a Recoverydocument
+ */
+static uint32_t version;
+
+/**
+ * Version of the latest Recoverydocument
+ */
+static uint32_t res_version;
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure with config
+ */
+static void
+run (void *cls)
+{
+ struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+
+ if (NULL == (plugin = SYNC_DB_plugin_load (cfg)))
+ {
+ result = 77;
+ return;
+ }
+ if (GNUNET_OK != plugin->drop_tables (plugin->cls))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Dropping tables failed\n");
+ result = 77;
+ return;
+ }
+ SYNC_DB_plugin_unload (plugin);
+ if (NULL == (plugin = SYNC_DB_plugin_load (cfg)))
+ {
+ result = 77;
+ return;
+ }
+
+ GNUNET_break (GNUNET_OK ==
+ plugin->drop_tables (plugin->cls));
+ SYNC_DB_plugin_unload (plugin);
+ plugin = NULL;
+}
+
+
+int
+main (int argc,
+ char *const argv[])
+{
+ const char *plugin_name;
+ char *config_filename;
+ char *testname;
+ struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ result = -1;
+ if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
+ {
+ GNUNET_break (0);
+ return -1;
+ }
+ GNUNET_log_setup (argv[0], "DEBUG", NULL);
+ plugin_name++;
+ (void) GNUNET_asprintf (&testname,
+ "%s",
+ plugin_name);
+ (void) GNUNET_asprintf (&config_filename,
+ "test_sync_db_%s.conf",
+ testname);
+ cfg = GNUNET_CONFIGURATION_create ();
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_parse (cfg,
+ config_filename))
+ {
+ GNUNET_break (0);
+ GNUNET_free (config_filename);
+ GNUNET_free (testname);
+ return 2;
+ }
+ GNUNET_SCHEDULER_run (&run, cfg);
+ GNUNET_CONFIGURATION_destroy (cfg);
+ GNUNET_free (config_filename);
+ GNUNET_free (testname);
+ return result;
+}
+
+/* end of test_sync_db.c */
diff --git a/src/syncdb/test_sync_db_postgres.conf b/src/syncdb/test_sync_db_postgres.conf
new file mode 100644
index 0000000..f91dea1
--- /dev/null
+++ b/src/syncdb/test_sync_db_postgres.conf
@@ -0,0 +1,7 @@
+[anastasis]
+#The DB plugin to use
+DB = postgres
+
+[anastasisdb-postgres]
+#The connection string the plugin has to use for connecting to the database
+CONFIG = postgres:///anastasischeck