OrthancPostgreSQL-2.0/.hg_archival.txt0000644000000000000000000000024212627602430016111 0ustar 00000000000000repo: 1d7c4b96183115894767b40ed485045665f2c75c node: 56dbbd7f5f785c5e343c60ab6a6e11b85d252615 branch: OrthancPostgreSQL-2.0 latesttag: null latesttagdistance: 88 OrthancPostgreSQL-2.0/AUTHORS0000644000000000000000000000035012627602430014073 0ustar 00000000000000PostgreSQL plugin for Orthanc ============================= Authors ------- * Sebastien Jodogne Department of Medical Physics University Hospital of Liege Belgium Overall design and lead developer. OrthancPostgreSQL-2.0/CMakeLists.txt0000644000000000000000000001417012627602430015570 0ustar 00000000000000# Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # # 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 . cmake_minimum_required(VERSION 2.8) project(OrthancPostgreSQL) set(ORTHANC_POSTGRESQL_VERSION "2.0") # Parameters of the build set(STATIC_BUILD OFF CACHE BOOL "Static build of the third-party libraries (necessary for Windows)") set(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages") set(BUILD_UNIT_TESTS ON CACHE BOOL "Build UnitTests") # Advanced parameters to fine-tune linking against system libraries set(USE_SYSTEM_JSONCPP ON CACHE BOOL "Use the system version of JsonCpp") set(USE_SYSTEM_BOOST ON CACHE BOOL "Use the system version of Boost") set(USE_SYSTEM_GOOGLE_TEST ON CACHE BOOL "Use the system version of Google Test") set(USE_SYSTEM_LIBPQ ON CACHE BOOL "Use the system version of the PostgreSQL client library") set(USE_SYSTEM_ORTHANC_SDK ON CACHE BOOL "Use the system version of the Orthanc plugin SDK") # Distribution-specific settings set(USE_GTEST_DEBIAN_SOURCE_PACKAGE OFF CACHE BOOL "Use the sources of Google Test shipped with libgtest-dev (Debian only)") mark_as_advanced(USE_GTEST_DEBIAN_SOURCE_PACKAGE) set(ORTHANC_ROOT ${CMAKE_SOURCE_DIR}/Orthanc) include(CheckIncludeFiles) include(CheckIncludeFileCXX) include(CheckLibraryExists) include(FindPythonInterp) include(${ORTHANC_ROOT}/Resources/CMake/Compiler.cmake) include(${ORTHANC_ROOT}/Resources/CMake/AutoGeneratedCode.cmake) include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake) include(${ORTHANC_ROOT}/Resources/CMake/BoostConfiguration.cmake) include(${ORTHANC_ROOT}/Resources/CMake/JsonCppConfiguration.cmake) include(${CMAKE_SOURCE_DIR}/Resources/CMake/PostgreSQLConfiguration.cmake) if (BUILD_UNIT_TESTS) include(${ORTHANC_ROOT}/Resources/CMake/GoogleTestConfiguration.cmake) endif() if (STATIC_BUILD OR NOT USE_SYSTEM_ORTHANC_SDK) include_directories(${ORTHANC_ROOT}/Sdk-0.9.5) else () CHECK_INCLUDE_FILE_CXX(orthanc/OrthancCppDatabasePlugin.h HAVE_ORTHANC_H) if (NOT HAVE_ORTHANC_H) message(FATAL_ERROR "Please install the headers of the Orthanc plugins SDK") endif() endif() if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") link_libraries(secur32) execute_process( COMMAND ${PYTHON_EXECUTABLE} ${ORTHANC_ROOT}/Resources/WindowsResources.py ${ORTHANC_POSTGRESQL_VERSION} "PostgreSQL storage plugin" OrthancPostgreSQLStorage.dll "PostgreSQL as a database back-end to Orthanc (storage area)" ERROR_VARIABLE Failure OUTPUT_FILE ${AUTOGENERATED_DIR}/StorageVersion.rc ) if (Failure) message(FATAL_ERROR "Error while computing the version information: ${Failure}") endif() execute_process( COMMAND ${PYTHON_EXECUTABLE} ${ORTHANC_ROOT}/Resources/WindowsResources.py ${ORTHANC_POSTGRESQL_VERSION} "PostgreSQL index plugin" OrthancPostgreSQLIndex.dll "PostgreSQL as a database back-end to Orthanc (index area)" ERROR_VARIABLE Failure OUTPUT_FILE ${AUTOGENERATED_DIR}/IndexVersion.rc ) if (Failure) message(FATAL_ERROR "Error while computing the version information: ${Failure}") endif() set(INDEX_RESOURCES ${AUTOGENERATED_DIR}/IndexVersion.rc) set(STORAGE_RESOURCES ${AUTOGENERATED_DIR}/StorageVersion.rc) endif() # Embed the SQL files into the binaries EmbedResources( --system-exception --namespace=OrthancPlugins POSTGRESQL_PREPARE ${CMAKE_CURRENT_SOURCE_DIR}/IndexPlugin/PostgreSQLPrepare.sql POSTGRESQL_PREPARE_V5 ${CMAKE_CURRENT_SOURCE_DIR}/IndexPlugin/PostgreSQLVersion5.sql POSTGRESQL_PREPARE_V6 ${CMAKE_CURRENT_SOURCE_DIR}/IndexPlugin/PostgreSQLVersion6.sql ) set(CORE_SOURCES ${CMAKE_SOURCE_DIR}/Core/PostgreSQLConnection.cpp ${CMAKE_SOURCE_DIR}/Core/PostgreSQLLargeObject.cpp ${CMAKE_SOURCE_DIR}/Core/PostgreSQLResult.cpp ${CMAKE_SOURCE_DIR}/Core/PostgreSQLStatement.cpp ${CMAKE_SOURCE_DIR}/Core/PostgreSQLTransaction.cpp ${CMAKE_SOURCE_DIR}/Core/Configuration.cpp ${CMAKE_SOURCE_DIR}/Core/GlobalProperties.cpp ${LIBPQ_SOURCES} ${BOOST_SOURCES} ${JSONCPP_SOURCES} ) add_library(OrthancPostgreSQLStorage SHARED ${CORE_SOURCES} ${CMAKE_SOURCE_DIR}/StoragePlugin/PostgreSQLStorageArea.cpp ${CMAKE_SOURCE_DIR}/StoragePlugin/Plugin.cpp ${STORAGE_RESOURCES} ) add_library(OrthancPostgreSQLIndex SHARED ${CORE_SOURCES} ${AUTOGENERATED_SOURCES} ${CMAKE_SOURCE_DIR}/IndexPlugin/PostgreSQLWrapper.cpp ${CMAKE_SOURCE_DIR}/IndexPlugin/Plugin.cpp ${INDEX_RESOURCES} ) message("Setting the version of the libraries to ${ORTHANC_POSTGRESQL_VERSION}") add_definitions(-DORTHANC_POSTGRESQL_VERSION="${ORTHANC_POSTGRESQL_VERSION}") set_target_properties(OrthancPostgreSQLStorage PROPERTIES VERSION ${ORTHANC_POSTGRESQL_VERSION} SOVERSION ${ORTHANC_POSTGRESQL_VERSION} ) set_target_properties(OrthancPostgreSQLIndex PROPERTIES VERSION ${ORTHANC_POSTGRESQL_VERSION} SOVERSION ${ORTHANC_POSTGRESQL_VERSION} ) install( TARGETS OrthancPostgreSQLStorage OrthancPostgreSQLIndex RUNTIME DESTINATION lib # Destination for Windows LIBRARY DESTINATION share/orthanc/plugins # Destination for Linux ) if (BUILD_UNIT_TESTS) add_executable(UnitTests ${CORE_SOURCES} ${GTEST_SOURCES} ${AUTOGENERATED_SOURCES} ${CMAKE_SOURCE_DIR}/IndexPlugin/PostgreSQLWrapper.cpp ${CMAKE_SOURCE_DIR}/StoragePlugin/PostgreSQLStorageArea.cpp ${CMAKE_SOURCE_DIR}/UnitTestsSources/UnitTestsMain.cpp ${CMAKE_SOURCE_DIR}/UnitTestsSources/PostgreSQLTests.cpp ${CMAKE_SOURCE_DIR}/UnitTestsSources/PostgreSQLWrapperTests.cpp ) endif() OrthancPostgreSQL-2.0/COPYING0000644000000000000000000010333012627602430014060 0ustar 00000000000000 GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. 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. Copyright (C) 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 . 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 . OrthancPostgreSQL-2.0/Core/Configuration.cpp0000644000000000000000000001164712627602430017241 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include "Configuration.h" #include "PostgreSQLException.h" #include #include #include // For UUID generation extern "C" { #ifdef WIN32 #include #else #include #endif } namespace OrthancPlugins { bool ReadConfiguration(Json::Value& configuration, OrthancPluginContext* context) { std::string s; { char* tmp = OrthancPluginGetConfiguration(context); if (tmp == NULL) { OrthancPluginLogError(context, "Error while retrieving the configuration from Orthanc"); return false; } s.assign(tmp); OrthancPluginFreeString(context, tmp); } Json::Reader reader; if (reader.parse(s, configuration)) { return true; } else { OrthancPluginLogError(context, "Unable to parse the configuration"); return false; } } std::string GetStringValue(const Json::Value& configuration, const std::string& key, const std::string& defaultValue) { if (configuration.type() != Json::objectValue || !configuration.isMember(key) || configuration[key].type() != Json::stringValue) { return defaultValue; } else { return configuration[key].asString(); } } int GetIntegerValue(const Json::Value& configuration, const std::string& key, int defaultValue) { if (configuration.type() != Json::objectValue || !configuration.isMember(key) || configuration[key].type() != Json::intValue) { return defaultValue; } else { return configuration[key].asInt(); } } bool GetBooleanValue(const Json::Value& configuration, const std::string& key, bool defaultValue) { if (configuration.type() != Json::objectValue || !configuration.isMember(key) || configuration[key].type() != Json::booleanValue) { return defaultValue; } else { return configuration[key].asBool(); } } PostgreSQLConnection* CreateConnection(bool& useLock, OrthancPluginContext* context, const Json::Value& configuration) { useLock = true; // Use locking by default std::auto_ptr connection(new PostgreSQLConnection); if (configuration.isMember("PostgreSQL")) { Json::Value c = configuration["PostgreSQL"]; if (c.isMember("ConnectionUri")) { connection->SetConnectionUri(c["ConnectionUri"].asString()); } else { connection->SetHost(GetStringValue(c, "Host", "localhost")); connection->SetPortNumber(GetIntegerValue(c, "Port", 5432)); connection->SetDatabase(GetStringValue(c, "Database", "orthanc")); connection->SetUsername(GetStringValue(c, "Username", "orthanc")); connection->SetPassword(GetStringValue(c, "Password", "orthanc")); } useLock = GetBooleanValue(c, "Lock", useLock); } if (!useLock) { OrthancPluginLogWarning(context, "Locking of the PostgreSQL database is disabled"); } connection->Open(); return connection.release(); } std::string GenerateUuid() { #ifdef WIN32 UUID uuid; UuidCreate ( &uuid ); unsigned char * str; UuidToStringA ( &uuid, &str ); std::string s( ( char* ) str ); RpcStringFreeA ( &str ); #else uuid_t uuid; uuid_generate_random ( uuid ); char s[37]; uuid_unparse ( uuid, s ); #endif return s; } bool IsFlagInCommandLineArguments(OrthancPluginContext* context, const std::string& flag) { uint32_t count = OrthancPluginGetCommandLineArgumentsCount(context); for (uint32_t i = 0; i < count; i++) { char* tmp = OrthancPluginGetCommandLineArgument(context, i); std::string arg(tmp); OrthancPluginFreeString(context, tmp); if (arg == flag) { return true; } } return false; } } OrthancPostgreSQL-2.0/Core/Configuration.h0000644000000000000000000000423412627602430016700 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #pragma once #include "PostgreSQLConnection.h" #include #include // This comes from the Orthanc source code static const int32_t GlobalProperty_DatabaseSchemaVersion = 1; static const int32_t GlobalProperty_IndexLock = 1024; static const int32_t GlobalProperty_StorageLock = 1025; static const std::string FLAG_UNLOCK = "--unlock"; namespace OrthancPlugins { bool ReadConfiguration(Json::Value& configuration, OrthancPluginContext* context); std::string GetStringValue(const Json::Value& configuration, const std::string& key, const std::string& defaultValue); int GetIntegerValue(const Json::Value& configuration, const std::string& key, int defaultValue); bool GetBooleanValue(const Json::Value& configuration, const std::string& key, bool defaultValue); PostgreSQLConnection* CreateConnection(bool& useLock, OrthancPluginContext* context, const Json::Value& configuration); std::string GenerateUuid(); bool IsFlagInCommandLineArguments(OrthancPluginContext* context, const std::string& flag); } OrthancPostgreSQL-2.0/Core/GlobalProperties.cpp0000644000000000000000000001075012627602430017701 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include "GlobalProperties.h" #include "Configuration.h" #include "PostgreSQLException.h" #include "PostgreSQLResult.h" #include "PostgreSQLTransaction.h" #define USE_ADVISORY_LOCK 1 namespace OrthancPlugins { GlobalProperties::GlobalProperties(PostgreSQLConnection& connection, bool useLock, int32_t lockKey) : connection_(connection), useLock_(useLock), lockKey_(lockKey) { PostgreSQLTransaction transaction(connection_); if (!connection_.DoesTableExist("GlobalProperties")) { connection_.Execute("CREATE TABLE GlobalProperties(" "property INTEGER PRIMARY KEY," "value TEXT)"); } transaction.Commit(); } void GlobalProperties::Lock(bool allowUnlock) { if (useLock_) { PostgreSQLTransaction transaction(connection_); #if USE_ADVISORY_LOCK == 1 PostgreSQLStatement s(connection_, "select pg_try_advisory_lock($1);"); s.DeclareInputInteger(0); s.BindInteger(0, lockKey_); PostgreSQLResult result(s); if (result.IsDone() || !result.GetBoolean(0)) { throw PostgreSQLException("The database is locked by another instance of Orthanc."); } #else PostgreSQLTransaction transaction(connection_); // Check the lock if (!allowUnlock) { std::string lock = "0"; if (LookupGlobalProperty(lock, lockKey_) && lock != "0") { throw PostgreSQLException("The database is locked by another instance of Orthanc. " "Use \"" + FLAG_UNLOCK + "\" to manually remove the lock."); } } // Lock the database SetGlobalProperty(lockKey_, "1"); #endif transaction.Commit(); } } bool GlobalProperties::LookupGlobalProperty(std::string& target, int32_t property) { if (lookupGlobalProperty_.get() == NULL) { lookupGlobalProperty_.reset (new PostgreSQLStatement (connection_, "SELECT value FROM GlobalProperties WHERE property=$1")); lookupGlobalProperty_->DeclareInputInteger(0); } lookupGlobalProperty_->BindInteger(0, static_cast(property)); PostgreSQLResult result(*lookupGlobalProperty_); if (result.IsDone()) { return false; } else { target = result.GetString(0); return true; } } void GlobalProperties::SetGlobalProperty(int32_t property, const char* value) { if (setGlobalProperty1_.get() == NULL || setGlobalProperty2_.get() == NULL) { setGlobalProperty1_.reset (new PostgreSQLStatement (connection_, "DELETE FROM GlobalProperties WHERE property=$1")); setGlobalProperty1_->DeclareInputInteger(0); setGlobalProperty2_.reset (new PostgreSQLStatement (connection_, "INSERT INTO GlobalProperties VALUES ($1, $2)")); setGlobalProperty2_->DeclareInputInteger(0); setGlobalProperty2_->DeclareInputString(1); } setGlobalProperty1_->BindInteger(0, property); setGlobalProperty1_->Run(); setGlobalProperty2_->BindInteger(0, property); setGlobalProperty2_->BindString(1, value); setGlobalProperty2_->Run(); } void GlobalProperties::Unlock() { if (useLock_) { #if USE_ADVISORY_LOCK == 1 // Nothing to do, the lock is released after the connection is closed #else // Remove the lock PostgreSQLTransaction transaction(connection_); SetGlobalProperty(lockKey_, "0"); transaction.Commit(); #endif } } } OrthancPostgreSQL-2.0/Core/GlobalProperties.h0000644000000000000000000000323112627602430017342 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #pragma once #include "PostgreSQLConnection.h" #include "PostgreSQLStatement.h" #include #include namespace OrthancPlugins { class GlobalProperties { private: PostgreSQLConnection& connection_; bool useLock_; int32_t lockKey_; std::auto_ptr lookupGlobalProperty_; std::auto_ptr setGlobalProperty1_; std::auto_ptr setGlobalProperty2_; public: GlobalProperties(PostgreSQLConnection& connection, bool useLock, int32_t lockKey); void Lock(bool allowUnlock); void Unlock(); bool LookupGlobalProperty(std::string& target, int32_t property); void SetGlobalProperty(int32_t property, const char* value); }; } OrthancPostgreSQL-2.0/Core/PostgreSQLConnection.cpp0000644000000000000000000001304012627602430020442 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include "PostgreSQLConnection.h" #include "PostgreSQLException.h" #include "PostgreSQLResult.h" #include "PostgreSQLStatement.h" #include "PostgreSQLTransaction.h" #include // PostgreSQL includes #include #include #include namespace OrthancPlugins { void PostgreSQLConnection::Close() { if (pg_ != NULL) { PQfinish(reinterpret_cast(pg_)); pg_ = NULL; } } PostgreSQLConnection::PostgreSQLConnection() { pg_ = NULL; host_ = "localhost"; port_ = 5432; username_ = "postgres"; password_ = "postgres"; database_ = ""; uri_.clear(); } PostgreSQLConnection::PostgreSQLConnection(const PostgreSQLConnection& other) : host_(other.host_), port_(other.port_), username_(other.username_), password_(other.password_), database_(other.database_), pg_(NULL) { } void PostgreSQLConnection::SetConnectionUri(const std::string& uri) { Close(); uri_ = uri; } std::string PostgreSQLConnection::GetConnectionUri() const { if (uri_.empty()) { return ("postgresql://" + username_ + ":" + password_ + "@" + host_ + ":" + boost::lexical_cast(port_) + "/" + database_); } else { return uri_; } } void PostgreSQLConnection::SetHost(const std::string& host) { Close(); uri_.clear(); host_ = host; } void PostgreSQLConnection::SetPortNumber(uint16_t port) { Close(); uri_.clear(); port_ = port; } void PostgreSQLConnection::SetUsername(const std::string& username) { Close(); uri_.clear(); username_ = username; } void PostgreSQLConnection::SetPassword(const std::string& password) { Close(); uri_.clear(); password_ = password; } void PostgreSQLConnection::SetDatabase(const std::string& database) { Close(); uri_.clear(); database_ = database; } void PostgreSQLConnection::Open() { if (pg_ != NULL) { // Already connected return; } std::string s; if (uri_.empty()) { s = std::string("sslmode=disable") + // TODO WHY SSL DOES NOT WORK? ("SSL error: wrong version number") " user=" + username_ + " password=" + password_ + " host=" + host_ + " port=" + boost::lexical_cast(port_); if (database_.size() > 0) { s += " dbname=" + database_; } } else { s = uri_; } pg_ = PQconnectdb(s.c_str()); if (pg_ == NULL || PQstatus(reinterpret_cast(pg_)) != CONNECTION_OK) { std::string message; if (pg_) { message = PQerrorMessage(reinterpret_cast(pg_)); PQfinish(reinterpret_cast(pg_)); pg_ = NULL; } throw PostgreSQLException(message); } } void PostgreSQLConnection::Execute(const std::string& sql) { Open(); PGresult* result = PQexec(reinterpret_cast(pg_), sql.c_str()); if (result == NULL) { throw PostgreSQLException(PQerrorMessage(reinterpret_cast(pg_))); } bool ok = (PQresultStatus(result) == PGRES_COMMAND_OK || PQresultStatus(result) == PGRES_TUPLES_OK); if (ok) { PQclear(result); } else { std::string message = PQresultErrorMessage(result); PQclear(result); throw PostgreSQLException(message); } } bool PostgreSQLConnection::DoesTableExist(const char* name) { std::string lower(name); std::transform(lower.begin(), lower.end(), lower.begin(), tolower); // http://stackoverflow.com/a/24089729/881731 PostgreSQLStatement statement(*this, "SELECT 1 FROM pg_catalog.pg_class c " "JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace " "WHERE n.nspname = 'public' AND c.relkind='r' " "AND c.relname=$1"); statement.DeclareInputString(0); statement.BindString(0, lower); PostgreSQLResult result(statement); return !result.IsDone(); } void PostgreSQLConnection::ClearAll() { PostgreSQLTransaction transaction(*this); // Remove all the large objects Execute("SELECT lo_unlink(loid) FROM (SELECT DISTINCT loid FROM pg_catalog.pg_largeobject) as loids;"); // http://stackoverflow.com/a/21247009/881731 Execute("DROP SCHEMA public CASCADE;"); Execute("CREATE SCHEMA public;"); Execute("GRANT ALL ON SCHEMA public TO postgres;"); Execute("GRANT ALL ON SCHEMA public TO public;"); Execute("COMMENT ON SCHEMA public IS 'standard public schema';"); transaction.Commit(); } } OrthancPostgreSQL-2.0/Core/PostgreSQLConnection.h0000644000000000000000000000524212627602430020114 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #pragma once #if defined(_WIN32) #include # if defined(_MSC_VER) // http://msdn.microsoft.com/en-us/library/a3140177.aspx # define htobe32(x) _byteswap_ulong(x) # define htobe64(x) _byteswap_uint64(x) # else // MinGW # define htobe32(x) __builtin_bswap32(x) # define htobe64(x) __builtin_bswap64(x) # endif #endif #include #include #include namespace OrthancPlugins { class PostgreSQLConnection : public boost::noncopyable { private: friend class PostgreSQLStatement; friend class PostgreSQLLargeObject; std::string host_; uint16_t port_; std::string username_; std::string password_; std::string database_; std::string uri_; void* pg_; /* Object of type "PGconn*" */ void Close(); public: PostgreSQLConnection(); PostgreSQLConnection(const PostgreSQLConnection& other); ~PostgreSQLConnection() { Close(); } void SetConnectionUri(const std::string& uri); std::string GetConnectionUri() const; void SetHost(const std::string& host); const std::string& GetHost() const { return host_; } void SetPortNumber(uint16_t port); uint16_t GetPortNumber() const { return port_; } void SetUsername(const std::string& username); const std::string& GetUsername() const { return username_; } void SetPassword(const std::string& password); const std::string& GetPassword() const { return password_; } void SetDatabase(const std::string& database); void ResetDatabase() { SetDatabase(""); } const std::string& GetDatabase() const { return database_; } void Open(); void Execute(const std::string& sql); bool DoesTableExist(const char* name); void ClearAll(); }; } OrthancPostgreSQL-2.0/Core/PostgreSQLException.h0000644000000000000000000000230312627602430017746 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #pragma once #include #include namespace OrthancPlugins { class PostgreSQLException : public std::runtime_error { public: PostgreSQLException() : std::runtime_error("Error in PostgreSQL") { } PostgreSQLException(const std::string& message) : std::runtime_error("Error in PostgreSQL: " + message) { } }; } OrthancPostgreSQL-2.0/Core/PostgreSQLLargeObject.cpp0000644000000000000000000001231712627602430020532 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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.postgresql.org/docs/9.1/static/lo-interfaces.html#AEN33102 #include "PostgreSQLLargeObject.h" #include "PostgreSQLException.h" #include #include namespace OrthancPlugins { void PostgreSQLLargeObject::Create() { PGconn* pg = reinterpret_cast(connection_.pg_); oid_ = lo_creat(pg, INV_WRITE); if (oid_ == 0) { throw PostgreSQLException("Cannot create a large object"); } } void PostgreSQLLargeObject::Write(const void* data, size_t size) { static int MAX_CHUNK_SIZE = 16 * 1024 * 1024; PGconn* pg = reinterpret_cast(connection_.pg_); int fd = lo_open(pg, oid_, INV_WRITE); if (fd < 0) { throw PostgreSQLException(); } const char* position = reinterpret_cast(data); while (size > 0) { int chunk = (size > static_cast(MAX_CHUNK_SIZE) ? MAX_CHUNK_SIZE : static_cast(size)); int nbytes = lo_write(pg, fd, position, chunk); if (nbytes <= 0) { lo_close(pg, fd); throw PostgreSQLException(); } size -= nbytes; position += nbytes; } lo_close(pg, fd); } PostgreSQLLargeObject::PostgreSQLLargeObject(PostgreSQLConnection& connection, const void* data, size_t size) : connection_(connection) { Create(); Write(data, size); } PostgreSQLLargeObject::PostgreSQLLargeObject(PostgreSQLConnection& connection, const std::string& s) : connection_(connection) { Create(); if (s.size() != 0) { Write(s.c_str(), s.size()); } else { Write(NULL, 0); } } class PostgreSQLLargeObject::Reader { private: PGconn* pg_; int fd_; size_t size_; public: Reader(PostgreSQLConnection& connection, const std::string& oid) { pg_ = reinterpret_cast(connection.pg_); Oid id = boost::lexical_cast(oid); fd_ = lo_open(pg_, id, INV_READ); if (fd_ < 0 || lo_lseek(pg_, fd_, 0, SEEK_END) < 0) { throw PostgreSQLException("No such large object in the connection; Make sure you use a transaction"); } // Get the size of the large object int size = lo_tell(pg_, fd_); if (size < 0) { throw PostgreSQLException("Internal error"); } size_ = static_cast(size); // Go to the first byte of the object lo_lseek(pg_, fd_, 0, SEEK_SET); } ~Reader() { lo_close(pg_, fd_); } size_t GetSize() const { return size_; } void Read(char* target) { for (size_t position = 0; position < size_; ) { size_t remaining = size_ - position; size_t nbytes = lo_read(pg_, fd_, target + position, remaining); if (nbytes < 0) { throw PostgreSQLException("Unable to read the large object in the database"); } position += nbytes; } } }; void PostgreSQLLargeObject::Read(std::string& target, PostgreSQLConnection& connection, const std::string& oid) { Reader reader(connection, oid); target.resize(reader.GetSize()); if (target.size() > 0) { reader.Read(&target[0]); } } void PostgreSQLLargeObject::Read(void*& target, size_t& size, PostgreSQLConnection& connection, const std::string& oid) { Reader reader(connection, oid); size = reader.GetSize(); if (size == 0) { target = NULL; } else { target = malloc(size); reader.Read(reinterpret_cast(target)); } } std::string PostgreSQLLargeObject::GetOid() const { return boost::lexical_cast(oid_); } void PostgreSQLLargeObject::Delete(PostgreSQLConnection& connection, const std::string& oid) { PGconn* pg = reinterpret_cast(connection.pg_); Oid id = boost::lexical_cast(oid); if (lo_unlink(pg, id) < 0) { throw PostgreSQLException("Unable to delete the large object from the database"); } } } OrthancPostgreSQL-2.0/Core/PostgreSQLLargeObject.h0000644000000000000000000000355712627602430020205 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #pragma once #include "PostgreSQLConnection.h" #include namespace OrthancPlugins { class PostgreSQLLargeObject : public boost::noncopyable { private: class Reader; PostgreSQLConnection& connection_; Oid oid_; void Create(); void Write(const void* data, size_t size); public: PostgreSQLLargeObject(PostgreSQLConnection& connection, const void* data, size_t size); PostgreSQLLargeObject(PostgreSQLConnection& connection, const std::string& s); std::string GetOid() const; static void Read(std::string& target, PostgreSQLConnection& connection, const std::string& oid); static void Read(void*& target, size_t& size, PostgreSQLConnection& connection, const std::string& oid); static void Delete(PostgreSQLConnection& connection, const std::string& oid); }; } OrthancPostgreSQL-2.0/Core/PostgreSQLResult.cpp0000644000000000000000000001227712627602430017634 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include "PostgreSQLResult.h" #include "PostgreSQLException.h" #include #include // PostgreSQL includes #include #include #include #if defined(__FreeBSD__) # include // ntohl() #elif defined(__APPLE__) # include # define htobe32(x) OSSwapHostToBigInt32(x) # define htobe64(x) OSSwapHostToBigInt64(x) #endif namespace OrthancPlugins { void PostgreSQLResult::Clear() { if (result_ != NULL) { PQclear(reinterpret_cast(result_)); result_ = NULL; } } void PostgreSQLResult::CheckDone() { if (position_ >= PQntuples(reinterpret_cast(result_))) { // We are at the end of the result set Clear(); } } void PostgreSQLResult::CheckColumn(unsigned int column, unsigned int /*Oid*/ expectedType) const { if (IsDone()) { throw PostgreSQLException("Bad sequence of calls"); } if (column >= static_cast(PQnfields(reinterpret_cast(result_)))) { throw PostgreSQLException("Parameter out of range"); } if (expectedType != 0 && expectedType != PQftype(reinterpret_cast(result_), column)) { throw PostgreSQLException("Bad type of parameter"); } } PostgreSQLResult::PostgreSQLResult(PostgreSQLStatement& statement) : position_(0), connection_(statement.GetConnection()) { result_ = statement.Execute(); assert(result_ != NULL); // An exception would have been thrown otherwise // This is the first call to "Step()" if (PQresultStatus(reinterpret_cast(result_)) != PGRES_TUPLES_OK) { throw PostgreSQLException("PostgreSQL: Step() applied to non-SELECT request"); } CheckDone(); } void PostgreSQLResult::Step() { position_++; CheckDone(); } bool PostgreSQLResult::IsNull(unsigned int column) const { CheckColumn(column, 0); return PQgetisnull(reinterpret_cast(result_), position_, column) != 0; } bool PostgreSQLResult::GetBoolean(unsigned int column) const { CheckColumn(column, BOOLOID); assert(PQfsize(reinterpret_cast(result_), column) == 1); const uint8_t *v = reinterpret_cast(PQgetvalue(reinterpret_cast(result_), position_, column)); return (v[0] != 0); } int PostgreSQLResult::GetInteger(unsigned int column) const { CheckColumn(column, INT4OID); assert(PQfsize(reinterpret_cast(result_), column) == 4); char *v = PQgetvalue(reinterpret_cast(result_), position_, column); return htobe32(*reinterpret_cast(v)); } int64_t PostgreSQLResult::GetInteger64(unsigned int column) const { CheckColumn(column, INT8OID); assert(PQfsize(reinterpret_cast(result_), column) == 8); char *v = PQgetvalue(reinterpret_cast(result_), position_, column); return htobe64(*reinterpret_cast(v)); } std::string PostgreSQLResult::GetString(unsigned int column) const { CheckColumn(column, 0); Oid oid = PQftype(reinterpret_cast(result_), column); if (oid != TEXTOID && oid != VARCHAROID && oid != BYTEAOID) { throw PostgreSQLException("Bad type of parameter"); } return std::string(PQgetvalue(reinterpret_cast(result_), position_, column)); } void PostgreSQLResult::GetLargeObject(std::string& result, unsigned int column) const { CheckColumn(column, OIDOID); Oid oid; assert(PQfsize(reinterpret_cast(result_), column) == sizeof(oid)); oid = *(const Oid*) PQgetvalue(reinterpret_cast(result_), position_, column); oid = ntohl(oid); PostgreSQLLargeObject::Read(result, connection_, boost::lexical_cast(oid)); } void PostgreSQLResult::GetLargeObject(void*& result, size_t& size, unsigned int column) const { CheckColumn(column, OIDOID); Oid oid; assert(PQfsize(reinterpret_cast(result_), column) == sizeof(oid)); oid = *(const Oid*) PQgetvalue(reinterpret_cast(result_), position_, column); oid = ntohl(oid); PostgreSQLLargeObject::Read(result, size, connection_, boost::lexical_cast(oid)); } } OrthancPostgreSQL-2.0/Core/PostgreSQLResult.h0000644000000000000000000000357112627602430017276 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #pragma once #include "PostgreSQLStatement.h" namespace OrthancPlugins { class PostgreSQLResult : public boost::noncopyable { private: void *result_; /* Object of type "PGresult*" */ int position_; PostgreSQLConnection& connection_; void Clear(); void CheckDone(); void CheckColumn(unsigned int column, /*Oid*/ unsigned int expectedType) const; public: PostgreSQLResult(PostgreSQLStatement& statement); ~PostgreSQLResult() { Clear(); } void Step(); bool IsDone() const { return result_ == NULL; } bool IsNull(unsigned int column) const; bool GetBoolean(unsigned int column) const; int GetInteger(unsigned int column) const; int64_t GetInteger64(unsigned int column) const; std::string GetString(unsigned int column) const; void GetLargeObject(std::string& result, unsigned int column) const; void GetLargeObject(void*& result, size_t& size, unsigned int column) const; }; } OrthancPostgreSQL-2.0/Core/PostgreSQLStatement.cpp0000644000000000000000000002154012627602430020313 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include "PostgreSQLStatement.h" #include "PostgreSQLException.h" #include "Configuration.h" #include // PostgreSQL includes #include #include #include #if defined(__APPLE__) # include # define htobe32(x) OSSwapHostToBigInt32(x) # define htobe64(x) OSSwapHostToBigInt64(x) #endif namespace OrthancPlugins { class PostgreSQLStatement::Inputs : public boost::noncopyable { private: std::vector values_; std::vector sizes_; static char* Allocate(const void* source, int size) { if (size == 0) { return NULL; } else { char* ptr = reinterpret_cast(malloc(size)); if (source != NULL) { memcpy(ptr, source, size); } return ptr; } } void Resize(size_t size) { // Shrinking of the vector for (size_t i = size; i < values_.size(); i++) { if (values_[i] != NULL) free(values_[i]); } values_.resize(size, NULL); sizes_.resize(size, 0); } void EnlargeForIndex(size_t index) { if (index >= values_.size()) { // The vector is too small Resize(index + 1); } } public: Inputs() { } ~Inputs() { Resize(0); } void SetItem(size_t pos, const void* source, int size) { EnlargeForIndex(pos); if (sizes_[pos] == size) { if (source && size != 0) { memcpy(values_[pos], source, size); } } else { if (values_[pos] != NULL) { free(values_[pos]); } values_[pos] = Allocate(source, size); sizes_[pos] = size; } } void SetItem(size_t pos, int size) { SetItem(pos, NULL, size); } void* GetItem(size_t pos) const { if (pos >= values_.size()) { throw PostgreSQLException("Parameter out of range"); } return values_[pos]; } const std::vector& GetValues() const { return values_; } const std::vector& GetSizes() const { return sizes_; } }; void PostgreSQLStatement::Prepare() { if (id_.size() > 0) { // Already prepared return; } for (size_t i = 0; i < oids_.size(); i++) { if (oids_[i] == 0) { // The type of an input parameter was not set throw PostgreSQLException(); } } id_ = GenerateUuid(); const unsigned int* tmp = oids_.size() ? &oids_[0] : NULL; PGresult* result = PQprepare(reinterpret_cast(connection_.pg_), id_.c_str(), sql_.c_str(), oids_.size(), tmp); if (result == NULL) { id_.clear(); throw PostgreSQLException(PQerrorMessage(reinterpret_cast(connection_.pg_))); } bool ok = (PQresultStatus(result) == PGRES_COMMAND_OK); if (ok) { PQclear(result); } else { std::string message = PQresultErrorMessage(result); PQclear(result); id_.clear(); throw PostgreSQLException(message); } } void PostgreSQLStatement::Unprepare() { if (id_.size() > 0) { // "Although there is no libpq function for deleting a // prepared statement, the SQL DEALLOCATE statement can be // used for that purpose." //connection_.Execute("DEALLOCATE " + id_); } id_.clear(); } void PostgreSQLStatement::DeclareInputInternal(unsigned int param, unsigned int /*Oid*/ type) { Unprepare(); if (oids_.size() <= param) { oids_.resize(param + 1, 0); binary_.resize(param + 1); } oids_[param] = type; binary_[param] = (type == TEXTOID || type == BYTEAOID || type == OIDOID) ? 0 : 1; } void PostgreSQLStatement::DeclareInputInteger(unsigned int param) { DeclareInputInternal(param, INT4OID); } void PostgreSQLStatement::DeclareInputInteger64(unsigned int param) { DeclareInputInternal(param, INT8OID); } void PostgreSQLStatement::DeclareInputString(unsigned int param) { DeclareInputInternal(param, TEXTOID); } void PostgreSQLStatement::DeclareInputBinary(unsigned int param) { DeclareInputInternal(param, BYTEAOID); } void PostgreSQLStatement::DeclareInputLargeObject(unsigned int param) { DeclareInputInternal(param, OIDOID); } void* /* PGresult* */ PostgreSQLStatement::Execute() { Prepare(); PGresult* result; if (oids_.size() == 0) { // No parameter result = PQexecPrepared(reinterpret_cast(connection_.pg_), id_.c_str(), 0, NULL, NULL, NULL, 1); } else { // At least 1 parameter result = PQexecPrepared(reinterpret_cast(connection_.pg_), id_.c_str(), oids_.size(), &inputs_->GetValues()[0], &inputs_->GetSizes()[0], &binary_[0], 1); } if (result == NULL) { throw PostgreSQLException(PQerrorMessage(reinterpret_cast(connection_.pg_))); } return result; } PostgreSQLStatement::PostgreSQLStatement(PostgreSQLConnection& connection, const std::string& sql) : connection_(connection), sql_(sql), inputs_(new Inputs) { connection_.Open(); } void PostgreSQLStatement::Run() { PGresult* result = reinterpret_cast(Execute()); assert(result != NULL); // An exception would have been thrown otherwise bool ok = (PQresultStatus(result) == PGRES_COMMAND_OK || PQresultStatus(result) == PGRES_TUPLES_OK); if (ok) { PQclear(result); } else { std::string error = PQresultErrorMessage(result); PQclear(result); throw PostgreSQLException(error); } } void PostgreSQLStatement::BindNull(unsigned int param) { if (param >= oids_.size()) { throw PostgreSQLException("Parameter out of range"); } inputs_->SetItem(param, 0); } void PostgreSQLStatement::BindInteger(unsigned int param, int value) { if (param >= oids_.size()) { throw PostgreSQLException("Parameter out of range"); } if (oids_[param] != INT4OID) { throw PostgreSQLException("Bad type of parameter"); } assert(sizeof(int32_t) == 4); int32_t v = htobe32(static_cast(value)); inputs_->SetItem(param, &v, sizeof(int32_t)); } void PostgreSQLStatement::BindInteger64(unsigned int param, int64_t value) { if (param >= oids_.size()) { throw PostgreSQLException("Parameter out of range"); } if (oids_[param] != INT8OID) { throw PostgreSQLException("Bad type of parameter"); } assert(sizeof(int64_t) == 8); int64_t v = htobe64(value); inputs_->SetItem(param, &v, sizeof(int64_t)); } void PostgreSQLStatement::BindString(unsigned int param, const std::string& value) { if (param >= oids_.size()) { throw PostgreSQLException("Parameter out of range"); } if (oids_[param] != TEXTOID && oids_[param] != BYTEAOID) { throw PostgreSQLException("Bad type of parameter"); } if (value.size() == 0) { inputs_->SetItem(param, "", 1 /* end-of-string character */); } else { inputs_->SetItem(param, value.c_str(), value.size() + 1); // "+1" for end-of-string character } } void PostgreSQLStatement::BindLargeObject(unsigned int param, const PostgreSQLLargeObject& value) { if (param >= oids_.size()) { throw PostgreSQLException("Parameter out of range"); } if (oids_[param] != OIDOID) { throw PostgreSQLException("Bad type of parameter"); } inputs_->SetItem(param, value.GetOid().c_str(), value.GetOid().size() + 1); // "+1" for end-of-string character } } OrthancPostgreSQL-2.0/Core/PostgreSQLStatement.h0000644000000000000000000000453612627602430017766 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #pragma once #include "PostgreSQLConnection.h" #include "PostgreSQLLargeObject.h" #include #include #include namespace OrthancPlugins { class PostgreSQLStatement : public boost::noncopyable { private: class Inputs; friend class PostgreSQLResult; PostgreSQLConnection& connection_; std::string id_; std::string sql_; std::vector oids_; std::vector binary_; boost::shared_ptr inputs_; void Prepare(); void Unprepare(); void DeclareInputInternal(unsigned int param, unsigned int /*Oid*/ type); void* /* PGresult* */ Execute(); public: PostgreSQLStatement(PostgreSQLConnection& connection, const std::string& sql); ~PostgreSQLStatement() { Unprepare(); } void DeclareInputInteger(unsigned int param); void DeclareInputInteger64(unsigned int param); void DeclareInputString(unsigned int param); void DeclareInputBinary(unsigned int param); void DeclareInputLargeObject(unsigned int param); void Run(); void BindNull(unsigned int param); void BindInteger(unsigned int param, int value); void BindInteger64(unsigned int param, int64_t value); void BindString(unsigned int param, const std::string& value); void BindLargeObject(unsigned int param, const PostgreSQLLargeObject& value); PostgreSQLConnection& GetConnection() const { return connection_; } }; } OrthancPostgreSQL-2.0/Core/PostgreSQLTransaction.cpp0000644000000000000000000000406612627602430020640 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include "PostgreSQLTransaction.h" #include "PostgreSQLException.h" namespace OrthancPlugins { PostgreSQLTransaction::PostgreSQLTransaction(PostgreSQLConnection& connection, bool open) : connection_(connection), isOpen_(false) { if (open) { Begin(); } } PostgreSQLTransaction::~PostgreSQLTransaction() { if (isOpen_) { connection_.Execute("ABORT"); } } void PostgreSQLTransaction::Begin() { if (isOpen_) { throw PostgreSQLException("PostgreSQL: Beginning a transaction twice!"); } connection_.Execute("BEGIN"); isOpen_ = true; } void PostgreSQLTransaction::Rollback() { if (!isOpen_) { throw PostgreSQLException("Attempting to rollback a nonexistent transaction. " "Did you remember to call Begin()?"); } connection_.Execute("ABORT"); isOpen_ = false; } void PostgreSQLTransaction::Commit() { if (!isOpen_) { throw PostgreSQLException("Attempting to roll back a nonexistent transaction. " "Did you remember to call Begin()?"); } connection_.Execute("COMMIT"); isOpen_ = false; } } OrthancPostgreSQL-2.0/Core/PostgreSQLTransaction.h0000644000000000000000000000234712627602430020305 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #pragma once #include "PostgreSQLConnection.h" namespace OrthancPlugins { class PostgreSQLTransaction { private: PostgreSQLConnection& connection_; bool isOpen_; public: explicit PostgreSQLTransaction(PostgreSQLConnection& connection, bool open = true); ~PostgreSQLTransaction(); void Begin(); void Rollback(); void Commit(); }; } OrthancPostgreSQL-2.0/IndexPlugin/Plugin.cpp0000644000000000000000000000726012627602430017222 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include #include "PostgreSQLWrapper.h" #include "../Core/PostgreSQLException.h" #include "../Core/Configuration.h" static OrthancPluginContext* context_ = NULL; static OrthancPlugins::PostgreSQLWrapper* backend_ = NULL; extern "C" { ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) { context_ = context; /* Check the version of the Orthanc core */ if (OrthancPluginCheckVersion(context_) == 0) { char info[1024]; sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", context_->orthancVersion, ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); OrthancPluginLogError(context_, info); return -1; } OrthancPluginSetDescription(context_, "Stores the Orthanc index into a PostgreSQL database."); Json::Value configuration; if (!OrthancPlugins::ReadConfiguration(configuration, context)) { OrthancPluginLogError(context_, "Unable to read the configuration file"); return -1; } if (!configuration.isMember("PostgreSQL") || configuration["PostgreSQL"].type() != Json::objectValue || !OrthancPlugins::GetBooleanValue(configuration["PostgreSQL"], "EnableIndex", false)) { OrthancPluginLogWarning(context_, "The PostgreSQL index is currently disabled, set \"EnableIndex\" to \"true\" in the \"PostgreSQL\" section of the configuration file of Orthanc"); return 0; } else { OrthancPluginLogWarning(context_, "Using PostgreSQL index"); } bool allowUnlock = OrthancPlugins::IsFlagInCommandLineArguments(context_, FLAG_UNLOCK); try { /* Create the connection to PostgreSQL */ bool useLock; std::auto_ptr pg(OrthancPlugins::CreateConnection(useLock, context_, configuration)); pg->Open(); //pg->ClearAll(); // Reset the database /* Create the database back-end */ backend_ = new OrthancPlugins::PostgreSQLWrapper(context_, pg.release(), useLock, allowUnlock); /* Register the PostgreSQL index into Orthanc */ OrthancPlugins::DatabaseBackendAdapter::Register(context_, *backend_); } catch (std::runtime_error& e) { OrthancPluginLogError(context_, e.what()); return -1; } return 0; } ORTHANC_PLUGINS_API void OrthancPluginFinalize() { OrthancPluginLogWarning(context_, "PostgreSQL index is finalizing"); if (backend_ != NULL) { delete backend_; backend_ = NULL; } } ORTHANC_PLUGINS_API const char* OrthancPluginGetName() { return "postgresql-index"; } ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() { return ORTHANC_POSTGRESQL_VERSION; } } OrthancPostgreSQL-2.0/IndexPlugin/PostgreSQLPrepare.sql0000644000000000000000000001026312627602430021320 0ustar 00000000000000-- Table "GlobalProperties" is created by the -- "OrthancPlugins::GlobalProperties" class CREATE TABLE Metadata( id BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, type INTEGER NOT NULL, value TEXT, PRIMARY KEY(id, type) ); CREATE TABLE AttachedFiles( id BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, fileType INTEGER, uuid VARCHAR(64) NOT NULL, compressedSize BIGINT, uncompressedSize BIGINT, compressionType INTEGER, uncompressedHash VARCHAR(40), compressedHash VARCHAR(40), PRIMARY KEY(id, fileType) ); CREATE TABLE Changes( seq BIGSERIAL NOT NULL PRIMARY KEY, changeType INTEGER, internalId BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, resourceType INTEGER, date VARCHAR(64) ); CREATE TABLE ExportedResources( seq BIGSERIAL NOT NULL PRIMARY KEY, resourceType INTEGER, publicId VARCHAR(64), remoteModality TEXT, patientId VARCHAR(64), studyInstanceUid TEXT, seriesInstanceUid TEXT, sopInstanceUid TEXT, date VARCHAR(64) ); CREATE TABLE PatientRecyclingOrder( seq BIGSERIAL NOT NULL PRIMARY KEY, patientId BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE ); CREATE INDEX ChildrenIndex ON Resources(parentId); CREATE INDEX PublicIndex ON Resources(publicId); CREATE INDEX ResourceTypeIndex ON Resources(resourceType); CREATE INDEX PatientRecyclingIndex ON PatientRecyclingOrder(patientId); CREATE INDEX MainDicomTagsIndex ON MainDicomTags(id); CREATE INDEX DicomIdentifiersIndex1 ON DicomIdentifiers(id); CREATE INDEX DicomIdentifiersIndex2 ON DicomIdentifiers(tagGroup, tagElement); CREATE INDEX DicomIdentifiersIndexValues ON DicomIdentifiers(value); CREATE INDEX ChangesIndex ON Changes(internalId); -- Differences with SQLite CREATE TABLE DeletedFiles( uuid VARCHAR(64) NOT NULL, -- 0 fileType INTEGER, -- 1 compressedSize BIGINT, -- 2 uncompressedSize BIGINT, -- 3 compressionType INTEGER, -- 4 uncompressedHash VARCHAR(40), -- 5 compressedHash VARCHAR(40) -- 6 ); CREATE TABLE RemainingAncestor( resourceType INTEGER NOT NULL, publicId VARCHAR(64) NOT NULL ); CREATE TABLE DeletedResources( resourceType INTEGER NOT NULL, publicId VARCHAR(64) NOT NULL ); -- End of differences CREATE FUNCTION AttachedFileDeletedFunc() RETURNS TRIGGER AS $body$ BEGIN INSERT INTO DeletedFiles VALUES (old.uuid, old.filetype, old.compressedSize, old.uncompressedSize, old.compressionType, old.uncompressedHash, old.compressedHash); RETURN NULL; END; $body$ LANGUAGE plpgsql; CREATE TRIGGER AttachedFileDeleted AFTER DELETE ON AttachedFiles FOR EACH ROW EXECUTE PROCEDURE AttachedFileDeletedFunc(); -- The following trigger combines 2 triggers from SQLite: -- ResourceDeleted + ResourceDeletedParentCleaning CREATE FUNCTION ResourceDeletedFunc() RETURNS TRIGGER AS $body$ BEGIN --RAISE NOTICE 'Delete resource %', old.parentId; INSERT INTO DeletedResources VALUES (old.resourceType, old.publicId); -- http://stackoverflow.com/a/11299968/881731 IF EXISTS (SELECT 1 FROM Resources WHERE parentId = old.parentId) THEN -- Signal that the deleted resource has a remaining parent INSERT INTO RemainingAncestor SELECT resourceType, publicId FROM Resources WHERE internalId = old.parentId; ELSE -- Delete a parent resource when its unique child is deleted DELETE FROM Resources WHERE internalId = old.parentId; END IF; RETURN NULL; END; $body$ LANGUAGE plpgsql; CREATE TRIGGER ResourceDeleted AFTER DELETE ON Resources FOR EACH ROW EXECUTE PROCEDURE ResourceDeletedFunc(); CREATE FUNCTION PatientAddedFunc() RETURNS TRIGGER AS $body$ BEGIN -- The "0" corresponds to "OrthancPluginResourceType_Patient" IF new.resourceType = 0 THEN INSERT INTO PatientRecyclingOrder VALUES (DEFAULT, new.internalId); END IF; RETURN NULL; END; $body$ LANGUAGE plpgsql; CREATE TRIGGER PatientAdded AFTER INSERT ON Resources FOR EACH ROW EXECUTE PROCEDURE PatientAddedFunc(); OrthancPostgreSQL-2.0/IndexPlugin/PostgreSQLVersion5.sql0000644000000000000000000000125712627602430021437 0ustar 00000000000000CREATE TABLE Resources( internalId BIGSERIAL NOT NULL PRIMARY KEY, resourceType INTEGER NOT NULL, publicId VARCHAR(64) NOT NULL, parentId BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE ); CREATE TABLE MainDicomTags( id BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, tagGroup INTEGER, tagElement INTEGER, value BYTEA, PRIMARY KEY(id, tagGroup, tagElement) ); CREATE TABLE DicomIdentifiers( id BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, tagGroup INTEGER, tagElement INTEGER, value BYTEA, PRIMARY KEY(id, tagGroup, tagElement) ); OrthancPostgreSQL-2.0/IndexPlugin/PostgreSQLVersion6.sql0000644000000000000000000000125512627602430021436 0ustar 00000000000000CREATE TABLE Resources( internalId BIGSERIAL NOT NULL PRIMARY KEY, resourceType INTEGER NOT NULL, publicId VARCHAR(64) NOT NULL, parentId BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE ); CREATE TABLE MainDicomTags( id BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, tagGroup INTEGER, tagElement INTEGER, value TEXT, PRIMARY KEY(id, tagGroup, tagElement) ); CREATE TABLE DicomIdentifiers( id BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, tagGroup INTEGER, tagElement INTEGER, value TEXT, PRIMARY KEY(id, tagGroup, tagElement) ); OrthancPostgreSQL-2.0/IndexPlugin/PostgreSQLWrapper.cpp0000644000000000000000000013141312627602430021326 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include "PostgreSQLWrapper.h" #include "EmbeddedResources.h" #include "../Core/Configuration.h" #include "../Core/PostgreSQLException.h" #include "../Core/PostgreSQLTransaction.h" #include namespace OrthancPlugins { PostgreSQLWrapper::PostgreSQLWrapper(OrthancPluginContext* context, PostgreSQLConnection* connection, bool useLock, bool allowUnlock) : context_(context), connection_(connection), globalProperties_(*connection, useLock, GlobalProperty_IndexLock) { globalProperties_.Lock(allowUnlock); Prepare(); /** * Below are the PostgreSQL precompiled statements that are used * in more than 1 method of this class. **/ getPublicId_.reset (new PostgreSQLStatement (*connection_, "SELECT publicId FROM Resources WHERE internalId=$1")); getPublicId_->DeclareInputInteger64(0); clearDeletedFiles_.reset (new PostgreSQLStatement (*connection_, "DELETE FROM DeletedFiles")); clearDeletedResources_.reset (new PostgreSQLStatement (*connection_, "DELETE FROM DeletedResources")); } void PostgreSQLWrapper::SignalDeletedFilesAndResources() { if (getDeletedFiles_.get() == NULL || getDeletedResources_.get() == NULL) { getDeletedFiles_.reset (new PostgreSQLStatement (*connection_, "SELECT * FROM DeletedFiles")); getDeletedResources_.reset (new PostgreSQLStatement (*connection_, "SELECT * FROM DeletedResources")); } { PostgreSQLResult result(*getDeletedFiles_); while (!result.IsDone()) { GetOutput().SignalDeletedAttachment(result.GetString(0).c_str(), result.GetInteger(1), result.GetInteger64(3), result.GetString(5).c_str(), result.GetInteger(4), result.GetInteger64(2), result.GetString(6).c_str()); result.Step(); } } { PostgreSQLResult result(*getDeletedResources_); while (!result.IsDone()) { OrthancPluginResourceType type = static_cast(result.GetInteger(0)); GetOutput().SignalDeletedResource(result.GetString(1), type); result.Step(); } } } void PostgreSQLWrapper::Prepare() { uint32_t expectedVersion; if (context_) { expectedVersion = OrthancPluginGetExpectedDatabaseVersion(context_); } else { // This case only occurs during unit testing expectedVersion = 6; } /* Check the expected version of the database */ if (expectedVersion != 5 && expectedVersion != 6) { char info[1024]; sprintf(info, "This database plugin is incompatible with your version of Orthanc " "expecting the DB schema version %d, but this plugin is compatible with versions 5 or 6", expectedVersion); OrthancPluginLogError(context_, info); throw PostgreSQLException(info); } PostgreSQLTransaction t(*connection_); if (!connection_->DoesTableExist("Resources")) { std::string query; if (expectedVersion == 5) { EmbeddedResources::GetFileResource(query, EmbeddedResources::POSTGRESQL_PREPARE_V5); } else { EmbeddedResources::GetFileResource(query, EmbeddedResources::POSTGRESQL_PREPARE_V6); } connection_->Execute(query); // Execute the common initialization between versions 5 and 6 EmbeddedResources::GetFileResource(query, EmbeddedResources::POSTGRESQL_PREPARE); connection_->Execute(query); // Set the version of the database schema // The "1" corresponds to the "GlobalProperty_DatabaseSchemaVersion" enumeration connection_->Execute("INSERT INTO GlobalProperties VALUES (1, '" + boost::lexical_cast(expectedVersion) + "')"); } // Check the version of the database version_ = GetDatabaseVersion(); if (version_ != 5 && version_ != 6) { std::string message = ("Incompatible version of the Orthanc PostgreSQL database: " + boost::lexical_cast(version_)); throw PostgreSQLException(message); } t.Commit(); } PostgreSQLWrapper::~PostgreSQLWrapper() { globalProperties_.Unlock(); } void PostgreSQLWrapper::AddAttachment(int64_t id, const OrthancPluginAttachment& attachment) { if (attachFile_.get() == NULL) { attachFile_.reset (new PostgreSQLStatement (*connection_, "INSERT INTO AttachedFiles VALUES($1, $2, $3, $4, $5, $6, $7, $8)")); attachFile_->DeclareInputInteger64(0); attachFile_->DeclareInputInteger(1); attachFile_->DeclareInputString(2); attachFile_->DeclareInputInteger64(3); attachFile_->DeclareInputInteger64(4); attachFile_->DeclareInputInteger(5); attachFile_->DeclareInputString(6); attachFile_->DeclareInputString(7); } attachFile_->BindInteger64(0, id); attachFile_->BindInteger(1, attachment.contentType); attachFile_->BindString(2, attachment.uuid); attachFile_->BindInteger64(3, attachment.compressedSize); attachFile_->BindInteger64(4, attachment.uncompressedSize); attachFile_->BindInteger(5, attachment.compressionType); attachFile_->BindString(6, attachment.uncompressedHash); attachFile_->BindString(7, attachment.compressedHash); attachFile_->Run(); } void PostgreSQLWrapper::AttachChild(int64_t parent, int64_t child) { if (attachChild_.get() == NULL) { attachChild_.reset (new PostgreSQLStatement (*connection_, "UPDATE Resources SET parentId = $1 WHERE internalId = $2")); attachChild_->DeclareInputInteger64(0); attachChild_->DeclareInputInteger64(1); } attachChild_->BindInteger64(0, parent); attachChild_->BindInteger64(1, child); attachChild_->Run(); } void PostgreSQLWrapper::ClearTable(const std::string& tableName) { connection_->Execute("DELETE FROM " + tableName); } int64_t PostgreSQLWrapper::CreateResource(const char* publicId, OrthancPluginResourceType type) { if (createResource_.get() == NULL) { createResource_.reset (new PostgreSQLStatement (*connection_, "INSERT INTO Resources VALUES(DEFAULT, $1, $2, NULL) RETURNING internalId")); createResource_->DeclareInputInteger(0); createResource_->DeclareInputString(1); } createResource_->BindInteger(0, static_cast(type)); createResource_->BindString(1, publicId); PostgreSQLResult result(*createResource_); if (result.IsDone()) { throw PostgreSQLException(); } return result.GetInteger64(0); } void PostgreSQLWrapper::DeleteAttachment(int64_t id, int32_t attachment) { clearDeletedFiles_->Run(); clearDeletedResources_->Run(); if (deleteAttachment_.get() == NULL) { deleteAttachment_.reset (new PostgreSQLStatement (*connection_, "DELETE FROM AttachedFiles WHERE id=$1 AND fileType=$2")); deleteAttachment_->DeclareInputInteger64(0); deleteAttachment_->DeclareInputInteger(1); } deleteAttachment_->BindInteger64(0, id); deleteAttachment_->BindInteger(1, static_cast(attachment)); deleteAttachment_->Run(); SignalDeletedFilesAndResources(); } void PostgreSQLWrapper::DeleteMetadata(int64_t id, int32_t type) { if (deleteMetadata_.get() == NULL) { deleteMetadata_.reset (new PostgreSQLStatement (*connection_, "DELETE FROM Metadata WHERE id=$1 and type=$2")); deleteMetadata_->DeclareInputInteger64(0); deleteMetadata_->DeclareInputInteger(1); } deleteMetadata_->BindInteger64(0, id); deleteMetadata_->BindInteger(1, static_cast(type)); deleteMetadata_->Run(); } void PostgreSQLWrapper::DeleteResource(int64_t id) { if (clearRemainingAncestor_.get() == NULL || getRemainingAncestor_.get() == NULL) { clearRemainingAncestor_.reset (new PostgreSQLStatement (*connection_, "DELETE FROM RemainingAncestor")); getRemainingAncestor_.reset (new PostgreSQLStatement (*connection_, "SELECT * FROM RemainingAncestor")); } clearDeletedFiles_->Run(); clearDeletedResources_->Run(); clearRemainingAncestor_->Run(); if (deleteResource_.get() == NULL) { deleteResource_.reset (new PostgreSQLStatement (*connection_, "DELETE FROM Resources WHERE internalId=$1")); deleteResource_->DeclareInputInteger64(0); } deleteResource_->BindInteger64(0, id); deleteResource_->Run(); PostgreSQLResult result(*getRemainingAncestor_); if (!result.IsDone()) { GetOutput().SignalRemainingAncestor(result.GetString(1), static_cast(result.GetInteger(0))); // There is at most 1 remaining ancestor assert((result.Step(), result.IsDone())); } SignalDeletedFilesAndResources(); } void PostgreSQLWrapper::GetAllPublicIds(std::list& target, OrthancPluginResourceType resourceType) { if (getAllPublicIds_.get() == NULL) { getAllPublicIds_.reset (new PostgreSQLStatement(*connection_, "SELECT publicId FROM Resources WHERE resourceType=$1")); getAllPublicIds_->DeclareInputInteger(0); } getAllPublicIds_->BindInteger(0, static_cast(resourceType)); PostgreSQLResult result(*getAllPublicIds_); target.clear(); while (!result.IsDone()) { target.push_back(result.GetString(0)); result.Step(); } } void PostgreSQLWrapper::GetAllInternalIds(std::list& target, OrthancPluginResourceType resourceType) { if (getAllInternalIds_.get() == NULL) { getAllInternalIds_.reset (new PostgreSQLStatement(*connection_, "SELECT internalId FROM Resources WHERE resourceType=$1")); getAllInternalIds_->DeclareInputInteger(0); } getAllInternalIds_->BindInteger(0, static_cast(resourceType)); PostgreSQLResult result(*getAllInternalIds_); target.clear(); while (!result.IsDone()) { target.push_back(result.GetInteger64(0)); result.Step(); } } void PostgreSQLWrapper::GetAllPublicIds(std::list& target, OrthancPluginResourceType resourceType, uint64_t since, uint64_t limit) { if (getAllPublicIdsWithLimit_.get() == NULL) { getAllPublicIdsWithLimit_.reset (new PostgreSQLStatement(*connection_, "SELECT * FROM (SELECT publicId FROM Resources WHERE resourceType=$1) AS tmp ORDER BY tmp.publicId LIMIT $2 OFFSET $3")); getAllPublicIdsWithLimit_->DeclareInputInteger(0); getAllPublicIdsWithLimit_->DeclareInputInteger64(1); getAllPublicIdsWithLimit_->DeclareInputInteger64(2); } getAllPublicIdsWithLimit_->BindInteger(0, static_cast(resourceType)); getAllPublicIdsWithLimit_->BindInteger64(1, limit); getAllPublicIdsWithLimit_->BindInteger64(2, since); PostgreSQLResult result(*getAllPublicIdsWithLimit_); target.clear(); while (!result.IsDone()) { target.push_back(result.GetString(0)); result.Step(); } } void PostgreSQLWrapper::GetChangesInternal(bool& done, PostgreSQLStatement& s, uint32_t maxResults) { PostgreSQLResult result(s); uint32_t count = 0; while (count < maxResults && !result.IsDone()) { GetOutput().AnswerChange(result.GetInteger64(0), result.GetInteger(1), static_cast(result.GetInteger(3)), GetPublicId(result.GetInteger64(2)), result.GetString(4)); result.Step(); count++; } done = !(count == maxResults && !result.IsDone()); } void PostgreSQLWrapper::GetChanges(bool& done, int64_t since, uint32_t maxResults) { if (getChanges_.get() == NULL) { getChanges_.reset (new PostgreSQLStatement (*connection_, "SELECT * FROM Changes WHERE seq>$1 ORDER BY seq LIMIT $2")); getChanges_->DeclareInputInteger64(0); getChanges_->DeclareInputInteger(1); } getChanges_->BindInteger64(0, since); getChanges_->BindInteger(1, maxResults + 1); GetChangesInternal(done, *getChanges_, maxResults); } void PostgreSQLWrapper::GetLastChange() { if (getLastChange_.get() == NULL) { getLastChange_.reset (new PostgreSQLStatement (*connection_, "SELECT * FROM Changes ORDER BY seq DESC LIMIT 1")); } bool done; // Ignored GetChangesInternal(done, *getLastChange_, 1); } void PostgreSQLWrapper::GetChildrenInternalId(std::list& target, int64_t id) { if (getChildrenInternalId_.get() == NULL) { getChildrenInternalId_.reset (new PostgreSQLStatement(*connection_, "SELECT a.internalId FROM Resources AS a, Resources AS b " "WHERE a.parentId = b.internalId AND b.internalId = $1")); getChildrenInternalId_->DeclareInputInteger64(0); } getChildrenInternalId_->BindInteger64(0, id); PostgreSQLResult result(*getChildrenInternalId_); target.clear(); while (!result.IsDone()) { target.push_back(result.GetInteger64(0)); result.Step(); } } void PostgreSQLWrapper::GetChildrenPublicId(std::list& target, int64_t id) { if (getChildrenPublicId_.get() == NULL) { getChildrenPublicId_.reset (new PostgreSQLStatement(*connection_, "SELECT a.publicId FROM Resources AS a, Resources AS b " "WHERE a.parentId = b.internalId AND b.internalId = $1")); getChildrenPublicId_->DeclareInputInteger64(0); } getChildrenPublicId_->BindInteger64(0, id); PostgreSQLResult result(*getChildrenPublicId_); target.clear(); while (!result.IsDone()) { target.push_back(result.GetString(0)); result.Step(); } } void PostgreSQLWrapper::GetExportedResourcesInternal(bool& done, PostgreSQLStatement& s, uint32_t maxResults) { PostgreSQLResult result(s); uint32_t count = 0; while (count < maxResults && !result.IsDone()) { int64_t seq = result.GetInteger64(0); OrthancPluginResourceType resourceType = static_cast(result.GetInteger(1)); std::string publicId = result.GetString(2); GetOutput().AnswerExportedResource(seq, resourceType, publicId, result.GetString(3), // modality result.GetString(8), // date result.GetString(4), // patient ID result.GetString(5), // study instance UID result.GetString(6), // series instance UID result.GetString(7)); // sop instance UID result.Step(); count++; } done = !(count == maxResults && !result.IsDone()); } void PostgreSQLWrapper::GetExportedResources(bool& done, int64_t since, uint32_t maxResults) { if (getExports_.get() == NULL) { getExports_.reset (new PostgreSQLStatement (*connection_, "SELECT * FROM ExportedResources WHERE seq>$1 ORDER BY seq LIMIT $2")); getExports_->DeclareInputInteger64(0); getExports_->DeclareInputInteger(1); } getExports_->BindInteger64(0, since); getExports_->BindInteger(1, maxResults + 1); GetExportedResourcesInternal(done, *getExports_, maxResults); } void PostgreSQLWrapper::GetLastExportedResource() { if (getLastExport_.get() == NULL) { getLastExport_.reset (new PostgreSQLStatement (*connection_, "SELECT * FROM ExportedResources ORDER BY seq DESC LIMIT 1")); } bool done; // Ignored GetExportedResourcesInternal(done, *getLastExport_, 1); } void PostgreSQLWrapper::GetMainDicomTags(int64_t id) { if (getMainDicomTags1_.get() == NULL || getMainDicomTags2_.get() == NULL) { getMainDicomTags1_.reset (new PostgreSQLStatement (*connection_, "SELECT * FROM MainDicomTags WHERE id=$1")); getMainDicomTags1_->DeclareInputInteger64(0); getMainDicomTags2_.reset (new PostgreSQLStatement (*connection_, "SELECT * FROM DicomIdentifiers WHERE id=$1")); getMainDicomTags2_->DeclareInputInteger64(0); } { getMainDicomTags1_->BindInteger64(0, id); PostgreSQLResult result(*getMainDicomTags1_); while (!result.IsDone()) { GetOutput().AnswerDicomTag(static_cast(result.GetInteger(1)), static_cast(result.GetInteger(2)), result.GetString(3)); result.Step(); } } if (version_ == 5) { getMainDicomTags2_->BindInteger64(0, id); PostgreSQLResult result(*getMainDicomTags2_); while (!result.IsDone()) { GetOutput().AnswerDicomTag(static_cast(result.GetInteger(1)), static_cast(result.GetInteger(2)), result.GetString(3)); result.Step(); } } } std::string PostgreSQLWrapper::GetPublicId(int64_t resourceId) { getPublicId_->BindInteger64(0, resourceId); PostgreSQLResult result(*getPublicId_); if (result.IsDone()) { throw PostgreSQLException("Unknown resource"); } return result.GetString(0); } uint64_t PostgreSQLWrapper::GetResourceCount(OrthancPluginResourceType resourceType) { if (getResourceCount_.get() == NULL) { getResourceCount_.reset (new PostgreSQLStatement (*connection_, "SELECT CAST(COUNT(*) AS BIGINT) FROM Resources WHERE resourceType=$1")); getResourceCount_->DeclareInputInteger(0); } getResourceCount_->BindInteger(0, static_cast(resourceType)); PostgreSQLResult result(*getResourceCount_); if (result.IsDone()) { throw PostgreSQLException(); } if (result.IsNull(0)) { return 0; } else { return result.GetInteger64(0); } } OrthancPluginResourceType PostgreSQLWrapper::GetResourceType(int64_t resourceId) { if (getResourceType_.get() == NULL) { getResourceType_.reset (new PostgreSQLStatement (*connection_, "SELECT resourceType FROM Resources WHERE internalId=$1")); getResourceType_->DeclareInputInteger64(0); } getResourceType_->BindInteger64(0, resourceId); PostgreSQLResult result(*getResourceType_); if (result.IsDone()) { throw PostgreSQLException("Unknown resource"); } return static_cast(result.GetInteger(0)); } uint64_t PostgreSQLWrapper::GetTotalCompressedSize() { if (getTotalCompressedSize_.get() == NULL) { getTotalCompressedSize_.reset (new PostgreSQLStatement (*connection_, "SELECT CAST(SUM(compressedSize) AS BIGINT) FROM AttachedFiles")); } PostgreSQLResult result(*getTotalCompressedSize_); if (result.IsDone()) { throw PostgreSQLException(); } if (result.IsNull(0)) { return 0; } else { return result.GetInteger64(0); } } uint64_t PostgreSQLWrapper::GetTotalUncompressedSize() { if (getTotalUncompressedSize_.get() == NULL) { getTotalUncompressedSize_.reset (new PostgreSQLStatement (*connection_, "SELECT CAST(SUM(uncompressedSize) AS BIGINT) FROM AttachedFiles")); } PostgreSQLResult result(*getTotalUncompressedSize_); if (result.IsDone()) { throw PostgreSQLException(); } if (result.IsNull(0)) { return 0; } else { return result.GetInteger64(0); } } bool PostgreSQLWrapper::IsExistingResource(int64_t internalId) { getPublicId_->BindInteger64(0, internalId); PostgreSQLResult result(*getPublicId_); return !result.IsDone(); } bool PostgreSQLWrapper::IsProtectedPatient(int64_t internalId) { if (isProtectedPatient_.get() == NULL) { isProtectedPatient_.reset (new PostgreSQLStatement (*connection_, "SELECT * FROM PatientRecyclingOrder WHERE patientId = $1")); isProtectedPatient_->DeclareInputInteger64(0); } isProtectedPatient_->BindInteger64(0, internalId); PostgreSQLResult result(*isProtectedPatient_); return result.IsDone(); } void PostgreSQLWrapper::ListAvailableMetadata(std::list& target, int64_t id) { if (listMetadata_.get() == NULL) { listMetadata_.reset (new PostgreSQLStatement (*connection_, "SELECT type FROM Metadata WHERE id=$1")); listMetadata_->DeclareInputInteger64(0); } listMetadata_->BindInteger64(0, id); PostgreSQLResult result(*listMetadata_); target.clear(); while (!result.IsDone()) { target.push_back(static_cast(result.GetInteger(0))); result.Step(); } } void PostgreSQLWrapper::ListAvailableAttachments(std::list& target, int64_t id) { if (listAttachments_.get() == NULL) { listAttachments_.reset (new PostgreSQLStatement (*connection_, "SELECT fileType FROM AttachedFiles WHERE id=$1")); listAttachments_->DeclareInputInteger64(0); } listAttachments_->BindInteger64(0, id); PostgreSQLResult result(*listAttachments_); target.clear(); while (!result.IsDone()) { target.push_back(static_cast(result.GetInteger(0))); result.Step(); } } void PostgreSQLWrapper::LogChange(const OrthancPluginChange& change) { if (logChange_.get() == NULL) { logChange_.reset (new PostgreSQLStatement (*connection_, "INSERT INTO Changes VALUES(DEFAULT, $1, $2, $3, $4)")); logChange_->DeclareInputInteger(0); logChange_->DeclareInputInteger64(1); logChange_->DeclareInputInteger(2); logChange_->DeclareInputString(3); } int64_t id; OrthancPluginResourceType type; if (!LookupResource(id, type, change.publicId) || type != change.resourceType) { throw PostgreSQLException(); } logChange_->BindInteger(0, change.changeType); logChange_->BindInteger64(1, id); logChange_->BindInteger(2, change.resourceType); logChange_->BindString(3, change.date); logChange_->Run(); } void PostgreSQLWrapper::LogExportedResource(const OrthancPluginExportedResource& resource) { if (logExport_.get() == NULL) { logExport_.reset (new PostgreSQLStatement (*connection_, "INSERT INTO ExportedResources VALUES(DEFAULT, $1, $2, $3, $4, $5, $6, $7, $8)")); logExport_->DeclareInputInteger(0); logExport_->DeclareInputString(1); logExport_->DeclareInputString(2); logExport_->DeclareInputString(3); logExport_->DeclareInputString(4); logExport_->DeclareInputString(5); logExport_->DeclareInputString(6); logExport_->DeclareInputString(7); } logExport_->BindInteger(0, resource.resourceType); logExport_->BindString(1, resource.publicId); logExport_->BindString(2, resource.modality); logExport_->BindString(3, resource.patientId); logExport_->BindString(4, resource.studyInstanceUid); logExport_->BindString(5, resource.seriesInstanceUid); logExport_->BindString(6, resource.sopInstanceUid); logExport_->BindString(7, resource.date); logExport_->Run(); } bool PostgreSQLWrapper::LookupAttachment(int64_t id, int32_t contentType) { if (lookupAttachment_.get() == NULL) { lookupAttachment_.reset (new PostgreSQLStatement (*connection_, "SELECT uuid, uncompressedSize, compressionType, compressedSize, " "uncompressedHash, compressedHash FROM AttachedFiles WHERE id=$1 AND fileType=$2")); lookupAttachment_->DeclareInputInteger64(0); lookupAttachment_->DeclareInputInteger(1); } lookupAttachment_->BindInteger64(0, id); lookupAttachment_->BindInteger(1, static_cast(contentType)); PostgreSQLResult result(*lookupAttachment_); if (!result.IsDone()) { GetOutput().AnswerAttachment(result.GetString(0), contentType, result.GetInteger64(1), result.GetString(4), result.GetInteger(2), result.GetInteger64(3), result.GetString(5)); return true; } else { return false; } } // Used only if Orthanc <= 0.9.4 void PostgreSQLWrapper::LookupIdentifier(std::list& target, uint16_t group, uint16_t element, const char* value) { if (lookupIdentifier1_.get() == NULL) { lookupIdentifier1_.reset (new PostgreSQLStatement (*connection_, "SELECT id FROM DicomIdentifiers WHERE tagGroup=$1 AND tagElement=$2 and value=$3")); lookupIdentifier1_->DeclareInputInteger(0); lookupIdentifier1_->DeclareInputInteger(1); if (version_ == 5) { lookupIdentifier1_->DeclareInputBinary(2); } else { lookupIdentifier1_->DeclareInputString(2); } } lookupIdentifier1_->BindInteger(0, group); lookupIdentifier1_->BindInteger(1, element); lookupIdentifier1_->BindString(2, value); PostgreSQLResult result(*lookupIdentifier1_); target.clear(); while (!result.IsDone()) { target.push_back(result.GetInteger64(0)); result.Step(); } } // Used only if Orthanc <= 0.9.4 void PostgreSQLWrapper::LookupIdentifier(std::list& target, const char* value) { if (lookupIdentifier2_.get() == NULL) { lookupIdentifier2_.reset (new PostgreSQLStatement (*connection_, "SELECT id FROM DicomIdentifiers WHERE value=$1")); if (version_ == 5) { lookupIdentifier2_->DeclareInputBinary(0); } else { lookupIdentifier2_->DeclareInputString(0); } } lookupIdentifier2_->BindString(0, value); PostgreSQLResult result(*lookupIdentifier2_); target.clear(); while (!result.IsDone()) { target.push_back(result.GetInteger64(0)); result.Step(); } } #if !(ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER <= 0 && ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER <= 9 && ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER <= 4) static std::string ConvertWildcardToLike(const std::string& query) { std::string s = query; for (size_t i = 0; i < s.size(); i++) { if (s[i] == '*') { s[i] = '%'; } else if (s[i] == '?') { s[i] = '_'; } } return s; } // Used only if Orthanc >= 0.9.5 void PostgreSQLWrapper::LookupIdentifier(std::list& target, OrthancPluginResourceType level, uint16_t group, uint16_t element, OrthancPluginIdentifierConstraint constraint, const char* value) { if (lookupIdentifierEQ_.get() == NULL) { lookupIdentifierEQ_.reset (new PostgreSQLStatement (*connection_, "SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE " "d.id = r.internalId AND r.resourceType=$1 AND d.tagGroup=$2 AND d.tagElement=$3 AND d.value=$4")); lookupIdentifierEQ_->DeclareInputInteger(0); lookupIdentifierEQ_->DeclareInputInteger(1); lookupIdentifierEQ_->DeclareInputInteger(2); lookupIdentifierEQ_->DeclareInputString(3); } if (lookupIdentifierLE_.get() == NULL) { lookupIdentifierLE_.reset (new PostgreSQLStatement (*connection_, "SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE " "d.id = r.internalId AND r.resourceType=$1 AND d.tagGroup=$2 AND d.tagElement=$3 AND d.value<=$4")); lookupIdentifierLE_->DeclareInputInteger(0); lookupIdentifierLE_->DeclareInputInteger(1); lookupIdentifierLE_->DeclareInputInteger(2); lookupIdentifierLE_->DeclareInputString(3); } if (lookupIdentifierGE_.get() == NULL) { lookupIdentifierGE_.reset (new PostgreSQLStatement (*connection_, "SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE " "d.id = r.internalId AND r.resourceType=$1 AND d.tagGroup=$2 AND d.tagElement=$3 AND d.value>=$4")); lookupIdentifierGE_->DeclareInputInteger(0); lookupIdentifierGE_->DeclareInputInteger(1); lookupIdentifierGE_->DeclareInputInteger(2); lookupIdentifierGE_->DeclareInputString(3); } if (lookupIdentifierWildcard_.get() == NULL) { lookupIdentifierWildcard_.reset (new PostgreSQLStatement (*connection_, "SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE " "d.id = r.internalId AND r.resourceType=$1 AND d.tagGroup=$2 AND d.tagElement=$3 AND d.value LIKE $4")); lookupIdentifierWildcard_->DeclareInputInteger(0); lookupIdentifierWildcard_->DeclareInputInteger(1); lookupIdentifierWildcard_->DeclareInputInteger(2); lookupIdentifierWildcard_->DeclareInputString(3); } PostgreSQLStatement* statement = NULL; switch (constraint) { case OrthancPluginIdentifierConstraint_Equal: statement = lookupIdentifierEQ_.get(); break; case OrthancPluginIdentifierConstraint_SmallerOrEqual: statement = lookupIdentifierLE_.get(); break; case OrthancPluginIdentifierConstraint_GreaterOrEqual: statement = lookupIdentifierGE_.get(); break; case OrthancPluginIdentifierConstraint_Wildcard: statement = lookupIdentifierWildcard_.get(); break; default: throw PostgreSQLException(); } assert(statement != NULL); statement->BindInteger(0, level); statement->BindInteger(1, group); statement->BindInteger(2, element); if (constraint == OrthancPluginIdentifierConstraint_Wildcard) { statement->BindString(3, ConvertWildcardToLike(value)); } else { statement->BindString(3, value); } PostgreSQLResult result(*statement); target.clear(); while (!result.IsDone()) { target.push_back(result.GetInteger64(0)); result.Step(); } } #endif bool PostgreSQLWrapper::LookupMetadata(std::string& target, int64_t id, int32_t type) { if (lookupMetadata_.get() == NULL) { lookupMetadata_.reset (new PostgreSQLStatement (*connection_, "SELECT value FROM Metadata WHERE id=$1 and type=$2")); lookupMetadata_->DeclareInputInteger64(0); lookupMetadata_->DeclareInputInteger(1); } lookupMetadata_->BindInteger64(0, id); lookupMetadata_->BindInteger(1, static_cast(type)); PostgreSQLResult result(*lookupMetadata_); if (result.IsDone()) { return false; } else { target = result.GetString(0); return true; } } bool PostgreSQLWrapper::LookupParent(int64_t& parentId, int64_t resourceId) { if (lookupParent_.get() == NULL) { lookupParent_.reset (new PostgreSQLStatement (*connection_, "SELECT parentId FROM Resources WHERE internalId=$1")); lookupParent_->DeclareInputInteger64(0); } lookupParent_->BindInteger64(0, resourceId); PostgreSQLResult result(*lookupParent_); if (result.IsDone()) { throw PostgreSQLException("Unknown resource"); } if (result.IsNull(0)) { return false; } else { parentId = result.GetInteger64(0); return true; } } bool PostgreSQLWrapper::LookupResource(int64_t& id, OrthancPluginResourceType& type, const char* publicId) { if (lookupResource_.get() == NULL) { lookupResource_.reset (new PostgreSQLStatement (*connection_, "SELECT internalId, resourceType FROM Resources WHERE publicId=$1")); lookupResource_->DeclareInputString(0); } lookupResource_->BindString(0, publicId); PostgreSQLResult result(*lookupResource_); if (result.IsDone()) { return false; } else { id = result.GetInteger64(0); type = static_cast(result.GetInteger(1)); return true; } } bool PostgreSQLWrapper::SelectPatientToRecycle(int64_t& internalId) { if (selectPatientToRecycle_.get() == NULL) { selectPatientToRecycle_.reset (new PostgreSQLStatement (*connection_, "SELECT patientId FROM PatientRecyclingOrder ORDER BY seq ASC LIMIT 1")); } PostgreSQLResult result(*selectPatientToRecycle_); if (result.IsDone()) { // No patient remaining or all the patients are protected return false; } else { internalId = result.GetInteger64(0); return true; } } bool PostgreSQLWrapper::SelectPatientToRecycle(int64_t& internalId, int64_t patientIdToAvoid) { if (selectPatientToRecycleAvoid_.get() == NULL) { selectPatientToRecycleAvoid_.reset (new PostgreSQLStatement (*connection_, "SELECT patientId FROM PatientRecyclingOrder WHERE patientId != $1 ORDER BY seq ASC LIMIT 1")); selectPatientToRecycleAvoid_->DeclareInputInteger64(0); } selectPatientToRecycleAvoid_->BindInteger64(0, patientIdToAvoid); PostgreSQLResult result(*selectPatientToRecycleAvoid_); if (result.IsDone()) { // No patient remaining or all the patients are protected return false; } else { internalId = result.GetInteger64(0); return true; } } static void SetTagInternal(PostgreSQLStatement& s, int64_t id, uint16_t group, uint16_t element, const char* value) { s.BindInteger64(0, id); s.BindInteger(1, group); s.BindInteger(2, element); s.BindString(3, value); s.Run(); } void PostgreSQLWrapper::SetMainDicomTag(int64_t id, uint16_t group, uint16_t element, const char* value) { if (setMainDicomTags_.get() == NULL) { setMainDicomTags_.reset (new PostgreSQLStatement (*connection_, "INSERT INTO MainDicomTags VALUES($1, $2, $3, $4)")); setMainDicomTags_->DeclareInputInteger64(0); setMainDicomTags_->DeclareInputInteger(1); setMainDicomTags_->DeclareInputInteger(2); if (version_ == 5) { setMainDicomTags_->DeclareInputBinary(3); } else { setMainDicomTags_->DeclareInputString(3); } } SetTagInternal(*setMainDicomTags_, id, group, element, value); } void PostgreSQLWrapper::SetIdentifierTag(int64_t id, uint16_t group, uint16_t element, const char* value) { if (setIdentifierTag_.get() == NULL) { setIdentifierTag_.reset (new PostgreSQLStatement (*connection_, "INSERT INTO DicomIdentifiers VALUES($1, $2, $3, $4)")); setIdentifierTag_->DeclareInputInteger64(0); setIdentifierTag_->DeclareInputInteger(1); setIdentifierTag_->DeclareInputInteger(2); if (version_ == 5) { setIdentifierTag_->DeclareInputBinary(3); } else { setIdentifierTag_->DeclareInputString(3); } } SetTagInternal(*setIdentifierTag_, id, group, element, value); } void PostgreSQLWrapper::SetMetadata(int64_t id, int32_t type, const char* value) { if (setMetadata1_.get() == NULL || setMetadata2_.get() == NULL) { setMetadata1_.reset (new PostgreSQLStatement (*connection_, "DELETE FROM Metadata WHERE id=$1 AND type=$2")); setMetadata1_->DeclareInputInteger64(0); setMetadata1_->DeclareInputInteger(1); setMetadata2_.reset (new PostgreSQLStatement (*connection_, "INSERT INTO Metadata VALUES ($1, $2, $3)")); setMetadata2_->DeclareInputInteger64(0); setMetadata2_->DeclareInputInteger(1); setMetadata2_->DeclareInputString(2); } setMetadata1_->BindInteger64(0, id); setMetadata1_->BindInteger(1, static_cast(type)); setMetadata1_->Run(); setMetadata2_->BindInteger64(0, id); setMetadata2_->BindInteger(1, static_cast(type)); setMetadata2_->BindString(2, value); setMetadata2_->Run(); } void PostgreSQLWrapper::SetProtectedPatient(int64_t internalId, bool isProtected) { if (protectPatient1_.get() == NULL || protectPatient2_.get() == NULL) { protectPatient1_.reset (new PostgreSQLStatement (*connection_, "DELETE FROM PatientRecyclingOrder WHERE patientId=$1")); protectPatient1_->DeclareInputInteger64(0); protectPatient2_.reset (new PostgreSQLStatement (*connection_, "INSERT INTO PatientRecyclingOrder VALUES(DEFAULT, $1)")); protectPatient2_->DeclareInputInteger64(0); } if (isProtected) { protectPatient1_->BindInteger64(0, internalId); protectPatient1_->Run(); } else if (IsProtectedPatient(internalId)) { protectPatient2_->BindInteger64(0, internalId); protectPatient2_->Run(); } else { // Nothing to do: The patient is already unprotected } } // For unit testing only! void PostgreSQLWrapper::GetChildren(std::list& childrenPublicIds, int64_t id) { PostgreSQLStatement s(*connection_, "SELECT publicId FROM Resources WHERE parentId=$1"); s.DeclareInputInteger64(0); s.BindInteger64(0, id); PostgreSQLResult result(s); childrenPublicIds.clear(); while (!result.IsDone()) { childrenPublicIds.push_back(result.GetString(0)); result.Step(); } } // For unit testing only! int64_t PostgreSQLWrapper::GetTableRecordCount(const std::string& table) { char buf[128]; sprintf(buf, "SELECT CAST(COUNT(*) AS BIGINT) FROM %s", table.c_str()); PostgreSQLStatement s(*connection_, buf); PostgreSQLResult result(s); if (result.IsDone()) { throw PostgreSQLException(); } if (result.IsNull(0)) { return 0; } else { return result.GetInteger64(0); } } // For unit testing only! bool PostgreSQLWrapper::GetParentPublicId(std::string& target, int64_t id) { PostgreSQLStatement s(*connection_, "SELECT a.publicId FROM Resources AS a, Resources AS b " "WHERE a.internalId = b.parentId AND b.internalId = $1"); s.DeclareInputInteger64(0); s.BindInteger64(0, id); PostgreSQLResult result(s); if (result.IsDone()) { return false; } else { target = result.GetString(0); return true; } } uint32_t PostgreSQLWrapper::GetDatabaseVersion() { // Check the version of the database std::string version = "unknown"; if (!LookupGlobalProperty(version, GlobalProperty_DatabaseSchemaVersion)) { throw PostgreSQLException("The database is corrupted. Drop it manually for Orthanc to recreate it"); } try { return boost::lexical_cast(version); } catch (boost::bad_lexical_cast&) { throw PostgreSQLException("The database is corrupted. Drop it manually for Orthanc to recreate it"); } } void PostgreSQLWrapper::UpgradeDatabase(uint32_t targetVersion, OrthancPluginStorageArea* storageArea) { unsigned int version = GetDatabaseVersion(); #if !(ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER <= 0 && ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER <= 9 && ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER <= 4) if (version == 5 && targetVersion == 6) { version_ = 6; // Must be here, otherwise calls to // SetMainDicomTag() during the reconstruction of // the DICOM tags will fail as the column type // has been altered connection_->Execute("ALTER TABLE MainDicomTags ALTER COLUMN value TYPE TEXT"); connection_->Execute("ALTER TABLE DicomIdentifiers ALTER COLUMN value TYPE TEXT"); OrthancPluginReconstructMainDicomTags(context_, storageArea, OrthancPluginResourceType_Patient); OrthancPluginReconstructMainDicomTags(context_, storageArea, OrthancPluginResourceType_Study); OrthancPluginReconstructMainDicomTags(context_, storageArea, OrthancPluginResourceType_Series); OrthancPluginReconstructMainDicomTags(context_, storageArea, OrthancPluginResourceType_Instance); connection_->Execute("DELETE FROM GlobalProperties WHERE property=1"); connection_->Execute("INSERT INTO GlobalProperties VALUES (1, '6');"); return; // Success } #endif std::string message = ("Unsupported call to upgrade from version " + boost::lexical_cast(version) + " to version " + boost::lexical_cast(targetVersion) + " of the database schema"); throw PostgreSQLException(message.c_str()); } void PostgreSQLWrapper::ClearMainDicomTags(int64_t id) { if (clearMainDicomTags_.get() == NULL || clearDicomIdentifiers_.get() == NULL) { clearMainDicomTags_.reset (new PostgreSQLStatement (*connection_, "DELETE FROM MainDicomTags WHERE id=$1")); clearMainDicomTags_->DeclareInputInteger64(0); clearDicomIdentifiers_.reset (new PostgreSQLStatement (*connection_, "DELETE FROM DicomIdentifiers WHERE id=$1")); clearDicomIdentifiers_->DeclareInputInteger64(0); } clearMainDicomTags_->BindInteger64(0, id); clearMainDicomTags_->Run(); clearDicomIdentifiers_->BindInteger64(0, id); clearDicomIdentifiers_->Run(); } } OrthancPostgreSQL-2.0/IndexPlugin/PostgreSQLWrapper.h0000644000000000000000000002730412627602430020776 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #pragma once #include #include "../Core/GlobalProperties.h" #include "../Core/PostgreSQLConnection.h" #include "../Core/PostgreSQLStatement.h" #include "../Core/PostgreSQLResult.h" #include "../Core/PostgreSQLTransaction.h" #include namespace OrthancPlugins { class PostgreSQLWrapper : public IDatabaseBackend { private: OrthancPluginContext* context_; uint32_t version_; std::auto_ptr connection_; std::auto_ptr transaction_; GlobalProperties globalProperties_; std::auto_ptr attachFile_; std::auto_ptr attachChild_; std::auto_ptr createResource_; std::auto_ptr deleteAttachment_; std::auto_ptr deleteMetadata_; std::auto_ptr deleteResource_; std::auto_ptr getAllMetadata_; std::auto_ptr getAllInternalIds_; std::auto_ptr getAllPublicIds_; std::auto_ptr getAllPublicIdsWithLimit_; std::auto_ptr getChanges_; std::auto_ptr getLastChange_; std::auto_ptr getChildrenInternalId_; std::auto_ptr getChildrenPublicId_; std::auto_ptr getExports_; std::auto_ptr getLastExport_; std::auto_ptr getMainDicomTags1_; std::auto_ptr getMainDicomTags2_; std::auto_ptr getPublicId_; std::auto_ptr getResourceCount_; std::auto_ptr getResourceType_; std::auto_ptr getTotalCompressedSize_; std::auto_ptr getTotalUncompressedSize_; std::auto_ptr isProtectedPatient_; std::auto_ptr listMetadata_; std::auto_ptr listAttachments_; std::auto_ptr logChange_; std::auto_ptr logExport_; std::auto_ptr lookupAttachment_; std::auto_ptr lookupIdentifier1_; std::auto_ptr lookupIdentifier2_; std::auto_ptr lookupIdentifierEQ_; // New in Orthanc 0.9.5 std::auto_ptr lookupIdentifierLE_; // New in Orthanc 0.9.5 std::auto_ptr lookupIdentifierGE_; // New in Orthanc 0.9.5 std::auto_ptr lookupIdentifierWildcard_; // New in Orthanc 0.9.5 std::auto_ptr lookupMetadata_; std::auto_ptr lookupParent_; std::auto_ptr lookupResource_; std::auto_ptr selectPatientToRecycle_; std::auto_ptr selectPatientToRecycleAvoid_; std::auto_ptr setMainDicomTags_; std::auto_ptr setIdentifierTag_; std::auto_ptr setMetadata1_; std::auto_ptr setMetadata2_; std::auto_ptr protectPatient1_; std::auto_ptr protectPatient2_; std::auto_ptr clearDeletedFiles_; std::auto_ptr clearDeletedResources_; std::auto_ptr clearRemainingAncestor_; std::auto_ptr clearMainDicomTags_; std::auto_ptr clearDicomIdentifiers_; std::auto_ptr getDeletedFiles_; std::auto_ptr getDeletedResources_; std::auto_ptr getRemainingAncestor_; void Prepare(); void SignalDeletedFilesAndResources(); void GetChangesInternal(bool& done, PostgreSQLStatement& s, uint32_t maxResults); void GetExportedResourcesInternal(bool& done, PostgreSQLStatement& s, uint32_t maxResults); void ClearTable(const std::string& tableName); public: PostgreSQLWrapper(OrthancPluginContext* context, PostgreSQLConnection* connection, // Takes the ownership of the connection bool useLock, bool allowUnlock); virtual ~PostgreSQLWrapper(); virtual void Open() { connection_->Open(); } virtual void Close() { transaction_.reset(NULL); } virtual void AddAttachment(int64_t id, const OrthancPluginAttachment& attachment); virtual void AttachChild(int64_t parent, int64_t child); virtual void ClearChanges() { ClearTable("Changes"); } virtual void ClearExportedResources() { ClearTable("ExportedResources"); } virtual int64_t CreateResource(const char* publicId, OrthancPluginResourceType type); virtual void DeleteAttachment(int64_t id, int32_t attachment); virtual void DeleteMetadata(int64_t id, int32_t type); virtual void DeleteResource(int64_t id); virtual void GetAllInternalIds(std::list& target, OrthancPluginResourceType resourceType); virtual void GetAllPublicIds(std::list& target, OrthancPluginResourceType resourceType); virtual void GetAllPublicIds(std::list& target, OrthancPluginResourceType resourceType, uint64_t since, uint64_t limit); virtual void GetChanges(bool& done /*out*/, int64_t since, uint32_t maxResults); virtual void GetChildrenInternalId(std::list& result, int64_t id); virtual void GetChildrenPublicId(std::list& result, int64_t id); virtual void GetExportedResources(bool& done /*out*/, int64_t since, uint32_t maxResults); virtual void GetLastChange(); virtual void GetLastExportedResource(); virtual void GetMainDicomTags(int64_t id); virtual std::string GetPublicId(int64_t resourceId); virtual uint64_t GetResourceCount(OrthancPluginResourceType resourceType); virtual OrthancPluginResourceType GetResourceType(int64_t resourceId); virtual uint64_t GetTotalCompressedSize(); virtual uint64_t GetTotalUncompressedSize(); virtual bool IsExistingResource(int64_t internalId); virtual bool IsProtectedPatient(int64_t internalId); virtual void ListAvailableMetadata(std::list& target, int64_t id); virtual void ListAvailableAttachments(std::list& result, int64_t id); virtual void LogChange(const OrthancPluginChange& change); virtual void LogExportedResource(const OrthancPluginExportedResource& resource); virtual bool LookupAttachment(int64_t id, int32_t contentType); virtual bool LookupGlobalProperty(std::string& target, int32_t property) { return globalProperties_.LookupGlobalProperty(target, property); } // Used only if Orthanc <= 0.9.4 virtual void LookupIdentifier(std::list& result, uint16_t group, uint16_t element, const char* value); // Used only if Orthanc <= 0.9.4 virtual void LookupIdentifier(std::list& result, const char* value); #if !(ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER <= 0 && ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER <= 9 && ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER <= 4) // Used only if Orthanc >= 0.9.5 virtual void LookupIdentifier(std::list& result, OrthancPluginResourceType level, uint16_t group, uint16_t element, OrthancPluginIdentifierConstraint constraint, const char* value); #endif virtual bool LookupMetadata(std::string& target, int64_t id, int32_t type); virtual bool LookupParent(int64_t& parentId, int64_t resourceId); virtual bool LookupResource(int64_t& id /*out*/, OrthancPluginResourceType& type /*out*/, const char* publicId); virtual bool SelectPatientToRecycle(int64_t& internalId); virtual bool SelectPatientToRecycle(int64_t& internalId, int64_t patientIdToAvoid); virtual void SetGlobalProperty(int32_t property, const char* value) { return globalProperties_.SetGlobalProperty(property, value); } virtual void SetMainDicomTag(int64_t id, uint16_t group, uint16_t element, const char* value); virtual void SetIdentifierTag(int64_t id, uint16_t group, uint16_t element, const char* value); virtual void SetMetadata(int64_t id, int32_t type, const char* value); virtual void SetProtectedPatient(int64_t internalId, bool isProtected); virtual void StartTransaction() { transaction_.reset(new PostgreSQLTransaction(*connection_)); } virtual void RollbackTransaction() { transaction_.reset(NULL); } virtual void CommitTransaction() { transaction_->Commit(); transaction_.reset(NULL); } // For unit tests only! void GetChildren(std::list& childrenPublicIds, int64_t id); // For unit tests only! int64_t GetTableRecordCount(const std::string& table); // For unit tests only! bool GetParentPublicId(std::string& result, int64_t id); virtual uint32_t GetDatabaseVersion(); // Used only if Orthanc >= 0.9.5 virtual void UpgradeDatabase(uint32_t targetVersion, OrthancPluginStorageArea* storageArea); // Used only if Orthanc >= 0.9.5 virtual void ClearMainDicomTags(int64_t id); }; } OrthancPostgreSQL-2.0/NEWS0000644000000000000000000000245612627602430013533 0ustar 00000000000000Pending changes in the mainline =============================== Release 2.0 (2015/12/02) ======================== => Minimum SDK version: 0.9.5 <= => Supported database versions: 5 (upgrade only) and 6 <= * Support version 6 of the database schema * The "value" column of tables "MainDicomTags" and "DicomIdentifiers" are now TEXT instead of BYTEA Release 1.3 (2015/10/07) ======================== => Minimum SDK version: 0.9.4 <= => Supported database versions: 5 <= * Fix build with Orthanc plugin SDK 0.9.4 * Implementation of "GetAllPublicIdsWithLimit" extension * Implementation of "UpgradeDatabase" extension Release 1.2 (2015/08/02) ======================== => Minimum SDK version: 0.9.1 <= * Inject version information into Windows binaries * CMake flag to prevent compiling the unit tests (if no PostgreSQL test server is available) * Update to Boost 1.58.0 for static and Windows builds * Support of OS X compilation Release 1.1 (2015/07/03) ======================== * Fixes * Support of Visual Studio 2008 * Support of FreeBSD thanks Mikhail Release 1.0 (2015/02/27) ======================== * Use of advisory locks * Support of connection URI in PostgreSQL * Options "EnableIndex" and "EnableStorage" to explicitly enable PostgreSQL 2015/02/06 ========== * Initial release OrthancPostgreSQL-2.0/Orthanc/Plugins/Samples/Common/ExportedSymbols.list0000644000000000000000000000030012627602430024731 0ustar 00000000000000# This is the list of the symbols that must be exported by Orthanc # plugins, if targeting OS X _OrthancPluginInitialize _OrthancPluginFinalize _OrthancPluginGetName _OrthancPluginGetVersion OrthancPostgreSQL-2.0/Orthanc/Plugins/Samples/Common/VersionScript.map0000644000000000000000000000026112627602430024210 0ustar 00000000000000# This is a version-script for Orthanc plugins { global: OrthancPluginInitialize; OrthancPluginFinalize; OrthancPluginGetName; OrthancPluginGetVersion; local: *; }; OrthancPostgreSQL-2.0/Orthanc/README.txt0000644000000000000000000000007712627602430016125 0ustar 00000000000000This folder contains an excerpt of the source code of Orthanc. OrthancPostgreSQL-2.0/Orthanc/Resources/CMake/AutoGeneratedCode.cmake0000644000000000000000000000274312627602430023707 0ustar 00000000000000set(AUTOGENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/AUTOGENERATED") set(AUTOGENERATED_SOURCES) file(MAKE_DIRECTORY ${AUTOGENERATED_DIR}) include_directories(${AUTOGENERATED_DIR}) macro(EmbedResources) # Convert a semicolon separated list to a whitespace separated string set(SCRIPT_OPTIONS) set(SCRIPT_ARGUMENTS) set(DEPENDENCIES) set(IS_PATH_NAME false) # Loop over the arguments of the function foreach(arg ${ARGN}) # Extract the first character of the argument string(SUBSTRING "${arg}" 0 1 FIRST_CHAR) if (${FIRST_CHAR} STREQUAL "-") # If the argument starts with a dash "-", this is an option to # EmbedResources.py list(APPEND SCRIPT_OPTIONS ${arg}) else() if (${IS_PATH_NAME}) list(APPEND SCRIPT_ARGUMENTS "${arg}") list(APPEND DEPENDENCIES "${arg}") set(IS_PATH_NAME false) else() list(APPEND SCRIPT_ARGUMENTS "${arg}") set(IS_PATH_NAME true) endif() endif() endforeach() set(TARGET_BASE "${AUTOGENERATED_DIR}/EmbeddedResources") add_custom_command( OUTPUT "${TARGET_BASE}.h" "${TARGET_BASE}.cpp" COMMAND ${PYTHON_EXECUTABLE} "${ORTHANC_ROOT}/Resources/EmbedResources.py" ${SCRIPT_OPTIONS} "${AUTOGENERATED_DIR}/EmbeddedResources" ${SCRIPT_ARGUMENTS} DEPENDS "${ORTHANC_ROOT}/Resources/EmbedResources.py" ${DEPENDENCIES} ) list(APPEND AUTOGENERATED_SOURCES "${AUTOGENERATED_DIR}/EmbeddedResources.cpp" ) endmacro() OrthancPostgreSQL-2.0/Orthanc/Resources/CMake/BoostConfiguration.cmake0000644000000000000000000001033712627602430024201 0ustar 00000000000000if (STATIC_BUILD OR NOT USE_SYSTEM_BOOST) set(BOOST_STATIC 1) else() include(FindBoost) set(BOOST_STATIC 0) #set(Boost_DEBUG 1) #set(Boost_USE_STATIC_LIBS ON) find_package(Boost COMPONENTS filesystem thread system date_time regex locale) if (NOT Boost_FOUND) message(FATAL_ERROR "Unable to locate Boost on this system") endif() # Boost releases 1.44 through 1.47 supply both V2 and V3 filesystem # http://www.boost.org/doc/libs/1_46_1/libs/filesystem/v3/doc/index.htm if (${Boost_VERSION} LESS 104400) add_definitions( -DBOOST_HAS_FILESYSTEM_V3=0 ) else() add_definitions( -DBOOST_HAS_FILESYSTEM_V3=1 -DBOOST_FILESYSTEM_VERSION=3 ) endif() #if (${Boost_VERSION} LESS 104800) # boost::locale is only available from 1.48.00 #message("Too old version of Boost (${Boost_LIB_VERSION}): Building the static version") # set(BOOST_STATIC 1) #endif() include_directories(${Boost_INCLUDE_DIRS}) link_libraries(${Boost_LIBRARIES}) endif() if (BOOST_STATIC) # Parameters for Boost 1.59.0 set(BOOST_NAME boost_1_59_0) set(BOOST_BCP_SUFFIX bcpdigest-0.9.5) set(BOOST_MD5 "08abb7cdbea0b380f9ab0d5cce476f12") set(BOOST_URL "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/${BOOST_NAME}_${BOOST_BCP_SUFFIX}.tar.gz") set(BOOST_FILESYSTEM_SOURCES_DIR "${BOOST_NAME}/libs/filesystem/src") set(BOOST_SOURCES_DIR ${CMAKE_BINARY_DIR}/${BOOST_NAME}) DownloadPackage(${BOOST_MD5} ${BOOST_URL} "${BOOST_SOURCES_DIR}") set(BOOST_SOURCES) if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD") list(APPEND BOOST_SOURCES ${BOOST_SOURCES_DIR}/libs/thread/src/pthread/once.cpp ${BOOST_SOURCES_DIR}/libs/thread/src/pthread/thread.cpp ) add_definitions( -DBOOST_LOCALE_WITH_ICONV=1 ) if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase") add_definitions(-DBOOST_HAS_SCHED_YIELD=1) endif() elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") list(APPEND BOOST_SOURCES ${BOOST_SOURCES_DIR}/libs/thread/src/win32/tss_dll.cpp ${BOOST_SOURCES_DIR}/libs/thread/src/win32/thread.cpp ${BOOST_SOURCES_DIR}/libs/thread/src/win32/tss_pe.cpp ${BOOST_FILESYSTEM_SOURCES_DIR}/windows_file_codecvt.cpp ) # Starting with release 0.8.2, Orthanc statically links against # libiconv, even on Windows. Indeed, the "WCONV" library of # Windows XP seems not to support properly several codepages # (notably "Latin3", "Hebrew", and "Arabic"). if (USE_BOOST_ICONV) include(${ORTHANC_ROOT}/Resources/CMake/LibIconvConfiguration.cmake) else() add_definitions(-DBOOST_LOCALE_WITH_WCONV=1) endif() else() message(FATAL_ERROR "Support your platform here") endif() if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") list(APPEND BOOST_SOURCES ${BOOST_SOURCES_DIR}/libs/filesystem/src/utf8_codecvt_facet.cpp ) endif() aux_source_directory(${BOOST_SOURCES_DIR}/libs/regex/src BOOST_REGEX_SOURCES) list(APPEND BOOST_SOURCES ${BOOST_REGEX_SOURCES} ${BOOST_SOURCES_DIR}/libs/date_time/src/gregorian/greg_month.cpp ${BOOST_FILESYSTEM_SOURCES_DIR}/codecvt_error_category.cpp ${BOOST_FILESYSTEM_SOURCES_DIR}/operations.cpp ${BOOST_FILESYSTEM_SOURCES_DIR}/path.cpp ${BOOST_FILESYSTEM_SOURCES_DIR}/path_traits.cpp ${BOOST_SOURCES_DIR}/libs/locale/src/encoding/codepage.cpp ${BOOST_SOURCES_DIR}/libs/system/src/error_code.cpp ) add_definitions( # Static build of Boost -DBOOST_ALL_NO_LIB -DBOOST_ALL_NOLIB -DBOOST_DATE_TIME_NO_LIB -DBOOST_THREAD_BUILD_LIB -DBOOST_PROGRAM_OPTIONS_NO_LIB -DBOOST_REGEX_NO_LIB -DBOOST_SYSTEM_NO_LIB -DBOOST_LOCALE_NO_LIB -DBOOST_HAS_LOCALE=1 -DBOOST_HAS_FILESYSTEM_V3=1 ) if (CMAKE_COMPILER_IS_GNUCXX) add_definitions(-isystem ${BOOST_SOURCES_DIR}) endif() include_directories( ${BOOST_SOURCES_DIR} ) source_group(ThirdParty\\Boost REGULAR_EXPRESSION ${BOOST_SOURCES_DIR}/.*) else() add_definitions( -DBOOST_HAS_LOCALE=1 ) endif() add_definitions( -DBOOST_HAS_DATE_TIME=1 -DBOOST_HAS_REGEX=1 ) OrthancPostgreSQL-2.0/Orthanc/Resources/CMake/Compiler.cmake0000644000000000000000000001253712627602430022141 0ustar 00000000000000# This file sets all the compiler-related flags if (CMAKE_CROSSCOMPILING) # Cross-compilation necessarily implies standalone and static build SET(STATIC_BUILD ON) SET(STANDALONE_BUILD ON) endif() if (CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-long-long -Wno-implicit-function-declaration") # --std=c99 makes libcurl not to compile # -pedantic gives a lot of warnings on OpenSSL set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wno-long-long -Wno-variadic-macros") if (CMAKE_CROSSCOMPILING) # http://stackoverflow.com/a/3543845/881731 set(CMAKE_RC_COMPILE_OBJECT " -O coff -I ") endif() elseif (MSVC) # Use static runtime under Visual Studio # http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace # http://stackoverflow.com/a/6510446 foreach(flag_var CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO) string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}") endforeach(flag_var) # Add /Zm256 compiler option to Visual Studio to fix PCH errors set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm256") add_definitions( -D_CRT_SECURE_NO_WARNINGS=1 -D_CRT_SECURE_NO_DEPRECATE=1 ) include_directories(${ORTHANC_ROOT}/Resources/ThirdParty/VisualStudio) link_libraries(netapi32) endif() if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined -Wl,--version-script=${ORTHANC_ROOT}/Plugins/Samples/Common/VersionScript.map") # Remove the "-rdynamic" option # http://www.mail-archive.com/cmake@cmake.org/msg08837.html set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") link_libraries(uuid pthread rt) if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--as-needed") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--as-needed") add_definitions( -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 ) link_libraries(dl) endif() elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") if (MSVC) message("MSVC compiler version = " ${MSVC_VERSION} "\n") # Starting Visual Studio 2013 (version 1800), it is not possible # to target Windows XP anymore if (MSVC_VERSION LESS 1800) add_definitions( -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 ) endif() else() add_definitions( -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 ) endif() add_definitions( -D_CRT_SECURE_NO_WARNINGS=1 ) link_libraries(rpcrt4 ws2_32) if (CMAKE_COMPILER_IS_GNUCXX) # This is a patch for MinGW64 SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++") CHECK_LIBRARY_EXISTS(winpthread pthread_create "" HAVE_WIN_PTHREAD) if (HAVE_WIN_PTHREAD) # This line is necessary to compile with recent versions of MinGW, # otherwise "libwinpthread-1.dll" is not statically linked. SET(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic") add_definitions(-DHAVE_WIN_PTHREAD=1) else() add_definitions(-DHAVE_WIN_PTHREAD=0) endif() endif() elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -exported_symbols_list ${ORTHANC_ROOT}/Plugins/Samples/Common/ExportedSymbols.list") add_definitions( -D_XOPEN_SOURCE=1 ) link_libraries(iconv) endif() if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -I${LSB_PATH}/include") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -nostdinc++ -I${LSB_PATH}/include -I${LSB_PATH}/include/c++ -I${LSB_PATH}/include/c++/backward -fpermissive") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -L${LSB_LIBPATH}") endif() if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") # In FreeBSD, the "/usr/local/" folder contains the ports and need to be imported SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/local/include") SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -I/usr/local/include") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L/usr/local/lib") endif() if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") CHECK_INCLUDE_FILES(rpc.h HAVE_UUID_H) else() CHECK_INCLUDE_FILES(uuid/uuid.h HAVE_UUID_H) endif() if (NOT HAVE_UUID_H) message(FATAL_ERROR "Please install the uuid-dev package") endif() if (STATIC_BUILD) add_definitions(-DORTHANC_STATIC=1) else() add_definitions(-DORTHANC_STATIC=0) endif() OrthancPostgreSQL-2.0/Orthanc/Resources/CMake/DownloadPackage.cmake0000644000000000000000000001147712627602430023414 0ustar 00000000000000macro(GetUrlFilename TargetVariable Url) string(REGEX REPLACE "^.*/" "" ${TargetVariable} "${Url}") endmacro() macro(GetUrlExtension TargetVariable Url) #string(REGEX REPLACE "^.*/[^.]*\\." "" TMP "${Url}") string(REGEX REPLACE "^.*\\." "" TMP "${Url}") string(TOLOWER "${TMP}" "${TargetVariable}") endmacro() ## ## Setup the patch command-line tool ## if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") set(PATCH_EXECUTABLE ${CMAKE_SOURCE_DIR}/Resources/ThirdParty/patch/patch.exe) else () find_program(PATCH_EXECUTABLE patch) if (${PATCH_EXECUTABLE} MATCHES "PATCH_EXECUTABLE-NOTFOUND") message(FATAL_ERROR "Please install the 'patch' standard command-line tool") endif() endif() ## ## Check the existence of the required decompression tools ## if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") find_program(ZIP_EXECUTABLE 7z PATHS "$ENV{ProgramFiles}/7-Zip" "$ENV{ProgramW6432}/7-Zip" ) if (${ZIP_EXECUTABLE} MATCHES "ZIP_EXECUTABLE-NOTFOUND") message(FATAL_ERROR "Please install the '7-zip' software (http://www.7-zip.org/)") endif() else() find_program(UNZIP_EXECUTABLE unzip) if (${UNZIP_EXECUTABLE} MATCHES "UNZIP_EXECUTABLE-NOTFOUND") message(FATAL_ERROR "Please install the 'unzip' package") endif() find_program(TAR_EXECUTABLE tar) if (${TAR_EXECUTABLE} MATCHES "TAR_EXECUTABLE-NOTFOUND") message(FATAL_ERROR "Please install the 'tar' package") endif() endif() macro(DownloadPackage MD5 Url TargetDirectory) if (NOT IS_DIRECTORY "${TargetDirectory}") GetUrlFilename(TMP_FILENAME "${Url}") set(TMP_PATH "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${TMP_FILENAME}") if (NOT EXISTS "${TMP_PATH}") message("Downloading ${Url}") # This fixes issue 6: "I think cmake shouldn't download the # packages which are not in the system, it should stop and let # user know." # https://code.google.com/p/orthanc/issues/detail?id=6 if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS) message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON") endif() file(DOWNLOAD "${Url}" "${TMP_PATH}" SHOW_PROGRESS EXPECTED_MD5 "${MD5}") else() message("Using local copy of ${Url}") endif() GetUrlExtension(TMP_EXTENSION "${Url}") #message(${TMP_EXTENSION}) message("Uncompressing ${TMP_FILENAME}") if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") # How to silently extract files using 7-zip # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly if (("${TMP_EXTENSION}" STREQUAL "gz") OR ("${TMP_EXTENSION}" STREQUAL "tgz")) execute_process( COMMAND ${ZIP_EXECUTABLE} e -y ${TMP_PATH} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} RESULT_VARIABLE Failure OUTPUT_QUIET ) if (Failure) message(FATAL_ERROR "Error while running the uncompression tool") endif() if ("${TMP_EXTENSION}" STREQUAL "tgz") string(REGEX REPLACE ".tgz$" ".tar" TMP_FILENAME2 "${TMP_FILENAME}") else() string(REGEX REPLACE ".gz$" "" TMP_FILENAME2 "${TMP_FILENAME}") endif() execute_process( COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_FILENAME2} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} RESULT_VARIABLE Failure OUTPUT_QUIET ) elseif ("${TMP_EXTENSION}" STREQUAL "zip") execute_process( COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_PATH} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} RESULT_VARIABLE Failure OUTPUT_QUIET ) else() message(FATAL_ERROR "Support your platform here") endif() else() if ("${TMP_EXTENSION}" STREQUAL "zip") execute_process( COMMAND sh -c "${UNZIP_EXECUTABLE} -q ${TMP_PATH}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR} RESULT_VARIABLE Failure ) elseif (("${TMP_EXTENSION}" STREQUAL "gz") OR ("${TMP_EXTENSION}" STREQUAL "tgz")) #message("tar xvfz ${TMP_PATH}") execute_process( COMMAND sh -c "${TAR_EXECUTABLE} xfz ${TMP_PATH}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR} RESULT_VARIABLE Failure ) elseif ("${TMP_EXTENSION}" STREQUAL "bz2") execute_process( COMMAND sh -c "${TAR_EXECUTABLE} xfj ${TMP_PATH}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR} RESULT_VARIABLE Failure ) else() message(FATAL_ERROR "Unknown package format.") endif() endif() if (Failure) message(FATAL_ERROR "Error while running the uncompression tool") endif() if (NOT IS_DIRECTORY "${TargetDirectory}") message(FATAL_ERROR "The package was not uncompressed at the proper location. Check the CMake instructions.") endif() endif() endmacro() OrthancPostgreSQL-2.0/Orthanc/Resources/CMake/GoogleTestConfiguration.cmake0000644000000000000000000000220712627602430025164 0ustar 00000000000000if (USE_GTEST_DEBIAN_SOURCE_PACKAGE) set(GTEST_SOURCES /usr/src/gtest/src/gtest-all.cc) include_directories(/usr/src/gtest) if (NOT EXISTS /usr/include/gtest/gtest.h OR NOT EXISTS ${GTEST_SOURCES}) message(FATAL_ERROR "Please install the libgtest-dev package") endif() elseif (STATIC_BUILD OR NOT USE_SYSTEM_GOOGLE_TEST) set(GTEST_SOURCES_DIR ${CMAKE_BINARY_DIR}/gtest-1.7.0) set(GTEST_URL "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/gtest-1.7.0.zip") set(GTEST_MD5 "2d6ec8ccdf5c46b05ba54a9fd1d130d7") DownloadPackage(${GTEST_MD5} ${GTEST_URL} "${GTEST_SOURCES_DIR}") include_directories( ${GTEST_SOURCES_DIR}/include ${GTEST_SOURCES_DIR} ) set(GTEST_SOURCES ${GTEST_SOURCES_DIR}/src/gtest-all.cc ) # https://code.google.com/p/googletest/issues/detail?id=412 if (MSVC) # VS2012 does not support tuples correctly yet add_definitions(/D _VARIADIC_MAX=10) endif() else() include(FindGTest) if (NOT GTEST_FOUND) message(FATAL_ERROR "Unable to find GoogleTest") endif() include_directories(${GTEST_INCLUDE_DIRS}) link_libraries(${GTEST_LIBRARIES}) endif() OrthancPostgreSQL-2.0/Orthanc/Resources/CMake/JsonCppConfiguration.cmake0000644000000000000000000000215112627602430024462 0ustar 00000000000000if (STATIC_BUILD OR NOT USE_SYSTEM_JSONCPP) set(JSONCPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/jsoncpp-0.10.5) set(JSONCPP_URL "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/jsoncpp-0.10.5.tar.gz") set(JSONCPP_MD5 "db146bac5a126ded9bd728ab7b61ed6b") DownloadPackage(${JSONCPP_MD5} ${JSONCPP_URL} "${JSONCPP_SOURCES_DIR}") set(JSONCPP_SOURCES ${JSONCPP_SOURCES_DIR}/src/lib_json/json_reader.cpp ${JSONCPP_SOURCES_DIR}/src/lib_json/json_value.cpp ${JSONCPP_SOURCES_DIR}/src/lib_json/json_writer.cpp ) include_directories( ${JSONCPP_SOURCES_DIR}/include ) source_group(ThirdParty\\JsonCpp REGULAR_EXPRESSION ${JSONCPP_SOURCES_DIR}/.*) else() find_path(JSONCPP_INCLUDE_DIR json/reader.h /usr/include/jsoncpp /usr/local/include/jsoncpp ) message("JsonCpp include dir: ${JSONCPP_INCLUDE_DIR}") include_directories(${JSONCPP_INCLUDE_DIR}) link_libraries(jsoncpp) CHECK_INCLUDE_FILE_CXX(${JSONCPP_INCLUDE_DIR}/json/reader.h HAVE_JSONCPP_H) if (NOT HAVE_JSONCPP_H) message(FATAL_ERROR "Please install the libjsoncpp-dev package") endif() endif() OrthancPostgreSQL-2.0/Orthanc/Resources/EmbedResources.py0000644000000000000000000002772312627602430021671 0ustar 00000000000000#!/usr/bin/python # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # In addition, as a special exception, the copyright holders of this # program give permission to link the code of its release with the # OpenSSL project's "OpenSSL" library (or with modified versions of it # that use the same license as the "OpenSSL" library), and distribute # the linked executables. You must obey the GNU General Public License # in all respects for all of the code used other than "OpenSSL". If you # modify file(s) with this exception, you may extend this exception to # your version of the file(s), but you are not obligated to do so. If # you do not wish to do so, delete this exception statement from your # version. If you delete this exception statement from all source files # in the program, then also delete it here. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import sys import os import os.path import pprint import re UPCASE_CHECK = True USE_SYSTEM_EXCEPTION = False EXCEPTION_CLASS = 'OrthancException' OUT_OF_RANGE_EXCEPTION = 'OrthancException(ErrorCode_ParameterOutOfRange)' INEXISTENT_PATH_EXCEPTION = 'OrthancException(ErrorCode_InexistentItem)' NAMESPACE = 'Orthanc' ARGS = [] for i in range(len(sys.argv)): if not sys.argv[i].startswith('--'): ARGS.append(sys.argv[i]) elif sys.argv[i].lower() == '--no-upcase-check': UPCASE_CHECK = False elif sys.argv[i].lower() == '--system-exception': USE_SYSTEM_EXCEPTION = True EXCEPTION_CLASS = '::std::runtime_error' OUT_OF_RANGE_EXCEPTION = '%s("Parameter out of range")' % EXCEPTION_CLASS INEXISTENT_PATH_EXCEPTION = '%s("Unknown path in a directory resource")' % EXCEPTION_CLASS elif sys.argv[i].startswith('--namespace='): NAMESPACE = sys.argv[i][sys.argv[i].find('=') + 1 : ] if len(ARGS) < 2 or len(ARGS) % 2 != 0: print ('Usage:') print ('python %s [--no-upcase-check] [--system-exception] [--namespace=] [ ]*' % sys.argv[0]) exit(-1) TARGET_BASE_FILENAME = ARGS[1] SOURCES = ARGS[2:] try: # Make sure the destination directory exists os.makedirs(os.path.normpath(os.path.join(TARGET_BASE_FILENAME, '..'))) except: pass ##################################################################### ## Read each resource file ##################################################################### def CheckNoUpcase(s): global UPCASE_CHECK if (UPCASE_CHECK and re.search('[A-Z]', s) != None): raise Exception("Path in a directory with an upcase letter: %s" % s) resources = {} counter = 0 i = 0 while i < len(SOURCES): resourceName = SOURCES[i].upper() pathName = SOURCES[i + 1] if not os.path.exists(pathName): raise Exception("Non existing path: %s" % pathName) if resourceName in resources: raise Exception("Twice the same resource: " + resourceName) if os.path.isdir(pathName): # The resource is a directory: Recursively explore its files content = {} for root, dirs, files in os.walk(pathName): base = os.path.relpath(root, pathName) # Fix issue #24 (Build fails on OSX when directory has .DS_Store files): # Ignore folders whose name starts with a dot (".") if base.find('/.') != -1: print('Ignoring folder: %s' % root) continue for f in files: if f.find('~') == -1: # Ignore Emacs backup files if base == '.': r = f else: r = os.path.join(base, f) CheckNoUpcase(r) r = '/' + r.replace('\\', '/') if r in content: raise Exception("Twice the same filename (check case): " + r) content[r] = { 'Filename' : os.path.join(root, f), 'Index' : counter } counter += 1 resources[resourceName] = { 'Type' : 'Directory', 'Files' : content } elif os.path.isfile(pathName): resources[resourceName] = { 'Type' : 'File', 'Index' : counter, 'Filename' : pathName } counter += 1 else: raise Exception("Not a regular file, nor a directory: " + pathName) i += 2 #pprint.pprint(resources) ##################################################################### ## Write .h header ##################################################################### header = open(TARGET_BASE_FILENAME + '.h', 'w') header.write(""" #pragma once #include #include namespace %s { namespace EmbeddedResources { enum FileResourceId { """ % NAMESPACE) isFirst = True for name in resources: if resources[name]['Type'] == 'File': if isFirst: isFirst = False else: header.write(',\n') header.write(' %s' % name) header.write(""" }; enum DirectoryResourceId { """) isFirst = True for name in resources: if resources[name]['Type'] == 'Directory': if isFirst: isFirst = False else: header.write(',\n') header.write(' %s' % name) header.write(""" }; const void* GetFileResourceBuffer(FileResourceId id); size_t GetFileResourceSize(FileResourceId id); void GetFileResource(std::string& result, FileResourceId id); const void* GetDirectoryResourceBuffer(DirectoryResourceId id, const char* path); size_t GetDirectoryResourceSize(DirectoryResourceId id, const char* path); void GetDirectoryResource(std::string& result, DirectoryResourceId id, const char* path); void ListResources(std::list& result, DirectoryResourceId id); } } """) header.close() ##################################################################### ## Write the resource content in the .cpp source ##################################################################### PYTHON_MAJOR_VERSION = sys.version_info[0] def WriteResource(cpp, item): cpp.write(' static const uint8_t resource%dBuffer[] = {' % item['Index']) f = open(item['Filename'], "rb") content = f.read() f.close() # http://stackoverflow.com/a/1035360 pos = 0 for b in content: if PYTHON_MAJOR_VERSION == 2: c = ord(b[0]) else: c = b if pos > 0: cpp.write(', ') if (pos % 16) == 0: cpp.write('\n ') if c < 0: raise Exception("Internal error") cpp.write("0x%02x" % c) pos += 1 # Zero-size array are disallowed, so we put one single void character in it. if pos == 0: cpp.write(' 0') cpp.write(' };\n') cpp.write(' static const size_t resource%dSize = %d;\n' % (item['Index'], pos)) cpp = open(TARGET_BASE_FILENAME + '.cpp', 'w') cpp.write('#include "%s.h"\n' % os.path.basename(TARGET_BASE_FILENAME)) if USE_SYSTEM_EXCEPTION: cpp.write('#include ') else: cpp.write('#include "%s/Core/OrthancException.h"' % os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) cpp.write(""" #include #include namespace %s { namespace EmbeddedResources { """ % NAMESPACE) for name in resources: if resources[name]['Type'] == 'File': WriteResource(cpp, resources[name]) else: for f in resources[name]['Files']: WriteResource(cpp, resources[name]['Files'][f]) ##################################################################### ## Write the accessors to the file resources in .cpp ##################################################################### cpp.write(""" const void* GetFileResourceBuffer(FileResourceId id) { switch (id) { """) for name in resources: if resources[name]['Type'] == 'File': cpp.write(' case %s:\n' % name) cpp.write(' return resource%dBuffer;\n' % resources[name]['Index']) cpp.write(""" default: throw %s; } } size_t GetFileResourceSize(FileResourceId id) { switch (id) { """ % OUT_OF_RANGE_EXCEPTION) for name in resources: if resources[name]['Type'] == 'File': cpp.write(' case %s:\n' % name) cpp.write(' return resource%dSize;\n' % resources[name]['Index']) cpp.write(""" default: throw %s; } } """ % OUT_OF_RANGE_EXCEPTION) ##################################################################### ## Write the accessors to the directory resources in .cpp ##################################################################### cpp.write(""" const void* GetDirectoryResourceBuffer(DirectoryResourceId id, const char* path) { switch (id) { """) for name in resources: if resources[name]['Type'] == 'Directory': cpp.write(' case %s:\n' % name) isFirst = True for path in resources[name]['Files']: cpp.write(' if (!strcmp(path, "%s"))\n' % path) cpp.write(' return resource%dBuffer;\n' % resources[name]['Files'][path]['Index']) cpp.write(' throw %s;\n\n' % INEXISTENT_PATH_EXCEPTION) cpp.write(""" default: throw %s; } } size_t GetDirectoryResourceSize(DirectoryResourceId id, const char* path) { switch (id) { """ % OUT_OF_RANGE_EXCEPTION) for name in resources: if resources[name]['Type'] == 'Directory': cpp.write(' case %s:\n' % name) isFirst = True for path in resources[name]['Files']: cpp.write(' if (!strcmp(path, "%s"))\n' % path) cpp.write(' return resource%dSize;\n' % resources[name]['Files'][path]['Index']) cpp.write(' throw %s;\n\n' % INEXISTENT_PATH_EXCEPTION) cpp.write(""" default: throw %s; } } """ % OUT_OF_RANGE_EXCEPTION) ##################################################################### ## List the resources in a directory ##################################################################### cpp.write(""" void ListResources(std::list& result, DirectoryResourceId id) { result.clear(); switch (id) { """) for name in resources: if resources[name]['Type'] == 'Directory': cpp.write(' case %s:\n' % name) for path in sorted(resources[name]['Files']): cpp.write(' result.push_back("%s");\n' % path) cpp.write(' break;\n\n') cpp.write(""" default: throw %s; } } """ % OUT_OF_RANGE_EXCEPTION) ##################################################################### ## Write the convenience wrappers in .cpp ##################################################################### cpp.write(""" void GetFileResource(std::string& result, FileResourceId id) { size_t size = GetFileResourceSize(id); result.resize(size); if (size > 0) memcpy(&result[0], GetFileResourceBuffer(id), size); } void GetDirectoryResource(std::string& result, DirectoryResourceId id, const char* path) { size_t size = GetDirectoryResourceSize(id, path); result.resize(size); if (size > 0) memcpy(&result[0], GetDirectoryResourceBuffer(id, path), size); } } } """) cpp.close() OrthancPostgreSQL-2.0/Orthanc/Resources/MinGW-W64-Toolchain32.cmake0000644000000000000000000000117112627602430023021 0ustar 00000000000000# the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) set(CMAKE_RC_COMPILER i686-w64-mingw32-windres) # here is the target environment located set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) OrthancPostgreSQL-2.0/Orthanc/Resources/MinGW-W64-Toolchain64.cmake0000644000000000000000000000117712627602430023034 0ustar 00000000000000# the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) # here is the target environment located set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) OrthancPostgreSQL-2.0/Orthanc/Resources/MinGWToolchain.cmake0000644000000000000000000000117112627602430022221 0ustar 00000000000000# the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ set(CMAKE_C_COMPILER i586-mingw32msvc-gcc) set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++) set(CMAKE_RC_COMPILER i586-mingw32msvc-windres) # here is the target environment located set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) OrthancPostgreSQL-2.0/Orthanc/Resources/ThirdParty/VisualStudio/stdint.h0000644000000000000000000001744712627602430024615 0ustar 00000000000000// ISO C9x compliant stdint.h for Microsoft Visual Studio // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 // // Copyright (c) 2006-2008 Alexander Chemeris // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. The name of the author may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////////// #ifndef _MSC_VER // [ #error "Use this header only with Microsoft Visual C++ compilers!" #endif // _MSC_VER ] #ifndef _MSC_STDINT_H_ // [ #define _MSC_STDINT_H_ #if _MSC_VER > 1000 #pragma once #endif #include // For Visual Studio 6 in C++ mode and for many Visual Studio versions when // compiling for ARM we should wrap include with 'extern "C++" {}' // or compiler give many errors like this: // error C2733: second C linkage of overloaded function 'wmemchr' not allowed #ifdef __cplusplus extern "C" { #endif # include #ifdef __cplusplus } #endif // Define _W64 macros to mark types changing their size, like intptr_t. #ifndef _W64 # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 # define _W64 __w64 # else # define _W64 # endif #endif // 7.18.1 Integer types // 7.18.1.1 Exact-width integer types // Visual Studio 6 and Embedded Visual C++ 4 doesn't // realize that, e.g. char has the same size as __int8 // so we give up on __intX for them. #if (_MSC_VER < 1300) typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #else typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; #endif typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; // 7.18.1.2 Minimum-width integer types typedef int8_t int_least8_t; typedef int16_t int_least16_t; typedef int32_t int_least32_t; typedef int64_t int_least64_t; typedef uint8_t uint_least8_t; typedef uint16_t uint_least16_t; typedef uint32_t uint_least32_t; typedef uint64_t uint_least64_t; // 7.18.1.3 Fastest minimum-width integer types typedef int8_t int_fast8_t; typedef int16_t int_fast16_t; typedef int32_t int_fast32_t; typedef int64_t int_fast64_t; typedef uint8_t uint_fast8_t; typedef uint16_t uint_fast16_t; typedef uint32_t uint_fast32_t; typedef uint64_t uint_fast64_t; // 7.18.1.4 Integer types capable of holding object pointers #ifdef _WIN64 // [ typedef signed __int64 intptr_t; typedef unsigned __int64 uintptr_t; #else // _WIN64 ][ typedef _W64 signed int intptr_t; typedef _W64 unsigned int uintptr_t; #endif // _WIN64 ] // 7.18.1.5 Greatest-width integer types typedef int64_t intmax_t; typedef uint64_t uintmax_t; // 7.18.2 Limits of specified-width integer types #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 // 7.18.2.1 Limits of exact-width integer types #define INT8_MIN ((int8_t)_I8_MIN) #define INT8_MAX _I8_MAX #define INT16_MIN ((int16_t)_I16_MIN) #define INT16_MAX _I16_MAX #define INT32_MIN ((int32_t)_I32_MIN) #define INT32_MAX _I32_MAX #define INT64_MIN ((int64_t)_I64_MIN) #define INT64_MAX _I64_MAX #define UINT8_MAX _UI8_MAX #define UINT16_MAX _UI16_MAX #define UINT32_MAX _UI32_MAX #define UINT64_MAX _UI64_MAX // 7.18.2.2 Limits of minimum-width integer types #define INT_LEAST8_MIN INT8_MIN #define INT_LEAST8_MAX INT8_MAX #define INT_LEAST16_MIN INT16_MIN #define INT_LEAST16_MAX INT16_MAX #define INT_LEAST32_MIN INT32_MIN #define INT_LEAST32_MAX INT32_MAX #define INT_LEAST64_MIN INT64_MIN #define INT_LEAST64_MAX INT64_MAX #define UINT_LEAST8_MAX UINT8_MAX #define UINT_LEAST16_MAX UINT16_MAX #define UINT_LEAST32_MAX UINT32_MAX #define UINT_LEAST64_MAX UINT64_MAX // 7.18.2.3 Limits of fastest minimum-width integer types #define INT_FAST8_MIN INT8_MIN #define INT_FAST8_MAX INT8_MAX #define INT_FAST16_MIN INT16_MIN #define INT_FAST16_MAX INT16_MAX #define INT_FAST32_MIN INT32_MIN #define INT_FAST32_MAX INT32_MAX #define INT_FAST64_MIN INT64_MIN #define INT_FAST64_MAX INT64_MAX #define UINT_FAST8_MAX UINT8_MAX #define UINT_FAST16_MAX UINT16_MAX #define UINT_FAST32_MAX UINT32_MAX #define UINT_FAST64_MAX UINT64_MAX // 7.18.2.4 Limits of integer types capable of holding object pointers #ifdef _WIN64 // [ # define INTPTR_MIN INT64_MIN # define INTPTR_MAX INT64_MAX # define UINTPTR_MAX UINT64_MAX #else // _WIN64 ][ # define INTPTR_MIN INT32_MIN # define INTPTR_MAX INT32_MAX # define UINTPTR_MAX UINT32_MAX #endif // _WIN64 ] // 7.18.2.5 Limits of greatest-width integer types #define INTMAX_MIN INT64_MIN #define INTMAX_MAX INT64_MAX #define UINTMAX_MAX UINT64_MAX // 7.18.3 Limits of other integer types #ifdef _WIN64 // [ # define PTRDIFF_MIN _I64_MIN # define PTRDIFF_MAX _I64_MAX #else // _WIN64 ][ # define PTRDIFF_MIN _I32_MIN # define PTRDIFF_MAX _I32_MAX #endif // _WIN64 ] #define SIG_ATOMIC_MIN INT_MIN #define SIG_ATOMIC_MAX INT_MAX #ifndef SIZE_MAX // [ # ifdef _WIN64 // [ # define SIZE_MAX _UI64_MAX # else // _WIN64 ][ # define SIZE_MAX _UI32_MAX # endif // _WIN64 ] #endif // SIZE_MAX ] // WCHAR_MIN and WCHAR_MAX are also defined in #ifndef WCHAR_MIN // [ # define WCHAR_MIN 0 #endif // WCHAR_MIN ] #ifndef WCHAR_MAX // [ # define WCHAR_MAX _UI16_MAX #endif // WCHAR_MAX ] #define WINT_MIN 0 #define WINT_MAX _UI16_MAX #endif // __STDC_LIMIT_MACROS ] // 7.18.4 Limits of other integer types #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 // 7.18.4.1 Macros for minimum-width integer constants #define INT8_C(val) val##i8 #define INT16_C(val) val##i16 #define INT32_C(val) val##i32 #define INT64_C(val) val##i64 #define UINT8_C(val) val##ui8 #define UINT16_C(val) val##ui16 #define UINT32_C(val) val##ui32 #define UINT64_C(val) val##ui64 // 7.18.4.2 Macros for greatest-width integer constants #define INTMAX_C INT64_C #define UINTMAX_C UINT64_C #endif // __STDC_CONSTANT_MACROS ] #endif // _MSC_STDINT_H_ ] OrthancPostgreSQL-2.0/Orthanc/Resources/WindowsResources.py0000644000000000000000000000657612627602430022312 0ustar 00000000000000#!/usr/bin/python # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # In addition, as a special exception, the copyright holders of this # program give permission to link the code of its release with the # OpenSSL project's "OpenSSL" library (or with modified versions of it # that use the same license as the "OpenSSL" library), and distribute # the linked executables. You must obey the GNU General Public License # in all respects for all of the code used other than "OpenSSL". If you # modify file(s) with this exception, you may extend this exception to # your version of the file(s), but you are not obligated to do so. If # you do not wish to do so, delete this exception statement from your # version. If you delete this exception statement from all source files # in the program, then also delete it here. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import sys import datetime if len(sys.argv) != 5: sys.stderr.write('Usage: %s \n\n' % sys.argv[0]) sys.stderr.write('Example: %s 0.9.1 Orthanc Orthanc.exe "Lightweight, RESTful DICOM server for medical imaging"\n' % sys.argv[0]) sys.exit(-1) SOURCE = os.path.join(os.path.dirname(__file__), 'WindowsResources.rc') VERSION = sys.argv[1] PRODUCT = sys.argv[2] FILENAME = sys.argv[3] DESCRIPTION = sys.argv[4] if VERSION == 'mainline': VERSION = '999.999.999' RELEASE = 'This is a mainline build, not an official release' else: RELEASE = 'Release %s' % VERSION v = VERSION.split('.') if len(v) != 2 and len(v) != 3: sys.stderr.write('Bad version number: %s\n' % VERSION) sys.exit(-1) if len(v) == 2: v.append('0') extension = os.path.splitext(FILENAME)[1] if extension.lower() == '.dll': BLOCK = '040904E4' TYPE = 'VFT_DLL' elif extension.lower() == '.exe': #BLOCK = '040904B0' # LANG_ENGLISH/SUBLANG_ENGLISH_US, BLOCK = '040904E4' # Lang=US English, CharSet=Windows Multilingual TYPE = 'VFT_APP' else: sys.stderr.write('Unsupported extension (.EXE or .DLL only): %s\n' % extension) sys.exit(-1) with open(SOURCE, 'r') as source: content = source.read() content = content.replace('${VERSION_MAJOR}', v[0]) content = content.replace('${VERSION_MINOR}', v[1]) content = content.replace('${VERSION_PATCH}', v[2]) content = content.replace('${RELEASE}', RELEASE) content = content.replace('${DESCRIPTION}', DESCRIPTION) content = content.replace('${PRODUCT}', PRODUCT) content = content.replace('${FILENAME}', FILENAME) content = content.replace('${YEAR}', str(datetime.datetime.now().year)) content = content.replace('${BLOCK}', BLOCK) content = content.replace('${TYPE}', TYPE) sys.stdout.write(content) OrthancPostgreSQL-2.0/Orthanc/Resources/WindowsResources.rc0000644000000000000000000000217012627602430022250 0ustar 00000000000000#include VS_VERSION_INFO VERSIONINFO FILEVERSION ${VERSION_MAJOR},${VERSION_MINOR},0,${VERSION_PATCH} PRODUCTVERSION ${VERSION_MAJOR},${VERSION_MINOR},0,0 FILEOS VOS_NT_WINDOWS32 FILETYPE ${TYPE} BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "${BLOCK}" BEGIN VALUE "Comments", "${RELEASE}" VALUE "CompanyName", "University Hospital of Liege, Belgium" VALUE "FileDescription", "${DESCRIPTION}" VALUE "FileVersion", "${VERSION_MAJOR}.${VERSION_MINOR}.0.${VERSION_PATCH}" VALUE "InternalName", "${PRODUCT}" VALUE "LegalCopyright", "(c) 2012-${YEAR}, Sebastien Jodogne, University Hospital of Liege, Belgium" VALUE "LegalTrademarks", "Licensing information is available at http://www.orthanc-server.com/" VALUE "OriginalFilename", "${FILENAME}" VALUE "ProductName", "${PRODUCT}" VALUE "ProductVersion", "${VERSION_MAJOR}.${VERSION_MINOR}" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1252 // U.S. English END END OrthancPostgreSQL-2.0/Orthanc/Sdk-0.9.5/orthanc/OrthancCDatabasePlugin.h0000644000000000000000000006144212627602430023736 0ustar 00000000000000/** * @ingroup CInterface **/ /** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * In addition, as a special exception, the copyright holders of this * program give permission to link the code of its release with the * OpenSSL project's "OpenSSL" library (or with modified versions of it * that use the same license as the "OpenSSL" library), and distribute * the linked executables. You must obey the GNU General Public License * in all respects for all of the code used other than "OpenSSL". If you * modify file(s) with this exception, you may extend this exception to * your version of the file(s), but you are not obligated to do so. If * you do not wish to do so, delete this exception statement from your * version. If you delete this exception statement from all source files * in the program, then also delete it here. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . **/ #pragma once #include "OrthancCPlugin.h" /** @{ */ #ifdef __cplusplus extern "C" { #endif /** * Opaque structure that represents the context of a custom database engine. * @ingroup Callbacks **/ typedef struct _OrthancPluginDatabaseContext_t OrthancPluginDatabaseContext; /*InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseAnswerChange( OrthancPluginContext* context, OrthancPluginDatabaseContext* database, const OrthancPluginChange* change) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_Change; params.valueUint32 = 0; params.valueGeneric = change; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseAnswerChangesDone( OrthancPluginContext* context, OrthancPluginDatabaseContext* database) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_Change; params.valueUint32 = 1; params.valueGeneric = NULL; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseAnswerInt32( OrthancPluginContext* context, OrthancPluginDatabaseContext* database, int32_t value) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_Int32; params.valueInt32 = value; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseAnswerInt64( OrthancPluginContext* context, OrthancPluginDatabaseContext* database, int64_t value) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_Int64; params.valueInt64 = value; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseAnswerExportedResource( OrthancPluginContext* context, OrthancPluginDatabaseContext* database, const OrthancPluginExportedResource* exported) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_ExportedResource; params.valueUint32 = 0; params.valueGeneric = exported; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseAnswerExportedResourcesDone( OrthancPluginContext* context, OrthancPluginDatabaseContext* database) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_ExportedResource; params.valueUint32 = 1; params.valueGeneric = NULL; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseAnswerDicomTag( OrthancPluginContext* context, OrthancPluginDatabaseContext* database, const OrthancPluginDicomTag* tag) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_DicomTag; params.valueGeneric = tag; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseAnswerAttachment( OrthancPluginContext* context, OrthancPluginDatabaseContext* database, const OrthancPluginAttachment* attachment) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_Attachment; params.valueGeneric = attachment; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseAnswerResource( OrthancPluginContext* context, OrthancPluginDatabaseContext* database, int64_t id, OrthancPluginResourceType resourceType) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_Resource; params.valueInt64 = id; params.valueInt32 = (int32_t) resourceType; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseSignalDeletedAttachment( OrthancPluginContext* context, OrthancPluginDatabaseContext* database, const OrthancPluginAttachment* attachment) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_DeletedAttachment; params.valueGeneric = attachment; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseSignalDeletedResource( OrthancPluginContext* context, OrthancPluginDatabaseContext* database, const char* publicId, OrthancPluginResourceType resourceType) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_DeletedResource; params.valueString = publicId; params.valueInt32 = (int32_t) resourceType; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } ORTHANC_PLUGIN_INLINE void OrthancPluginDatabaseSignalRemainingAncestor( OrthancPluginContext* context, OrthancPluginDatabaseContext* database, const char* ancestorId, OrthancPluginResourceType ancestorType) { _OrthancPluginDatabaseAnswer params; memset(¶ms, 0, sizeof(params)); params.database = database; params.type = _OrthancPluginDatabaseAnswerType_RemainingAncestor; params.valueString = ancestorId; params.valueInt32 = (int32_t) ancestorType; context->InvokeService(context, _OrthancPluginService_DatabaseAnswer, ¶ms); } typedef struct { OrthancPluginErrorCode (*addAttachment) ( /* inputs */ void* payload, int64_t id, const OrthancPluginAttachment* attachment); OrthancPluginErrorCode (*attachChild) ( /* inputs */ void* payload, int64_t parent, int64_t child); OrthancPluginErrorCode (*clearChanges) ( /* inputs */ void* payload); OrthancPluginErrorCode (*clearExportedResources) ( /* inputs */ void* payload); OrthancPluginErrorCode (*createResource) ( /* outputs */ int64_t* id, /* inputs */ void* payload, const char* publicId, OrthancPluginResourceType resourceType); OrthancPluginErrorCode (*deleteAttachment) ( /* inputs */ void* payload, int64_t id, int32_t contentType); OrthancPluginErrorCode (*deleteMetadata) ( /* inputs */ void* payload, int64_t id, int32_t metadataType); OrthancPluginErrorCode (*deleteResource) ( /* inputs */ void* payload, int64_t id); /* Output: Use OrthancPluginDatabaseAnswerString() */ OrthancPluginErrorCode (*getAllPublicIds) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, OrthancPluginResourceType resourceType); /* Output: Use OrthancPluginDatabaseAnswerChange() and * OrthancPluginDatabaseAnswerChangesDone() */ OrthancPluginErrorCode (*getChanges) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t since, uint32_t maxResult); /* Output: Use OrthancPluginDatabaseAnswerInt64() */ OrthancPluginErrorCode (*getChildrenInternalId) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t id); /* Output: Use OrthancPluginDatabaseAnswerString() */ OrthancPluginErrorCode (*getChildrenPublicId) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t id); /* Output: Use OrthancPluginDatabaseAnswerExportedResource() and * OrthancPluginDatabaseAnswerExportedResourcesDone() */ OrthancPluginErrorCode (*getExportedResources) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t since, uint32_t maxResult); /* Output: Use OrthancPluginDatabaseAnswerChange() */ OrthancPluginErrorCode (*getLastChange) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload); /* Output: Use OrthancPluginDatabaseAnswerExportedResource() */ OrthancPluginErrorCode (*getLastExportedResource) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload); /* Output: Use OrthancPluginDatabaseAnswerDicomTag() */ OrthancPluginErrorCode (*getMainDicomTags) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t id); /* Output: Use OrthancPluginDatabaseAnswerString() */ OrthancPluginErrorCode (*getPublicId) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t id); OrthancPluginErrorCode (*getResourceCount) ( /* outputs */ uint64_t* target, /* inputs */ void* payload, OrthancPluginResourceType resourceType); OrthancPluginErrorCode (*getResourceType) ( /* outputs */ OrthancPluginResourceType* resourceType, /* inputs */ void* payload, int64_t id); OrthancPluginErrorCode (*getTotalCompressedSize) ( /* outputs */ uint64_t* target, /* inputs */ void* payload); OrthancPluginErrorCode (*getTotalUncompressedSize) ( /* outputs */ uint64_t* target, /* inputs */ void* payload); OrthancPluginErrorCode (*isExistingResource) ( /* outputs */ int32_t* existing, /* inputs */ void* payload, int64_t id); OrthancPluginErrorCode (*isProtectedPatient) ( /* outputs */ int32_t* isProtected, /* inputs */ void* payload, int64_t id); /* Output: Use OrthancPluginDatabaseAnswerInt32() */ OrthancPluginErrorCode (*listAvailableMetadata) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t id); /* Output: Use OrthancPluginDatabaseAnswerInt32() */ OrthancPluginErrorCode (*listAvailableAttachments) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t id); OrthancPluginErrorCode (*logChange) ( /* inputs */ void* payload, const OrthancPluginChange* change); OrthancPluginErrorCode (*logExportedResource) ( /* inputs */ void* payload, const OrthancPluginExportedResource* exported); /* Output: Use OrthancPluginDatabaseAnswerAttachment() */ OrthancPluginErrorCode (*lookupAttachment) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t id, int32_t contentType); /* Output: Use OrthancPluginDatabaseAnswerString() */ OrthancPluginErrorCode (*lookupGlobalProperty) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int32_t property); /* Use "OrthancPluginDatabaseExtensions::lookupIdentifier3" instead of this function as of Orthanc 0.9.5 (db v6), can be set to NULL. Output: Use OrthancPluginDatabaseAnswerInt64() */ OrthancPluginErrorCode (*lookupIdentifier) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, const OrthancPluginDicomTag* tag); /* Unused starting with Orthanc 0.9.5 (db v6), can be set to NULL. Output: Use OrthancPluginDatabaseAnswerInt64() */ OrthancPluginErrorCode (*lookupIdentifier2) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, const char* value); /* Output: Use OrthancPluginDatabaseAnswerString() */ OrthancPluginErrorCode (*lookupMetadata) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t id, int32_t metadata); /* Output: Use OrthancPluginDatabaseAnswerInt64() */ OrthancPluginErrorCode (*lookupParent) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t id); /* Output: Use OrthancPluginDatabaseAnswerResource() */ OrthancPluginErrorCode (*lookupResource) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, const char* publicId); /* Output: Use OrthancPluginDatabaseAnswerInt64() */ OrthancPluginErrorCode (*selectPatientToRecycle) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload); /* Output: Use OrthancPluginDatabaseAnswerInt64() */ OrthancPluginErrorCode (*selectPatientToRecycle2) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, int64_t patientIdToAvoid); OrthancPluginErrorCode (*setGlobalProperty) ( /* inputs */ void* payload, int32_t property, const char* value); OrthancPluginErrorCode (*setMainDicomTag) ( /* inputs */ void* payload, int64_t id, const OrthancPluginDicomTag* tag); OrthancPluginErrorCode (*setIdentifierTag) ( /* inputs */ void* payload, int64_t id, const OrthancPluginDicomTag* tag); OrthancPluginErrorCode (*setMetadata) ( /* inputs */ void* payload, int64_t id, int32_t metadata, const char* value); OrthancPluginErrorCode (*setProtectedPatient) ( /* inputs */ void* payload, int64_t id, int32_t isProtected); OrthancPluginErrorCode (*startTransaction) ( /* inputs */ void* payload); OrthancPluginErrorCode (*rollbackTransaction) ( /* inputs */ void* payload); OrthancPluginErrorCode (*commitTransaction) ( /* inputs */ void* payload); OrthancPluginErrorCode (*open) ( /* inputs */ void* payload); OrthancPluginErrorCode (*close) ( /* inputs */ void* payload); } OrthancPluginDatabaseBackend; typedef struct { /* Output: Use OrthancPluginDatabaseAnswerString() */ OrthancPluginErrorCode (*getAllPublicIdsWithLimit) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, OrthancPluginResourceType resourceType, uint64_t since, uint64_t limit); OrthancPluginErrorCode (*getDatabaseVersion) ( /* outputs */ uint32_t* version, /* inputs */ void* payload); OrthancPluginErrorCode (*upgradeDatabase) ( /* inputs */ void* payload, uint32_t targetVersion, OrthancPluginStorageArea* storageArea); OrthancPluginErrorCode (*clearMainDicomTags) ( /* inputs */ void* payload, int64_t id); /* Output: Use OrthancPluginDatabaseAnswerInt64() */ OrthancPluginErrorCode (*getAllInternalIds) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, OrthancPluginResourceType resourceType); /* Output: Use OrthancPluginDatabaseAnswerInt64() */ OrthancPluginErrorCode (*lookupIdentifier3) ( /* outputs */ OrthancPluginDatabaseContext* context, /* inputs */ void* payload, OrthancPluginResourceType resourceType, const OrthancPluginDicomTag* tag, OrthancPluginIdentifierConstraint constraint); } OrthancPluginDatabaseExtensions; /*InvokeService(context, _OrthancPluginService_RegisterDatabaseBackend, ¶ms) || result == NULL) { /* Error */ return NULL; } else { return result; } } typedef struct { OrthancPluginDatabaseContext** result; const OrthancPluginDatabaseBackend* backend; void* payload; const OrthancPluginDatabaseExtensions* extensions; uint32_t extensionsSize; } _OrthancPluginRegisterDatabaseBackendV2; /** * Register a custom database back-end. * * Instead of manually filling the OrthancPluginDatabaseBackendV2 * structure, you should instead implement a concrete C++ class * deriving from ::OrthancPlugins::IDatabaseBackend, and register it * using ::OrthancPlugins::DatabaseBackendAdapter::Register(). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param backend The callbacks of the custom database engine. * @param payload Pointer containing private information for the database engine. * @param extensions Extensions to the base database SDK that was shipped until Orthanc 0.9.3. * @return The context of the database engine (it must not be manually freed). * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE OrthancPluginDatabaseContext* OrthancPluginRegisterDatabaseBackendV2( OrthancPluginContext* context, const OrthancPluginDatabaseBackend* backend, const OrthancPluginDatabaseExtensions* extensions, void* payload) { OrthancPluginDatabaseContext* result = NULL; _OrthancPluginRegisterDatabaseBackendV2 params; if (sizeof(int32_t) != sizeof(_OrthancPluginDatabaseAnswerType)) { return NULL; } memset(¶ms, 0, sizeof(params)); params.backend = backend; params.result = &result; params.payload = payload; params.extensions = extensions; params.extensionsSize = sizeof(OrthancPluginDatabaseExtensions); if (context->InvokeService(context, _OrthancPluginService_RegisterDatabaseBackendV2, ¶ms) || result == NULL) { /* Error */ return NULL; } else { return result; } } #ifdef __cplusplus } #endif /** @} */ OrthancPostgreSQL-2.0/Orthanc/Sdk-0.9.5/orthanc/OrthancCPlugin.h0000644000000000000000000047500312627602430022313 0ustar 00000000000000/** * \mainpage * * This C/C++ SDK allows external developers to create plugins that * can be loaded into Orthanc to extend its functionality. Each * Orthanc plugin must expose 4 public functions with the following * signatures: * * -# int32_t OrthancPluginInitialize(const OrthancPluginContext* context): * This function is invoked by Orthanc when it loads the plugin on startup. * The plugin must: * - Check its compatibility with the Orthanc version using * ::OrthancPluginCheckVersion(). * - Store the context pointer so that it can use the plugin * services of Orthanc. * - Register all its REST callbacks using ::OrthancPluginRegisterRestCallback(). * - Possibly register its callback for received DICOM instances using ::OrthancPluginRegisterOnStoredInstanceCallback(). * - Possibly register its callback for changes to the DICOM store using ::OrthancPluginRegisterOnChangeCallback(). * - Possibly register a custom storage area using ::OrthancPluginRegisterStorageArea(). * - Possibly register a custom database back-end area using OrthancPluginRegisterDatabaseBackendV2(). * - Possibly register a handler for C-Find SCP against DICOM worklists using OrthancPluginRegisterWorklistCallback(). * - Possibly register a custom decoder for DICOM images using OrthancPluginRegisterDecodeImageCallback(). * -# void OrthancPluginFinalize(): * This function is invoked by Orthanc during its shutdown. The plugin * must free all its memory. * -# const char* OrthancPluginGetName(): * The plugin must return a short string to identify itself. * -# const char* OrthancPluginGetVersion(): * The plugin must return a string containing its version number. * * The name and the version of a plugin is only used to prevent it * from being loaded twice. Note that, in C++, it is mandatory to * declare these functions within an extern "C" section. * * To ensure multi-threading safety, the various REST callbacks are * guaranteed to be executed in mutual exclusion since Orthanc * 0.8.5. If this feature is undesired (notably when developing * high-performance plugins handling simultaneous requests), use * ::OrthancPluginRegisterRestCallbackNoLock(). **/ /** * @defgroup Images Images and compression * @brief Functions to deal with images and compressed buffers. * * @defgroup REST REST * @brief Functions to answer REST requests in a callback. * * @defgroup Callbacks Callbacks * @brief Functions to register and manage callbacks by the plugins. * * @defgroup Worklists Worklists * @brief Functions to register and manage worklists. * * @defgroup Orthanc Orthanc * @brief Functions to access the content of the Orthanc server. **/ /** * @defgroup Toolbox Toolbox * @brief Generic functions to help with the creation of plugins. **/ /** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * In addition, as a special exception, the copyright holders of this * program give permission to link the code of its release with the * OpenSSL project's "OpenSSL" library (or with modified versions of it * that use the same license as the "OpenSSL" library), and distribute * the linked executables. You must obey the GNU General Public License * in all respects for all of the code used other than "OpenSSL". If you * modify file(s) with this exception, you may extend this exception to * your version of the file(s), but you are not obligated to do so. If * you do not wish to do so, delete this exception statement from your * version. If you delete this exception statement from all source files * in the program, then also delete it here. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . **/ #pragma once #include #include #ifdef WIN32 #define ORTHANC_PLUGINS_API __declspec(dllexport) #else #define ORTHANC_PLUGINS_API #endif #define ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER 0 #define ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER 9 #define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER 5 /******************************************************************** ** Check that function inlining is properly supported. The use of ** inlining is required, to avoid the duplication of object code ** between two compilation modules that would use the Orthanc Plugin ** API. ********************************************************************/ /* If the auto-detection of the "inline" keyword below does not work automatically and that your compiler is known to properly support inlining, uncomment the following #define and adapt the definition of "static inline". */ /* #define ORTHANC_PLUGIN_INLINE static inline */ #ifndef ORTHANC_PLUGIN_INLINE # if __STDC_VERSION__ >= 199901L /* This is C99 or above: http://predef.sourceforge.net/prestd.html */ # define ORTHANC_PLUGIN_INLINE static inline # elif defined(__cplusplus) /* This is C++ */ # define ORTHANC_PLUGIN_INLINE static inline # elif defined(__GNUC__) /* This is GCC running in C89 mode */ # define ORTHANC_PLUGIN_INLINE static __inline # elif defined(_MSC_VER) /* This is Visual Studio running in C89 mode */ # define ORTHANC_PLUGIN_INLINE static __inline # else # error Your compiler is not known to support the "inline" keyword # endif #endif /******************************************************************** ** Inclusion of standard libraries. ********************************************************************/ /** * For Microsoft Visual Studio, a compatibility "stdint.h" can be * downloaded at the following URL: * https://orthanc.googlecode.com/hg/Resources/ThirdParty/VisualStudio/stdint.h **/ #include #include /******************************************************************** ** Definition of the Orthanc Plugin API. ********************************************************************/ /** @{ */ #ifdef __cplusplus extern "C" { #endif /** * The various error codes that can be returned by the Orthanc core. **/ typedef enum { OrthancPluginErrorCode_InternalError = -1 /*!< Internal error */, OrthancPluginErrorCode_Success = 0 /*!< Success */, OrthancPluginErrorCode_Plugin = 1 /*!< Error encountered within the plugin engine */, OrthancPluginErrorCode_NotImplemented = 2 /*!< Not implemented yet */, OrthancPluginErrorCode_ParameterOutOfRange = 3 /*!< Parameter out of range */, OrthancPluginErrorCode_NotEnoughMemory = 4 /*!< Not enough memory */, OrthancPluginErrorCode_BadParameterType = 5 /*!< Bad type for a parameter */, OrthancPluginErrorCode_BadSequenceOfCalls = 6 /*!< Bad sequence of calls */, OrthancPluginErrorCode_InexistentItem = 7 /*!< Accessing an inexistent item */, OrthancPluginErrorCode_BadRequest = 8 /*!< Bad request */, OrthancPluginErrorCode_NetworkProtocol = 9 /*!< Error in the network protocol */, OrthancPluginErrorCode_SystemCommand = 10 /*!< Error while calling a system command */, OrthancPluginErrorCode_Database = 11 /*!< Error with the database engine */, OrthancPluginErrorCode_UriSyntax = 12 /*!< Badly formatted URI */, OrthancPluginErrorCode_InexistentFile = 13 /*!< Inexistent file */, OrthancPluginErrorCode_CannotWriteFile = 14 /*!< Cannot write to file */, OrthancPluginErrorCode_BadFileFormat = 15 /*!< Bad file format */, OrthancPluginErrorCode_Timeout = 16 /*!< Timeout */, OrthancPluginErrorCode_UnknownResource = 17 /*!< Unknown resource */, OrthancPluginErrorCode_IncompatibleDatabaseVersion = 18 /*!< Incompatible version of the database */, OrthancPluginErrorCode_FullStorage = 19 /*!< The file storage is full */, OrthancPluginErrorCode_CorruptedFile = 20 /*!< Corrupted file (e.g. inconsistent MD5 hash) */, OrthancPluginErrorCode_InexistentTag = 21 /*!< Inexistent tag */, OrthancPluginErrorCode_ReadOnly = 22 /*!< Cannot modify a read-only data structure */, OrthancPluginErrorCode_IncompatibleImageFormat = 23 /*!< Incompatible format of the images */, OrthancPluginErrorCode_IncompatibleImageSize = 24 /*!< Incompatible size of the images */, OrthancPluginErrorCode_SharedLibrary = 25 /*!< Error while using a shared library (plugin) */, OrthancPluginErrorCode_UnknownPluginService = 26 /*!< Plugin invoking an unknown service */, OrthancPluginErrorCode_UnknownDicomTag = 27 /*!< Unknown DICOM tag */, OrthancPluginErrorCode_BadJson = 28 /*!< Cannot parse a JSON document */, OrthancPluginErrorCode_Unauthorized = 29 /*!< Bad credentials were provided to an HTTP request */, OrthancPluginErrorCode_BadFont = 30 /*!< Badly formatted font file */, OrthancPluginErrorCode_DatabasePlugin = 31 /*!< The plugin implementing a custom database back-end does not fulfill the proper interface */, OrthancPluginErrorCode_StorageAreaPlugin = 32 /*!< Error in the plugin implementing a custom storage area */, OrthancPluginErrorCode_EmptyRequest = 33 /*!< The request is empty */, OrthancPluginErrorCode_NotAcceptable = 34 /*!< Cannot send a response which is acceptable according to the Accept HTTP header */, OrthancPluginErrorCode_SQLiteNotOpened = 1000 /*!< SQLite: The database is not opened */, OrthancPluginErrorCode_SQLiteAlreadyOpened = 1001 /*!< SQLite: Connection is already open */, OrthancPluginErrorCode_SQLiteCannotOpen = 1002 /*!< SQLite: Unable to open the database */, OrthancPluginErrorCode_SQLiteStatementAlreadyUsed = 1003 /*!< SQLite: This cached statement is already being referred to */, OrthancPluginErrorCode_SQLiteExecute = 1004 /*!< SQLite: Cannot execute a command */, OrthancPluginErrorCode_SQLiteRollbackWithoutTransaction = 1005 /*!< SQLite: Rolling back a nonexistent transaction (have you called Begin()?) */, OrthancPluginErrorCode_SQLiteCommitWithoutTransaction = 1006 /*!< SQLite: Committing a nonexistent transaction */, OrthancPluginErrorCode_SQLiteRegisterFunction = 1007 /*!< SQLite: Unable to register a function */, OrthancPluginErrorCode_SQLiteFlush = 1008 /*!< SQLite: Unable to flush the database */, OrthancPluginErrorCode_SQLiteCannotRun = 1009 /*!< SQLite: Cannot run a cached statement */, OrthancPluginErrorCode_SQLiteCannotStep = 1010 /*!< SQLite: Cannot step over a cached statement */, OrthancPluginErrorCode_SQLiteBindOutOfRange = 1011 /*!< SQLite: Bing a value while out of range (serious error) */, OrthancPluginErrorCode_SQLitePrepareStatement = 1012 /*!< SQLite: Cannot prepare a cached statement */, OrthancPluginErrorCode_SQLiteTransactionAlreadyStarted = 1013 /*!< SQLite: Beginning the same transaction twice */, OrthancPluginErrorCode_SQLiteTransactionCommit = 1014 /*!< SQLite: Failure when committing the transaction */, OrthancPluginErrorCode_SQLiteTransactionBegin = 1015 /*!< SQLite: Cannot start a transaction */, OrthancPluginErrorCode_DirectoryOverFile = 2000 /*!< The directory to be created is already occupied by a regular file */, OrthancPluginErrorCode_FileStorageCannotWrite = 2001 /*!< Unable to create a subdirectory or a file in the file storage */, OrthancPluginErrorCode_DirectoryExpected = 2002 /*!< The specified path does not point to a directory */, OrthancPluginErrorCode_HttpPortInUse = 2003 /*!< The TCP port of the HTTP server is already in use */, OrthancPluginErrorCode_DicomPortInUse = 2004 /*!< The TCP port of the DICOM server is already in use */, OrthancPluginErrorCode_BadHttpStatusInRest = 2005 /*!< This HTTP status is not allowed in a REST API */, OrthancPluginErrorCode_RegularFileExpected = 2006 /*!< The specified path does not point to a regular file */, OrthancPluginErrorCode_PathToExecutable = 2007 /*!< Unable to get the path to the executable */, OrthancPluginErrorCode_MakeDirectory = 2008 /*!< Cannot create a directory */, OrthancPluginErrorCode_BadApplicationEntityTitle = 2009 /*!< An application entity title (AET) cannot be empty or be longer than 16 characters */, OrthancPluginErrorCode_NoCFindHandler = 2010 /*!< No request handler factory for DICOM C-FIND SCP */, OrthancPluginErrorCode_NoCMoveHandler = 2011 /*!< No request handler factory for DICOM C-MOVE SCP */, OrthancPluginErrorCode_NoCStoreHandler = 2012 /*!< No request handler factory for DICOM C-STORE SCP */, OrthancPluginErrorCode_NoApplicationEntityFilter = 2013 /*!< No application entity filter */, OrthancPluginErrorCode_NoSopClassOrInstance = 2014 /*!< DicomUserConnection: Unable to find the SOP class and instance */, OrthancPluginErrorCode_NoPresentationContext = 2015 /*!< DicomUserConnection: No acceptable presentation context for modality */, OrthancPluginErrorCode_DicomFindUnavailable = 2016 /*!< DicomUserConnection: The C-FIND command is not supported by the remote SCP */, OrthancPluginErrorCode_DicomMoveUnavailable = 2017 /*!< DicomUserConnection: The C-MOVE command is not supported by the remote SCP */, OrthancPluginErrorCode_CannotStoreInstance = 2018 /*!< Cannot store an instance */, OrthancPluginErrorCode_CreateDicomNotString = 2019 /*!< Only string values are supported when creating DICOM instances */, OrthancPluginErrorCode_CreateDicomOverrideTag = 2020 /*!< Trying to override a value inherited from a parent module */, OrthancPluginErrorCode_CreateDicomUseContent = 2021 /*!< Use \"Content\" to inject an image into a new DICOM instance */, OrthancPluginErrorCode_CreateDicomNoPayload = 2022 /*!< No payload is present for one instance in the series */, OrthancPluginErrorCode_CreateDicomUseDataUriScheme = 2023 /*!< The payload of the DICOM instance must be specified according to Data URI scheme */, OrthancPluginErrorCode_CreateDicomBadParent = 2024 /*!< Trying to attach a new DICOM instance to an inexistent resource */, OrthancPluginErrorCode_CreateDicomParentIsInstance = 2025 /*!< Trying to attach a new DICOM instance to an instance (must be a series, study or patient) */, OrthancPluginErrorCode_CreateDicomParentEncoding = 2026 /*!< Unable to get the encoding of the parent resource */, OrthancPluginErrorCode_UnknownModality = 2027 /*!< Unknown modality */, OrthancPluginErrorCode_BadJobOrdering = 2028 /*!< Bad ordering of filters in a job */, OrthancPluginErrorCode_JsonToLuaTable = 2029 /*!< Cannot convert the given JSON object to a Lua table */, OrthancPluginErrorCode_CannotCreateLua = 2030 /*!< Cannot create the Lua context */, OrthancPluginErrorCode_CannotExecuteLua = 2031 /*!< Cannot execute a Lua command */, OrthancPluginErrorCode_LuaAlreadyExecuted = 2032 /*!< Arguments cannot be pushed after the Lua function is executed */, OrthancPluginErrorCode_LuaBadOutput = 2033 /*!< The Lua function does not give the expected number of outputs */, OrthancPluginErrorCode_NotLuaPredicate = 2034 /*!< The Lua function is not a predicate (only true/false outputs allowed) */, OrthancPluginErrorCode_LuaReturnsNoString = 2035 /*!< The Lua function does not return a string */, OrthancPluginErrorCode_StorageAreaAlreadyRegistered = 2036 /*!< Another plugin has already registered a custom storage area */, OrthancPluginErrorCode_DatabaseBackendAlreadyRegistered = 2037 /*!< Another plugin has already registered a custom database back-end */, OrthancPluginErrorCode_DatabaseNotInitialized = 2038 /*!< Plugin trying to call the database during its initialization */, OrthancPluginErrorCode_SslDisabled = 2039 /*!< Orthanc has been built without SSL support */, OrthancPluginErrorCode_CannotOrderSlices = 2040 /*!< Unable to order the slices of the series */, OrthancPluginErrorCode_NoWorklistHandler = 2041 /*!< No request handler factory for DICOM C-Find Modality SCP */, _OrthancPluginErrorCode_INTERNAL = 0x7fffffff } OrthancPluginErrorCode; /** * Forward declaration of one of the mandatory functions for Orthanc * plugins. **/ ORTHANC_PLUGINS_API const char* OrthancPluginGetName(); /** * The various HTTP methods for a REST call. **/ typedef enum { OrthancPluginHttpMethod_Get = 1, /*!< GET request */ OrthancPluginHttpMethod_Post = 2, /*!< POST request */ OrthancPluginHttpMethod_Put = 3, /*!< PUT request */ OrthancPluginHttpMethod_Delete = 4, /*!< DELETE request */ _OrthancPluginHttpMethod_INTERNAL = 0x7fffffff } OrthancPluginHttpMethod; /** * @brief The parameters of a REST request. * @ingroup Callbacks **/ typedef struct { /** * @brief The HTTP method. **/ OrthancPluginHttpMethod method; /** * @brief The number of groups of the regular expression. **/ uint32_t groupsCount; /** * @brief The matched values for the groups of the regular expression. **/ const char* const* groups; /** * @brief For a GET request, the number of GET parameters. **/ uint32_t getCount; /** * @brief For a GET request, the keys of the GET parameters. **/ const char* const* getKeys; /** * @brief For a GET request, the values of the GET parameters. **/ const char* const* getValues; /** * @brief For a PUT or POST request, the content of the body. **/ const char* body; /** * @brief For a PUT or POST request, the number of bytes of the body. **/ uint32_t bodySize; /* -------------------------------------------------- New in version 0.8.1 -------------------------------------------------- */ /** * @brief The number of HTTP headers. **/ uint32_t headersCount; /** * @brief The keys of the HTTP headers (always converted to low-case). **/ const char* const* headersKeys; /** * @brief The values of the HTTP headers. **/ const char* const* headersValues; } OrthancPluginHttpRequest; typedef enum { /* Generic services */ _OrthancPluginService_LogInfo = 1, _OrthancPluginService_LogWarning = 2, _OrthancPluginService_LogError = 3, _OrthancPluginService_GetOrthancPath = 4, _OrthancPluginService_GetOrthancDirectory = 5, _OrthancPluginService_GetConfigurationPath = 6, _OrthancPluginService_SetPluginProperty = 7, _OrthancPluginService_GetGlobalProperty = 8, _OrthancPluginService_SetGlobalProperty = 9, _OrthancPluginService_GetCommandLineArgumentsCount = 10, _OrthancPluginService_GetCommandLineArgument = 11, _OrthancPluginService_GetExpectedDatabaseVersion = 12, _OrthancPluginService_GetConfiguration = 13, _OrthancPluginService_BufferCompression = 14, _OrthancPluginService_ReadFile = 15, _OrthancPluginService_WriteFile = 16, _OrthancPluginService_GetErrorDescription = 17, _OrthancPluginService_CallHttpClient = 18, _OrthancPluginService_RegisterErrorCode = 19, _OrthancPluginService_RegisterDictionaryTag = 20, _OrthancPluginService_DicomBufferToJson = 21, _OrthancPluginService_DicomInstanceToJson = 22, _OrthancPluginService_CreateDicom = 23, _OrthancPluginService_ComputeMd5 = 24, _OrthancPluginService_ComputeSha1 = 25, _OrthancPluginService_LookupDictionary = 26, /* Registration of callbacks */ _OrthancPluginService_RegisterRestCallback = 1000, _OrthancPluginService_RegisterOnStoredInstanceCallback = 1001, _OrthancPluginService_RegisterStorageArea = 1002, _OrthancPluginService_RegisterOnChangeCallback = 1003, _OrthancPluginService_RegisterRestCallbackNoLock = 1004, _OrthancPluginService_RegisterWorklistCallback = 1005, _OrthancPluginService_RegisterDecodeImageCallback = 1006, /* Sending answers to REST calls */ _OrthancPluginService_AnswerBuffer = 2000, _OrthancPluginService_CompressAndAnswerPngImage = 2001, /* Unused as of Orthanc 0.9.4 */ _OrthancPluginService_Redirect = 2002, _OrthancPluginService_SendHttpStatusCode = 2003, _OrthancPluginService_SendUnauthorized = 2004, _OrthancPluginService_SendMethodNotAllowed = 2005, _OrthancPluginService_SetCookie = 2006, _OrthancPluginService_SetHttpHeader = 2007, _OrthancPluginService_StartMultipartAnswer = 2008, _OrthancPluginService_SendMultipartItem = 2009, _OrthancPluginService_SendHttpStatus = 2010, _OrthancPluginService_CompressAndAnswerImage = 2011, /* Access to the Orthanc database and API */ _OrthancPluginService_GetDicomForInstance = 3000, _OrthancPluginService_RestApiGet = 3001, _OrthancPluginService_RestApiPost = 3002, _OrthancPluginService_RestApiDelete = 3003, _OrthancPluginService_RestApiPut = 3004, _OrthancPluginService_LookupPatient = 3005, _OrthancPluginService_LookupStudy = 3006, _OrthancPluginService_LookupSeries = 3007, _OrthancPluginService_LookupInstance = 3008, _OrthancPluginService_LookupStudyWithAccessionNumber = 3009, _OrthancPluginService_RestApiGetAfterPlugins = 3010, _OrthancPluginService_RestApiPostAfterPlugins = 3011, _OrthancPluginService_RestApiDeleteAfterPlugins = 3012, _OrthancPluginService_RestApiPutAfterPlugins = 3013, _OrthancPluginService_ReconstructMainDicomTags = 3014, _OrthancPluginService_RestApiGet2 = 3015, /* Access to DICOM instances */ _OrthancPluginService_GetInstanceRemoteAet = 4000, _OrthancPluginService_GetInstanceSize = 4001, _OrthancPluginService_GetInstanceData = 4002, _OrthancPluginService_GetInstanceJson = 4003, _OrthancPluginService_GetInstanceSimplifiedJson = 4004, _OrthancPluginService_HasInstanceMetadata = 4005, _OrthancPluginService_GetInstanceMetadata = 4006, _OrthancPluginService_GetInstanceOrigin = 4007, /* Services for plugins implementing a database back-end */ _OrthancPluginService_RegisterDatabaseBackend = 5000, _OrthancPluginService_DatabaseAnswer = 5001, _OrthancPluginService_RegisterDatabaseBackendV2 = 5002, _OrthancPluginService_StorageAreaCreate = 5003, _OrthancPluginService_StorageAreaRead = 5004, _OrthancPluginService_StorageAreaRemove = 5005, /* Primitives for handling images */ _OrthancPluginService_GetImagePixelFormat = 6000, _OrthancPluginService_GetImageWidth = 6001, _OrthancPluginService_GetImageHeight = 6002, _OrthancPluginService_GetImagePitch = 6003, _OrthancPluginService_GetImageBuffer = 6004, _OrthancPluginService_UncompressImage = 6005, _OrthancPluginService_FreeImage = 6006, _OrthancPluginService_CompressImage = 6007, _OrthancPluginService_ConvertPixelFormat = 6008, _OrthancPluginService_GetFontsCount = 6009, _OrthancPluginService_GetFontInfo = 6010, _OrthancPluginService_DrawText = 6011, _OrthancPluginService_CreateImage = 6012, _OrthancPluginService_CreateImageAccessor = 6013, _OrthancPluginService_DecodeDicomImage = 6014, /* Primitives for handling worklists */ _OrthancPluginService_WorklistAddAnswer = 7000, _OrthancPluginService_WorklistMarkIncomplete = 7001, _OrthancPluginService_WorklistIsMatch = 7002, _OrthancPluginService_WorklistGetDicomQuery = 7003, _OrthancPluginService_INTERNAL = 0x7fffffff } _OrthancPluginService; typedef enum { _OrthancPluginProperty_Description = 1, _OrthancPluginProperty_RootUri = 2, _OrthancPluginProperty_OrthancExplorer = 3, _OrthancPluginProperty_INTERNAL = 0x7fffffff } _OrthancPluginProperty; /** * The memory layout of the pixels of an image. * @ingroup Images **/ typedef enum { /** * @brief Graylevel 8bpp image. * * The image is graylevel. Each pixel is unsigned and stored in * one byte. **/ OrthancPluginPixelFormat_Grayscale8 = 1, /** * @brief Graylevel, unsigned 16bpp image. * * The image is graylevel. Each pixel is unsigned and stored in * two bytes. **/ OrthancPluginPixelFormat_Grayscale16 = 2, /** * @brief Graylevel, signed 16bpp image. * * The image is graylevel. Each pixel is signed and stored in two * bytes. **/ OrthancPluginPixelFormat_SignedGrayscale16 = 3, /** * @brief Color image in RGB24 format. * * This format describes a color image. The pixels are stored in 3 * consecutive bytes. The memory layout is RGB. **/ OrthancPluginPixelFormat_RGB24 = 4, /** * @brief Color image in RGBA32 format. * * This format describes a color image. The pixels are stored in 4 * consecutive bytes. The memory layout is RGBA. **/ OrthancPluginPixelFormat_RGBA32 = 5, OrthancPluginPixelFormat_Unknown = 6, /*!< Unknown pixel format */ _OrthancPluginPixelFormat_INTERNAL = 0x7fffffff } OrthancPluginPixelFormat; /** * The content types that are supported by Orthanc plugins. **/ typedef enum { OrthancPluginContentType_Unknown = 0, /*!< Unknown content type */ OrthancPluginContentType_Dicom = 1, /*!< DICOM */ OrthancPluginContentType_DicomAsJson = 2, /*!< JSON summary of a DICOM file */ _OrthancPluginContentType_INTERNAL = 0x7fffffff } OrthancPluginContentType; /** * The supported types of DICOM resources. **/ typedef enum { OrthancPluginResourceType_Patient = 0, /*!< Patient */ OrthancPluginResourceType_Study = 1, /*!< Study */ OrthancPluginResourceType_Series = 2, /*!< Series */ OrthancPluginResourceType_Instance = 3, /*!< Instance */ OrthancPluginResourceType_None = 4, /*!< Unavailable resource type */ _OrthancPluginResourceType_INTERNAL = 0x7fffffff } OrthancPluginResourceType; /** * The supported types of changes that can happen to DICOM resources. * @ingroup Callbacks **/ typedef enum { OrthancPluginChangeType_CompletedSeries = 0, /*!< Series is now complete */ OrthancPluginChangeType_Deleted = 1, /*!< Deleted resource */ OrthancPluginChangeType_NewChildInstance = 2, /*!< A new instance was added to this resource */ OrthancPluginChangeType_NewInstance = 3, /*!< New instance received */ OrthancPluginChangeType_NewPatient = 4, /*!< New patient created */ OrthancPluginChangeType_NewSeries = 5, /*!< New series created */ OrthancPluginChangeType_NewStudy = 6, /*!< New study created */ OrthancPluginChangeType_StablePatient = 7, /*!< Timeout: No new instance in this patient */ OrthancPluginChangeType_StableSeries = 8, /*!< Timeout: No new instance in this series */ OrthancPluginChangeType_StableStudy = 9, /*!< Timeout: No new instance in this study */ OrthancPluginChangeType_OrthancStarted = 10, /*!< Orthanc has started */ OrthancPluginChangeType_OrthancStopped = 11, /*!< Orthanc is stopping */ OrthancPluginChangeType_UpdatedAttachment = 12, /*!< Some user-defined attachment has changed for this resource */ OrthancPluginChangeType_UpdatedMetadata = 13, /*!< Some user-defined metadata has changed for this resource */ _OrthancPluginChangeType_INTERNAL = 0x7fffffff } OrthancPluginChangeType; /** * The compression algorithms that are supported by the Orthanc core. * @ingroup Images **/ typedef enum { OrthancPluginCompressionType_Zlib = 0, /*!< Standard zlib compression */ OrthancPluginCompressionType_ZlibWithSize = 1, /*!< zlib, prefixed with uncompressed size (uint64_t) */ OrthancPluginCompressionType_Gzip = 2, /*!< Standard gzip compression */ OrthancPluginCompressionType_GzipWithSize = 3, /*!< gzip, prefixed with uncompressed size (uint64_t) */ _OrthancPluginCompressionType_INTERNAL = 0x7fffffff } OrthancPluginCompressionType; /** * The image formats that are supported by the Orthanc core. * @ingroup Images **/ typedef enum { OrthancPluginImageFormat_Png = 0, /*!< Image compressed using PNG */ OrthancPluginImageFormat_Jpeg = 1, /*!< Image compressed using JPEG */ OrthancPluginImageFormat_Dicom = 2, /*!< Image compressed using DICOM */ _OrthancPluginImageFormat_INTERNAL = 0x7fffffff } OrthancPluginImageFormat; /** * The value representations present in the DICOM standard (version 2013). * @ingroup Toolbox **/ typedef enum { OrthancPluginValueRepresentation_AE = 1, /*!< Application Entity */ OrthancPluginValueRepresentation_AS = 2, /*!< Age String */ OrthancPluginValueRepresentation_AT = 3, /*!< Attribute Tag */ OrthancPluginValueRepresentation_CS = 4, /*!< Code String */ OrthancPluginValueRepresentation_DA = 5, /*!< Date */ OrthancPluginValueRepresentation_DS = 6, /*!< Decimal String */ OrthancPluginValueRepresentation_DT = 7, /*!< Date Time */ OrthancPluginValueRepresentation_FD = 8, /*!< Floating Point Double */ OrthancPluginValueRepresentation_FL = 9, /*!< Floating Point Single */ OrthancPluginValueRepresentation_IS = 10, /*!< Integer String */ OrthancPluginValueRepresentation_LO = 11, /*!< Long String */ OrthancPluginValueRepresentation_LT = 12, /*!< Long Text */ OrthancPluginValueRepresentation_OB = 13, /*!< Other Byte String */ OrthancPluginValueRepresentation_OF = 14, /*!< Other Float String */ OrthancPluginValueRepresentation_OW = 15, /*!< Other Word String */ OrthancPluginValueRepresentation_PN = 16, /*!< Person Name */ OrthancPluginValueRepresentation_SH = 17, /*!< Short String */ OrthancPluginValueRepresentation_SL = 18, /*!< Signed Long */ OrthancPluginValueRepresentation_SQ = 19, /*!< Sequence of Items */ OrthancPluginValueRepresentation_SS = 20, /*!< Signed Short */ OrthancPluginValueRepresentation_ST = 21, /*!< Short Text */ OrthancPluginValueRepresentation_TM = 22, /*!< Time */ OrthancPluginValueRepresentation_UI = 23, /*!< Unique Identifier (UID) */ OrthancPluginValueRepresentation_UL = 24, /*!< Unsigned Long */ OrthancPluginValueRepresentation_UN = 25, /*!< Unknown */ OrthancPluginValueRepresentation_US = 26, /*!< Unsigned Short */ OrthancPluginValueRepresentation_UT = 27, /*!< Unlimited Text */ _OrthancPluginValueRepresentation_INTERNAL = 0x7fffffff } OrthancPluginValueRepresentation; /** * The possible output formats for a DICOM-to-JSON conversion. * @ingroup Toolbox * @see OrthancPluginDicomToJson() **/ typedef enum { OrthancPluginDicomToJsonFormat_Full = 1, /*!< Full output, with most details */ OrthancPluginDicomToJsonFormat_Short = 2, /*!< Tags output as hexadecimal numbers */ OrthancPluginDicomToJsonFormat_Human = 3, /*!< Human-readable JSON */ _OrthancPluginDicomToJsonFormat_INTERNAL = 0x7fffffff } OrthancPluginDicomToJsonFormat; /** * Flags to customize a DICOM-to-JSON conversion. By default, binary * tags are formatted using Data URI scheme. * @ingroup Toolbox **/ typedef enum { OrthancPluginDicomToJsonFlags_IncludeBinary = (1 << 0), /*!< Include the binary tags */ OrthancPluginDicomToJsonFlags_IncludePrivateTags = (1 << 1), /*!< Include the private tags */ OrthancPluginDicomToJsonFlags_IncludeUnknownTags = (1 << 2), /*!< Include the tags unknown by the dictionary */ OrthancPluginDicomToJsonFlags_IncludePixelData = (1 << 3), /*!< Include the pixel data */ OrthancPluginDicomToJsonFlags_ConvertBinaryToAscii = (1 << 4), /*!< Output binary tags as-is, dropping non-ASCII */ OrthancPluginDicomToJsonFlags_ConvertBinaryToNull = (1 << 5), /*!< Signal binary tags as null values */ _OrthancPluginDicomToJsonFlags_INTERNAL = 0x7fffffff } OrthancPluginDicomToJsonFlags; /** * Flags to the creation of a DICOM file. * @ingroup Toolbox * @see OrthancPluginCreateDicom() **/ typedef enum { OrthancPluginCreateDicomFlags_DecodeDataUriScheme = (1 << 0), /*!< Decode fields encoded using data URI scheme */ OrthancPluginCreateDicomFlags_GenerateIdentifiers = (1 << 1), /*!< Automatically generate DICOM identifiers */ _OrthancPluginCreateDicomFlags_INTERNAL = 0x7fffffff } OrthancPluginCreateDicomFlags; /** * The constraints on the DICOM identifiers that must be supported * by the database plugins. **/ typedef enum { OrthancPluginIdentifierConstraint_Equal = 1, /*!< Equal */ OrthancPluginIdentifierConstraint_SmallerOrEqual = 2, /*!< Less or equal */ OrthancPluginIdentifierConstraint_GreaterOrEqual = 3, /*!< More or equal */ OrthancPluginIdentifierConstraint_Wildcard = 4, /*!< Case-sensitive wildcard matching (with * and ?) */ _OrthancPluginIdentifierConstraint_INTERNAL = 0x7fffffff } OrthancPluginIdentifierConstraint; /** * The origin of a DICOM instance that has been received by Orthanc. **/ typedef enum { OrthancPluginInstanceOrigin_Unknown = 1, /*!< Unknown origin */ OrthancPluginInstanceOrigin_DicomProtocol = 2, /*!< Instance received through DICOM protocol */ OrthancPluginInstanceOrigin_RestApi = 3, /*!< Instance received through REST API of Orthanc */ OrthancPluginInstanceOrigin_Plugin = 4, /*!< Instance added to Orthanc by a plugin */ OrthancPluginInstanceOrigin_Lua = 5, /*!< Instance added to Orthanc by a Lua script */ _OrthancPluginInstanceOrigin_INTERNAL = 0x7fffffff } OrthancPluginInstanceOrigin; /** * @brief A memory buffer allocated by the core system of Orthanc. * * A memory buffer allocated by the core system of Orthanc. When the * content of the buffer is not useful anymore, it must be free by a * call to ::OrthancPluginFreeMemoryBuffer(). **/ typedef struct { /** * @brief The content of the buffer. **/ void* data; /** * @brief The number of bytes in the buffer. **/ uint32_t size; } OrthancPluginMemoryBuffer; /** * @brief Opaque structure that represents the HTTP connection to the client application. * @ingroup Callback **/ typedef struct _OrthancPluginRestOutput_t OrthancPluginRestOutput; /** * @brief Opaque structure that represents a DICOM instance received by Orthanc. **/ typedef struct _OrthancPluginDicomInstance_t OrthancPluginDicomInstance; /** * @brief Opaque structure that represents an image that is uncompressed in memory. * @ingroup Images **/ typedef struct _OrthancPluginImage_t OrthancPluginImage; /** * @brief Opaque structure that represents the storage area that is actually used by Orthanc. * @ingroup Images **/ typedef struct _OrthancPluginStorageArea_t OrthancPluginStorageArea; /** * @brief Opaque structure to an object that represents a C-Find query. * @ingroup Worklists **/ typedef struct _OrthancPluginWorklistQuery_t OrthancPluginWorklistQuery; /** * @brief Opaque structure to an object that represents the answers to a C-Find query. * @ingroup Worklists **/ typedef struct _OrthancPluginWorklistAnswers_t OrthancPluginWorklistAnswers; /** * @brief Signature of a callback function that answers to a REST request. * @ingroup Callbacks **/ typedef OrthancPluginErrorCode (*OrthancPluginRestCallback) ( OrthancPluginRestOutput* output, const char* url, const OrthancPluginHttpRequest* request); /** * @brief Signature of a callback function that is triggered when Orthanc receives a DICOM instance. * @ingroup Callbacks **/ typedef OrthancPluginErrorCode (*OrthancPluginOnStoredInstanceCallback) ( OrthancPluginDicomInstance* instance, const char* instanceId); /** * @brief Signature of a callback function that is triggered when a change happens to some DICOM resource. * @ingroup Callbacks **/ typedef OrthancPluginErrorCode (*OrthancPluginOnChangeCallback) ( OrthancPluginChangeType changeType, OrthancPluginResourceType resourceType, const char* resourceId); /** * @brief Signature of a callback function to decode a DICOM instance as an image. * @ingroup Callbacks **/ typedef OrthancPluginErrorCode (*OrthancPluginDecodeImageCallback) ( OrthancPluginImage** target, const void* dicom, const uint32_t size, uint32_t frameIndex); /** * @brief Signature of a function to free dynamic memory. **/ typedef void (*OrthancPluginFree) (void* buffer); /** * @brief Callback for writing to the storage area. * * Signature of a callback function that is triggered when Orthanc writes a file to the storage area. * * @param uuid The UUID of the file. * @param content The content of the file. * @param size The size of the file. * @param type The content type corresponding to this file. * @return 0 if success, other value if error. * @ingroup Callbacks **/ typedef OrthancPluginErrorCode (*OrthancPluginStorageCreate) ( const char* uuid, const void* content, int64_t size, OrthancPluginContentType type); /** * @brief Callback for reading from the storage area. * * Signature of a callback function that is triggered when Orthanc reads a file from the storage area. * * @param content The content of the file (output). * @param size The size of the file (output). * @param uuid The UUID of the file of interest. * @param type The content type corresponding to this file. * @return 0 if success, other value if error. * @ingroup Callbacks **/ typedef OrthancPluginErrorCode (*OrthancPluginStorageRead) ( void** content, int64_t* size, const char* uuid, OrthancPluginContentType type); /** * @brief Callback for removing a file from the storage area. * * Signature of a callback function that is triggered when Orthanc deletes a file from the storage area. * * @param uuid The UUID of the file to be removed. * @param type The content type corresponding to this file. * @return 0 if success, other value if error. * @ingroup Callbacks **/ typedef OrthancPluginErrorCode (*OrthancPluginStorageRemove) ( const char* uuid, OrthancPluginContentType type); /** * @brief Callback to handle the C-Find SCP requests received by Orthanc. * * Signature of a callback function that is triggered when Orthanc * receives a C-Find SCP request against modality worklists. * * @param answers The target structure where answers must be stored. * @param query The worklist query. * @param remoteAet The Application Entity Title (AET) of the modality from which the request originates. * @param calledAet The Application Entity Title (AET) of the modality that is called by the request. * @return 0 if success, other value if error. * @ingroup Worklists **/ typedef OrthancPluginErrorCode (*OrthancPluginWorklistCallback) ( OrthancPluginWorklistAnswers* answers, const OrthancPluginWorklistQuery* query, const char* remoteAet, const char* calledAet); /** * @brief Data structure that contains information about the Orthanc core. **/ typedef struct _OrthancPluginContext_t { void* pluginsManager; const char* orthancVersion; OrthancPluginFree Free; OrthancPluginErrorCode (*InvokeService) (struct _OrthancPluginContext_t* context, _OrthancPluginService service, const void* params); } OrthancPluginContext; /** * @brief An entry in the dictionary of DICOM tags. **/ typedef struct { uint16_t group; /*!< The group of the tag */ uint16_t element; /*!< The element of the tag */ OrthancPluginValueRepresentation vr; /*!< The value representation of the tag */ uint32_t minMultiplicity; /*!< The minimum multiplicity of the tag */ uint32_t maxMultiplicity; /*!< The maximum multiplicity of the tag (0 means arbitrary) */ } OrthancPluginDictionaryEntry; /** * @brief Free a string. * * Free a string that was allocated by the core system of Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param str The string to be freed. **/ ORTHANC_PLUGIN_INLINE void OrthancPluginFreeString( OrthancPluginContext* context, char* str) { if (str != NULL) { context->Free(str); } } /** * @brief Check the compatibility of the plugin wrt. the version of its hosting Orthanc. * * This function checks whether the version of this C header is * compatible with the current version of Orthanc. The result of * this function should always be checked in the * OrthancPluginInitialize() entry point of the plugin. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @return 1 if and only if the versions are compatible. If the * result is 0, the initialization of the plugin should fail. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE int OrthancPluginCheckVersion( OrthancPluginContext* context) { int major, minor, revision; if (sizeof(int32_t) != sizeof(OrthancPluginErrorCode) || sizeof(int32_t) != sizeof(OrthancPluginHttpMethod) || sizeof(int32_t) != sizeof(_OrthancPluginService) || sizeof(int32_t) != sizeof(_OrthancPluginProperty) || sizeof(int32_t) != sizeof(OrthancPluginPixelFormat) || sizeof(int32_t) != sizeof(OrthancPluginContentType) || sizeof(int32_t) != sizeof(OrthancPluginResourceType) || sizeof(int32_t) != sizeof(OrthancPluginChangeType) || sizeof(int32_t) != sizeof(OrthancPluginCompressionType) || sizeof(int32_t) != sizeof(OrthancPluginImageFormat) || sizeof(int32_t) != sizeof(OrthancPluginValueRepresentation) || sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFormat) || sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFlags) || sizeof(int32_t) != sizeof(OrthancPluginCreateDicomFlags) || sizeof(int32_t) != sizeof(OrthancPluginIdentifierConstraint) || sizeof(int32_t) != sizeof(OrthancPluginInstanceOrigin)) { /* Mismatch in the size of the enumerations */ return 0; } /* Assume compatibility with the mainline */ if (!strcmp(context->orthancVersion, "mainline")) { return 1; } /* Parse the version of the Orthanc core */ if ( #ifdef _MSC_VER sscanf_s #else sscanf #endif (context->orthancVersion, "%4d.%4d.%4d", &major, &minor, &revision) != 3) { return 0; } /* Check the major number of the version */ if (major > ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER) { return 1; } if (major < ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER) { return 0; } /* Check the minor number of the version */ if (minor > ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER) { return 1; } if (minor < ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER) { return 0; } /* Check the revision number of the version */ if (revision >= ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER) { return 1; } else { return 0; } } /** * @brief Free a memory buffer. * * Free a memory buffer that was allocated by the core system of Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param buffer The memory buffer to release. **/ ORTHANC_PLUGIN_INLINE void OrthancPluginFreeMemoryBuffer( OrthancPluginContext* context, OrthancPluginMemoryBuffer* buffer) { context->Free(buffer->data); } /** * @brief Log an error. * * Log an error message using the Orthanc logging system. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param message The message to be logged. **/ ORTHANC_PLUGIN_INLINE void OrthancPluginLogError( OrthancPluginContext* context, const char* message) { context->InvokeService(context, _OrthancPluginService_LogError, message); } /** * @brief Log a warning. * * Log a warning message using the Orthanc logging system. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param message The message to be logged. **/ ORTHANC_PLUGIN_INLINE void OrthancPluginLogWarning( OrthancPluginContext* context, const char* message) { context->InvokeService(context, _OrthancPluginService_LogWarning, message); } /** * @brief Log an information. * * Log an information message using the Orthanc logging system. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param message The message to be logged. **/ ORTHANC_PLUGIN_INLINE void OrthancPluginLogInfo( OrthancPluginContext* context, const char* message) { context->InvokeService(context, _OrthancPluginService_LogInfo, message); } typedef struct { const char* pathRegularExpression; OrthancPluginRestCallback callback; } _OrthancPluginRestCallback; /** * @brief Register a REST callback. * * This function registers a REST callback against a regular * expression for a URI. This function must be called during the * initialization of the plugin, i.e. inside the * OrthancPluginInitialize() public function. * * Each REST callback is guaranteed to run in mutual exclusion. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param pathRegularExpression Regular expression for the URI. May contain groups. * @param callback The callback function to handle the REST call. * @see OrthancPluginRegisterRestCallbackNoLock() * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallback( OrthancPluginContext* context, const char* pathRegularExpression, OrthancPluginRestCallback callback) { _OrthancPluginRestCallback params; params.pathRegularExpression = pathRegularExpression; params.callback = callback; context->InvokeService(context, _OrthancPluginService_RegisterRestCallback, ¶ms); } /** * @brief Register a REST callback, without locking. * * This function registers a REST callback against a regular * expression for a URI. This function must be called during the * initialization of the plugin, i.e. inside the * OrthancPluginInitialize() public function. * * Contrarily to OrthancPluginRegisterRestCallback(), the callback * will NOT be invoked in mutual exclusion. This can be useful for * high-performance plugins that must handle concurrent requests * (Orthanc uses a pool of threads, one thread being assigned to * each incoming HTTP request). Of course, it is up to the plugin to * implement the required locking mechanisms. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param pathRegularExpression Regular expression for the URI. May contain groups. * @param callback The callback function to handle the REST call. * @see OrthancPluginRegisterRestCallback() * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallbackNoLock( OrthancPluginContext* context, const char* pathRegularExpression, OrthancPluginRestCallback callback) { _OrthancPluginRestCallback params; params.pathRegularExpression = pathRegularExpression; params.callback = callback; context->InvokeService(context, _OrthancPluginService_RegisterRestCallbackNoLock, ¶ms); } typedef struct { OrthancPluginOnStoredInstanceCallback callback; } _OrthancPluginOnStoredInstanceCallback; /** * @brief Register a callback for received instances. * * This function registers a callback function that is called * whenever a new DICOM instance is stored into the Orthanc core. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param callback The callback function. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnStoredInstanceCallback( OrthancPluginContext* context, OrthancPluginOnStoredInstanceCallback callback) { _OrthancPluginOnStoredInstanceCallback params; params.callback = callback; context->InvokeService(context, _OrthancPluginService_RegisterOnStoredInstanceCallback, ¶ms); } typedef struct { OrthancPluginRestOutput* output; const char* answer; uint32_t answerSize; const char* mimeType; } _OrthancPluginAnswerBuffer; /** * @brief Answer to a REST request. * * This function answers to a REST request with the content of a memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param answer Pointer to the memory buffer containing the answer. * @param answerSize Number of bytes of the answer. * @param mimeType The MIME type of the answer. * @ingroup REST **/ ORTHANC_PLUGIN_INLINE void OrthancPluginAnswerBuffer( OrthancPluginContext* context, OrthancPluginRestOutput* output, const char* answer, uint32_t answerSize, const char* mimeType) { _OrthancPluginAnswerBuffer params; params.output = output; params.answer = answer; params.answerSize = answerSize; params.mimeType = mimeType; context->InvokeService(context, _OrthancPluginService_AnswerBuffer, ¶ms); } typedef struct { OrthancPluginRestOutput* output; OrthancPluginPixelFormat format; uint32_t width; uint32_t height; uint32_t pitch; const void* buffer; } _OrthancPluginCompressAndAnswerPngImage; typedef struct { OrthancPluginRestOutput* output; OrthancPluginImageFormat imageFormat; OrthancPluginPixelFormat pixelFormat; uint32_t width; uint32_t height; uint32_t pitch; const void* buffer; uint8_t quality; } _OrthancPluginCompressAndAnswerImage; /** * @brief Answer to a REST request with a PNG image. * * This function answers to a REST request with a PNG image. The * parameters of this function describe a memory buffer that * contains an uncompressed image. The image will be automatically compressed * as a PNG image by the core system of Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param format The memory layout of the uncompressed image. * @param width The width of the image. * @param height The height of the image. * @param pitch The pitch of the image (i.e. the number of bytes * between 2 successive lines of the image in the memory buffer). * @param buffer The memory buffer containing the uncompressed image. * @ingroup REST **/ ORTHANC_PLUGIN_INLINE void OrthancPluginCompressAndAnswerPngImage( OrthancPluginContext* context, OrthancPluginRestOutput* output, OrthancPluginPixelFormat format, uint32_t width, uint32_t height, uint32_t pitch, const void* buffer) { _OrthancPluginCompressAndAnswerImage params; params.output = output; params.imageFormat = OrthancPluginImageFormat_Png; params.pixelFormat = format; params.width = width; params.height = height; params.pitch = pitch; params.buffer = buffer; params.quality = 0; /* No quality for PNG */ context->InvokeService(context, _OrthancPluginService_CompressAndAnswerImage, ¶ms); } typedef struct { OrthancPluginMemoryBuffer* target; const char* instanceId; } _OrthancPluginGetDicomForInstance; /** * @brief Retrieve a DICOM instance using its Orthanc identifier. * * Retrieve a DICOM instance using its Orthanc identifier. The DICOM * file is stored into a newly allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param instanceId The Orthanc identifier of the DICOM instance of interest. * @return 0 if success, or the error code if failure. * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginGetDicomForInstance( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* instanceId) { _OrthancPluginGetDicomForInstance params; params.target = target; params.instanceId = instanceId; return context->InvokeService(context, _OrthancPluginService_GetDicomForInstance, ¶ms); } typedef struct { OrthancPluginMemoryBuffer* target; const char* uri; } _OrthancPluginRestApiGet; /** * @brief Make a GET call to the built-in Orthanc REST API. * * Make a GET call to the built-in Orthanc REST API. The result to * the query is stored into a newly allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param uri The URI in the built-in Orthanc API. * @return 0 if success, or the error code if failure. * @see OrthancPluginRestApiGetAfterPlugins * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiGet( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* uri) { _OrthancPluginRestApiGet params; params.target = target; params.uri = uri; return context->InvokeService(context, _OrthancPluginService_RestApiGet, ¶ms); } /** * @brief Make a GET call to the REST API, as tainted by the plugins. * * Make a GET call to the Orthanc REST API, after all the plugins * are applied. In other words, if some plugin overrides or adds the * called URI to the built-in Orthanc REST API, this call will * return the result provided by this plugin. The result to the * query is stored into a newly allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param uri The URI in the built-in Orthanc API. * @return 0 if success, or the error code if failure. * @see OrthancPluginRestApiGet * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiGetAfterPlugins( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* uri) { _OrthancPluginRestApiGet params; params.target = target; params.uri = uri; return context->InvokeService(context, _OrthancPluginService_RestApiGetAfterPlugins, ¶ms); } typedef struct { OrthancPluginMemoryBuffer* target; const char* uri; const char* body; uint32_t bodySize; } _OrthancPluginRestApiPostPut; /** * @brief Make a POST call to the built-in Orthanc REST API. * * Make a POST call to the built-in Orthanc REST API. The result to * the query is stored into a newly allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param uri The URI in the built-in Orthanc API. * @param body The body of the POST request. * @param bodySize The size of the body. * @return 0 if success, or the error code if failure. * @see OrthancPluginRestApiPostAfterPlugins * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPost( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* uri, const char* body, uint32_t bodySize) { _OrthancPluginRestApiPostPut params; params.target = target; params.uri = uri; params.body = body; params.bodySize = bodySize; return context->InvokeService(context, _OrthancPluginService_RestApiPost, ¶ms); } /** * @brief Make a POST call to the REST API, as tainted by the plugins. * * Make a POST call to the Orthanc REST API, after all the plugins * are applied. In other words, if some plugin overrides or adds the * called URI to the built-in Orthanc REST API, this call will * return the result provided by this plugin. The result to the * query is stored into a newly allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param uri The URI in the built-in Orthanc API. * @param body The body of the POST request. * @param bodySize The size of the body. * @return 0 if success, or the error code if failure. * @see OrthancPluginRestApiPost * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPostAfterPlugins( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* uri, const char* body, uint32_t bodySize) { _OrthancPluginRestApiPostPut params; params.target = target; params.uri = uri; params.body = body; params.bodySize = bodySize; return context->InvokeService(context, _OrthancPluginService_RestApiPostAfterPlugins, ¶ms); } /** * @brief Make a DELETE call to the built-in Orthanc REST API. * * Make a DELETE call to the built-in Orthanc REST API. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param uri The URI to delete in the built-in Orthanc API. * @return 0 if success, or the error code if failure. * @see OrthancPluginRestApiDeleteAfterPlugins * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiDelete( OrthancPluginContext* context, const char* uri) { return context->InvokeService(context, _OrthancPluginService_RestApiDelete, uri); } /** * @brief Make a DELETE call to the REST API, as tainted by the plugins. * * Make a DELETE call to the Orthanc REST API, after all the plugins * are applied. In other words, if some plugin overrides or adds the * called URI to the built-in Orthanc REST API, this call will * return the result provided by this plugin. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param uri The URI to delete in the built-in Orthanc API. * @return 0 if success, or the error code if failure. * @see OrthancPluginRestApiDelete * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiDeleteAfterPlugins( OrthancPluginContext* context, const char* uri) { return context->InvokeService(context, _OrthancPluginService_RestApiDeleteAfterPlugins, uri); } /** * @brief Make a PUT call to the built-in Orthanc REST API. * * Make a PUT call to the built-in Orthanc REST API. The result to * the query is stored into a newly allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param uri The URI in the built-in Orthanc API. * @param body The body of the PUT request. * @param bodySize The size of the body. * @return 0 if success, or the error code if failure. * @see OrthancPluginRestApiPutAfterPlugins * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPut( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* uri, const char* body, uint32_t bodySize) { _OrthancPluginRestApiPostPut params; params.target = target; params.uri = uri; params.body = body; params.bodySize = bodySize; return context->InvokeService(context, _OrthancPluginService_RestApiPut, ¶ms); } /** * @brief Make a PUT call to the REST API, as tainted by the plugins. * * Make a PUT call to the Orthanc REST API, after all the plugins * are applied. In other words, if some plugin overrides or adds the * called URI to the built-in Orthanc REST API, this call will * return the result provided by this plugin. The result to the * query is stored into a newly allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param uri The URI in the built-in Orthanc API. * @param body The body of the PUT request. * @param bodySize The size of the body. * @return 0 if success, or the error code if failure. * @see OrthancPluginRestApiPut * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPutAfterPlugins( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* uri, const char* body, uint32_t bodySize) { _OrthancPluginRestApiPostPut params; params.target = target; params.uri = uri; params.body = body; params.bodySize = bodySize; return context->InvokeService(context, _OrthancPluginService_RestApiPutAfterPlugins, ¶ms); } typedef struct { OrthancPluginRestOutput* output; const char* argument; } _OrthancPluginOutputPlusArgument; /** * @brief Redirect a REST request. * * This function answers to a REST request by redirecting the user * to another URI using HTTP status 301. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param redirection Where to redirect. * @ingroup REST **/ ORTHANC_PLUGIN_INLINE void OrthancPluginRedirect( OrthancPluginContext* context, OrthancPluginRestOutput* output, const char* redirection) { _OrthancPluginOutputPlusArgument params; params.output = output; params.argument = redirection; context->InvokeService(context, _OrthancPluginService_Redirect, ¶ms); } typedef struct { char** result; const char* argument; } _OrthancPluginRetrieveDynamicString; /** * @brief Look for a patient. * * Look for a patient stored in Orthanc, using its Patient ID tag (0x0010, 0x0020). * This function uses the database index to run as fast as possible (it does not loop * over all the stored patients). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param patientID The Patient ID of interest. * @return The NULL value if the patient is non-existent, or a string containing the * Orthanc ID of the patient. This string must be freed by OrthancPluginFreeString(). * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupPatient( OrthancPluginContext* context, const char* patientID) { char* result; _OrthancPluginRetrieveDynamicString params; params.result = &result; params.argument = patientID; if (context->InvokeService(context, _OrthancPluginService_LookupPatient, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Look for a study. * * Look for a study stored in Orthanc, using its Study Instance UID tag (0x0020, 0x000d). * This function uses the database index to run as fast as possible (it does not loop * over all the stored studies). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param studyUID The Study Instance UID of interest. * @return The NULL value if the study is non-existent, or a string containing the * Orthanc ID of the study. This string must be freed by OrthancPluginFreeString(). * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupStudy( OrthancPluginContext* context, const char* studyUID) { char* result; _OrthancPluginRetrieveDynamicString params; params.result = &result; params.argument = studyUID; if (context->InvokeService(context, _OrthancPluginService_LookupStudy, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Look for a study, using the accession number. * * Look for a study stored in Orthanc, using its Accession Number tag (0x0008, 0x0050). * This function uses the database index to run as fast as possible (it does not loop * over all the stored studies). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param accessionNumber The Accession Number of interest. * @return The NULL value if the study is non-existent, or a string containing the * Orthanc ID of the study. This string must be freed by OrthancPluginFreeString(). * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupStudyWithAccessionNumber( OrthancPluginContext* context, const char* accessionNumber) { char* result; _OrthancPluginRetrieveDynamicString params; params.result = &result; params.argument = accessionNumber; if (context->InvokeService(context, _OrthancPluginService_LookupStudyWithAccessionNumber, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Look for a series. * * Look for a series stored in Orthanc, using its Series Instance UID tag (0x0020, 0x000e). * This function uses the database index to run as fast as possible (it does not loop * over all the stored series). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param seriesUID The Series Instance UID of interest. * @return The NULL value if the series is non-existent, or a string containing the * Orthanc ID of the series. This string must be freed by OrthancPluginFreeString(). * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupSeries( OrthancPluginContext* context, const char* seriesUID) { char* result; _OrthancPluginRetrieveDynamicString params; params.result = &result; params.argument = seriesUID; if (context->InvokeService(context, _OrthancPluginService_LookupSeries, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Look for an instance. * * Look for an instance stored in Orthanc, using its SOP Instance UID tag (0x0008, 0x0018). * This function uses the database index to run as fast as possible (it does not loop * over all the stored instances). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param sopInstanceUID The SOP Instance UID of interest. * @return The NULL value if the instance is non-existent, or a string containing the * Orthanc ID of the instance. This string must be freed by OrthancPluginFreeString(). * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupInstance( OrthancPluginContext* context, const char* sopInstanceUID) { char* result; _OrthancPluginRetrieveDynamicString params; params.result = &result; params.argument = sopInstanceUID; if (context->InvokeService(context, _OrthancPluginService_LookupInstance, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } typedef struct { OrthancPluginRestOutput* output; uint16_t status; } _OrthancPluginSendHttpStatusCode; /** * @brief Send a HTTP status code. * * This function answers to a REST request by sending a HTTP status * code (such as "400 - Bad Request"). Note that: * - Successful requests (status 200) must use ::OrthancPluginAnswerBuffer(). * - Redirections (status 301) must use ::OrthancPluginRedirect(). * - Unauthorized access (status 401) must use ::OrthancPluginSendUnauthorized(). * - Methods not allowed (status 405) must use ::OrthancPluginSendMethodNotAllowed(). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param status The HTTP status code to be sent. * @ingroup REST * @see OrthancPluginSendHttpStatus() **/ ORTHANC_PLUGIN_INLINE void OrthancPluginSendHttpStatusCode( OrthancPluginContext* context, OrthancPluginRestOutput* output, uint16_t status) { _OrthancPluginSendHttpStatusCode params; params.output = output; params.status = status; context->InvokeService(context, _OrthancPluginService_SendHttpStatusCode, ¶ms); } /** * @brief Signal that a REST request is not authorized. * * This function answers to a REST request by signaling that it is * not authorized. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param realm The realm for the authorization process. * @ingroup REST **/ ORTHANC_PLUGIN_INLINE void OrthancPluginSendUnauthorized( OrthancPluginContext* context, OrthancPluginRestOutput* output, const char* realm) { _OrthancPluginOutputPlusArgument params; params.output = output; params.argument = realm; context->InvokeService(context, _OrthancPluginService_SendUnauthorized, ¶ms); } /** * @brief Signal that this URI does not support this HTTP method. * * This function answers to a REST request by signaling that the * queried URI does not support this method. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param allowedMethods The allowed methods for this URI (e.g. "GET,POST" after a PUT or a POST request). * @ingroup REST **/ ORTHANC_PLUGIN_INLINE void OrthancPluginSendMethodNotAllowed( OrthancPluginContext* context, OrthancPluginRestOutput* output, const char* allowedMethods) { _OrthancPluginOutputPlusArgument params; params.output = output; params.argument = allowedMethods; context->InvokeService(context, _OrthancPluginService_SendMethodNotAllowed, ¶ms); } typedef struct { OrthancPluginRestOutput* output; const char* key; const char* value; } _OrthancPluginSetHttpHeader; /** * @brief Set a cookie. * * This function sets a cookie in the HTTP client. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param cookie The cookie to be set. * @param value The value of the cookie. * @ingroup REST **/ ORTHANC_PLUGIN_INLINE void OrthancPluginSetCookie( OrthancPluginContext* context, OrthancPluginRestOutput* output, const char* cookie, const char* value) { _OrthancPluginSetHttpHeader params; params.output = output; params.key = cookie; params.value = value; context->InvokeService(context, _OrthancPluginService_SetCookie, ¶ms); } /** * @brief Set some HTTP header. * * This function sets a HTTP header in the HTTP answer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param key The HTTP header to be set. * @param value The value of the HTTP header. * @ingroup REST **/ ORTHANC_PLUGIN_INLINE void OrthancPluginSetHttpHeader( OrthancPluginContext* context, OrthancPluginRestOutput* output, const char* key, const char* value) { _OrthancPluginSetHttpHeader params; params.output = output; params.key = key; params.value = value; context->InvokeService(context, _OrthancPluginService_SetHttpHeader, ¶ms); } typedef struct { char** resultStringToFree; const char** resultString; int64_t* resultInt64; const char* key; OrthancPluginDicomInstance* instance; OrthancPluginInstanceOrigin* resultOrigin; /* New in Orthanc 0.9.5 SDK */ } _OrthancPluginAccessDicomInstance; /** * @brief Get the AET of a DICOM instance. * * This function returns the Application Entity Title (AET) of the * DICOM modality from which a DICOM instance originates. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param instance The instance of interest. * @return The AET if success, NULL if error. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceRemoteAet( OrthancPluginContext* context, OrthancPluginDicomInstance* instance) { const char* result; _OrthancPluginAccessDicomInstance params; memset(¶ms, 0, sizeof(params)); params.resultString = &result; params.instance = instance; if (context->InvokeService(context, _OrthancPluginService_GetInstanceRemoteAet, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Get the size of a DICOM file. * * This function returns the number of bytes of the given DICOM instance. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param instance The instance of interest. * @return The size of the file, -1 in case of error. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE int64_t OrthancPluginGetInstanceSize( OrthancPluginContext* context, OrthancPluginDicomInstance* instance) { int64_t size; _OrthancPluginAccessDicomInstance params; memset(¶ms, 0, sizeof(params)); params.resultInt64 = &size; params.instance = instance; if (context->InvokeService(context, _OrthancPluginService_GetInstanceSize, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return -1; } else { return size; } } /** * @brief Get the data of a DICOM file. * * This function returns a pointer to the content of the given DICOM instance. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param instance The instance of interest. * @return The pointer to the DICOM data, NULL in case of error. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceData( OrthancPluginContext* context, OrthancPluginDicomInstance* instance) { const char* result; _OrthancPluginAccessDicomInstance params; memset(¶ms, 0, sizeof(params)); params.resultString = &result; params.instance = instance; if (context->InvokeService(context, _OrthancPluginService_GetInstanceData, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Get the DICOM tag hierarchy as a JSON file. * * This function returns a pointer to a newly created string * containing a JSON file. This JSON file encodes the tag hierarchy * of the given DICOM instance. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param instance The instance of interest. * @return The NULL value in case of error, or a string containing the JSON file. * This string must be freed by OrthancPluginFreeString(). * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginGetInstanceJson( OrthancPluginContext* context, OrthancPluginDicomInstance* instance) { char* result; _OrthancPluginAccessDicomInstance params; memset(¶ms, 0, sizeof(params)); params.resultStringToFree = &result; params.instance = instance; if (context->InvokeService(context, _OrthancPluginService_GetInstanceJson, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Get the DICOM tag hierarchy as a JSON file (with simplification). * * This function returns a pointer to a newly created string * containing a JSON file. This JSON file encodes the tag hierarchy * of the given DICOM instance. In contrast with * ::OrthancPluginGetInstanceJson(), the returned JSON file is in * its simplified version. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param instance The instance of interest. * @return The NULL value in case of error, or a string containing the JSON file. * This string must be freed by OrthancPluginFreeString(). * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginGetInstanceSimplifiedJson( OrthancPluginContext* context, OrthancPluginDicomInstance* instance) { char* result; _OrthancPluginAccessDicomInstance params; memset(¶ms, 0, sizeof(params)); params.resultStringToFree = &result; params.instance = instance; if (context->InvokeService(context, _OrthancPluginService_GetInstanceSimplifiedJson, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Check whether a DICOM instance is associated with some metadata. * * This function checks whether the DICOM instance of interest is * associated with some metadata. As of Orthanc 0.8.1, in the * callbacks registered by * ::OrthancPluginRegisterOnStoredInstanceCallback(), the only * possibly available metadata are "ReceptionDate", "RemoteAET" and * "IndexInSeries". * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param instance The instance of interest. * @param metadata The metadata of interest. * @return 1 if the metadata is present, 0 if it is absent, -1 in case of error. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE int OrthancPluginHasInstanceMetadata( OrthancPluginContext* context, OrthancPluginDicomInstance* instance, const char* metadata) { int64_t result; _OrthancPluginAccessDicomInstance params; memset(¶ms, 0, sizeof(params)); params.resultInt64 = &result; params.instance = instance; params.key = metadata; if (context->InvokeService(context, _OrthancPluginService_HasInstanceMetadata, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return -1; } else { return (result != 0); } } /** * @brief Get the value of some metadata associated with a given DICOM instance. * * This functions returns the value of some metadata that is associated with the DICOM instance of interest. * Before calling this function, the existence of the metadata must have been checked with * ::OrthancPluginHasInstanceMetadata(). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param instance The instance of interest. * @param metadata The metadata of interest. * @return The metadata value if success, NULL if error. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceMetadata( OrthancPluginContext* context, OrthancPluginDicomInstance* instance, const char* metadata) { const char* result; _OrthancPluginAccessDicomInstance params; memset(¶ms, 0, sizeof(params)); params.resultString = &result; params.instance = instance; params.key = metadata; if (context->InvokeService(context, _OrthancPluginService_GetInstanceMetadata, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } typedef struct { OrthancPluginStorageCreate create; OrthancPluginStorageRead read; OrthancPluginStorageRemove remove; OrthancPluginFree free; } _OrthancPluginRegisterStorageArea; /** * @brief Register a custom storage area. * * This function registers a custom storage area, to replace the * built-in way Orthanc stores its files on the filesystem. This * function must be called during the initialization of the plugin, * i.e. inside the OrthancPluginInitialize() public function. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param create The callback function to store a file on the custom storage area. * @param read The callback function to read a file from the custom storage area. * @param remove The callback function to remove a file from the custom storage area. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterStorageArea( OrthancPluginContext* context, OrthancPluginStorageCreate create, OrthancPluginStorageRead read, OrthancPluginStorageRemove remove) { _OrthancPluginRegisterStorageArea params; params.create = create; params.read = read; params.remove = remove; #ifdef __cplusplus params.free = ::free; #else params.free = free; #endif context->InvokeService(context, _OrthancPluginService_RegisterStorageArea, ¶ms); } /** * @brief Return the path to the Orthanc executable. * * This function returns the path to the Orthanc executable. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @return NULL in the case of an error, or a newly allocated string * containing the path. This string must be freed by * OrthancPluginFreeString(). **/ ORTHANC_PLUGIN_INLINE char *OrthancPluginGetOrthancPath(OrthancPluginContext* context) { char* result; _OrthancPluginRetrieveDynamicString params; params.result = &result; params.argument = NULL; if (context->InvokeService(context, _OrthancPluginService_GetOrthancPath, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Return the directory containing the Orthanc. * * This function returns the path to the directory containing the Orthanc executable. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @return NULL in the case of an error, or a newly allocated string * containing the path. This string must be freed by * OrthancPluginFreeString(). **/ ORTHANC_PLUGIN_INLINE char *OrthancPluginGetOrthancDirectory(OrthancPluginContext* context) { char* result; _OrthancPluginRetrieveDynamicString params; params.result = &result; params.argument = NULL; if (context->InvokeService(context, _OrthancPluginService_GetOrthancDirectory, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Return the path to the configuration file(s). * * This function returns the path to the configuration file(s) that * was specified when starting Orthanc. Since version 0.9.1, this * path can refer to a folder that stores a set of configuration * files. This function is deprecated in favor of * OrthancPluginGetConfiguration(). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @return NULL in the case of an error, or a newly allocated string * containing the path. This string must be freed by * OrthancPluginFreeString(). * @see OrthancPluginGetConfiguration() **/ ORTHANC_PLUGIN_INLINE char *OrthancPluginGetConfigurationPath(OrthancPluginContext* context) { char* result; _OrthancPluginRetrieveDynamicString params; params.result = &result; params.argument = NULL; if (context->InvokeService(context, _OrthancPluginService_GetConfigurationPath, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } typedef struct { OrthancPluginOnChangeCallback callback; } _OrthancPluginOnChangeCallback; /** * @brief Register a callback to monitor changes. * * This function registers a callback function that is called * whenever a change happens to some DICOM resource. * * @warning If your change callback has to call the REST API of * Orthanc, you should make these calls in a separate thread (with * the events passing through a message queue). Otherwise, this * could result in deadlocks in the presence of other plugins or Lua * script. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param callback The callback function. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnChangeCallback( OrthancPluginContext* context, OrthancPluginOnChangeCallback callback) { _OrthancPluginOnChangeCallback params; params.callback = callback; context->InvokeService(context, _OrthancPluginService_RegisterOnChangeCallback, ¶ms); } typedef struct { const char* plugin; _OrthancPluginProperty property; const char* value; } _OrthancPluginSetPluginProperty; /** * @brief Set the URI where the plugin provides its Web interface. * * For plugins that come with a Web interface, this function * declares the entry path where to find this interface. This * information is notably used in the "Plugins" page of Orthanc * Explorer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param uri The root URI for this plugin. **/ ORTHANC_PLUGIN_INLINE void OrthancPluginSetRootUri( OrthancPluginContext* context, const char* uri) { _OrthancPluginSetPluginProperty params; params.plugin = OrthancPluginGetName(); params.property = _OrthancPluginProperty_RootUri; params.value = uri; context->InvokeService(context, _OrthancPluginService_SetPluginProperty, ¶ms); } /** * @brief Set a description for this plugin. * * Set a description for this plugin. It is displayed in the * "Plugins" page of Orthanc Explorer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param description The description. **/ ORTHANC_PLUGIN_INLINE void OrthancPluginSetDescription( OrthancPluginContext* context, const char* description) { _OrthancPluginSetPluginProperty params; params.plugin = OrthancPluginGetName(); params.property = _OrthancPluginProperty_Description; params.value = description; context->InvokeService(context, _OrthancPluginService_SetPluginProperty, ¶ms); } /** * @brief Extend the JavaScript code of Orthanc Explorer. * * Add JavaScript code to customize the default behavior of Orthanc * Explorer. This can for instance be used to add new buttons. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param javascript The custom JavaScript code. **/ ORTHANC_PLUGIN_INLINE void OrthancPluginExtendOrthancExplorer( OrthancPluginContext* context, const char* javascript) { _OrthancPluginSetPluginProperty params; params.plugin = OrthancPluginGetName(); params.property = _OrthancPluginProperty_OrthancExplorer; params.value = javascript; context->InvokeService(context, _OrthancPluginService_SetPluginProperty, ¶ms); } typedef struct { char** result; int32_t property; const char* value; } _OrthancPluginGlobalProperty; /** * @brief Get the value of a global property. * * Get the value of a global property that is stored in the Orthanc database. Global * properties whose index is below 1024 are reserved by Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param property The global property of interest. * @param defaultValue The value to return, if the global property is unset. * @return The value of the global property, or NULL in the case of an error. This * string must be freed by OrthancPluginFreeString(). * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginGetGlobalProperty( OrthancPluginContext* context, int32_t property, const char* defaultValue) { char* result; _OrthancPluginGlobalProperty params; params.result = &result; params.property = property; params.value = defaultValue; if (context->InvokeService(context, _OrthancPluginService_GetGlobalProperty, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Set the value of a global property. * * Set the value of a global property into the Orthanc * database. Setting a global property can be used by plugins to * save their internal parameters. Plugins are only allowed to set * properties whose index are above or equal to 1024 (properties * below 1024 are read-only and reserved by Orthanc). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param property The global property of interest. * @param value The value to be set in the global property. * @return 0 if success, or the error code if failure. * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSetGlobalProperty( OrthancPluginContext* context, int32_t property, const char* value) { _OrthancPluginGlobalProperty params; params.result = NULL; params.property = property; params.value = value; return context->InvokeService(context, _OrthancPluginService_SetGlobalProperty, ¶ms); } typedef struct { int32_t *resultInt32; uint32_t *resultUint32; int64_t *resultInt64; uint64_t *resultUint64; } _OrthancPluginReturnSingleValue; /** * @brief Get the number of command-line arguments. * * Retrieve the number of command-line arguments that were used to launch Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @return The number of arguments. **/ ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetCommandLineArgumentsCount( OrthancPluginContext* context) { uint32_t count = 0; _OrthancPluginReturnSingleValue params; memset(¶ms, 0, sizeof(params)); params.resultUint32 = &count; if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgumentsCount, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return 0; } else { return count; } } /** * @brief Get the value of a command-line argument. * * Get the value of one of the command-line arguments that were used * to launch Orthanc. The number of available arguments can be * retrieved by OrthancPluginGetCommandLineArgumentsCount(). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param argument The index of the argument. * @return The value of the argument, or NULL in the case of an error. This * string must be freed by OrthancPluginFreeString(). **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginGetCommandLineArgument( OrthancPluginContext* context, uint32_t argument) { char* result; _OrthancPluginGlobalProperty params; params.result = &result; params.property = (int32_t) argument; params.value = NULL; if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgument, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Get the expected version of the database schema. * * Retrieve the expected version of the database schema. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @return The version. * @ingroup Callbacks * @deprecated Please instead use IDatabaseBackend::UpgradeDatabase() **/ ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetExpectedDatabaseVersion( OrthancPluginContext* context) { uint32_t count = 0; _OrthancPluginReturnSingleValue params; memset(¶ms, 0, sizeof(params)); params.resultUint32 = &count; if (context->InvokeService(context, _OrthancPluginService_GetExpectedDatabaseVersion, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return 0; } else { return count; } } /** * @brief Return the content of the configuration file(s). * * This function returns the content of the configuration that is * used by Orthanc, formatted as a JSON string. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @return NULL in the case of an error, or a newly allocated string * containing the configuration. This string must be freed by * OrthancPluginFreeString(). **/ ORTHANC_PLUGIN_INLINE char *OrthancPluginGetConfiguration(OrthancPluginContext* context) { char* result; _OrthancPluginRetrieveDynamicString params; params.result = &result; params.argument = NULL; if (context->InvokeService(context, _OrthancPluginService_GetConfiguration, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } typedef struct { OrthancPluginRestOutput* output; const char* subType; const char* contentType; } _OrthancPluginStartMultipartAnswer; /** * @brief Start an HTTP multipart answer. * * Initiates a HTTP multipart answer, as the result of a REST request. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param subType The sub-type of the multipart answer ("mixed" or "related"). * @param contentType The MIME type of the items in the multipart answer. * @return 0 if success, or the error code if failure. * @see OrthancPluginSendMultipartItem() * @ingroup REST **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStartMultipartAnswer( OrthancPluginContext* context, OrthancPluginRestOutput* output, const char* subType, const char* contentType) { _OrthancPluginStartMultipartAnswer params; params.output = output; params.subType = subType; params.contentType = contentType; return context->InvokeService(context, _OrthancPluginService_StartMultipartAnswer, ¶ms); } /** * @brief Send an item as a part of some HTTP multipart answer. * * This function sends an item as a part of some HTTP multipart * answer that was initiated by OrthancPluginStartMultipartAnswer(). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param answer Pointer to the memory buffer containing the item. * @param answerSize Number of bytes of the item. * @return 0 if success, or the error code if failure (this notably happens * if the connection is closed by the client). * @ingroup REST **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem( OrthancPluginContext* context, OrthancPluginRestOutput* output, const char* answer, uint32_t answerSize) { _OrthancPluginAnswerBuffer params; params.output = output; params.answer = answer; params.answerSize = answerSize; params.mimeType = NULL; return context->InvokeService(context, _OrthancPluginService_SendMultipartItem, ¶ms); } typedef struct { OrthancPluginMemoryBuffer* target; const void* source; uint32_t size; OrthancPluginCompressionType compression; uint8_t uncompress; } _OrthancPluginBufferCompression; /** * @brief Compress or decompress a buffer. * * This function compresses or decompresses a buffer, using the * version of the zlib library that is used by the Orthanc core. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param source The source buffer. * @param size The size in bytes of the source buffer. * @param compression The compression algorithm. * @param uncompress If set to "0", the buffer must be compressed. * If set to "1", the buffer must be uncompressed. * @return 0 if success, or the error code if failure. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginBufferCompression( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const void* source, uint32_t size, OrthancPluginCompressionType compression, uint8_t uncompress) { _OrthancPluginBufferCompression params; params.target = target; params.source = source; params.size = size; params.compression = compression; params.uncompress = uncompress; return context->InvokeService(context, _OrthancPluginService_BufferCompression, ¶ms); } typedef struct { OrthancPluginMemoryBuffer* target; const char* path; } _OrthancPluginReadFile; /** * @brief Read a file. * * Read the content of a file on the filesystem, and returns it into * a newly allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param path The path of the file to be read. * @return 0 if success, or the error code if failure. **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginReadFile( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* path) { _OrthancPluginReadFile params; params.target = target; params.path = path; return context->InvokeService(context, _OrthancPluginService_ReadFile, ¶ms); } typedef struct { const char* path; const void* data; uint32_t size; } _OrthancPluginWriteFile; /** * @brief Write a file. * * Write the content of a memory buffer to the filesystem. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param path The path of the file to be written. * @param data The content of the memory buffer. * @param size The size of the memory buffer. * @return 0 if success, or the error code if failure. **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWriteFile( OrthancPluginContext* context, const char* path, const void* data, uint32_t size) { _OrthancPluginWriteFile params; params.path = path; params.data = data; params.size = size; return context->InvokeService(context, _OrthancPluginService_WriteFile, ¶ms); } typedef struct { const char** target; OrthancPluginErrorCode error; } _OrthancPluginGetErrorDescription; /** * @brief Get the description of a given error code. * * This function returns the description of a given error code. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param error The error code of interest. * @return The error description. This is a statically-allocated * string, do not free it. **/ ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetErrorDescription( OrthancPluginContext* context, OrthancPluginErrorCode error) { const char* result = NULL; _OrthancPluginGetErrorDescription params; params.target = &result; params.error = error; if (context->InvokeService(context, _OrthancPluginService_GetErrorDescription, ¶ms) != OrthancPluginErrorCode_Success || result == NULL) { return "Unknown error code"; } else { return result; } } typedef struct { OrthancPluginRestOutput* output; uint16_t status; const char* body; uint32_t bodySize; } _OrthancPluginSendHttpStatus; /** * @brief Send a HTTP status, with a custom body. * * This function answers to a HTTP request by sending a HTTP status * code (such as "400 - Bad Request"), together with a body * describing the error. The body will only be returned if the * configuration option "HttpDescribeErrors" of Orthanc is set to "true". * * Note that: * - Successful requests (status 200) must use ::OrthancPluginAnswerBuffer(). * - Redirections (status 301) must use ::OrthancPluginRedirect(). * - Unauthorized access (status 401) must use ::OrthancPluginSendUnauthorized(). * - Methods not allowed (status 405) must use ::OrthancPluginSendMethodNotAllowed(). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param status The HTTP status code to be sent. * @param body The body of the answer. * @param bodySize The size of the body. * @see OrthancPluginSendHttpStatusCode() * @ingroup REST **/ ORTHANC_PLUGIN_INLINE void OrthancPluginSendHttpStatus( OrthancPluginContext* context, OrthancPluginRestOutput* output, uint16_t status, const char* body, uint32_t bodySize) { _OrthancPluginSendHttpStatus params; params.output = output; params.status = status; params.body = body; params.bodySize = bodySize; context->InvokeService(context, _OrthancPluginService_SendHttpStatus, ¶ms); } typedef struct { const OrthancPluginImage* image; uint32_t* resultUint32; OrthancPluginPixelFormat* resultPixelFormat; void** resultBuffer; } _OrthancPluginGetImageInfo; /** * @brief Return the pixel format of an image. * * This function returns the type of memory layout for the pixels of the given image. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param image The image of interest. * @return The pixel format. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE OrthancPluginPixelFormat OrthancPluginGetImagePixelFormat( OrthancPluginContext* context, const OrthancPluginImage* image) { OrthancPluginPixelFormat target; _OrthancPluginGetImageInfo params; memset(¶ms, 0, sizeof(params)); params.image = image; params.resultPixelFormat = ⌖ if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, ¶ms) != OrthancPluginErrorCode_Success) { return OrthancPluginPixelFormat_Unknown; } else { return (OrthancPluginPixelFormat) target; } } /** * @brief Return the width of an image. * * This function returns the width of the given image. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param image The image of interest. * @return The width. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetImageWidth( OrthancPluginContext* context, const OrthancPluginImage* image) { uint32_t width; _OrthancPluginGetImageInfo params; memset(¶ms, 0, sizeof(params)); params.image = image; params.resultUint32 = &width; if (context->InvokeService(context, _OrthancPluginService_GetImageWidth, ¶ms) != OrthancPluginErrorCode_Success) { return 0; } else { return width; } } /** * @brief Return the height of an image. * * This function returns the height of the given image. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param image The image of interest. * @return The height. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetImageHeight( OrthancPluginContext* context, const OrthancPluginImage* image) { uint32_t height; _OrthancPluginGetImageInfo params; memset(¶ms, 0, sizeof(params)); params.image = image; params.resultUint32 = &height; if (context->InvokeService(context, _OrthancPluginService_GetImageHeight, ¶ms) != OrthancPluginErrorCode_Success) { return 0; } else { return height; } } /** * @brief Return the pitch of an image. * * This function returns the pitch of the given image. The pitch is * defined as the number of bytes between 2 successive lines of the * image in the memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param image The image of interest. * @return The pitch. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetImagePitch( OrthancPluginContext* context, const OrthancPluginImage* image) { uint32_t pitch; _OrthancPluginGetImageInfo params; memset(¶ms, 0, sizeof(params)); params.image = image; params.resultUint32 = &pitch; if (context->InvokeService(context, _OrthancPluginService_GetImagePitch, ¶ms) != OrthancPluginErrorCode_Success) { return 0; } else { return pitch; } } /** * @brief Return a pointer to the content of an image. * * This function returns a pointer to the memory buffer that * contains the pixels of the image. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param image The image of interest. * @return The pointer. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE void* OrthancPluginGetImageBuffer( OrthancPluginContext* context, const OrthancPluginImage* image) { void* target = NULL; _OrthancPluginGetImageInfo params; memset(¶ms, 0, sizeof(params)); params.resultBuffer = ⌖ params.image = image; if (context->InvokeService(context, _OrthancPluginService_GetImageBuffer, ¶ms) != OrthancPluginErrorCode_Success) { return NULL; } else { return target; } } typedef struct { OrthancPluginImage** target; const void* data; uint32_t size; OrthancPluginImageFormat format; } _OrthancPluginUncompressImage; /** * @brief Decode a compressed image. * * This function decodes a compressed image from a memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param data Pointer to a memory buffer containing the compressed image. * @param size Size of the memory buffer containing the compressed image. * @param format The file format of the compressed image. * @return The uncompressed image. It must be freed with OrthancPluginFreeImage(). * @ingroup Images **/ ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginUncompressImage( OrthancPluginContext* context, const void* data, uint32_t size, OrthancPluginImageFormat format) { OrthancPluginImage* target = NULL; _OrthancPluginUncompressImage params; memset(¶ms, 0, sizeof(params)); params.target = ⌖ params.data = data; params.size = size; params.format = format; if (context->InvokeService(context, _OrthancPluginService_UncompressImage, ¶ms) != OrthancPluginErrorCode_Success) { return NULL; } else { return target; } } typedef struct { OrthancPluginImage* image; } _OrthancPluginFreeImage; /** * @brief Free an image. * * This function frees an image that was decoded with OrthancPluginUncompressImage(). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param image The image. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE void OrthancPluginFreeImage( OrthancPluginContext* context, OrthancPluginImage* image) { _OrthancPluginFreeImage params; params.image = image; context->InvokeService(context, _OrthancPluginService_FreeImage, ¶ms); } typedef struct { OrthancPluginMemoryBuffer* target; OrthancPluginImageFormat imageFormat; OrthancPluginPixelFormat pixelFormat; uint32_t width; uint32_t height; uint32_t pitch; const void* buffer; uint8_t quality; } _OrthancPluginCompressImage; /** * @brief Encode a PNG image. * * This function compresses the given memory buffer containing an * image using the PNG specification, and stores the result of the * compression into a newly allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param format The memory layout of the uncompressed image. * @param width The width of the image. * @param height The height of the image. * @param pitch The pitch of the image (i.e. the number of bytes * between 2 successive lines of the image in the memory buffer). * @param buffer The memory buffer containing the uncompressed image. * @return 0 if success, or the error code if failure. * @see OrthancPluginCompressAndAnswerPngImage() * @ingroup Images **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressPngImage( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, OrthancPluginPixelFormat format, uint32_t width, uint32_t height, uint32_t pitch, const void* buffer) { _OrthancPluginCompressImage params; memset(¶ms, 0, sizeof(params)); params.target = target; params.imageFormat = OrthancPluginImageFormat_Png; params.pixelFormat = format; params.width = width; params.height = height; params.pitch = pitch; params.buffer = buffer; params.quality = 0; /* Unused for PNG */ return context->InvokeService(context, _OrthancPluginService_CompressImage, ¶ms); } /** * @brief Encode a JPEG image. * * This function compresses the given memory buffer containing an * image using the JPEG specification, and stores the result of the * compression into a newly allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param format The memory layout of the uncompressed image. * @param width The width of the image. * @param height The height of the image. * @param pitch The pitch of the image (i.e. the number of bytes * between 2 successive lines of the image in the memory buffer). * @param buffer The memory buffer containing the uncompressed image. * @param quality The quality of the JPEG encoding, between 1 (worst * quality, best compression) and 100 (best quality, worst * compression). * @return 0 if success, or the error code if failure. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressJpegImage( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, OrthancPluginPixelFormat format, uint32_t width, uint32_t height, uint32_t pitch, const void* buffer, uint8_t quality) { _OrthancPluginCompressImage params; memset(¶ms, 0, sizeof(params)); params.target = target; params.imageFormat = OrthancPluginImageFormat_Jpeg; params.pixelFormat = format; params.width = width; params.height = height; params.pitch = pitch; params.buffer = buffer; params.quality = quality; return context->InvokeService(context, _OrthancPluginService_CompressImage, ¶ms); } /** * @brief Answer to a REST request with a JPEG image. * * This function answers to a REST request with a JPEG image. The * parameters of this function describe a memory buffer that * contains an uncompressed image. The image will be automatically compressed * as a JPEG image by the core system of Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param output The HTTP connection to the client application. * @param format The memory layout of the uncompressed image. * @param width The width of the image. * @param height The height of the image. * @param pitch The pitch of the image (i.e. the number of bytes * between 2 successive lines of the image in the memory buffer). * @param buffer The memory buffer containing the uncompressed image. * @param quality The quality of the JPEG encoding, between 1 (worst * quality, best compression) and 100 (best quality, worst * compression). * @ingroup REST **/ ORTHANC_PLUGIN_INLINE void OrthancPluginCompressAndAnswerJpegImage( OrthancPluginContext* context, OrthancPluginRestOutput* output, OrthancPluginPixelFormat format, uint32_t width, uint32_t height, uint32_t pitch, const void* buffer, uint8_t quality) { _OrthancPluginCompressAndAnswerImage params; params.output = output; params.imageFormat = OrthancPluginImageFormat_Jpeg; params.pixelFormat = format; params.width = width; params.height = height; params.pitch = pitch; params.buffer = buffer; params.quality = quality; context->InvokeService(context, _OrthancPluginService_CompressAndAnswerImage, ¶ms); } typedef struct { OrthancPluginMemoryBuffer* target; OrthancPluginHttpMethod method; const char* url; const char* username; const char* password; const char* body; uint32_t bodySize; } _OrthancPluginCallHttpClient; /** * @brief Issue a HTTP GET call. * * Make a HTTP GET call to the given URL. The result to the query is * stored into a newly allocated memory buffer. Favor * OrthancPluginRestApiGet() if calling the built-in REST API of the * Orthanc instance that hosts this plugin. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param url The URL of interest. * @param username The username (can be NULL if no password protection). * @param password The password (can be NULL if no password protection). * @return 0 if success, or the error code if failure. **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpGet( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* url, const char* username, const char* password) { _OrthancPluginCallHttpClient params; memset(¶ms, 0, sizeof(params)); params.target = target; params.method = OrthancPluginHttpMethod_Get; params.url = url; params.username = username; params.password = password; return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); } /** * @brief Issue a HTTP POST call. * * Make a HTTP POST call to the given URL. The result to the query * is stored into a newly allocated memory buffer. Favor * OrthancPluginRestApiPost() if calling the built-in REST API of * the Orthanc instance that hosts this plugin. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param url The URL of interest. * @param body The content of the body of the request. * @param bodySize The size of the body of the request. * @param username The username (can be NULL if no password protection). * @param password The password (can be NULL if no password protection). * @return 0 if success, or the error code if failure. **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpPost( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* url, const char* body, uint32_t bodySize, const char* username, const char* password) { _OrthancPluginCallHttpClient params; memset(¶ms, 0, sizeof(params)); params.target = target; params.method = OrthancPluginHttpMethod_Post; params.url = url; params.body = body; params.bodySize = bodySize; params.username = username; params.password = password; return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); } /** * @brief Issue a HTTP PUT call. * * Make a HTTP PUT call to the given URL. The result to the query is * stored into a newly allocated memory buffer. Favor * OrthancPluginRestApiPut() if calling the built-in REST API of the * Orthanc instance that hosts this plugin. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param url The URL of interest. * @param body The content of the body of the request. * @param bodySize The size of the body of the request. * @param username The username (can be NULL if no password protection). * @param password The password (can be NULL if no password protection). * @return 0 if success, or the error code if failure. **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpPut( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* url, const char* body, uint32_t bodySize, const char* username, const char* password) { _OrthancPluginCallHttpClient params; memset(¶ms, 0, sizeof(params)); params.target = target; params.method = OrthancPluginHttpMethod_Put; params.url = url; params.body = body; params.bodySize = bodySize; params.username = username; params.password = password; return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); } /** * @brief Issue a HTTP DELETE call. * * Make a HTTP DELETE call to the given URL. Favor * OrthancPluginRestApiDelete() if calling the built-in REST API of * the Orthanc instance that hosts this plugin. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param url The URL of interest. * @param username The username (can be NULL if no password protection). * @param password The password (can be NULL if no password protection). * @return 0 if success, or the error code if failure. **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpDelete( OrthancPluginContext* context, const char* url, const char* username, const char* password) { _OrthancPluginCallHttpClient params; memset(¶ms, 0, sizeof(params)); params.method = OrthancPluginHttpMethod_Delete; params.url = url; params.username = username; params.password = password; return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); } typedef struct { OrthancPluginImage** target; const OrthancPluginImage* source; OrthancPluginPixelFormat targetFormat; } _OrthancPluginConvertPixelFormat; /** * @brief Change the pixel format of an image. * * This function creates a new image, changing the memory layout of the pixels. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param source The source image. * @param targetFormat The target pixel format. * @return The resulting image. It must be freed with OrthancPluginFreeImage(). * @ingroup Images **/ ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginConvertPixelFormat( OrthancPluginContext* context, const OrthancPluginImage* source, OrthancPluginPixelFormat targetFormat) { OrthancPluginImage* target = NULL; _OrthancPluginConvertPixelFormat params; params.target = ⌖ params.source = source; params.targetFormat = targetFormat; if (context->InvokeService(context, _OrthancPluginService_ConvertPixelFormat, ¶ms) != OrthancPluginErrorCode_Success) { return NULL; } else { return target; } } /** * @brief Return the number of available fonts. * * This function returns the number of fonts that are built in the * Orthanc core. These fonts can be used to draw texts on images * through OrthancPluginDrawText(). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @return The number of fonts. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFontsCount( OrthancPluginContext* context) { uint32_t count = 0; _OrthancPluginReturnSingleValue params; memset(¶ms, 0, sizeof(params)); params.resultUint32 = &count; if (context->InvokeService(context, _OrthancPluginService_GetFontsCount, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return 0; } else { return count; } } typedef struct { uint32_t fontIndex; /* in */ const char** name; /* out */ uint32_t* size; /* out */ } _OrthancPluginGetFontInfo; /** * @brief Return the name of a font. * * This function returns the name of a font that is built in the Orthanc core. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount(). * @return The font name. This is a statically-allocated string, do not free it. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetFontName( OrthancPluginContext* context, uint32_t fontIndex) { const char* result = NULL; _OrthancPluginGetFontInfo params; memset(¶ms, 0, sizeof(params)); params.name = &result; params.fontIndex = fontIndex; if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, ¶ms) != OrthancPluginErrorCode_Success) { return NULL; } else { return result; } } /** * @brief Return the size of a font. * * This function returns the size of a font that is built in the Orthanc core. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount(). * @return The font size. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFontSize( OrthancPluginContext* context, uint32_t fontIndex) { uint32_t result; _OrthancPluginGetFontInfo params; memset(¶ms, 0, sizeof(params)); params.size = &result; params.fontIndex = fontIndex; if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, ¶ms) != OrthancPluginErrorCode_Success) { return 0; } else { return result; } } typedef struct { OrthancPluginImage* image; uint32_t fontIndex; const char* utf8Text; int32_t x; int32_t y; uint8_t r; uint8_t g; uint8_t b; } _OrthancPluginDrawText; /** * @brief Draw text on an image. * * This function draws some text on some image. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param image The image upon which to draw the text. * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount(). * @param utf8Text The text to be drawn, encoded as an UTF-8 zero-terminated string. * @param x The X position of the text over the image. * @param y The Y position of the text over the image. * @param r The value of the red color channel of the text. * @param g The value of the green color channel of the text. * @param b The value of the blue color channel of the text. * @return 0 if success, other value if error. * @ingroup Images **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginDrawText( OrthancPluginContext* context, OrthancPluginImage* image, uint32_t fontIndex, const char* utf8Text, int32_t x, int32_t y, uint8_t r, uint8_t g, uint8_t b) { _OrthancPluginDrawText params; memset(¶ms, 0, sizeof(params)); params.image = image; params.fontIndex = fontIndex; params.utf8Text = utf8Text; params.x = x; params.y = y; params.r = r; params.g = g; params.b = b; return context->InvokeService(context, _OrthancPluginService_DrawText, ¶ms); } typedef struct { OrthancPluginStorageArea* storageArea; const char* uuid; const void* content; uint64_t size; OrthancPluginContentType type; } _OrthancPluginStorageAreaCreate; /** * @brief Create a file inside the storage area. * * This function creates a new file inside the storage area that is * currently used by Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param storageArea The storage area. * @param uuid The identifier of the file to be created. * @param content The content to store in the newly created file. * @param size The size of the content. * @param type The type of the file content. * @return 0 if success, other value if error. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStorageAreaCreate( OrthancPluginContext* context, OrthancPluginStorageArea* storageArea, const char* uuid, const void* content, uint64_t size, OrthancPluginContentType type) { _OrthancPluginStorageAreaCreate params; params.storageArea = storageArea; params.uuid = uuid; params.content = content; params.size = size; params.type = type; return context->InvokeService(context, _OrthancPluginService_StorageAreaCreate, ¶ms); } typedef struct { OrthancPluginMemoryBuffer* target; OrthancPluginStorageArea* storageArea; const char* uuid; OrthancPluginContentType type; } _OrthancPluginStorageAreaRead; /** * @brief Read a file from the storage area. * * This function reads the content of a given file from the storage * area that is currently used by Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param storageArea The storage area. * @param uuid The identifier of the file to be read. * @param type The type of the file content. * @return 0 if success, other value if error. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStorageAreaRead( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, OrthancPluginStorageArea* storageArea, const char* uuid, OrthancPluginContentType type) { _OrthancPluginStorageAreaRead params; params.target = target; params.storageArea = storageArea; params.uuid = uuid; params.type = type; return context->InvokeService(context, _OrthancPluginService_StorageAreaRead, ¶ms); } typedef struct { OrthancPluginStorageArea* storageArea; const char* uuid; OrthancPluginContentType type; } _OrthancPluginStorageAreaRemove; /** * @brief Remove a file from the storage area. * * This function removes a given file from the storage area that is * currently used by Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param storageArea The storage area. * @param uuid The identifier of the file to be removed. * @param type The type of the file content. * @return 0 if success, other value if error. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStorageAreaRemove( OrthancPluginContext* context, OrthancPluginStorageArea* storageArea, const char* uuid, OrthancPluginContentType type) { _OrthancPluginStorageAreaRemove params; params.storageArea = storageArea; params.uuid = uuid; params.type = type; return context->InvokeService(context, _OrthancPluginService_StorageAreaRemove, ¶ms); } typedef struct { OrthancPluginErrorCode* target; int32_t code; uint16_t httpStatus; const char* message; } _OrthancPluginRegisterErrorCode; /** * @brief Declare a custom error code for this plugin. * * This function declares a custom error code that can be generated * by this plugin. This declaration is used to enrich the body of * the HTTP answer in the case of an error, and to set the proper * HTTP status code. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param code The error code that is internal to this plugin. * @param httpStatus The HTTP status corresponding to this error. * @param message The description of the error. * @return The error code that has been assigned inside the Orthanc core. * @ingroup Toolbox **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterErrorCode( OrthancPluginContext* context, int32_t code, uint16_t httpStatus, const char* message) { OrthancPluginErrorCode target; _OrthancPluginRegisterErrorCode params; params.target = ⌖ params.code = code; params.httpStatus = httpStatus; params.message = message; if (context->InvokeService(context, _OrthancPluginService_RegisterErrorCode, ¶ms) == OrthancPluginErrorCode_Success) { return target; } else { /* There was an error while assigned the error. Use a generic code. */ return OrthancPluginErrorCode_Plugin; } } typedef struct { uint16_t group; uint16_t element; OrthancPluginValueRepresentation vr; const char* name; uint32_t minMultiplicity; uint32_t maxMultiplicity; } _OrthancPluginRegisterDictionaryTag; /** * @brief Register a new tag into the DICOM dictionary. * * This function declares a new tag in the dictionary of DICOM tags * that are known to Orthanc. This function should be used in the * OrthancPluginInitialize() callback. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param group The group of the tag. * @param element The element of the tag. * @param vr The value representation of the tag. * @param name The nickname of the tag. * @param minMultiplicity The minimum multiplicity of the tag (must be above 0). * @param maxMultiplicity The maximum multiplicity of the tag. A value of 0 means * an arbitrary multiplicity ("n"). * @return 0 if success, other value if error. * @ingroup Toolbox **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterDictionaryTag( OrthancPluginContext* context, uint16_t group, uint16_t element, OrthancPluginValueRepresentation vr, const char* name, uint32_t minMultiplicity, uint32_t maxMultiplicity) { _OrthancPluginRegisterDictionaryTag params; params.group = group; params.element = element; params.vr = vr; params.name = name; params.minMultiplicity = minMultiplicity; params.maxMultiplicity = maxMultiplicity; return context->InvokeService(context, _OrthancPluginService_RegisterDictionaryTag, ¶ms); } typedef struct { OrthancPluginStorageArea* storageArea; OrthancPluginResourceType level; } _OrthancPluginReconstructMainDicomTags; /** * @brief Reconstruct the main DICOM tags. * * This function requests the Orthanc core to reconstruct the main * DICOM tags of all the resources of the given type. This function * can only be used as a part of the upgrade of a custom database * back-end * (cf. OrthancPlugins::IDatabaseBackend::UpgradeDatabase). A * database transaction will be automatically setup. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param storageArea The storage area. * @param level The type of the resources of interest. * @return 0 if success, other value if error. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginReconstructMainDicomTags( OrthancPluginContext* context, OrthancPluginStorageArea* storageArea, OrthancPluginResourceType level) { _OrthancPluginReconstructMainDicomTags params; params.level = level; params.storageArea = storageArea; return context->InvokeService(context, _OrthancPluginService_ReconstructMainDicomTags, ¶ms); } typedef struct { char** result; const char* instanceId; const char* buffer; uint32_t size; OrthancPluginDicomToJsonFormat format; OrthancPluginDicomToJsonFlags flags; uint32_t maxStringLength; } _OrthancPluginDicomToJson; /** * @brief Format a DICOM memory buffer as a JSON string. * * This function takes as input a memory buffer containing a DICOM * file, and outputs a JSON string representing the tags of this * DICOM file. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param buffer The memory buffer containing the DICOM file. * @param size The size of the memory buffer. * @param format The output format. * @param flags Flags governing the output. * @param maxStringLength The maximum length of a field. Too long fields will * be output as "null". The 0 value means no maximum length. * @return The NULL value if the case of an error, or the JSON * string. This string must be freed by OrthancPluginFreeString(). * @ingroup Toolbox * @see OrthancPluginDicomInstanceToJson **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginDicomBufferToJson( OrthancPluginContext* context, const char* buffer, uint32_t size, OrthancPluginDicomToJsonFormat format, OrthancPluginDicomToJsonFlags flags, uint32_t maxStringLength) { char* result; _OrthancPluginDicomToJson params; memset(¶ms, 0, sizeof(params)); params.result = &result; params.buffer = buffer; params.size = size; params.format = format; params.flags = flags; params.maxStringLength = maxStringLength; if (context->InvokeService(context, _OrthancPluginService_DicomBufferToJson, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Format a DICOM instance as a JSON string. * * This function formats a DICOM instance that is stored in Orthanc, * and outputs a JSON string representing the tags of this DICOM * instance. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param instanceId The Orthanc identifier of the instance. * @param format The output format. * @param flags Flags governing the output. * @param maxStringLength The maximum length of a field. Too long fields will * be output as "null". The 0 value means no maximum length. * @return The NULL value if the case of an error, or the JSON * string. This string must be freed by OrthancPluginFreeString(). * @ingroup Toolbox * @see OrthancPluginDicomInstanceToJson **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginDicomInstanceToJson( OrthancPluginContext* context, const char* instanceId, OrthancPluginDicomToJsonFormat format, OrthancPluginDicomToJsonFlags flags, uint32_t maxStringLength) { char* result; _OrthancPluginDicomToJson params; memset(¶ms, 0, sizeof(params)); params.result = &result; params.instanceId = instanceId; params.format = format; params.flags = flags; params.maxStringLength = maxStringLength; if (context->InvokeService(context, _OrthancPluginService_DicomInstanceToJson, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } typedef struct { OrthancPluginMemoryBuffer* target; const char* uri; uint32_t headersCount; const char* const* headersKeys; const char* const* headersValues; int32_t afterPlugins; } _OrthancPluginRestApiGet2; /** * @brief Make a GET call to the Orthanc REST API, with custom HTTP headers. * * Make a GET call to the Orthanc REST API with extended * parameters. The result to the query is stored into a newly * allocated memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param uri The URI in the built-in Orthanc API. * @param headersCount The number of HTTP headers. * @param headersKeys Array containing the keys of the HTTP headers. * @param headersValues Array containing the values of the HTTP headers. * @param afterPlugins If 0, the built-in API of Orthanc is used. * If 1, the API is tainted by the plugins. * @return 0 if success, or the error code if failure. * @see OrthancPluginRestApiGet, OrthancPluginRestApiGetAfterPlugins * @ingroup Orthanc **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiGet2( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* uri, uint32_t headersCount, const char* const* headersKeys, const char* const* headersValues, int32_t afterPlugins) { _OrthancPluginRestApiGet2 params; params.target = target; params.uri = uri; params.headersCount = headersCount; params.headersKeys = headersKeys; params.headersValues = headersValues; params.afterPlugins = afterPlugins; return context->InvokeService(context, _OrthancPluginService_RestApiGet2, ¶ms); } typedef struct { OrthancPluginWorklistCallback callback; } _OrthancPluginWorklistCallback; /** * @brief Register a callback to handle modality worklists requests. * * This function registers a callback to handle C-Find SCP requests * on modality worklists. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param callback The callback. * @return 0 if success, other value if error. * @ingroup Worklists **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterWorklistCallback( OrthancPluginContext* context, OrthancPluginWorklistCallback callback) { _OrthancPluginWorklistCallback params; params.callback = callback; return context->InvokeService(context, _OrthancPluginService_RegisterWorklistCallback, ¶ms); } typedef struct { OrthancPluginWorklistAnswers* answers; const OrthancPluginWorklistQuery* query; const void* dicom; uint32_t size; } _OrthancPluginWorklistAnswersOperation; /** * @brief Add one answer to some modality worklist request. * * This function adds one worklist (encoded as a DICOM file) to the * set of answers corresponding to some C-Find SCP request against * modality worklists. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param answers The set of answers. * @param query The worklist query, as received by the callback. * @param dicom The worklist to answer, encoded as a DICOM file. * @param size The size of the DICOM file. * @return 0 if success, other value if error. * @ingroup Worklists **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWorklistAddAnswer( OrthancPluginContext* context, OrthancPluginWorklistAnswers* answers, const OrthancPluginWorklistQuery* query, const void* dicom, uint32_t size) { _OrthancPluginWorklistAnswersOperation params; params.answers = answers; params.query = query; params.dicom = dicom; params.size = size; return context->InvokeService(context, _OrthancPluginService_WorklistAddAnswer, ¶ms); } /** * @brief Mark the set of worklist answers as incomplete. * * This function marks as incomplete the set of answers * corresponding to some C-Find SCP request against modality * worklists. This must be used if canceling the handling of a * request when too many answers are to be returned. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param answers The set of answers. * @return 0 if success, other value if error. * @ingroup Worklists **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWorklistMarkIncomplete( OrthancPluginContext* context, OrthancPluginWorklistAnswers* answers) { _OrthancPluginWorklistAnswersOperation params; params.answers = answers; params.query = NULL; params.dicom = NULL; params.size = 0; return context->InvokeService(context, _OrthancPluginService_WorklistMarkIncomplete, ¶ms); } typedef struct { const OrthancPluginWorklistQuery* query; const void* dicom; uint32_t size; int32_t* isMatch; OrthancPluginMemoryBuffer* target; } _OrthancPluginWorklistQueryOperation; /** * @brief Test whether a worklist matches the query. * * This function checks whether one worklist (encoded as a DICOM * file) matches the C-Find SCP query against modality * worklists. This function must be called before adding the * worklist as an answer through OrthancPluginWorklistAddAnswer(). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param query The worklist query, as received by the callback. * @param dicom The worklist to answer, encoded as a DICOM file. * @param size The size of the DICOM file. * @return 1 if the worklist matches the query, 0 otherwise. * @ingroup Worklists **/ ORTHANC_PLUGIN_INLINE int32_t OrthancPluginWorklistIsMatch( OrthancPluginContext* context, const OrthancPluginWorklistQuery* query, const void* dicom, uint32_t size) { int32_t isMatch = 0; _OrthancPluginWorklistQueryOperation params; params.query = query; params.dicom = dicom; params.size = size; params.isMatch = &isMatch; params.target = NULL; if (context->InvokeService(context, _OrthancPluginService_WorklistIsMatch, ¶ms) == OrthancPluginErrorCode_Success) { return isMatch; } else { /* Error: Assume non-match */ return 0; } } /** * @brief Retrieve the worklist query as a DICOM file. * * This function retrieves the DICOM file that underlies a C-Find * SCP query against modality worklists. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target Memory buffer where to store the DICOM file. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param query The worklist query, as received by the callback. * @return 0 if success, other value if error. * @ingroup Worklists **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWorklistGetDicomQuery( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const OrthancPluginWorklistQuery* query) { _OrthancPluginWorklistQueryOperation params; params.query = query; params.dicom = NULL; params.size = 0; params.isMatch = NULL; params.target = target; return context->InvokeService(context, _OrthancPluginService_WorklistGetDicomQuery, ¶ms); } /** * @brief Get the origin of a DICOM file. * * This function returns the origin of a DICOM instance that has been received by Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param instance The instance of interest. * @return The origin of the instance. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE OrthancPluginInstanceOrigin OrthancPluginGetInstanceOrigin( OrthancPluginContext* context, OrthancPluginDicomInstance* instance) { OrthancPluginInstanceOrigin origin; _OrthancPluginAccessDicomInstance params; memset(¶ms, 0, sizeof(params)); params.resultOrigin = &origin; params.instance = instance; if (context->InvokeService(context, _OrthancPluginService_GetInstanceOrigin, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return OrthancPluginInstanceOrigin_Unknown; } else { return origin; } } typedef struct { OrthancPluginMemoryBuffer* target; const char* json; const OrthancPluginImage* pixelData; OrthancPluginCreateDicomFlags flags; } _OrthancPluginCreateDicom; /** * @brief Create a DICOM instance from a JSON string and an image. * * This function takes as input a string containing a JSON file * describing the content of a DICOM instance. As an output, it * writes the corresponding DICOM instance to a newly allocated * memory buffer. Additionally, an image to be encoded within the * DICOM instance can also be provided. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). * @param json The input JSON file. * @param pixelData The image. Can be NULL, if the pixel data is encoded inside the JSON with the data URI scheme. * @param flags Flags governing the output. * @return 0 if success, other value if error. * @ingroup Toolbox * @see OrthancPluginDicomBufferToJson **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCreateDicom( OrthancPluginContext* context, OrthancPluginMemoryBuffer* target, const char* json, const OrthancPluginImage* pixelData, OrthancPluginCreateDicomFlags flags) { _OrthancPluginCreateDicom params; params.target = target; params.json = json; params.pixelData = pixelData; params.flags = flags; return context->InvokeService(context, _OrthancPluginService_CreateDicom, ¶ms); } typedef struct { OrthancPluginDecodeImageCallback callback; } _OrthancPluginDecodeImageCallback; /** * @brief Register a callback to handle the decoding of DICOM images. * * This function registers a custom callback to the decoding of * DICOM images, replacing the built-in decoder of Orthanc. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param callback The callback. * @return 0 if success, other value if error. * @ingroup Callbacks **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterDecodeImageCallback( OrthancPluginContext* context, OrthancPluginDecodeImageCallback callback) { _OrthancPluginDecodeImageCallback params; params.callback = callback; return context->InvokeService(context, _OrthancPluginService_RegisterDecodeImageCallback, ¶ms); } typedef struct { OrthancPluginImage** target; OrthancPluginPixelFormat format; uint32_t width; uint32_t height; uint32_t pitch; void* buffer; const void* constBuffer; uint32_t bufferSize; uint32_t frameIndex; } _OrthancPluginCreateImage; /** * @brief Create an image. * * This function creates an image of given size and format. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param format The format of the pixels. * @param width The width of the image. * @param height The height of the image. * @return The newly allocated image. It must be freed with OrthancPluginFreeImage(). * @ingroup Images **/ ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginCreateImage( OrthancPluginContext* context, OrthancPluginPixelFormat format, uint32_t width, uint32_t height) { OrthancPluginImage* target = NULL; _OrthancPluginCreateImage params; memset(¶ms, 0, sizeof(params)); params.target = ⌖ params.format = format; params.width = width; params.height = height; if (context->InvokeService(context, _OrthancPluginService_CreateImage, ¶ms) != OrthancPluginErrorCode_Success) { return NULL; } else { return target; } } /** * @brief Create an image pointing to a memory buffer. * * This function creates an image whose content points to a memory * buffer managed by the plugin. Note that the buffer is directly * accessed, no memory is allocated and no data is copied. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param format The format of the pixels. * @param width The width of the image. * @param height The height of the image. * @param pitch The pitch of the image (i.e. the number of bytes * between 2 successive lines of the image in the memory buffer). * @param buffer The memory buffer. * @return The newly allocated image. It must be freed with OrthancPluginFreeImage(). * @ingroup Images **/ ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginCreateImageAccessor( OrthancPluginContext* context, OrthancPluginPixelFormat format, uint32_t width, uint32_t height, uint32_t pitch, void* buffer) { OrthancPluginImage* target = NULL; _OrthancPluginCreateImage params; memset(¶ms, 0, sizeof(params)); params.target = ⌖ params.format = format; params.width = width; params.height = height; params.pitch = pitch; params.buffer = buffer; if (context->InvokeService(context, _OrthancPluginService_CreateImageAccessor, ¶ms) != OrthancPluginErrorCode_Success) { return NULL; } else { return target; } } /** * @brief Decode one frame from a DICOM instance. * * This function decodes one frame of a DICOM image that is stored * in a memory buffer. This function will give the same result as * OrthancPluginUncompressImage() for single-frame DICOM images. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param buffer Pointer to a memory buffer containing the DICOM image. * @param bufferSize Size of the memory buffer containing the DICOM image. * @param frameIndex The index of the frame of interest in a multi-frame image. * @return The uncompressed image. It must be freed with OrthancPluginFreeImage(). * @ingroup Images **/ ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginDecodeDicomImage( OrthancPluginContext* context, const void* buffer, uint32_t bufferSize, uint32_t frameIndex) { OrthancPluginImage* target = NULL; _OrthancPluginCreateImage params; memset(¶ms, 0, sizeof(params)); params.target = ⌖ params.constBuffer = buffer; params.bufferSize = bufferSize; params.frameIndex = frameIndex; if (context->InvokeService(context, _OrthancPluginService_DecodeDicomImage, ¶ms) != OrthancPluginErrorCode_Success) { return NULL; } else { return target; } } typedef struct { char** result; const void* buffer; uint32_t size; } _OrthancPluginComputeHash; /** * @brief Compute an MD5 hash. * * This functions computes the MD5 cryptographic hash of the given memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param buffer The source memory buffer. * @param size The size in bytes of the source buffer. * @return The NULL value in case of error, or a string containing the cryptographic hash. * This string must be freed by OrthancPluginFreeString(). * @ingroup Toolbox **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginComputeMd5( OrthancPluginContext* context, const void* buffer, uint32_t size) { char* result; _OrthancPluginComputeHash params; params.result = &result; params.buffer = buffer; params.size = size; if (context->InvokeService(context, _OrthancPluginService_ComputeMd5, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } /** * @brief Compute a SHA-1 hash. * * This functions computes the SHA-1 cryptographic hash of the given memory buffer. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param buffer The source memory buffer. * @param size The size in bytes of the source buffer. * @return The NULL value in case of error, or a string containing the cryptographic hash. * This string must be freed by OrthancPluginFreeString(). * @ingroup Toolbox **/ ORTHANC_PLUGIN_INLINE char* OrthancPluginComputeSha1( OrthancPluginContext* context, const void* buffer, uint32_t size) { char* result; _OrthancPluginComputeHash params; params.result = &result; params.buffer = buffer; params.size = size; if (context->InvokeService(context, _OrthancPluginService_ComputeSha1, ¶ms) != OrthancPluginErrorCode_Success) { /* Error */ return NULL; } else { return result; } } typedef struct { OrthancPluginDictionaryEntry* target; const char* name; } _OrthancPluginLookupDictionary; /** * @brief Get information about the given DICOM tag. * * This functions makes a lookup in the dictionary of DICOM tags * that are known to Orthanc, and returns information about this * tag. The tag can be specified using its human-readable name * (e.g. "PatientName") or a set of two hexadecimal numbers * (e.g. "0010-0020"). * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param target Where to store the information about the tag. * @param name The name of the DICOM tag. * @return 0 if success, other value if error. * @ingroup Toolbox **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginLookupDictionary( OrthancPluginContext* context, OrthancPluginDictionaryEntry* target, const char* name) { _OrthancPluginLookupDictionary params; params.target = target; params.name = name; return context->InvokeService(context, _OrthancPluginService_LookupDictionary, ¶ms); } #ifdef __cplusplus } #endif /** @} */ OrthancPostgreSQL-2.0/Orthanc/Sdk-0.9.5/orthanc/OrthancCppDatabasePlugin.h0000644000000000000000000016767712627602430024317 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * In addition, as a special exception, the copyright holders of this * program give permission to link the code of its release with the * OpenSSL project's "OpenSSL" library (or with modified versions of it * that use the same license as the "OpenSSL" library), and distribute * the linked executables. You must obey the GNU General Public License * in all respects for all of the code used other than "OpenSSL". If you * modify file(s) with this exception, you may extend this exception to * your version of the file(s), but you are not obligated to do so. If * you do not wish to do so, delete this exception statement from your * version. If you delete this exception statement from all source files * in the program, then also delete it here. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . **/ #pragma once #include "OrthancCDatabasePlugin.h" #include #include #include namespace OrthancPlugins { //! @cond Doxygen_Suppress // This class mimics "boost::noncopyable" class NonCopyable { private: NonCopyable(const NonCopyable&); NonCopyable& operator= (const NonCopyable&); protected: NonCopyable() { } ~NonCopyable() { } }; //! @endcond /** * @ingroup Callbacks **/ class DatabaseException { private: OrthancPluginErrorCode code_; public: DatabaseException() : code_(OrthancPluginErrorCode_DatabasePlugin) { } DatabaseException(OrthancPluginErrorCode code) : code_(code) { } OrthancPluginErrorCode GetErrorCode() const { return code_; } }; /** * @ingroup Callbacks **/ class DatabaseBackendOutput : public NonCopyable { friend class DatabaseBackendAdapter; private: enum AllowedAnswers { AllowedAnswers_All, AllowedAnswers_None, AllowedAnswers_Attachment, AllowedAnswers_Change, AllowedAnswers_DicomTag, AllowedAnswers_ExportedResource }; OrthancPluginContext* context_; OrthancPluginDatabaseContext* database_; AllowedAnswers allowedAnswers_; void SetAllowedAnswers(AllowedAnswers allowed) { allowedAnswers_ = allowed; } public: DatabaseBackendOutput(OrthancPluginContext* context, OrthancPluginDatabaseContext* database) : context_(context), database_(database), allowedAnswers_(AllowedAnswers_All /* for unit tests */) { } OrthancPluginContext* GetContext() { return context_; } void LogError(const std::string& message) { OrthancPluginLogError(context_, message.c_str()); } void LogWarning(const std::string& message) { OrthancPluginLogWarning(context_, message.c_str()); } void LogInfo(const std::string& message) { OrthancPluginLogInfo(context_, message.c_str()); } void SignalDeletedAttachment(const std::string& uuid, int32_t contentType, uint64_t uncompressedSize, const std::string& uncompressedHash, int32_t compressionType, uint64_t compressedSize, const std::string& compressedHash) { OrthancPluginAttachment attachment; attachment.uuid = uuid.c_str(); attachment.contentType = contentType; attachment.uncompressedSize = uncompressedSize; attachment.uncompressedHash = uncompressedHash.c_str(); attachment.compressionType = compressionType; attachment.compressedSize = compressedSize; attachment.compressedHash = compressedHash.c_str(); OrthancPluginDatabaseSignalDeletedAttachment(context_, database_, &attachment); } void SignalDeletedResource(const std::string& publicId, OrthancPluginResourceType resourceType) { OrthancPluginDatabaseSignalDeletedResource(context_, database_, publicId.c_str(), resourceType); } void SignalRemainingAncestor(const std::string& ancestorId, OrthancPluginResourceType ancestorType) { OrthancPluginDatabaseSignalRemainingAncestor(context_, database_, ancestorId.c_str(), ancestorType); } void AnswerAttachment(const std::string& uuid, int32_t contentType, uint64_t uncompressedSize, const std::string& uncompressedHash, int32_t compressionType, uint64_t compressedSize, const std::string& compressedHash) { if (allowedAnswers_ != AllowedAnswers_All && allowedAnswers_ != AllowedAnswers_Attachment) { throw std::runtime_error("Cannot answer with an attachment in the current state"); } OrthancPluginAttachment attachment; attachment.uuid = uuid.c_str(); attachment.contentType = contentType; attachment.uncompressedSize = uncompressedSize; attachment.uncompressedHash = uncompressedHash.c_str(); attachment.compressionType = compressionType; attachment.compressedSize = compressedSize; attachment.compressedHash = compressedHash.c_str(); OrthancPluginDatabaseAnswerAttachment(context_, database_, &attachment); } void AnswerChange(int64_t seq, int32_t changeType, OrthancPluginResourceType resourceType, const std::string& publicId, const std::string& date) { if (allowedAnswers_ != AllowedAnswers_All && allowedAnswers_ != AllowedAnswers_Change) { throw std::runtime_error("Cannot answer with a change in the current state"); } OrthancPluginChange change; change.seq = seq; change.changeType = changeType; change.resourceType = resourceType; change.publicId = publicId.c_str(); change.date = date.c_str(); OrthancPluginDatabaseAnswerChange(context_, database_, &change); } void AnswerDicomTag(uint16_t group, uint16_t element, const std::string& value) { if (allowedAnswers_ != AllowedAnswers_All && allowedAnswers_ != AllowedAnswers_DicomTag) { throw std::runtime_error("Cannot answer with a DICOM tag in the current state"); } OrthancPluginDicomTag tag; tag.group = group; tag.element = element; tag.value = value.c_str(); OrthancPluginDatabaseAnswerDicomTag(context_, database_, &tag); } void AnswerExportedResource(int64_t seq, OrthancPluginResourceType resourceType, const std::string& publicId, const std::string& modality, const std::string& date, const std::string& patientId, const std::string& studyInstanceUid, const std::string& seriesInstanceUid, const std::string& sopInstanceUid) { if (allowedAnswers_ != AllowedAnswers_All && allowedAnswers_ != AllowedAnswers_ExportedResource) { throw std::runtime_error("Cannot answer with an exported resource in the current state"); } OrthancPluginExportedResource exported; exported.seq = seq; exported.resourceType = resourceType; exported.publicId = publicId.c_str(); exported.modality = modality.c_str(); exported.date = date.c_str(); exported.patientId = patientId.c_str(); exported.studyInstanceUid = studyInstanceUid.c_str(); exported.seriesInstanceUid = seriesInstanceUid.c_str(); exported.sopInstanceUid = sopInstanceUid.c_str(); OrthancPluginDatabaseAnswerExportedResource(context_, database_, &exported); } }; /** * @ingroup Callbacks **/ class IDatabaseBackend : public NonCopyable { friend class DatabaseBackendAdapter; private: DatabaseBackendOutput* output_; void Finalize() { if (output_ != NULL) { delete output_; output_ = NULL; } } protected: DatabaseBackendOutput& GetOutput() { return *output_; } public: IDatabaseBackend() : output_(NULL) { } virtual ~IDatabaseBackend() { Finalize(); } // This takes the ownership void RegisterOutput(DatabaseBackendOutput* output) { Finalize(); output_ = output; } virtual void Open() = 0; virtual void Close() = 0; virtual void AddAttachment(int64_t id, const OrthancPluginAttachment& attachment) = 0; virtual void AttachChild(int64_t parent, int64_t child) = 0; virtual void ClearChanges() = 0; virtual void ClearExportedResources() = 0; virtual int64_t CreateResource(const char* publicId, OrthancPluginResourceType type) = 0; virtual void DeleteAttachment(int64_t id, int32_t attachment) = 0; virtual void DeleteMetadata(int64_t id, int32_t metadataType) = 0; virtual void DeleteResource(int64_t id) = 0; virtual void GetAllInternalIds(std::list& target, OrthancPluginResourceType resourceType) = 0; virtual void GetAllPublicIds(std::list& target, OrthancPluginResourceType resourceType) = 0; virtual void GetAllPublicIds(std::list& target, OrthancPluginResourceType resourceType, uint64_t since, uint64_t limit) = 0; /* Use GetOutput().AnswerChange() */ virtual void GetChanges(bool& done /*out*/, int64_t since, uint32_t maxResults) = 0; virtual void GetChildrenInternalId(std::list& target /*out*/, int64_t id) = 0; virtual void GetChildrenPublicId(std::list& target /*out*/, int64_t id) = 0; /* Use GetOutput().AnswerExportedResource() */ virtual void GetExportedResources(bool& done /*out*/, int64_t since, uint32_t maxResults) = 0; /* Use GetOutput().AnswerChange() */ virtual void GetLastChange() = 0; /* Use GetOutput().AnswerExportedResource() */ virtual void GetLastExportedResource() = 0; /* Use GetOutput().AnswerDicomTag() */ virtual void GetMainDicomTags(int64_t id) = 0; virtual std::string GetPublicId(int64_t resourceId) = 0; virtual uint64_t GetResourceCount(OrthancPluginResourceType resourceType) = 0; virtual OrthancPluginResourceType GetResourceType(int64_t resourceId) = 0; virtual uint64_t GetTotalCompressedSize() = 0; virtual uint64_t GetTotalUncompressedSize() = 0; virtual bool IsExistingResource(int64_t internalId) = 0; virtual bool IsProtectedPatient(int64_t internalId) = 0; virtual void ListAvailableMetadata(std::list& target /*out*/, int64_t id) = 0; virtual void ListAvailableAttachments(std::list& target /*out*/, int64_t id) = 0; virtual void LogChange(const OrthancPluginChange& change) = 0; virtual void LogExportedResource(const OrthancPluginExportedResource& resource) = 0; /* Use GetOutput().AnswerAttachment() */ virtual bool LookupAttachment(int64_t id, int32_t contentType) = 0; virtual bool LookupGlobalProperty(std::string& target /*out*/, int32_t property) = 0; virtual void LookupIdentifier(std::list& target /*out*/, OrthancPluginResourceType resourceType, uint16_t group, uint16_t element, OrthancPluginIdentifierConstraint constraint, const char* value) = 0; virtual bool LookupMetadata(std::string& target /*out*/, int64_t id, int32_t metadataType) = 0; virtual bool LookupParent(int64_t& parentId /*out*/, int64_t resourceId) = 0; virtual bool LookupResource(int64_t& id /*out*/, OrthancPluginResourceType& type /*out*/, const char* publicId) = 0; virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/) = 0; virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/, int64_t patientIdToAvoid) = 0; virtual void SetGlobalProperty(int32_t property, const char* value) = 0; virtual void SetMainDicomTag(int64_t id, uint16_t group, uint16_t element, const char* value) = 0; virtual void SetIdentifierTag(int64_t id, uint16_t group, uint16_t element, const char* value) = 0; virtual void SetMetadata(int64_t id, int32_t metadataType, const char* value) = 0; virtual void SetProtectedPatient(int64_t internalId, bool isProtected) = 0; virtual void StartTransaction() = 0; virtual void RollbackTransaction() = 0; virtual void CommitTransaction() = 0; virtual uint32_t GetDatabaseVersion() = 0; /** * Upgrade the database to the specified version of the database * schema. The upgrade script is allowed to make calls to * OrthancPluginReconstructMainDicomTags(). **/ virtual void UpgradeDatabase(uint32_t targetVersion, OrthancPluginStorageArea* storageArea) = 0; virtual void ClearMainDicomTags(int64_t internalId) = 0; }; /** * @brief Bridge between C and C++ database engines. * * Class creating the bridge between the C low-level primitives for * custom database engines, and the high-level IDatabaseBackend C++ * interface. * * @ingroup Callbacks **/ class DatabaseBackendAdapter { private: // This class cannot be instantiated DatabaseBackendAdapter() { } static void LogError(IDatabaseBackend* backend, const std::runtime_error& e) { backend->GetOutput().LogError("Exception in database back-end: " + std::string(e.what())); } static OrthancPluginErrorCode AddAttachment(void* payload, int64_t id, const OrthancPluginAttachment* attachment) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->AddAttachment(id, *attachment); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode AttachChild(void* payload, int64_t parent, int64_t child) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->AttachChild(parent, child); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode ClearChanges(void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->ClearChanges(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode ClearExportedResources(void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->ClearExportedResources(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode CreateResource(int64_t* id, void* payload, const char* publicId, OrthancPluginResourceType resourceType) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *id = backend->CreateResource(publicId, resourceType); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode DeleteAttachment(void* payload, int64_t id, int32_t contentType) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->DeleteAttachment(id, contentType); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode DeleteMetadata(void* payload, int64_t id, int32_t metadataType) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->DeleteMetadata(id, metadataType); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode DeleteResource(void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->DeleteResource(id); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetAllInternalIds(OrthancPluginDatabaseContext* context, void* payload, OrthancPluginResourceType resourceType) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list target; backend->GetAllInternalIds(target, resourceType); for (std::list::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetAllPublicIds(OrthancPluginDatabaseContext* context, void* payload, OrthancPluginResourceType resourceType) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list ids; backend->GetAllPublicIds(ids, resourceType); for (std::list::const_iterator it = ids.begin(); it != ids.end(); ++it) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, it->c_str()); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetAllPublicIdsWithLimit(OrthancPluginDatabaseContext* context, void* payload, OrthancPluginResourceType resourceType, uint64_t since, uint64_t limit) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list ids; backend->GetAllPublicIds(ids, resourceType, since, limit); for (std::list::const_iterator it = ids.begin(); it != ids.end(); ++it) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, it->c_str()); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetChanges(OrthancPluginDatabaseContext* context, void* payload, int64_t since, uint32_t maxResult) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Change); try { bool done; backend->GetChanges(done, since, maxResult); if (done) { OrthancPluginDatabaseAnswerChangesDone(backend->GetOutput().context_, backend->GetOutput().database_); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetChildrenInternalId(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list target; backend->GetChildrenInternalId(target, id); for (std::list::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetChildrenPublicId(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list ids; backend->GetChildrenPublicId(ids, id); for (std::list::const_iterator it = ids.begin(); it != ids.end(); ++it) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, it->c_str()); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetExportedResources(OrthancPluginDatabaseContext* context, void* payload, int64_t since, uint32_t maxResult) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_ExportedResource); try { bool done; backend->GetExportedResources(done, since, maxResult); if (done) { OrthancPluginDatabaseAnswerExportedResourcesDone(backend->GetOutput().context_, backend->GetOutput().database_); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetLastChange(OrthancPluginDatabaseContext* context, void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Change); try { backend->GetLastChange(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetLastExportedResource(OrthancPluginDatabaseContext* context, void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_ExportedResource); try { backend->GetLastExportedResource(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetMainDicomTags(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_DicomTag); try { backend->GetMainDicomTags(id); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetPublicId(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::string s = backend->GetPublicId(id); OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, s.c_str()); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetResourceCount(uint64_t* target, void* payload, OrthancPluginResourceType resourceType) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *target = backend->GetResourceCount(resourceType); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetResourceType(OrthancPluginResourceType* resourceType, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *resourceType = backend->GetResourceType(id); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetTotalCompressedSize(uint64_t* target, void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *target = backend->GetTotalCompressedSize(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetTotalUncompressedSize(uint64_t* target, void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *target = backend->GetTotalUncompressedSize(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode IsExistingResource(int32_t* existing, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *existing = backend->IsExistingResource(id); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode IsProtectedPatient(int32_t* isProtected, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *isProtected = backend->IsProtectedPatient(id); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode ListAvailableMetadata(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list target; backend->ListAvailableMetadata(target, id); for (std::list::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt32(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode ListAvailableAttachments(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list target; backend->ListAvailableAttachments(target, id); for (std::list::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt32(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode LogChange(void* payload, const OrthancPluginChange* change) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->LogChange(*change); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode LogExportedResource(void* payload, const OrthancPluginExportedResource* exported) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->LogExportedResource(*exported); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode LookupAttachment(OrthancPluginDatabaseContext* context, void* payload, int64_t id, int32_t contentType) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Attachment); try { backend->LookupAttachment(id, contentType); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode LookupGlobalProperty(OrthancPluginDatabaseContext* context, void* payload, int32_t property) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::string s; if (backend->LookupGlobalProperty(s, property)) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, s.c_str()); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode LookupIdentifier3(OrthancPluginDatabaseContext* context, void* payload, OrthancPluginResourceType resourceType, const OrthancPluginDicomTag* tag, OrthancPluginIdentifierConstraint constraint) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list target; backend->LookupIdentifier(target, resourceType, tag->group, tag->element, constraint, tag->value); for (std::list::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode LookupMetadata(OrthancPluginDatabaseContext* context, void* payload, int64_t id, int32_t metadata) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::string s; if (backend->LookupMetadata(s, id, metadata)) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, s.c_str()); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode LookupParent(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { int64_t parent; if (backend->LookupParent(parent, id)) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, parent); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode LookupResource(OrthancPluginDatabaseContext* context, void* payload, const char* publicId) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { int64_t id; OrthancPluginResourceType type; if (backend->LookupResource(id, type, publicId)) { OrthancPluginDatabaseAnswerResource(backend->GetOutput().context_, backend->GetOutput().database_, id, type); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode SelectPatientToRecycle(OrthancPluginDatabaseContext* context, void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { int64_t id; if (backend->SelectPatientToRecycle(id)) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, id); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode SelectPatientToRecycle2(OrthancPluginDatabaseContext* context, void* payload, int64_t patientIdToAvoid) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { int64_t id; if (backend->SelectPatientToRecycle(id, patientIdToAvoid)) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, id); } return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode SetGlobalProperty(void* payload, int32_t property, const char* value) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetGlobalProperty(property, value); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode SetMainDicomTag(void* payload, int64_t id, const OrthancPluginDicomTag* tag) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetMainDicomTag(id, tag->group, tag->element, tag->value); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode SetIdentifierTag(void* payload, int64_t id, const OrthancPluginDicomTag* tag) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetIdentifierTag(id, tag->group, tag->element, tag->value); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode SetMetadata(void* payload, int64_t id, int32_t metadata, const char* value) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetMetadata(id, metadata, value); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode SetProtectedPatient(void* payload, int64_t id, int32_t isProtected) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetProtectedPatient(id, (isProtected != 0)); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode StartTransaction(void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->StartTransaction(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode RollbackTransaction(void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->RollbackTransaction(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode CommitTransaction(void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->CommitTransaction(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode Open(void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->Open(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode Close(void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->Close(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode GetDatabaseVersion(uint32_t* version, void* payload) { IDatabaseBackend* backend = reinterpret_cast(payload); try { *version = backend->GetDatabaseVersion(); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode UpgradeDatabase(void* payload, uint32_t targetVersion, OrthancPluginStorageArea* storageArea) { IDatabaseBackend* backend = reinterpret_cast(payload); try { backend->UpgradeDatabase(targetVersion, storageArea); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } static OrthancPluginErrorCode ClearMainDicomTags(void* payload, int64_t internalId) { IDatabaseBackend* backend = reinterpret_cast(payload); try { backend->ClearMainDicomTags(internalId); return OrthancPluginErrorCode_Success; } catch (std::runtime_error& e) { LogError(backend, e); return OrthancPluginErrorCode_DatabasePlugin; } catch (DatabaseException& e) { return e.GetErrorCode(); } } public: /** * Register a custom database back-end written in C++. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param backend Your custom database engine. **/ static void Register(OrthancPluginContext* context, IDatabaseBackend& backend) { OrthancPluginDatabaseBackend params; memset(¶ms, 0, sizeof(params)); OrthancPluginDatabaseExtensions extensions; memset(&extensions, 0, sizeof(extensions)); params.addAttachment = AddAttachment; params.attachChild = AttachChild; params.clearChanges = ClearChanges; params.clearExportedResources = ClearExportedResources; params.createResource = CreateResource; params.deleteAttachment = DeleteAttachment; params.deleteMetadata = DeleteMetadata; params.deleteResource = DeleteResource; params.getAllPublicIds = GetAllPublicIds; params.getChanges = GetChanges; params.getChildrenInternalId = GetChildrenInternalId; params.getChildrenPublicId = GetChildrenPublicId; params.getExportedResources = GetExportedResources; params.getLastChange = GetLastChange; params.getLastExportedResource = GetLastExportedResource; params.getMainDicomTags = GetMainDicomTags; params.getPublicId = GetPublicId; params.getResourceCount = GetResourceCount; params.getResourceType = GetResourceType; params.getTotalCompressedSize = GetTotalCompressedSize; params.getTotalUncompressedSize = GetTotalUncompressedSize; params.isExistingResource = IsExistingResource; params.isProtectedPatient = IsProtectedPatient; params.listAvailableMetadata = ListAvailableMetadata; params.listAvailableAttachments = ListAvailableAttachments; params.logChange = LogChange; params.logExportedResource = LogExportedResource; params.lookupAttachment = LookupAttachment; params.lookupGlobalProperty = LookupGlobalProperty; params.lookupIdentifier = NULL; // Unused starting with Orthanc 0.9.5 (db v6) params.lookupIdentifier2 = NULL; // Unused starting with Orthanc 0.9.5 (db v6) params.lookupMetadata = LookupMetadata; params.lookupParent = LookupParent; params.lookupResource = LookupResource; params.selectPatientToRecycle = SelectPatientToRecycle; params.selectPatientToRecycle2 = SelectPatientToRecycle2; params.setGlobalProperty = SetGlobalProperty; params.setMainDicomTag = SetMainDicomTag; params.setIdentifierTag = SetIdentifierTag; params.setMetadata = SetMetadata; params.setProtectedPatient = SetProtectedPatient; params.startTransaction = StartTransaction; params.rollbackTransaction = RollbackTransaction; params.commitTransaction = CommitTransaction; params.open = Open; params.close = Close; extensions.getAllPublicIdsWithLimit = GetAllPublicIdsWithLimit; extensions.getDatabaseVersion = GetDatabaseVersion; extensions.upgradeDatabase = UpgradeDatabase; extensions.clearMainDicomTags = ClearMainDicomTags; extensions.getAllInternalIds = GetAllInternalIds; // New in Orthanc 0.9.5 (db v6) extensions.lookupIdentifier3 = LookupIdentifier3; // New in Orthanc 0.9.5 (db v6) OrthancPluginDatabaseContext* database = OrthancPluginRegisterDatabaseBackendV2(context, ¶ms, &extensions, &backend); if (!context) { throw std::runtime_error("Unable to register the database backend"); } backend.RegisterOutput(new DatabaseBackendOutput(context, database)); } }; } OrthancPostgreSQL-2.0/README0000644000000000000000000000225312627602430013707 0ustar 00000000000000PostgreSQL plugins for Orthanc ============================== General Information ------------------- This repository contains the source code of 2 plugins for Orthanc, the lightweight, RESTful DICOM server. These 2 plugins enable Orthanc to store its files and its index as PostgreSQL databases. Licensing --------- The PostgreSQL plugins for Orthanc are licensed under the AGPL license. We also kindly ask scientific works and clinical studies that make use of Orthanc to cite Orthanc in their associated publications. Similarly, we ask open-source and closed-source products that make use of Orthanc to warn us about this use. You can cite our work using the following BibTeX entry: @inproceedings{Jodogne:ISBI2013, author = {Jodogne, S. and Bernard, C. and Devillers, M. and Lenaerts, E. and Coucke, P.}, title = {Orthanc -- {A} Lightweight, {REST}ful {DICOM} Server for Healthcare and Medical Research}, booktitle={Biomedical Imaging ({ISBI}), {IEEE} 10th International Symposium on}, year={2013}, pages={190-193}, ISSN={1945-7928}, month=apr, url={http://ieeexplore.ieee.org/xpl/articleDetails.jsp?tp=&arnumber=6556444}, address={San Francisco, {CA}, {USA}} } OrthancPostgreSQL-2.0/Resources/CMake/FindPostgreSQL.cmake0000644000000000000000000001671312627602430021575 0ustar 00000000000000# - Find the PostgreSQL installation. # In Windows, we make the assumption that, if the PostgreSQL files are installed, the default directory # will be C:\Program Files\PostgreSQL. # # This module defines # PostgreSQL_LIBRARIES - the PostgreSQL libraries needed for linking # PostgreSQL_INCLUDE_DIRS - the directories of the PostgreSQL headers # PostgreSQL_VERSION_STRING - the version of PostgreSQL found (since CMake 2.8.8) #============================================================================= # Copyright 2004-2009 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) # ---------------------------------------------------------------------------- # History: # This module is derived from the module originally found in the VTK source tree. # # ---------------------------------------------------------------------------- # Note: # PostgreSQL_ADDITIONAL_VERSIONS is a variable that can be used to set the # version mumber of the implementation of PostgreSQL. # In Windows the default installation of PostgreSQL uses that as part of the path. # E.g C:\Program Files\PostgreSQL\8.4. # Currently, the following version numbers are known to this module: # "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0" # # To use this variable just do something like this: # set(PostgreSQL_ADDITIONAL_VERSIONS "9.2" "8.4.4") # before calling find_package(PostgreSQL) in your CMakeLists.txt file. # This will mean that the versions you set here will be found first in the order # specified before the default ones are searched. # # ---------------------------------------------------------------------------- # You may need to manually set: # PostgreSQL_INCLUDE_DIR - the path to where the PostgreSQL include files are. # PostgreSQL_LIBRARY_DIR - The path to where the PostgreSQL library files are. # If FindPostgreSQL.cmake cannot find the include files or the library files. # # ---------------------------------------------------------------------------- # The following variables are set if PostgreSQL is found: # PostgreSQL_FOUND - Set to true when PostgreSQL is found. # PostgreSQL_INCLUDE_DIRS - Include directories for PostgreSQL # PostgreSQL_LIBRARY_DIRS - Link directories for PostgreSQL libraries # PostgreSQL_LIBRARIES - The PostgreSQL libraries. # # ---------------------------------------------------------------------------- # If you have installed PostgreSQL in a non-standard location. # (Please note that in the following comments, it is assumed that # points to the root directory of the include directory of PostgreSQL.) # Then you have three options. # 1) After CMake runs, set PostgreSQL_INCLUDE_DIR to /include and # PostgreSQL_LIBRARY_DIR to wherever the library pq (or libpq in windows) is # 2) Use CMAKE_INCLUDE_PATH to set a path to /PostgreSQL<-version>. This will allow find_path() # to locate PostgreSQL_INCLUDE_DIR by utilizing the PATH_SUFFIXES option. e.g. In your CMakeLists.txt file # set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "/include") # 3) Set an environment variable called ${PostgreSQL_ROOT} that points to the root of where you have # installed PostgreSQL, e.g. . # # ---------------------------------------------------------------------------- set(PostgreSQL_INCLUDE_PATH_DESCRIPTION "top-level directory containing the PostgreSQL include directories. E.g /usr/local/include/PostgreSQL/8.4 or C:/Program Files/PostgreSQL/8.4/include") set(PostgreSQL_INCLUDE_DIR_MESSAGE "Set the PostgreSQL_INCLUDE_DIR cmake cache entry to the ${PostgreSQL_INCLUDE_PATH_DESCRIPTION}") set(PostgreSQL_LIBRARY_PATH_DESCRIPTION "top-level directory containing the PostgreSQL libraries.") set(PostgreSQL_LIBRARY_DIR_MESSAGE "Set the PostgreSQL_LIBRARY_DIR cmake cache entry to the ${PostgreSQL_LIBRARY_PATH_DESCRIPTION}") set(PostgreSQL_ROOT_DIR_MESSAGE "Set the PostgreSQL_ROOT system variable to where PostgreSQL is found on the machine E.g C:/Program Files/PostgreSQL/8.4") set(PostgreSQL_KNOWN_VERSIONS ${PostgreSQL_ADDITIONAL_VERSIONS} "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0") # Define additional search paths for root directories. if ( WIN32 ) foreach (suffix ${PostgreSQL_KNOWN_VERSIONS} ) set(PostgreSQL_ADDITIONAL_SEARCH_PATHS ${PostgreSQL_ADDITIONAL_SEARCH_PATHS} "C:/Program Files/PostgreSQL/${suffix}" ) endforeach() else() foreach (suffix ${PostgreSQL_KNOWN_VERSIONS} ) set(PostgreSQL_ADDITIONAL_SEARCH_PATHS ${PostgreSQL_ADDITIONAL_SEARCH_PATHS} "/usr/include/postgresql/${suffix}" "/usr/local/include/postgresql/${suffix}") endforeach() endif() set( PostgreSQL_ROOT_DIRECTORIES ENV PostgreSQL_ROOT ${PostgreSQL_ROOT} ${PostgreSQL_ADDITIONAL_SEARCH_PATHS} ) # # Look for an installation. # find_path(PostgreSQL_INCLUDE_DIR NAMES libpq-fe.h PATHS # Look in other places. ${PostgreSQL_ROOT_DIRECTORIES} PATH_SUFFIXES pgsql postgresql include # Help the user find it if we cannot. DOC "The ${PostgreSQL_INCLUDE_DIR_MESSAGE}" ) find_path(PostgreSQL_TYPE_INCLUDE_DIR NAMES catalog/pg_type.h PATHS # Look in other places. ${PostgreSQL_ROOT_DIRECTORIES} PATH_SUFFIXES postgresql pgsql/server postgresql/server include/server server # Help the user find it if we cannot. DOC "The ${PostgreSQL_INCLUDE_DIR_MESSAGE}" ) # The PostgreSQL library. set (PostgreSQL_LIBRARY_TO_FIND pq) # Setting some more prefixes for the library set (PostgreSQL_LIB_PREFIX "") if ( WIN32 ) set (PostgreSQL_LIB_PREFIX ${PostgreSQL_LIB_PREFIX} "lib") set ( PostgreSQL_LIBRARY_TO_FIND ${PostgreSQL_LIB_PREFIX}${PostgreSQL_LIBRARY_TO_FIND}) endif() find_library( PostgreSQL_LIBRARY NAMES ${PostgreSQL_LIBRARY_TO_FIND} PATHS ${PostgreSQL_ROOT_DIRECTORIES} PATH_SUFFIXES lib ) get_filename_component(PostgreSQL_LIBRARY_DIR ${PostgreSQL_LIBRARY} PATH) if (PostgreSQL_INCLUDE_DIR AND EXISTS "${PostgreSQL_INCLUDE_DIR}/pg_config.h") file(STRINGS "${PostgreSQL_INCLUDE_DIR}/pg_config.h" pgsql_version_str REGEX "^#define[\t ]+PG_VERSION[\t ]+\".*\"") string(REGEX REPLACE "^#define[\t ]+PG_VERSION[\t ]+\"([^\"]*)\".*" "\\1" PostgreSQL_VERSION_STRING "${pgsql_version_str}") unset(pgsql_version_str) endif() # Did we find anything? include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PostgreSQL REQUIRED_VARS PostgreSQL_LIBRARY PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR VERSION_VAR PostgreSQL_VERSION_STRING) set( PostgreSQL_FOUND ${POSTGRESQL_FOUND}) # Now try to get the include and library path. if(PostgreSQL_FOUND) set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR} ${PostgreSQL_TYPE_INCLUDE_DIR} ) set(PostgreSQL_LIBRARY_DIRS ${PostgreSQL_LIBRARY_DIR} ) set(PostgreSQL_LIBRARIES ${PostgreSQL_LIBRARY_TO_FIND}) #message("Final PostgreSQL include dir: ${PostgreSQL_INCLUDE_DIRS}") #message("Final PostgreSQL library dir: ${PostgreSQL_LIBRARY_DIRS}") #message("Final PostgreSQL libraries: ${PostgreSQL_LIBRARIES}") endif() mark_as_advanced(PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR PostgreSQL_LIBRARY ) OrthancPostgreSQL-2.0/Resources/CMake/PostgreSQLConfiguration.cmake0000644000000000000000000001355512627602430023525 0ustar 00000000000000# Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # # 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 . ##################################################################### ## PostgreSQL ##################################################################### if (STATIC_BUILD OR NOT USE_SYSTEM_LIBPQ) SET(PQ_SOURCES_DIR ${CMAKE_BINARY_DIR}/postgresql-9.4.0) DownloadPackage( "349552802c809c4e8b09d8045a437787" "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/postgresql-9.4.0.tar.gz" "${PQ_SOURCES_DIR}") if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") set(PQ_CONFIG_H ${PQ_SOURCES_DIR}/src/include/pg_config.h.win32) if (${MSVC}) configure_file( ${PQ_SOURCES_DIR}/src/include/pg_config.h.win32 ${AUTOGENERATED_DIR}/pg_config.h COPY_ONLY) configure_file( ${PQ_SOURCES_DIR}/src/include/pg_config_ext.h.win32 ${AUTOGENERATED_DIR}/pg_config_ext.h COPY_ONLY) else() if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") set(PQ_CONFIG_H ${CMAKE_SOURCE_DIR}/Resources/Platforms/pg_config-windows64.h) else() set(PQ_CONFIG_H ${CMAKE_SOURCE_DIR}/Resources/Platforms/pg_config-windows32.h) endif() endif() add_definitions( -DEXEC_BACKEND ) configure_file( ${PQ_SOURCES_DIR}/src/include/port/win32.h ${AUTOGENERATED_DIR}/pg_config_os.h COPY_ONLY) else() set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread") if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") set(PQ_CONFIG_H ${CMAKE_SOURCE_DIR}/Resources/Platforms/pg_config-linux64.h) else() set(PQ_CONFIG_H ${CMAKE_SOURCE_DIR}/Resources/Platforms/pg_config-linux32.h) endif() add_definitions( -D_GNU_SOURCE -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS ) configure_file( ${PQ_SOURCES_DIR}/src/include/port/linux.h ${AUTOGENERATED_DIR}/pg_config_os.h COPY_ONLY) endif() configure_file( ${PQ_CONFIG_H} ${AUTOGENERATED_DIR}/pg_config.h COPY_ONLY ) configure_file( ${CMAKE_SOURCE_DIR}/Resources/Platforms/pg_config_ext.h ${AUTOGENERATED_DIR}/pg_config_ext.h COPY_ONLY ) file(WRITE ${AUTOGENERATED_DIR}/pg_config_paths.h "") add_definitions( -D_REENTRANT -DFRONTEND -DUNSAFE_STAT_OK -DSYSCONFDIR="" ) include_directories( ${PQ_SOURCES_DIR}/src/include ${PQ_SOURCES_DIR}/src/include/libpq ${PQ_SOURCES_DIR}/src/interfaces/libpq ) set(LIBPQ_SOURCES ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-auth.c ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-connect.c ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-exec.c ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-lobj.c ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-misc.c ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-print.c ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-protocol2.c ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-protocol3.c ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-secure.c ${PQ_SOURCES_DIR}/src/interfaces/libpq/libpq-events.c ${PQ_SOURCES_DIR}/src/interfaces/libpq/pqexpbuffer.c # libpgport C files we always use ${PQ_SOURCES_DIR}/src/port/chklocale.c ${PQ_SOURCES_DIR}/src/port/inet_net_ntop.c ${PQ_SOURCES_DIR}/src/port/noblock.c ${PQ_SOURCES_DIR}/src/port/pgstrcasecmp.c ${PQ_SOURCES_DIR}/src/port/pqsignal.c ${PQ_SOURCES_DIR}/src/port/thread.c ${PQ_SOURCES_DIR}/src/backend/libpq/ip.c ${PQ_SOURCES_DIR}/src/backend/libpq/md5.c ${PQ_SOURCES_DIR}/src/backend/utils/mb/encnames.c ${PQ_SOURCES_DIR}/src/backend/utils/mb/wchar.c ${PQ_SOURCES_DIR}/src/port/strlcpy.c ) if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") include_directories( ${PQ_SOURCES_DIR}/src/include/port/win32 ${PQ_SOURCES_DIR}/src/port ) LIST(APPEND LIBPQ_SOURCES # libpgport C files that are needed if identified by configure ${PQ_SOURCES_DIR}/src/interfaces/libpq/win32.c ${PQ_SOURCES_DIR}/src/port/crypt.c ${PQ_SOURCES_DIR}/src/port/inet_aton.c ${PQ_SOURCES_DIR}/src/port/open.c ${PQ_SOURCES_DIR}/src/port/pgsleep.c ${PQ_SOURCES_DIR}/src/port/snprintf.c ${PQ_SOURCES_DIR}/src/port/system.c ${PQ_SOURCES_DIR}/src/port/win32setlocale.c ${PQ_SOURCES_DIR}/src/port/getaddrinfo.c ) if (${CMAKE_COMPILER_IS_GNUCXX}) LIST(APPEND LIBPQ_SOURCES ${PQ_SOURCES_DIR}/src/port/win32error.c) endif() if (${MSVC}) LIST(APPEND LIBPQ_SOURCES ${PQ_SOURCES_DIR}/src/interfaces/libpq/pthread-win32.c) endif() endif() if (${CMAKE_COMPILER_IS_GNUCXX}) LIST(APPEND LIBPQ_SOURCES ${PQ_SOURCES_DIR}/src/port/getpeereid.c ) elseif (${MSVC}) include_directories( ${PQ_SOURCES_DIR}/src/include/port/win32_msvc ) LIST(APPEND LIBPQ_SOURCES ${PQ_SOURCES_DIR}/src/port/dirent.c ${PQ_SOURCES_DIR}/src/port/dirmod.c ) endif() source_group(ThirdParty\\PostgreSQL REGULAR_EXPRESSION ${PQ_SOURCES_DIR}/.*) else() include(${CMAKE_SOURCE_DIR}/Resources/CMake/FindPostgreSQL.cmake) include_directories( ${PostgreSQL_INCLUDE_DIR} ${PostgreSQL_TYPE_INCLUDE_DIR} ) link_libraries(${PostgreSQL_LIBRARY}) endif() OrthancPostgreSQL-2.0/Resources/OldLockingMechanism.txt0000644000000000000000000000216412627602430021415 0ustar 00000000000000LOCKING ======= This text file archives information about the locking mechanism in the initial release of the PostgreSQL plugins. THIS INFORMATION IS NOT VALID ANYMORE! >>>>>>>> The plugins implement a locking system to prevent other instances of Orthanc from using the same PostgreSQL database. If for some reason, Orthanc has not properly shutdown (for instance because of a power outage), you will have to manually unlock the database. This can be done by adding the `--unlock` flag at the command line: {{{ # ./Orthanc Configuration.json --unlock }}} If you dislike the locking mechanism and wish to disable it, set the "`Lock`" option to `false` in the configuration: { "Name" : "MyOrthanc", [...] "PostgreSQL" : { "Lock" : false, "EnableIndex" : true, "EnableStorage" : true, "Host" : "localhost", "Port" : 5432, "Database" : "orthanc", "Username" : "orthanc", "Password" : "orthanc" }, "Plugins" : [ "/home/user/OrthancPostgreSQL/Build/libOrthancPostgreSQLIndex.so", "/home/user/OrthancPostgreSQL/Build/libOrthancPostgreSQLStorage.so" ] } OrthancPostgreSQL-2.0/Resources/Platforms/pg_config-linux32.h0000644000000000000000000006443712627602430022372 0ustar 00000000000000/* src/include/pg_config.h. Generated from pg_config.h.in by configure. */ /* src/include/pg_config.h.in. Generated from configure.in by autoheader. */ /* Define to the type of arg 1 of 'accept' */ #define ACCEPT_TYPE_ARG1 int /* Define to the type of arg 2 of 'accept' */ #define ACCEPT_TYPE_ARG2 struct sockaddr * /* Define to the type of arg 3 of 'accept' */ #define ACCEPT_TYPE_ARG3 size_t /* Define to the return type of 'accept' */ #define ACCEPT_TYPE_RETURN int /* Define if building universal (internal helper macro) */ /* #undef AC_APPLE_UNIVERSAL_BUILD */ /* The normal alignment of `double', in bytes. */ #define ALIGNOF_DOUBLE 4 /* The normal alignment of `int', in bytes. */ #define ALIGNOF_INT 4 /* The normal alignment of `long', in bytes. */ #define ALIGNOF_LONG 4 /* The normal alignment of `long long int', in bytes. */ #define ALIGNOF_LONG_LONG_INT 4 /* The normal alignment of `short', in bytes. */ #define ALIGNOF_SHORT 2 /* Size of a disk block --- this also limits the size of a tuple. You can set it bigger if you need bigger tuples (although TOAST should reduce the need to have large tuples, since fields can be spread across multiple tuples). BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is currently 2^15 (32768). This is determined by the 15-bit widths of the lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h). Changing BLCKSZ requires an initdb. */ #define BLCKSZ 8192 /* Define to the default TCP port number on which the server listens and to which clients will try to connect. This can be overridden at run-time, but it's convenient if your clients have the right default compiled in. (--with-pgport=PORTNUM) */ #define DEF_PGPORT 5432 /* Define to the default TCP port number as a string constant. */ #define DEF_PGPORT_STR "5432" /* Define to build with GSSAPI support. (--with-gssapi) */ /* #undef ENABLE_GSS */ /* Define to 1 if you want National Language Support. (--enable-nls) */ /* #undef ENABLE_NLS */ /* Define to 1 to build client libraries as thread-safe code. (--enable-thread-safety) */ #define ENABLE_THREAD_SAFETY 1 /* Define to nothing if C supports flexible array members, and to 1 if it does not. That way, with a declaration like `struct s { int n; double d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99 compilers. When computing the size of such an object, don't use 'sizeof (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)' instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with MSVC and with C++ compilers. */ #define FLEXIBLE_ARRAY_MEMBER /**/ /* float4 values are passed by value if 'true', by reference if 'false' */ #define FLOAT4PASSBYVAL true /* float8, int8, and related values are passed by value if 'true', by reference if 'false' */ #define FLOAT8PASSBYVAL false /* Define to 1 if getpwuid_r() takes a 5th argument. */ #define GETPWUID_R_5ARG 1 /* Define to 1 if gettimeofday() takes only 1 argument. */ /* #undef GETTIMEOFDAY_1ARG */ #ifdef GETTIMEOFDAY_1ARG # define gettimeofday(a,b) gettimeofday(a) #endif /* Define to 1 if you have the `append_history' function. */ /* #undef HAVE_APPEND_HISTORY */ /* Define to 1 if you have the `cbrt' function. */ #define HAVE_CBRT 1 /* Define to 1 if you have the `class' function. */ /* #undef HAVE_CLASS */ /* Define to 1 if you have the header file. */ /* #undef HAVE_CRTDEFS_H */ /* Define to 1 if you have the `crypt' function. */ #define HAVE_CRYPT 1 /* Define to 1 if you have the header file. */ #define HAVE_CRYPT_H 1 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you don't. */ #define HAVE_DECL_FDATASYNC 1 /* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you don't. */ #define HAVE_DECL_F_FULLFSYNC 0 /* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you don't. */ #define HAVE_DECL_POSIX_FADVISE 1 /* Define to 1 if you have the declaration of `snprintf', and to 0 if you don't. */ #define HAVE_DECL_SNPRINTF 1 /* Define to 1 if you have the declaration of `strlcat', and to 0 if you don't. */ #define HAVE_DECL_STRLCAT 0 /* Define to 1 if you have the declaration of `strlcpy', and to 0 if you don't. */ #define HAVE_DECL_STRLCPY 0 /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 1 /* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you don't. */ #define HAVE_DECL_VSNPRINTF 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_DLD_H */ /* Define to 1 if you have the `dlopen' function. */ #define HAVE_DLOPEN 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_EDITLINE_HISTORY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_EDITLINE_READLINE_H */ /* Define to 1 if you have the `fdatasync' function. */ #define HAVE_FDATASYNC 1 /* Define to 1 if you have the `fls' function. */ /* #undef HAVE_FLS */ /* Define to 1 if you have the `fpclass' function. */ /* #undef HAVE_FPCLASS */ /* Define to 1 if you have the `fp_class' function. */ /* #undef HAVE_FP_CLASS */ /* Define to 1 if you have the `fp_class_d' function. */ /* #undef HAVE_FP_CLASS_D */ /* Define to 1 if you have the header file. */ /* #undef HAVE_FP_CLASS_H */ /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #define HAVE_FSEEKO 1 /* Define to 1 if your compiler understands __func__. */ #define HAVE_FUNCNAME__FUNC 1 /* Define to 1 if your compiler understands __FUNCTION__. */ /* #undef HAVE_FUNCNAME__FUNCTION */ /* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */ #define HAVE_GCC_INT_ATOMICS 1 /* Define to 1 if you have the `getaddrinfo' function. */ #define HAVE_GETADDRINFO 1 /* Define to 1 if you have the `gethostbyname_r' function. */ #define HAVE_GETHOSTBYNAME_R 1 /* Define to 1 if you have the `getifaddrs' function. */ #define HAVE_GETIFADDRS 1 /* Define to 1 if you have the `getopt' function. */ #define HAVE_GETOPT 1 /* Define to 1 if you have the header file. */ #define HAVE_GETOPT_H 1 /* Define to 1 if you have the `getopt_long' function. */ #define HAVE_GETOPT_LONG 1 /* Define to 1 if you have the `getpeereid' function. */ /* #undef HAVE_GETPEEREID */ /* Define to 1 if you have the `getpeerucred' function. */ /* #undef HAVE_GETPEERUCRED */ /* Define to 1 if you have the `getpwuid_r' function. */ #define HAVE_GETPWUID_R 1 /* Define to 1 if you have the `getrlimit' function. */ #define HAVE_GETRLIMIT 1 /* Define to 1 if you have the `getrusage' function. */ #define HAVE_GETRUSAGE 1 /* Define to 1 if you have the `gettimeofday' function. */ /* #undef HAVE_GETTIMEOFDAY */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_GSSAPI_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_HISTORY_H */ /* Define to 1 if you have the `history_truncate_file' function. */ /* #undef HAVE_HISTORY_TRUNCATE_FILE */ /* Define to 1 if you have the header file. */ /* #undef HAVE_IEEEFP_H */ /* Define to 1 if you have the header file. */ #define HAVE_IFADDRS_H 1 /* Define to 1 if you have the `inet_aton' function. */ #define HAVE_INET_ATON 1 /* Define to 1 if the system has the type `int64'. */ /* #undef HAVE_INT64 */ /* Define to 1 if the system has the type `int8'. */ /* #undef HAVE_INT8 */ /* Define to 1 if the system has the type `intptr_t'. */ #define HAVE_INTPTR_T 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the global variable 'int opterr'. */ #define HAVE_INT_OPTERR 1 /* Define to 1 if you have the global variable 'int optreset'. */ /* #undef HAVE_INT_OPTRESET */ /* Define to 1 if you have the global variable 'int timezone'. */ #define HAVE_INT_TIMEZONE 1 /* Define to 1 if you have support for IPv6. */ #define HAVE_IPV6 1 /* Define to 1 if you have isinf(). */ #define HAVE_ISINF 1 /* Define to 1 if you have the header file. */ #define HAVE_LANGINFO_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_LDAP_H */ /* Define to 1 if you have the `crypto' library (-lcrypto). */ /* #undef HAVE_LIBCRYPTO */ /* Define to 1 if you have the `ldap' library (-lldap). */ /* #undef HAVE_LIBLDAP */ /* Define to 1 if you have the `ldap_r' library (-lldap_r). */ /* #undef HAVE_LIBLDAP_R */ /* Define to 1 if you have the `m' library (-lm). */ #define HAVE_LIBM 1 /* Define to 1 if you have the `pam' library (-lpam). */ /* #undef HAVE_LIBPAM */ /* Define if you have a function readline library */ /* #undef HAVE_LIBREADLINE */ /* Define to 1 if you have the `selinux' library (-lselinux). */ /* #undef HAVE_LIBSELINUX */ /* Define to 1 if you have the `ssl' library (-lssl). */ /* #undef HAVE_LIBSSL */ /* Define to 1 if you have the `wldap32' library (-lwldap32). */ /* #undef HAVE_LIBWLDAP32 */ /* Define to 1 if you have the `xml2' library (-lxml2). */ /* #undef HAVE_LIBXML2 */ /* Define to 1 if you have the `xslt' library (-lxslt). */ /* #undef HAVE_LIBXSLT */ /* Define to 1 if you have the `z' library (-lz). */ /* #undef HAVE_LIBZ */ /* Define to 1 if constants of type 'long long int' should have the suffix LL. */ #define HAVE_LL_CONSTANTS 1 /* Define to 1 if the system has the type `locale_t'. */ #define HAVE_LOCALE_T 1 /* Define to 1 if `long int' works and is 64 bits. */ /* #undef HAVE_LONG_INT_64 */ /* Define to 1 if the system has the type `long long int'. */ #define HAVE_LONG_LONG_INT 1 /* Define to 1 if `long long int' works and is 64 bits. */ #define HAVE_LONG_LONG_INT_64 1 /* Define to 1 if you have the `mbstowcs_l' function. */ /* #undef HAVE_MBSTOWCS_L */ /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if the system has the type `MINIDUMP_TYPE'. */ /* #undef HAVE_MINIDUMP_TYPE */ /* Define to 1 if you have the `mkdtemp' function. */ #define HAVE_MKDTEMP 1 /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_NETINET_TCP_H 1 /* Define to 1 if you have the header file. */ #define HAVE_NET_IF_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_OSSP_UUID_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_PAM_PAM_APPL_H */ /* Define to 1 if you have the `poll' function. */ #define HAVE_POLL 1 /* Define to 1 if you have the header file. */ #define HAVE_POLL_H 1 /* Define to 1 if you have the `posix_fadvise' function. */ #define HAVE_POSIX_FADVISE 1 /* Define to 1 if you have the POSIX signal interface. */ #define HAVE_POSIX_SIGNALS 1 /* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */ /* #undef HAVE_PPC_LWARX_MUTEX_HINT */ /* Define to 1 if you have the `pstat' function. */ /* #undef HAVE_PSTAT */ /* Define to 1 if the PS_STRINGS thing exists. */ /* #undef HAVE_PS_STRINGS */ /* Define if you have POSIX threads libraries and header files. */ /* #undef HAVE_PTHREAD */ /* Define to 1 if you have the header file. */ #define HAVE_PWD_H 1 /* Define to 1 if you have the `random' function. */ #define HAVE_RANDOM 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_HISTORY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_READLINE_H */ /* Define to 1 if you have the `readlink' function. */ #define HAVE_READLINK 1 /* Define to 1 if you have the `rint' function. */ #define HAVE_RINT 1 /* Define to 1 if you have the global variable 'rl_completion_append_character'. */ /* #undef HAVE_RL_COMPLETION_APPEND_CHARACTER */ /* Define to 1 if you have the `rl_completion_matches' function. */ /* #undef HAVE_RL_COMPLETION_MATCHES */ /* Define to 1 if you have the `rl_filename_completion_function' function. */ /* #undef HAVE_RL_FILENAME_COMPLETION_FUNCTION */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SECURITY_PAM_APPL_H */ /* Define to 1 if you have the `setproctitle' function. */ /* #undef HAVE_SETPROCTITLE */ /* Define to 1 if you have the `setsid' function. */ #define HAVE_SETSID 1 /* Define to 1 if you have the `shm_open' function. */ #define HAVE_SHM_OPEN 1 /* Define to 1 if you have the `sigprocmask' function. */ #define HAVE_SIGPROCMASK 1 /* Define to 1 if you have sigsetjmp(). */ #define HAVE_SIGSETJMP 1 /* Define to 1 if the system has the type `sig_atomic_t'. */ #define HAVE_SIG_ATOMIC_T 1 /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 /* Define to 1 if you have spinlocks. */ #define HAVE_SPINLOCKS 1 /* Define to 1 if you have the `srandom' function. */ #define HAVE_SRANDOM 1 /* Define to 1 if you have the `SSL_get_current_compression' function. */ /* #undef HAVE_SSL_GET_CURRENT_COMPRESSION */ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `strerror_r' function. */ #define HAVE_STRERROR_R 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcat' function. */ /* #undef HAVE_STRLCAT */ /* Define to 1 if you have the `strlcpy' function. */ /* #undef HAVE_STRLCPY */ /* Define to 1 if you have the `strtoll' function. */ #define HAVE_STRTOLL 1 /* Define to 1 if you have the `strtoq' function. */ /* #undef HAVE_STRTOQ */ /* Define to 1 if you have the `strtoull' function. */ #define HAVE_STRTOULL 1 /* Define to 1 if you have the `strtouq' function. */ /* #undef HAVE_STRTOUQ */ /* Define to 1 if the system has the type `struct addrinfo'. */ #define HAVE_STRUCT_ADDRINFO 1 /* Define to 1 if the system has the type `struct cmsgcred'. */ /* #undef HAVE_STRUCT_CMSGCRED */ /* Define to 1 if the system has the type `struct option'. */ #define HAVE_STRUCT_OPTION 1 /* Define to 1 if `sa_len' is a member of `struct sockaddr'. */ /* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */ /* Define to 1 if the system has the type `struct sockaddr_storage'. */ #define HAVE_STRUCT_SOCKADDR_STORAGE 1 /* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ #define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 /* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */ /* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ /* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */ /* Define to 1 if `tm_zone' is a member of `struct tm'. */ #define HAVE_STRUCT_TM_TM_ZONE 1 /* Define to 1 if you have the `symlink' function. */ #define HAVE_SYMLINK 1 /* Define to 1 if you have the `sync_file_range' function. */ #define HAVE_SYNC_FILE_RANGE 1 /* Define to 1 if you have the syslog interface. */ #define HAVE_SYSLOG 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_IOCTL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_IPC_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_POLL_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_PSTAT_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SELECT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SEM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SHM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SOCKET_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SOCKIO_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_TAS_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_UCRED_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_UN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_TERMIOS_H 1 /* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use `HAVE_STRUCT_TM_TM_ZONE' instead. */ #define HAVE_TM_ZONE 1 /* Define to 1 if you have the `towlower' function. */ #define HAVE_TOWLOWER 1 /* Define to 1 if you have the external array `tzname'. */ #define HAVE_TZNAME 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_UCRED_H */ /* Define to 1 if the system has the type `uint64'. */ /* #undef HAVE_UINT64 */ /* Define to 1 if the system has the type `uint8'. */ /* #undef HAVE_UINT8 */ /* Define to 1 if the system has the type `uintptr_t'. */ #define HAVE_UINTPTR_T 1 /* Define to 1 if the system has the type `union semun'. */ /* #undef HAVE_UNION_SEMUN */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have unix sockets. */ #define HAVE_UNIX_SOCKETS 1 /* Define to 1 if you have the `unsetenv' function. */ #define HAVE_UNSETENV 1 /* Define to 1 if the system has the type `unsigned long long int'. */ #define HAVE_UNSIGNED_LONG_LONG_INT 1 /* Define to 1 if you have the `utime' function. */ #define HAVE_UTIME 1 /* Define to 1 if you have the `utimes' function. */ #define HAVE_UTIMES 1 /* Define to 1 if you have the header file. */ #define HAVE_UTIME_H 1 /* Define to 1 if you have BSD UUID support. */ /* #undef HAVE_UUID_BSD */ /* Define to 1 if you have E2FS UUID support. */ /* #undef HAVE_UUID_E2FS */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UUID_H */ /* Define to 1 if you have OSSP UUID support. */ /* #undef HAVE_UUID_OSSP */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UUID_UUID_H */ /* Define to 1 if you have the `vsnprintf' function. */ #define HAVE_VSNPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcstombs' function. */ #define HAVE_WCSTOMBS 1 /* Define to 1 if you have the `wcstombs_l' function. */ /* #undef HAVE_WCSTOMBS_L */ /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_WINLDAP_H */ /* Define to 1 if your compiler understands __builtin_constant_p. */ #define HAVE__BUILTIN_CONSTANT_P 1 /* Define to 1 if your compiler understands __builtin_types_compatible_p. */ #define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1 /* Define to 1 if your compiler understands __builtin_unreachable. */ #define HAVE__BUILTIN_UNREACHABLE 1 /* Define to 1 if your compiler understands _Static_assert. */ #define HAVE__STATIC_ASSERT 1 /* Define to 1 if your compiler understands __VA_ARGS__ in macros. */ #define HAVE__VA_ARGS 1 /* Define to the appropriate snprintf format for 64-bit ints. */ #define INT64_FORMAT "%lld" /* Define to 1 if `locale_t' requires . */ /* #undef LOCALE_T_IN_XLOCALE */ /* Define as the maximum alignment requirement of any C data type. */ #define MAXIMUM_ALIGNOF 4 /* Define bytes to use libc memset(). */ #define MEMSET_LOOP_LIMIT 1024 /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "pgsql-bugs@postgresql.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "PostgreSQL" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "PostgreSQL 9.4.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "postgresql" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "9.4.0" /* Define to the name of a signed 64-bit integer type. */ #define PG_INT64_TYPE long long int /* Define to the name of the default PostgreSQL service principal in Kerberos (GSSAPI). (--with-krb-srvnam=NAME) */ #define PG_KRB_SRVNAM "postgres" /* PostgreSQL major version as a string */ #define PG_MAJORVERSION "9.4" /* Define to 1 if "static inline" works without unwanted warnings from compilations where static inline functions are defined but not called. */ #define PG_USE_INLINE 1 /* PostgreSQL version as a string */ #define PG_VERSION "9.4.0" /* PostgreSQL version as a number */ #define PG_VERSION_NUM 90400 /* A string containing the version number, platform, and C compiler */ #define PG_VERSION_STR "PostgreSQL 9.4.0 on i686-pc-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2, 32-bit" /* Define to 1 to allow profiling output to be saved separately for each process. */ /* #undef PROFILE_PID_DIR */ /* Define to the necessary symbol if this constant uses a non-standard name on your system. */ /* #undef PTHREAD_CREATE_JOINABLE */ /* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus, the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be less than your OS' limit on file size. This is often 2 GB or 4GB in a 32-bit operating system, unless you have large file support enabled. By default, we make the limit 1 GB to avoid any possible integer-overflow problems within the OS. A limit smaller than necessary only means we divide a large relation into more chunks than necessary, so it seems best to err in the direction of a small limit. A power-of-2 value is recommended to save a few cycles in md.c, but is not absolutely required. Changing RELSEG_SIZE requires an initdb. */ #define RELSEG_SIZE 131072 /* The size of `long', as computed by sizeof. */ #define SIZEOF_LONG 4 /* The size of `off_t', as computed by sizeof. */ #define SIZEOF_OFF_T 8 /* The size of `size_t', as computed by sizeof. */ #define SIZEOF_SIZE_T 4 /* The size of `void *', as computed by sizeof. */ #define SIZEOF_VOID_P 4 /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define to 1 if strerror_r() returns a int. */ /* #undef STRERROR_R_INT */ /* Define to 1 if your declares `struct tm'. */ /* #undef TM_IN_SYS_TIME */ /* Define to the appropriate snprintf format for unsigned 64-bit ints. */ #define UINT64_FORMAT "%llu" /* Define to 1 to build with assertion checks. (--enable-cassert) */ /* #undef USE_ASSERT_CHECKING */ /* Define to 1 to build with Bonjour support. (--with-bonjour) */ /* #undef USE_BONJOUR */ /* Define to 1 if you want float4 values to be passed by value. (--enable-float4-byval) */ #define USE_FLOAT4_BYVAL 1 /* Define to 1 if you want float8, int8, etc values to be passed by value. (--enable-float8-byval) */ /* #undef USE_FLOAT8_BYVAL */ /* Define to 1 if you want 64-bit integer timestamp and interval support. (--enable-integer-datetimes) */ #define USE_INTEGER_DATETIMES 1 /* Define to 1 to build with LDAP support. (--with-ldap) */ /* #undef USE_LDAP */ /* Define to 1 to build with XML support. (--with-libxml) */ /* #undef USE_LIBXML */ /* Define to 1 to use XSLT support when building contrib/xml2. (--with-libxslt) */ /* #undef USE_LIBXSLT */ /* Define to select named POSIX semaphores. */ /* #undef USE_NAMED_POSIX_SEMAPHORES */ /* Define to 1 to build with PAM support. (--with-pam) */ /* #undef USE_PAM */ /* Use replacement snprintf() functions. */ /* #undef USE_REPL_SNPRINTF */ /* Define to build with (Open)SSL support. (--with-openssl) */ /* #undef USE_SSL */ /* Define to select SysV-style semaphores. */ #define USE_SYSV_SEMAPHORES 1 /* Define to select SysV-style shared memory. */ #define USE_SYSV_SHARED_MEMORY 1 /* Define to select unnamed POSIX semaphores. */ /* #undef USE_UNNAMED_POSIX_SEMAPHORES */ /* Define to select Win32-style semaphores. */ /* #undef USE_WIN32_SEMAPHORES */ /* Define to select Win32-style shared memory. */ /* #undef USE_WIN32_SHARED_MEMORY */ /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN /* # undef WORDS_BIGENDIAN */ # endif #endif /* Size of a WAL file block. This need have no particular relation to BLCKSZ. XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O, XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb. */ #define XLOG_BLCKSZ 8192 /* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2 and larger than XLOG_BLCKSZ (preferably, a great deal larger than XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */ #define XLOG_SEG_SIZE (16 * 1024 * 1024) /* Number of bits in a file offset, on hosts where this is settable. */ #define _FILE_OFFSET_BITS 64 /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ /* #undef _LARGEFILE_SOURCE */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to the type of a signed integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ /* #undef intptr_t */ /* Define to empty if the C compiler does not understand signed types. */ /* #undef signed */ /* Define to the type of an unsigned integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ /* #undef uintptr_t */ OrthancPostgreSQL-2.0/Resources/Platforms/pg_config-linux64.h0000644000000000000000000006443712627602430022377 0ustar 00000000000000/* src/include/pg_config.h. Generated from pg_config.h.in by configure. */ /* src/include/pg_config.h.in. Generated from configure.in by autoheader. */ /* Define to the type of arg 1 of 'accept' */ #define ACCEPT_TYPE_ARG1 int /* Define to the type of arg 2 of 'accept' */ #define ACCEPT_TYPE_ARG2 struct sockaddr * /* Define to the type of arg 3 of 'accept' */ #define ACCEPT_TYPE_ARG3 socklen_t /* Define to the return type of 'accept' */ #define ACCEPT_TYPE_RETURN int /* Define if building universal (internal helper macro) */ /* #undef AC_APPLE_UNIVERSAL_BUILD */ /* The normal alignment of `double', in bytes. */ #define ALIGNOF_DOUBLE 8 /* The normal alignment of `int', in bytes. */ #define ALIGNOF_INT 4 /* The normal alignment of `long', in bytes. */ #define ALIGNOF_LONG 8 /* The normal alignment of `long long int', in bytes. */ /* #undef ALIGNOF_LONG_LONG_INT */ /* The normal alignment of `short', in bytes. */ #define ALIGNOF_SHORT 2 /* Size of a disk block --- this also limits the size of a tuple. You can set it bigger if you need bigger tuples (although TOAST should reduce the need to have large tuples, since fields can be spread across multiple tuples). BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is currently 2^15 (32768). This is determined by the 15-bit widths of the lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h). Changing BLCKSZ requires an initdb. */ #define BLCKSZ 8192 /* Define to the default TCP port number on which the server listens and to which clients will try to connect. This can be overridden at run-time, but it's convenient if your clients have the right default compiled in. (--with-pgport=PORTNUM) */ #define DEF_PGPORT 5432 /* Define to the default TCP port number as a string constant. */ #define DEF_PGPORT_STR "5432" /* Define to build with GSSAPI support. (--with-gssapi) */ /* #undef ENABLE_GSS */ /* Define to 1 if you want National Language Support. (--enable-nls) */ /* #undef ENABLE_NLS */ /* Define to 1 to build client libraries as thread-safe code. (--enable-thread-safety) */ #define ENABLE_THREAD_SAFETY 1 /* Define to nothing if C supports flexible array members, and to 1 if it does not. That way, with a declaration like `struct s { int n; double d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99 compilers. When computing the size of such an object, don't use 'sizeof (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)' instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with MSVC and with C++ compilers. */ #define FLEXIBLE_ARRAY_MEMBER /**/ /* float4 values are passed by value if 'true', by reference if 'false' */ #define FLOAT4PASSBYVAL true /* float8, int8, and related values are passed by value if 'true', by reference if 'false' */ #define FLOAT8PASSBYVAL true /* Define to 1 if getpwuid_r() takes a 5th argument. */ #define GETPWUID_R_5ARG 1 /* Define to 1 if gettimeofday() takes only 1 argument. */ /* #undef GETTIMEOFDAY_1ARG */ #ifdef GETTIMEOFDAY_1ARG # define gettimeofday(a,b) gettimeofday(a) #endif /* Define to 1 if you have the `append_history' function. */ /* #undef HAVE_APPEND_HISTORY */ /* Define to 1 if you have the `cbrt' function. */ #define HAVE_CBRT 1 /* Define to 1 if you have the `class' function. */ /* #undef HAVE_CLASS */ /* Define to 1 if you have the header file. */ /* #undef HAVE_CRTDEFS_H */ /* Define to 1 if you have the `crypt' function. */ #define HAVE_CRYPT 1 /* Define to 1 if you have the header file. */ #define HAVE_CRYPT_H 1 /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you don't. */ #define HAVE_DECL_FDATASYNC 1 /* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you don't. */ #define HAVE_DECL_F_FULLFSYNC 0 /* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you don't. */ #define HAVE_DECL_POSIX_FADVISE 1 /* Define to 1 if you have the declaration of `snprintf', and to 0 if you don't. */ #define HAVE_DECL_SNPRINTF 1 /* Define to 1 if you have the declaration of `strlcat', and to 0 if you don't. */ #define HAVE_DECL_STRLCAT 0 /* Define to 1 if you have the declaration of `strlcpy', and to 0 if you don't. */ #define HAVE_DECL_STRLCPY 0 /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 1 /* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you don't. */ #define HAVE_DECL_VSNPRINTF 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_DLD_H */ /* Define to 1 if you have the `dlopen' function. */ #define HAVE_DLOPEN 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_EDITLINE_HISTORY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_EDITLINE_READLINE_H */ /* Define to 1 if you have the `fdatasync' function. */ #define HAVE_FDATASYNC 1 /* Define to 1 if you have the `fls' function. */ /* #undef HAVE_FLS */ /* Define to 1 if you have the `fpclass' function. */ /* #undef HAVE_FPCLASS */ /* Define to 1 if you have the `fp_class' function. */ /* #undef HAVE_FP_CLASS */ /* Define to 1 if you have the `fp_class_d' function. */ /* #undef HAVE_FP_CLASS_D */ /* Define to 1 if you have the header file. */ /* #undef HAVE_FP_CLASS_H */ /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #define HAVE_FSEEKO 1 /* Define to 1 if your compiler understands __func__. */ #define HAVE_FUNCNAME__FUNC 1 /* Define to 1 if your compiler understands __FUNCTION__. */ /* #undef HAVE_FUNCNAME__FUNCTION */ /* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */ #define HAVE_GCC_INT_ATOMICS 1 /* Define to 1 if you have the `getaddrinfo' function. */ #define HAVE_GETADDRINFO 1 /* Define to 1 if you have the `gethostbyname_r' function. */ #define HAVE_GETHOSTBYNAME_R 1 /* Define to 1 if you have the `getifaddrs' function. */ #define HAVE_GETIFADDRS 1 /* Define to 1 if you have the `getopt' function. */ #define HAVE_GETOPT 1 /* Define to 1 if you have the header file. */ #define HAVE_GETOPT_H 1 /* Define to 1 if you have the `getopt_long' function. */ #define HAVE_GETOPT_LONG 1 /* Define to 1 if you have the `getpeereid' function. */ /* #undef HAVE_GETPEEREID */ /* Define to 1 if you have the `getpeerucred' function. */ /* #undef HAVE_GETPEERUCRED */ /* Define to 1 if you have the `getpwuid_r' function. */ #define HAVE_GETPWUID_R 1 /* Define to 1 if you have the `getrlimit' function. */ #define HAVE_GETRLIMIT 1 /* Define to 1 if you have the `getrusage' function. */ #define HAVE_GETRUSAGE 1 /* Define to 1 if you have the `gettimeofday' function. */ /* #undef HAVE_GETTIMEOFDAY */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_GSSAPI_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_HISTORY_H */ /* Define to 1 if you have the `history_truncate_file' function. */ /* #undef HAVE_HISTORY_TRUNCATE_FILE */ /* Define to 1 if you have the header file. */ /* #undef HAVE_IEEEFP_H */ /* Define to 1 if you have the header file. */ #define HAVE_IFADDRS_H 1 /* Define to 1 if you have the `inet_aton' function. */ #define HAVE_INET_ATON 1 /* Define to 1 if the system has the type `int64'. */ /* #undef HAVE_INT64 */ /* Define to 1 if the system has the type `int8'. */ /* #undef HAVE_INT8 */ /* Define to 1 if the system has the type `intptr_t'. */ #define HAVE_INTPTR_T 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the global variable 'int opterr'. */ #define HAVE_INT_OPTERR 1 /* Define to 1 if you have the global variable 'int optreset'. */ /* #undef HAVE_INT_OPTRESET */ /* Define to 1 if you have the global variable 'int timezone'. */ #define HAVE_INT_TIMEZONE 1 /* Define to 1 if you have support for IPv6. */ #define HAVE_IPV6 1 /* Define to 1 if you have isinf(). */ #define HAVE_ISINF 1 /* Define to 1 if you have the header file. */ #define HAVE_LANGINFO_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_LDAP_H */ /* Define to 1 if you have the `crypto' library (-lcrypto). */ /* #undef HAVE_LIBCRYPTO */ /* Define to 1 if you have the `ldap' library (-lldap). */ /* #undef HAVE_LIBLDAP */ /* Define to 1 if you have the `ldap_r' library (-lldap_r). */ /* #undef HAVE_LIBLDAP_R */ /* Define to 1 if you have the `m' library (-lm). */ #define HAVE_LIBM 1 /* Define to 1 if you have the `pam' library (-lpam). */ /* #undef HAVE_LIBPAM */ /* Define if you have a function readline library */ /* #undef HAVE_LIBREADLINE */ /* Define to 1 if you have the `selinux' library (-lselinux). */ /* #undef HAVE_LIBSELINUX */ /* Define to 1 if you have the `ssl' library (-lssl). */ /* #undef HAVE_LIBSSL */ /* Define to 1 if you have the `wldap32' library (-lwldap32). */ /* #undef HAVE_LIBWLDAP32 */ /* Define to 1 if you have the `xml2' library (-lxml2). */ /* #undef HAVE_LIBXML2 */ /* Define to 1 if you have the `xslt' library (-lxslt). */ /* #undef HAVE_LIBXSLT */ /* Define to 1 if you have the `z' library (-lz). */ /* #undef HAVE_LIBZ */ /* Define to 1 if constants of type 'long long int' should have the suffix LL. */ /* #undef HAVE_LL_CONSTANTS */ /* Define to 1 if the system has the type `locale_t'. */ #define HAVE_LOCALE_T 1 /* Define to 1 if `long int' works and is 64 bits. */ #define HAVE_LONG_INT_64 1 /* Define to 1 if the system has the type `long long int'. */ #define HAVE_LONG_LONG_INT 1 /* Define to 1 if `long long int' works and is 64 bits. */ /* #undef HAVE_LONG_LONG_INT_64 */ /* Define to 1 if you have the `mbstowcs_l' function. */ /* #undef HAVE_MBSTOWCS_L */ /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if the system has the type `MINIDUMP_TYPE'. */ /* #undef HAVE_MINIDUMP_TYPE */ /* Define to 1 if you have the `mkdtemp' function. */ #define HAVE_MKDTEMP 1 /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_NETINET_TCP_H 1 /* Define to 1 if you have the header file. */ #define HAVE_NET_IF_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_OSSP_UUID_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_PAM_PAM_APPL_H */ /* Define to 1 if you have the `poll' function. */ #define HAVE_POLL 1 /* Define to 1 if you have the header file. */ #define HAVE_POLL_H 1 /* Define to 1 if you have the `posix_fadvise' function. */ #define HAVE_POSIX_FADVISE 1 /* Define to 1 if you have the POSIX signal interface. */ #define HAVE_POSIX_SIGNALS 1 /* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */ /* #undef HAVE_PPC_LWARX_MUTEX_HINT */ /* Define to 1 if you have the `pstat' function. */ /* #undef HAVE_PSTAT */ /* Define to 1 if the PS_STRINGS thing exists. */ /* #undef HAVE_PS_STRINGS */ /* Define if you have POSIX threads libraries and header files. */ /* #undef HAVE_PTHREAD */ /* Define to 1 if you have the header file. */ #define HAVE_PWD_H 1 /* Define to 1 if you have the `random' function. */ #define HAVE_RANDOM 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_HISTORY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_READLINE_H */ /* Define to 1 if you have the `readlink' function. */ #define HAVE_READLINK 1 /* Define to 1 if you have the `rint' function. */ #define HAVE_RINT 1 /* Define to 1 if you have the global variable 'rl_completion_append_character'. */ /* #undef HAVE_RL_COMPLETION_APPEND_CHARACTER */ /* Define to 1 if you have the `rl_completion_matches' function. */ /* #undef HAVE_RL_COMPLETION_MATCHES */ /* Define to 1 if you have the `rl_filename_completion_function' function. */ /* #undef HAVE_RL_FILENAME_COMPLETION_FUNCTION */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SECURITY_PAM_APPL_H */ /* Define to 1 if you have the `setproctitle' function. */ /* #undef HAVE_SETPROCTITLE */ /* Define to 1 if you have the `setsid' function. */ #define HAVE_SETSID 1 /* Define to 1 if you have the `shm_open' function. */ #define HAVE_SHM_OPEN 1 /* Define to 1 if you have the `sigprocmask' function. */ #define HAVE_SIGPROCMASK 1 /* Define to 1 if you have sigsetjmp(). */ #define HAVE_SIGSETJMP 1 /* Define to 1 if the system has the type `sig_atomic_t'. */ #define HAVE_SIG_ATOMIC_T 1 /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 /* Define to 1 if you have spinlocks. */ #define HAVE_SPINLOCKS 1 /* Define to 1 if you have the `srandom' function. */ #define HAVE_SRANDOM 1 /* Define to 1 if you have the `SSL_get_current_compression' function. */ /* #undef HAVE_SSL_GET_CURRENT_COMPRESSION */ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `strerror_r' function. */ #define HAVE_STRERROR_R 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcat' function. */ /* #undef HAVE_STRLCAT */ /* Define to 1 if you have the `strlcpy' function. */ /* #undef HAVE_STRLCPY */ /* Define to 1 if you have the `strtoll' function. */ #define HAVE_STRTOLL 1 /* Define to 1 if you have the `strtoq' function. */ /* #undef HAVE_STRTOQ */ /* Define to 1 if you have the `strtoull' function. */ #define HAVE_STRTOULL 1 /* Define to 1 if you have the `strtouq' function. */ /* #undef HAVE_STRTOUQ */ /* Define to 1 if the system has the type `struct addrinfo'. */ #define HAVE_STRUCT_ADDRINFO 1 /* Define to 1 if the system has the type `struct cmsgcred'. */ /* #undef HAVE_STRUCT_CMSGCRED */ /* Define to 1 if the system has the type `struct option'. */ #define HAVE_STRUCT_OPTION 1 /* Define to 1 if `sa_len' is a member of `struct sockaddr'. */ /* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */ /* Define to 1 if the system has the type `struct sockaddr_storage'. */ #define HAVE_STRUCT_SOCKADDR_STORAGE 1 /* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ #define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 /* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */ /* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ /* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */ /* Define to 1 if `tm_zone' is a member of `struct tm'. */ #define HAVE_STRUCT_TM_TM_ZONE 1 /* Define to 1 if you have the `symlink' function. */ #define HAVE_SYMLINK 1 /* Define to 1 if you have the `sync_file_range' function. */ #define HAVE_SYNC_FILE_RANGE 1 /* Define to 1 if you have the syslog interface. */ #define HAVE_SYSLOG 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_IOCTL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_IPC_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_POLL_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_PSTAT_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SELECT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SEM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SHM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SOCKET_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SOCKIO_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_TAS_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_UCRED_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_UN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_TERMIOS_H 1 /* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use `HAVE_STRUCT_TM_TM_ZONE' instead. */ #define HAVE_TM_ZONE 1 /* Define to 1 if you have the `towlower' function. */ #define HAVE_TOWLOWER 1 /* Define to 1 if you have the external array `tzname'. */ #define HAVE_TZNAME 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_UCRED_H */ /* Define to 1 if the system has the type `uint64'. */ /* #undef HAVE_UINT64 */ /* Define to 1 if the system has the type `uint8'. */ /* #undef HAVE_UINT8 */ /* Define to 1 if the system has the type `uintptr_t'. */ #define HAVE_UINTPTR_T 1 /* Define to 1 if the system has the type `union semun'. */ /* #undef HAVE_UNION_SEMUN */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have unix sockets. */ #define HAVE_UNIX_SOCKETS 1 /* Define to 1 if you have the `unsetenv' function. */ #define HAVE_UNSETENV 1 /* Define to 1 if the system has the type `unsigned long long int'. */ #define HAVE_UNSIGNED_LONG_LONG_INT 1 /* Define to 1 if you have the `utime' function. */ #define HAVE_UTIME 1 /* Define to 1 if you have the `utimes' function. */ #define HAVE_UTIMES 1 /* Define to 1 if you have the header file. */ #define HAVE_UTIME_H 1 /* Define to 1 if you have BSD UUID support. */ /* #undef HAVE_UUID_BSD */ /* Define to 1 if you have E2FS UUID support. */ /* #undef HAVE_UUID_E2FS */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UUID_H */ /* Define to 1 if you have OSSP UUID support. */ /* #undef HAVE_UUID_OSSP */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UUID_UUID_H */ /* Define to 1 if you have the `vsnprintf' function. */ #define HAVE_VSNPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcstombs' function. */ #define HAVE_WCSTOMBS 1 /* Define to 1 if you have the `wcstombs_l' function. */ /* #undef HAVE_WCSTOMBS_L */ /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_WINLDAP_H */ /* Define to 1 if your compiler understands __builtin_constant_p. */ #define HAVE__BUILTIN_CONSTANT_P 1 /* Define to 1 if your compiler understands __builtin_types_compatible_p. */ #define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1 /* Define to 1 if your compiler understands __builtin_unreachable. */ #define HAVE__BUILTIN_UNREACHABLE 1 /* Define to 1 if your compiler understands _Static_assert. */ #define HAVE__STATIC_ASSERT 1 /* Define to 1 if your compiler understands __VA_ARGS__ in macros. */ #define HAVE__VA_ARGS 1 /* Define to the appropriate snprintf format for 64-bit ints. */ #define INT64_FORMAT "%ld" /* Define to 1 if `locale_t' requires . */ /* #undef LOCALE_T_IN_XLOCALE */ /* Define as the maximum alignment requirement of any C data type. */ #define MAXIMUM_ALIGNOF 8 /* Define bytes to use libc memset(). */ #define MEMSET_LOOP_LIMIT 1024 /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "pgsql-bugs@postgresql.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "PostgreSQL" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "PostgreSQL 9.4.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "postgresql" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "9.4.0" /* Define to the name of a signed 64-bit integer type. */ #define PG_INT64_TYPE long int /* Define to the name of the default PostgreSQL service principal in Kerberos (GSSAPI). (--with-krb-srvnam=NAME) */ #define PG_KRB_SRVNAM "postgres" /* PostgreSQL major version as a string */ #define PG_MAJORVERSION "9.4" /* Define to 1 if "static inline" works without unwanted warnings from compilations where static inline functions are defined but not called. */ #define PG_USE_INLINE 1 /* PostgreSQL version as a string */ #define PG_VERSION "9.4.0" /* PostgreSQL version as a number */ #define PG_VERSION_NUM 90400 /* A string containing the version number, platform, and C compiler */ #define PG_VERSION_STR "PostgreSQL 9.4.0 on i686-pc-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2, 64-bit" /* Define to 1 to allow profiling output to be saved separately for each process. */ /* #undef PROFILE_PID_DIR */ /* Define to the necessary symbol if this constant uses a non-standard name on your system. */ /* #undef PTHREAD_CREATE_JOINABLE */ /* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus, the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be less than your OS' limit on file size. This is often 2 GB or 4GB in a 32-bit operating system, unless you have large file support enabled. By default, we make the limit 1 GB to avoid any possible integer-overflow problems within the OS. A limit smaller than necessary only means we divide a large relation into more chunks than necessary, so it seems best to err in the direction of a small limit. A power-of-2 value is recommended to save a few cycles in md.c, but is not absolutely required. Changing RELSEG_SIZE requires an initdb. */ #define RELSEG_SIZE 131072 /* The size of `long', as computed by sizeof. */ #define SIZEOF_LONG 8 /* The size of `off_t', as computed by sizeof. */ #define SIZEOF_OFF_T 8 /* The size of `size_t', as computed by sizeof. */ #define SIZEOF_SIZE_T 8 /* The size of `void *', as computed by sizeof. */ #define SIZEOF_VOID_P 8 /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define to 1 if strerror_r() returns a int. */ /* #undef STRERROR_R_INT */ /* Define to 1 if your declares `struct tm'. */ /* #undef TM_IN_SYS_TIME */ /* Define to the appropriate snprintf format for unsigned 64-bit ints. */ #define UINT64_FORMAT "%lu" /* Define to 1 to build with assertion checks. (--enable-cassert) */ /* #undef USE_ASSERT_CHECKING */ /* Define to 1 to build with Bonjour support. (--with-bonjour) */ /* #undef USE_BONJOUR */ /* Define to 1 if you want float4 values to be passed by value. (--enable-float4-byval) */ #define USE_FLOAT4_BYVAL 1 /* Define to 1 if you want float8, int8, etc values to be passed by value. (--enable-float8-byval) */ #define USE_FLOAT8_BYVAL 1 /* Define to 1 if you want 64-bit integer timestamp and interval support. (--enable-integer-datetimes) */ #define USE_INTEGER_DATETIMES 1 /* Define to 1 to build with LDAP support. (--with-ldap) */ /* #undef USE_LDAP */ /* Define to 1 to build with XML support. (--with-libxml) */ /* #undef USE_LIBXML */ /* Define to 1 to use XSLT support when building contrib/xml2. (--with-libxslt) */ /* #undef USE_LIBXSLT */ /* Define to select named POSIX semaphores. */ /* #undef USE_NAMED_POSIX_SEMAPHORES */ /* Define to 1 to build with PAM support. (--with-pam) */ /* #undef USE_PAM */ /* Use replacement snprintf() functions. */ /* #undef USE_REPL_SNPRINTF */ /* Define to build with (Open)SSL support. (--with-openssl) */ /* #undef USE_SSL */ /* Define to select SysV-style semaphores. */ #define USE_SYSV_SEMAPHORES 1 /* Define to select SysV-style shared memory. */ #define USE_SYSV_SHARED_MEMORY 1 /* Define to select unnamed POSIX semaphores. */ /* #undef USE_UNNAMED_POSIX_SEMAPHORES */ /* Define to select Win32-style semaphores. */ /* #undef USE_WIN32_SEMAPHORES */ /* Define to select Win32-style shared memory. */ /* #undef USE_WIN32_SHARED_MEMORY */ /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN /* # undef WORDS_BIGENDIAN */ # endif #endif /* Size of a WAL file block. This need have no particular relation to BLCKSZ. XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O, XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb. */ #define XLOG_BLCKSZ 8192 /* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2 and larger than XLOG_BLCKSZ (preferably, a great deal larger than XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */ #define XLOG_SEG_SIZE (16 * 1024 * 1024) /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ /* #undef _LARGEFILE_SOURCE */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to the type of a signed integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ /* #undef intptr_t */ /* Define to empty if the C compiler does not understand signed types. */ /* #undef signed */ /* Define to the type of an unsigned integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ /* #undef uintptr_t */ OrthancPostgreSQL-2.0/Resources/Platforms/pg_config-windows32.h0000644000000000000000000006466212627602430022725 0ustar 00000000000000/* src/include/pg_config.h. Generated from pg_config.h.in by configure. */ /* src/include/pg_config.h.in. Generated from configure.in by autoheader. */ /* Define to the type of arg 1 of 'accept' */ #define ACCEPT_TYPE_ARG1 unsigned int /* Define to the type of arg 2 of 'accept' */ #define ACCEPT_TYPE_ARG2 struct sockaddr * /* Define to the type of arg 3 of 'accept' */ #define ACCEPT_TYPE_ARG3 int /* Define to the return type of 'accept' */ #define ACCEPT_TYPE_RETURN unsigned int PASCAL /* Define if building universal (internal helper macro) */ /* #undef AC_APPLE_UNIVERSAL_BUILD */ /* The normal alignment of `double', in bytes. */ #define ALIGNOF_DOUBLE 8 /* The normal alignment of `int', in bytes. */ #define ALIGNOF_INT 4 /* The normal alignment of `long', in bytes. */ #define ALIGNOF_LONG 4 /* The normal alignment of `long long int', in bytes. */ #define ALIGNOF_LONG_LONG_INT 8 /* The normal alignment of `short', in bytes. */ #define ALIGNOF_SHORT 2 /* Size of a disk block --- this also limits the size of a tuple. You can set it bigger if you need bigger tuples (although TOAST should reduce the need to have large tuples, since fields can be spread across multiple tuples). BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is currently 2^15 (32768). This is determined by the 15-bit widths of the lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h). Changing BLCKSZ requires an initdb. */ #define BLCKSZ 8192 /* Define to the default TCP port number on which the server listens and to which clients will try to connect. This can be overridden at run-time, but it's convenient if your clients have the right default compiled in. (--with-pgport=PORTNUM) */ #define DEF_PGPORT 5432 /* Define to the default TCP port number as a string constant. */ #define DEF_PGPORT_STR "5432" /* Define to build with GSSAPI support. (--with-gssapi) */ /* #undef ENABLE_GSS */ /* Define to 1 if you want National Language Support. (--enable-nls) */ /* #undef ENABLE_NLS */ /* Define to 1 to build client libraries as thread-safe code. (--enable-thread-safety) */ #define ENABLE_THREAD_SAFETY 1 /* Define to nothing if C supports flexible array members, and to 1 if it does not. That way, with a declaration like `struct s { int n; double d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99 compilers. When computing the size of such an object, don't use 'sizeof (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)' instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with MSVC and with C++ compilers. */ #define FLEXIBLE_ARRAY_MEMBER /**/ /* float4 values are passed by value if 'true', by reference if 'false' */ #define FLOAT4PASSBYVAL true /* float8, int8, and related values are passed by value if 'true', by reference if 'false' */ #define FLOAT8PASSBYVAL false /* Define to 1 if getpwuid_r() takes a 5th argument. */ /* #undef GETPWUID_R_5ARG */ /* Define to 1 if gettimeofday() takes only 1 argument. */ /* #undef GETTIMEOFDAY_1ARG */ #ifdef GETTIMEOFDAY_1ARG # define gettimeofday(a,b) gettimeofday(a) #endif /* Define to 1 if you have the `append_history' function. */ /* #undef HAVE_APPEND_HISTORY */ /* Define to 1 if you have the `cbrt' function. */ #define HAVE_CBRT 1 /* Define to 1 if you have the `class' function. */ /* #undef HAVE_CLASS */ /* Define to 1 if you have the header file. */ #define HAVE_CRTDEFS_H 1 /* Define to 1 if you have the `crypt' function. */ /* #undef HAVE_CRYPT */ /* Define to 1 if you have the header file. */ /* #undef HAVE_CRYPT_H */ /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you don't. */ #define HAVE_DECL_FDATASYNC 0 /* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you don't. */ #define HAVE_DECL_F_FULLFSYNC 0 /* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you don't. */ #define HAVE_DECL_POSIX_FADVISE 0 /* Define to 1 if you have the declaration of `snprintf', and to 0 if you don't. */ #define HAVE_DECL_SNPRINTF 1 /* Define to 1 if you have the declaration of `strlcat', and to 0 if you don't. */ #define HAVE_DECL_STRLCAT 0 /* Define to 1 if you have the declaration of `strlcpy', and to 0 if you don't. */ #define HAVE_DECL_STRLCPY 0 /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 0 /* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you don't. */ #define HAVE_DECL_VSNPRINTF 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_DLD_H */ /* Define to 1 if you have the `dlopen' function. */ /* #undef HAVE_DLOPEN */ /* Define to 1 if you have the header file. */ /* #undef HAVE_EDITLINE_HISTORY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_EDITLINE_READLINE_H */ /* Define to 1 if you have the `fdatasync' function. */ /* #undef HAVE_FDATASYNC */ /* Define to 1 if you have the `fls' function. */ /* #undef HAVE_FLS */ /* Define to 1 if you have the `fpclass' function. */ /* #undef HAVE_FPCLASS */ /* Define to 1 if you have the `fp_class' function. */ /* #undef HAVE_FP_CLASS */ /* Define to 1 if you have the `fp_class_d' function. */ /* #undef HAVE_FP_CLASS_D */ /* Define to 1 if you have the header file. */ /* #undef HAVE_FP_CLASS_H */ /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #define HAVE_FSEEKO 1 /* Define to 1 if your compiler understands __func__. */ #define HAVE_FUNCNAME__FUNC 1 /* Define to 1 if your compiler understands __FUNCTION__. */ /* #undef HAVE_FUNCNAME__FUNCTION */ /* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */ #define HAVE_GCC_INT_ATOMICS 1 /* Define to 1 if you have the `getaddrinfo' function. */ /* #undef HAVE_GETADDRINFO */ /* Define to 1 if you have the `gethostbyname_r' function. */ /* #undef HAVE_GETHOSTBYNAME_R */ /* Define to 1 if you have the `getifaddrs' function. */ /* #undef HAVE_GETIFADDRS */ /* Define to 1 if you have the `getopt' function. */ #define HAVE_GETOPT 1 /* Define to 1 if you have the header file. */ #define HAVE_GETOPT_H 1 /* Define to 1 if you have the `getopt_long' function. */ #define HAVE_GETOPT_LONG 1 /* Define to 1 if you have the `getpeereid' function. */ #define HAVE_GETPEEREID 1 /* Define to 1 if you have the `getpeerucred' function. */ /* #undef HAVE_GETPEERUCRED */ /* Define to 1 if you have the `getpwuid_r' function. */ /* #undef HAVE_GETPWUID_R */ /* Define to 1 if you have the `getrlimit' function. */ /* #undef HAVE_GETRLIMIT */ /* Define to 1 if you have the `getrusage' function. */ /* #undef HAVE_GETRUSAGE */ /* Define to 1 if you have the `gettimeofday' function. */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_GSSAPI_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_HISTORY_H */ /* Define to 1 if you have the `history_truncate_file' function. */ /* #undef HAVE_HISTORY_TRUNCATE_FILE */ /* Define to 1 if you have the header file. */ /* #undef HAVE_IEEEFP_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_IFADDRS_H */ /* Define to 1 if you have the `inet_aton' function. */ /* #undef HAVE_INET_ATON */ /* Define to 1 if the system has the type `int64'. */ /* #undef HAVE_INT64 */ /* Define to 1 if the system has the type `int8'. */ /* #undef HAVE_INT8 */ /* Define to 1 if the system has the type `intptr_t'. */ #define HAVE_INTPTR_T 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the global variable 'int opterr'. */ #define HAVE_INT_OPTERR 1 /* Define to 1 if you have the global variable 'int optreset'. */ #define HAVE_INT_OPTRESET 1 /* Define to 1 if you have the global variable 'int timezone'. */ #define HAVE_INT_TIMEZONE 1 /* Define to 1 if you have support for IPv6. */ #define HAVE_IPV6 1 /* Define to 1 if you have isinf(). */ #define HAVE_ISINF 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_LANGINFO_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LDAP_H */ /* Define to 1 if you have the `crypto' library (-lcrypto). */ /* #undef HAVE_LIBCRYPTO */ /* Define to 1 if you have the `ldap' library (-lldap). */ /* #undef HAVE_LIBLDAP */ /* Define to 1 if you have the `ldap_r' library (-lldap_r). */ /* #undef HAVE_LIBLDAP_R */ /* Define to 1 if you have the `m' library (-lm). */ #define HAVE_LIBM 1 /* Define to 1 if you have the `pam' library (-lpam). */ /* #undef HAVE_LIBPAM */ /* Define if you have a function readline library */ /* #undef HAVE_LIBREADLINE */ /* Define to 1 if you have the `selinux' library (-lselinux). */ /* #undef HAVE_LIBSELINUX */ /* Define to 1 if you have the `ssl' library (-lssl). */ /* #undef HAVE_LIBSSL */ /* Define to 1 if you have the `wldap32' library (-lwldap32). */ /* #undef HAVE_LIBWLDAP32 */ /* Define to 1 if you have the `xml2' library (-lxml2). */ /* #undef HAVE_LIBXML2 */ /* Define to 1 if you have the `xslt' library (-lxslt). */ /* #undef HAVE_LIBXSLT */ /* Define to 1 if you have the `z' library (-lz). */ /* #undef HAVE_LIBZ */ /* Define to 1 if constants of type 'long long int' should have the suffix LL. */ #define HAVE_LL_CONSTANTS 1 /* Define to 1 if the system has the type `locale_t'. */ /* #undef HAVE_LOCALE_T */ /* Define to 1 if `long int' works and is 64 bits. */ /* #undef HAVE_LONG_INT_64 */ /* Define to 1 if the system has the type `long long int'. */ #define HAVE_LONG_LONG_INT 1 /* Define to 1 if `long long int' works and is 64 bits. */ #define HAVE_LONG_LONG_INT_64 1 /* Define to 1 if you have the `mbstowcs_l' function. */ /* #undef HAVE_MBSTOWCS_L */ /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if the system has the type `MINIDUMP_TYPE'. */ #define HAVE_MINIDUMP_TYPE 1 /* Define to 1 if you have the `mkdtemp' function. */ /* #undef HAVE_MKDTEMP */ /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_NETINET_TCP_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NET_IF_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_OSSP_UUID_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_PAM_PAM_APPL_H */ /* Define to 1 if you have the `poll' function. */ /* #undef HAVE_POLL */ /* Define to 1 if you have the header file. */ /* #undef HAVE_POLL_H */ /* Define to 1 if you have the `posix_fadvise' function. */ /* #undef HAVE_POSIX_FADVISE */ /* Define to 1 if you have the POSIX signal interface. */ /* #undef HAVE_POSIX_SIGNALS */ /* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */ /* #undef HAVE_PPC_LWARX_MUTEX_HINT */ /* Define to 1 if you have the `pstat' function. */ /* #undef HAVE_PSTAT */ /* Define to 1 if the PS_STRINGS thing exists. */ /* #undef HAVE_PS_STRINGS */ /* Define if you have POSIX threads libraries and header files. */ /* #undef HAVE_PTHREAD */ /* Define to 1 if you have the header file. */ #define HAVE_PWD_H 1 /* Define to 1 if you have the `random' function. */ /* #undef HAVE_RANDOM */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_HISTORY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_READLINE_H */ /* Define to 1 if you have the `readlink' function. */ /* #undef HAVE_READLINK */ /* Define to 1 if you have the `rint' function. */ #define HAVE_RINT 1 /* Define to 1 if you have the global variable 'rl_completion_append_character'. */ /* #undef HAVE_RL_COMPLETION_APPEND_CHARACTER */ /* Define to 1 if you have the `rl_completion_matches' function. */ /* #undef HAVE_RL_COMPLETION_MATCHES */ /* Define to 1 if you have the `rl_filename_completion_function' function. */ /* #undef HAVE_RL_FILENAME_COMPLETION_FUNCTION */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SECURITY_PAM_APPL_H */ /* Define to 1 if you have the `setproctitle' function. */ /* #undef HAVE_SETPROCTITLE */ /* Define to 1 if you have the `setsid' function. */ /* #undef HAVE_SETSID */ /* Define to 1 if you have the `shm_open' function. */ /* #undef HAVE_SHM_OPEN */ /* Define to 1 if you have the `sigprocmask' function. */ /* #undef HAVE_SIGPROCMASK */ /* Define to 1 if you have sigsetjmp(). */ /* #undef HAVE_SIGSETJMP */ /* Define to 1 if the system has the type `sig_atomic_t'. */ #define HAVE_SIG_ATOMIC_T 1 /* Define to 1 if you have the `snprintf' function. */ /* #undef HAVE_SNPRINTF */ /* Define to 1 if you have spinlocks. */ #define HAVE_SPINLOCKS 1 /* Define to 1 if you have the `srandom' function. */ /* #undef HAVE_SRANDOM */ /* Define to 1 if you have the `SSL_get_current_compression' function. */ /* #undef HAVE_SSL_GET_CURRENT_COMPRESSION */ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `strerror_r' function. */ /* #undef HAVE_STRERROR_R */ /* Define to 1 if you have the header file. */ /* #undef HAVE_STRINGS_H */ /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcat' function. */ /* #undef HAVE_STRLCAT */ /* Define to 1 if you have the `strlcpy' function. */ /* #undef HAVE_STRLCPY */ /* Define to 1 if you have the `strtoll' function. */ #define HAVE_STRTOLL 1 /* Define to 1 if you have the `strtoq' function. */ /* #undef HAVE_STRTOQ */ /* Define to 1 if you have the `strtoull' function. */ #define HAVE_STRTOULL 1 /* Define to 1 if you have the `strtouq' function. */ /* #undef HAVE_STRTOUQ */ /* Define to 1 if the system has the type `struct addrinfo'. */ #define HAVE_STRUCT_ADDRINFO 1 /* Define to 1 if the system has the type `struct cmsgcred'. */ /* #undef HAVE_STRUCT_CMSGCRED */ /* Define to 1 if the system has the type `struct option'. */ #define HAVE_STRUCT_OPTION 1 /* Define to 1 if `sa_len' is a member of `struct sockaddr'. */ /* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */ /* Define to 1 if the system has the type `struct sockaddr_storage'. */ #define HAVE_STRUCT_SOCKADDR_STORAGE 1 /* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ #define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 /* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */ /* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ /* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */ /* Define to 1 if `tm_zone' is a member of `struct tm'. */ /* #undef HAVE_STRUCT_TM_TM_ZONE */ /* Define to 1 if you have the `symlink' function. */ #define HAVE_SYMLINK 1 /* Define to 1 if you have the `sync_file_range' function. */ /* #undef HAVE_SYNC_FILE_RANGE */ /* Define to 1 if you have the syslog interface. */ /* #undef HAVE_SYSLOG */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_IOCTL_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_IPC_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_POLL_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_PSTAT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_RESOURCE_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SELECT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SEM_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SHM_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_SOCKET_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SOCKIO_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_TAS_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_UCRED_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_UN_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_TERMIOS_H */ /* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use `HAVE_STRUCT_TM_TM_ZONE' instead. */ /* #undef HAVE_TM_ZONE */ /* Define to 1 if you have the `towlower' function. */ #define HAVE_TOWLOWER 1 /* Define to 1 if you have the external array `tzname'. */ /* #undef HAVE_TZNAME */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UCRED_H */ /* Define to 1 if the system has the type `uint64'. */ /* #undef HAVE_UINT64 */ /* Define to 1 if the system has the type `uint8'. */ /* #undef HAVE_UINT8 */ /* Define to 1 if the system has the type `uintptr_t'. */ #define HAVE_UINTPTR_T 1 /* Define to 1 if the system has the type `union semun'. */ /* #undef HAVE_UNION_SEMUN */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have unix sockets. */ /* #undef HAVE_UNIX_SOCKETS */ /* Define to 1 if you have the `unsetenv' function. */ #define HAVE_UNSETENV 1 /* Define to 1 if the system has the type `unsigned long long int'. */ #define HAVE_UNSIGNED_LONG_LONG_INT 1 /* Define to 1 if you have the `utime' function. */ #define HAVE_UTIME 1 /* Define to 1 if you have the `utimes' function. */ /* #undef HAVE_UTIMES */ /* Define to 1 if you have the header file. */ #define HAVE_UTIME_H 1 /* Define to 1 if you have BSD UUID support. */ /* #undef HAVE_UUID_BSD */ /* Define to 1 if you have E2FS UUID support. */ /* #undef HAVE_UUID_E2FS */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UUID_H */ /* Define to 1 if you have OSSP UUID support. */ /* #undef HAVE_UUID_OSSP */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UUID_UUID_H */ /* Define to 1 if you have the `vsnprintf' function. */ /* #undef HAVE_VSNPRINTF */ /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcstombs' function. */ #define HAVE_WCSTOMBS 1 /* Define to 1 if you have the `wcstombs_l' function. */ /* #undef HAVE_WCSTOMBS_L */ /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_WINLDAP_H */ /* Define to 1 if your compiler understands __builtin_constant_p. */ #define HAVE__BUILTIN_CONSTANT_P 1 /* Define to 1 if your compiler understands __builtin_types_compatible_p. */ #define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1 /* Define to 1 if your compiler understands __builtin_unreachable. */ #define HAVE__BUILTIN_UNREACHABLE 1 /* Define to 1 if your compiler understands _Static_assert. */ #define HAVE__STATIC_ASSERT 1 /* Define to 1 if your compiler understands __VA_ARGS__ in macros. */ #define HAVE__VA_ARGS 1 /* Define to the appropriate snprintf format for 64-bit ints. */ #define INT64_FORMAT "%lld" /* Define to 1 if `locale_t' requires . */ /* #undef LOCALE_T_IN_XLOCALE */ /* Define as the maximum alignment requirement of any C data type. */ #define MAXIMUM_ALIGNOF 8 /* Define bytes to use libc memset(). */ #define MEMSET_LOOP_LIMIT 1024 /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "pgsql-bugs@postgresql.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "PostgreSQL" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "PostgreSQL 9.4.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "postgresql" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "9.4.0" /* Define to the name of a signed 64-bit integer type. */ #define PG_INT64_TYPE long long int /* Define to the name of the default PostgreSQL service principal in Kerberos (GSSAPI). (--with-krb-srvnam=NAME) */ #define PG_KRB_SRVNAM "postgres" /* PostgreSQL major version as a string */ #define PG_MAJORVERSION "9.4" /* Define to 1 if "static inline" works without unwanted warnings from compilations where static inline functions are defined but not called. */ #define PG_USE_INLINE 1 /* PostgreSQL version as a string */ #define PG_VERSION "9.4.0" /* PostgreSQL version as a number */ #define PG_VERSION_NUM 90400 /* A string containing the version number, platform, and C compiler */ #define PG_VERSION_STR "PostgreSQL 9.4.0 on i586-pc-mingw32msvc, compiled by i586-mingw32msvc-gcc (GCC) 4.6.3, 32-bit" /* Define to 1 to allow profiling output to be saved separately for each process. */ /* #undef PROFILE_PID_DIR */ /* Define to the necessary symbol if this constant uses a non-standard name on your system. */ /* #undef PTHREAD_CREATE_JOINABLE */ /* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus, the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be less than your OS' limit on file size. This is often 2 GB or 4GB in a 32-bit operating system, unless you have large file support enabled. By default, we make the limit 1 GB to avoid any possible integer-overflow problems within the OS. A limit smaller than necessary only means we divide a large relation into more chunks than necessary, so it seems best to err in the direction of a small limit. A power-of-2 value is recommended to save a few cycles in md.c, but is not absolutely required. Changing RELSEG_SIZE requires an initdb. */ #define RELSEG_SIZE 131072 /* The size of `long', as computed by sizeof. */ #define SIZEOF_LONG 4 /* The size of `off_t', as computed by sizeof. */ #define SIZEOF_OFF_T 4 /* The size of `size_t', as computed by sizeof. */ #define SIZEOF_SIZE_T 4 /* The size of `void *', as computed by sizeof. */ #define SIZEOF_VOID_P 4 /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define to 1 if strerror_r() returns a int. */ /* #undef STRERROR_R_INT */ /* Define to 1 if your declares `struct tm'. */ /* #undef TM_IN_SYS_TIME */ /* Define to the appropriate snprintf format for unsigned 64-bit ints. */ #define UINT64_FORMAT "%llu" /* Define to 1 to build with assertion checks. (--enable-cassert) */ /* #undef USE_ASSERT_CHECKING */ /* Define to 1 to build with Bonjour support. (--with-bonjour) */ /* #undef USE_BONJOUR */ /* Define to 1 if you want float4 values to be passed by value. (--enable-float4-byval) */ #define USE_FLOAT4_BYVAL 1 /* Define to 1 if you want float8, int8, etc values to be passed by value. (--enable-float8-byval) */ /* #undef USE_FLOAT8_BYVAL */ /* Define to 1 if you want 64-bit integer timestamp and interval support. (--enable-integer-datetimes) */ #define USE_INTEGER_DATETIMES 1 /* Define to 1 to build with LDAP support. (--with-ldap) */ /* #undef USE_LDAP */ /* Define to 1 to build with XML support. (--with-libxml) */ /* #undef USE_LIBXML */ /* Define to 1 to use XSLT support when building contrib/xml2. (--with-libxslt) */ /* #undef USE_LIBXSLT */ /* Define to select named POSIX semaphores. */ /* #undef USE_NAMED_POSIX_SEMAPHORES */ /* Define to 1 to build with PAM support. (--with-pam) */ /* #undef USE_PAM */ /* Use replacement snprintf() functions. */ #define USE_REPL_SNPRINTF 1 /* Define to build with (Open)SSL support. (--with-openssl) */ /* #undef USE_SSL */ /* Define to select SysV-style semaphores. */ /* #undef USE_SYSV_SEMAPHORES */ /* Define to select SysV-style shared memory. */ /* #undef USE_SYSV_SHARED_MEMORY */ /* Define to select unnamed POSIX semaphores. */ /* #undef USE_UNNAMED_POSIX_SEMAPHORES */ /* Define to select Win32-style semaphores. */ #define USE_WIN32_SEMAPHORES 1 /* Define to select Win32-style shared memory. */ #define USE_WIN32_SHARED_MEMORY 1 /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN /* # undef WORDS_BIGENDIAN */ # endif #endif /* Size of a WAL file block. This need have no particular relation to BLCKSZ. XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O, XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb. */ #define XLOG_BLCKSZ 8192 /* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2 and larger than XLOG_BLCKSZ (preferably, a great deal larger than XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */ #define XLOG_SEG_SIZE (16 * 1024 * 1024) /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ /* #undef _LARGEFILE_SOURCE */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to the type of a signed integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ /* #undef intptr_t */ /* Define to empty if the C compiler does not understand signed types. */ /* #undef signed */ /* Define to the type of an unsigned integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ /* #undef uintptr_t */ OrthancPostgreSQL-2.0/Resources/Platforms/pg_config-windows64.h0000644000000000000000000006465712627602430022736 0ustar 00000000000000/* src/include/pg_config.h. Generated from pg_config.h.in by configure. */ /* src/include/pg_config.h.in. Generated from configure.in by autoheader. */ /* Define to the type of arg 1 of 'accept' */ #define ACCEPT_TYPE_ARG1 unsigned int /* Define to the type of arg 2 of 'accept' */ #define ACCEPT_TYPE_ARG2 struct sockaddr * /* Define to the type of arg 3 of 'accept' */ #define ACCEPT_TYPE_ARG3 int /* Define to the return type of 'accept' */ #define ACCEPT_TYPE_RETURN unsigned int PASCAL /* Define if building universal (internal helper macro) */ /* #undef AC_APPLE_UNIVERSAL_BUILD */ /* The normal alignment of `double', in bytes. */ #define ALIGNOF_DOUBLE 8 /* The normal alignment of `int', in bytes. */ #define ALIGNOF_INT 4 /* The normal alignment of `long', in bytes. */ #define ALIGNOF_LONG 4 /* The normal alignment of `long long int', in bytes. */ #define ALIGNOF_LONG_LONG_INT 8 /* The normal alignment of `short', in bytes. */ #define ALIGNOF_SHORT 2 /* Size of a disk block --- this also limits the size of a tuple. You can set it bigger if you need bigger tuples (although TOAST should reduce the need to have large tuples, since fields can be spread across multiple tuples). BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is currently 2^15 (32768). This is determined by the 15-bit widths of the lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h). Changing BLCKSZ requires an initdb. */ #define BLCKSZ 8192 /* Define to the default TCP port number on which the server listens and to which clients will try to connect. This can be overridden at run-time, but it's convenient if your clients have the right default compiled in. (--with-pgport=PORTNUM) */ #define DEF_PGPORT 5432 /* Define to the default TCP port number as a string constant. */ #define DEF_PGPORT_STR "5432" /* Define to build with GSSAPI support. (--with-gssapi) */ /* #undef ENABLE_GSS */ /* Define to 1 if you want National Language Support. (--enable-nls) */ /* #undef ENABLE_NLS */ /* Define to 1 to build client libraries as thread-safe code. (--enable-thread-safety) */ #define ENABLE_THREAD_SAFETY 1 /* Define to nothing if C supports flexible array members, and to 1 if it does not. That way, with a declaration like `struct s { int n; double d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99 compilers. When computing the size of such an object, don't use 'sizeof (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)' instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with MSVC and with C++ compilers. */ #define FLEXIBLE_ARRAY_MEMBER /**/ /* float4 values are passed by value if 'true', by reference if 'false' */ #define FLOAT4PASSBYVAL true /* float8, int8, and related values are passed by value if 'true', by reference if 'false' */ #define FLOAT8PASSBYVAL false /* Define to 1 if getpwuid_r() takes a 5th argument. */ /* #undef GETPWUID_R_5ARG */ /* Define to 1 if gettimeofday() takes only 1 argument. */ /* #undef GETTIMEOFDAY_1ARG */ #ifdef GETTIMEOFDAY_1ARG # define gettimeofday(a,b) gettimeofday(a) #endif /* Define to 1 if you have the `append_history' function. */ /* #undef HAVE_APPEND_HISTORY */ /* Define to 1 if you have the `cbrt' function. */ #define HAVE_CBRT 1 /* Define to 1 if you have the `class' function. */ /* #undef HAVE_CLASS */ /* Define to 1 if you have the header file. */ #define HAVE_CRTDEFS_H 1 /* Define to 1 if you have the `crypt' function. */ /* #undef HAVE_CRYPT */ /* Define to 1 if you have the header file. */ /* #undef HAVE_CRYPT_H */ /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you don't. */ #define HAVE_DECL_FDATASYNC 0 /* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you don't. */ #define HAVE_DECL_F_FULLFSYNC 0 /* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you don't. */ #define HAVE_DECL_POSIX_FADVISE 0 /* Define to 1 if you have the declaration of `snprintf', and to 0 if you don't. */ #define HAVE_DECL_SNPRINTF 1 /* Define to 1 if you have the declaration of `strlcat', and to 0 if you don't. */ #define HAVE_DECL_STRLCAT 0 /* Define to 1 if you have the declaration of `strlcpy', and to 0 if you don't. */ #define HAVE_DECL_STRLCPY 0 /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 0 /* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you don't. */ #define HAVE_DECL_VSNPRINTF 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_DLD_H */ /* Define to 1 if you have the `dlopen' function. */ /* #undef HAVE_DLOPEN */ /* Define to 1 if you have the header file. */ /* #undef HAVE_EDITLINE_HISTORY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_EDITLINE_READLINE_H */ /* Define to 1 if you have the `fdatasync' function. */ /* #undef HAVE_FDATASYNC */ /* Define to 1 if you have the `fls' function. */ /* #undef HAVE_FLS */ /* Define to 1 if you have the `fpclass' function. */ /* #undef HAVE_FPCLASS */ /* Define to 1 if you have the `fp_class' function. */ /* #undef HAVE_FP_CLASS */ /* Define to 1 if you have the `fp_class_d' function. */ /* #undef HAVE_FP_CLASS_D */ /* Define to 1 if you have the header file. */ /* #undef HAVE_FP_CLASS_H */ /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #define HAVE_FSEEKO 1 /* Define to 1 if your compiler understands __func__. */ #define HAVE_FUNCNAME__FUNC 1 /* Define to 1 if your compiler understands __FUNCTION__. */ /* #undef HAVE_FUNCNAME__FUNCTION */ /* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */ #define HAVE_GCC_INT_ATOMICS 1 /* Define to 1 if you have the `getaddrinfo' function. */ /* #undef HAVE_GETADDRINFO */ /* Define to 1 if you have the `gethostbyname_r' function. */ /* #undef HAVE_GETHOSTBYNAME_R */ /* Define to 1 if you have the `getifaddrs' function. */ /* #undef HAVE_GETIFADDRS */ /* Define to 1 if you have the `getopt' function. */ #define HAVE_GETOPT 1 /* Define to 1 if you have the header file. */ #define HAVE_GETOPT_H 1 /* Define to 1 if you have the `getopt_long' function. */ #define HAVE_GETOPT_LONG 1 /* Define to 1 if you have the `getpeereid' function. */ #define HAVE_GETPEEREID 1 /* Define to 1 if you have the `getpeerucred' function. */ /* #undef HAVE_GETPEERUCRED */ /* Define to 1 if you have the `getpwuid_r' function. */ /* #undef HAVE_GETPWUID_R */ /* Define to 1 if you have the `getrlimit' function. */ /* #undef HAVE_GETRLIMIT */ /* Define to 1 if you have the `getrusage' function. */ /* #undef HAVE_GETRUSAGE */ /* Define to 1 if you have the `gettimeofday' function. */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_GSSAPI_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_HISTORY_H */ /* Define to 1 if you have the `history_truncate_file' function. */ /* #undef HAVE_HISTORY_TRUNCATE_FILE */ /* Define to 1 if you have the header file. */ /* #undef HAVE_IEEEFP_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_IFADDRS_H */ /* Define to 1 if you have the `inet_aton' function. */ /* #undef HAVE_INET_ATON */ /* Define to 1 if the system has the type `int64'. */ /* #undef HAVE_INT64 */ /* Define to 1 if the system has the type `int8'. */ /* #undef HAVE_INT8 */ /* Define to 1 if the system has the type `intptr_t'. */ #define HAVE_INTPTR_T 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the global variable 'int opterr'. */ #define HAVE_INT_OPTERR 1 /* Define to 1 if you have the global variable 'int optreset'. */ #define HAVE_INT_OPTRESET 1 /* Define to 1 if you have the global variable 'int timezone'. */ #define HAVE_INT_TIMEZONE 1 /* Define to 1 if you have support for IPv6. */ #define HAVE_IPV6 1 /* Define to 1 if you have isinf(). */ #define HAVE_ISINF 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_LANGINFO_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LDAP_H */ /* Define to 1 if you have the `crypto' library (-lcrypto). */ /* #undef HAVE_LIBCRYPTO */ /* Define to 1 if you have the `ldap' library (-lldap). */ /* #undef HAVE_LIBLDAP */ /* Define to 1 if you have the `ldap_r' library (-lldap_r). */ /* #undef HAVE_LIBLDAP_R */ /* Define to 1 if you have the `m' library (-lm). */ #define HAVE_LIBM 1 /* Define to 1 if you have the `pam' library (-lpam). */ /* #undef HAVE_LIBPAM */ /* Define if you have a function readline library */ /* #undef HAVE_LIBREADLINE */ /* Define to 1 if you have the `selinux' library (-lselinux). */ /* #undef HAVE_LIBSELINUX */ /* Define to 1 if you have the `ssl' library (-lssl). */ /* #undef HAVE_LIBSSL */ /* Define to 1 if you have the `wldap32' library (-lwldap32). */ /* #undef HAVE_LIBWLDAP32 */ /* Define to 1 if you have the `xml2' library (-lxml2). */ /* #undef HAVE_LIBXML2 */ /* Define to 1 if you have the `xslt' library (-lxslt). */ /* #undef HAVE_LIBXSLT */ /* Define to 1 if you have the `z' library (-lz). */ /* #undef HAVE_LIBZ */ /* Define to 1 if constants of type 'long long int' should have the suffix LL. */ #define HAVE_LL_CONSTANTS 1 /* Define to 1 if the system has the type `locale_t'. */ /* #undef HAVE_LOCALE_T */ /* Define to 1 if `long int' works and is 64 bits. */ /* #undef HAVE_LONG_INT_64 */ /* Define to 1 if the system has the type `long long int'. */ #define HAVE_LONG_LONG_INT 1 /* Define to 1 if `long long int' works and is 64 bits. */ #define HAVE_LONG_LONG_INT_64 1 /* Define to 1 if you have the `mbstowcs_l' function. */ /* #undef HAVE_MBSTOWCS_L */ /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if the system has the type `MINIDUMP_TYPE'. */ #define HAVE_MINIDUMP_TYPE 1 /* Define to 1 if you have the `mkdtemp' function. */ /* #undef HAVE_MKDTEMP */ /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_NETINET_TCP_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NET_IF_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_OSSP_UUID_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_PAM_PAM_APPL_H */ /* Define to 1 if you have the `poll' function. */ /* #undef HAVE_POLL */ /* Define to 1 if you have the header file. */ /* #undef HAVE_POLL_H */ /* Define to 1 if you have the `posix_fadvise' function. */ /* #undef HAVE_POSIX_FADVISE */ /* Define to 1 if you have the POSIX signal interface. */ /* #undef HAVE_POSIX_SIGNALS */ /* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */ /* #undef HAVE_PPC_LWARX_MUTEX_HINT */ /* Define to 1 if you have the `pstat' function. */ /* #undef HAVE_PSTAT */ /* Define to 1 if the PS_STRINGS thing exists. */ /* #undef HAVE_PS_STRINGS */ /* Define if you have POSIX threads libraries and header files. */ /* #undef HAVE_PTHREAD */ /* Define to 1 if you have the header file. */ #define HAVE_PWD_H 1 /* Define to 1 if you have the `random' function. */ /* #undef HAVE_RANDOM */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_HISTORY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_READLINE_H */ /* Define to 1 if you have the `readlink' function. */ /* #undef HAVE_READLINK */ /* Define to 1 if you have the `rint' function. */ #define HAVE_RINT 1 /* Define to 1 if you have the global variable 'rl_completion_append_character'. */ /* #undef HAVE_RL_COMPLETION_APPEND_CHARACTER */ /* Define to 1 if you have the `rl_completion_matches' function. */ /* #undef HAVE_RL_COMPLETION_MATCHES */ /* Define to 1 if you have the `rl_filename_completion_function' function. */ /* #undef HAVE_RL_FILENAME_COMPLETION_FUNCTION */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SECURITY_PAM_APPL_H */ /* Define to 1 if you have the `setproctitle' function. */ /* #undef HAVE_SETPROCTITLE */ /* Define to 1 if you have the `setsid' function. */ /* #undef HAVE_SETSID */ /* Define to 1 if you have the `shm_open' function. */ /* #undef HAVE_SHM_OPEN */ /* Define to 1 if you have the `sigprocmask' function. */ /* #undef HAVE_SIGPROCMASK */ /* Define to 1 if you have sigsetjmp(). */ /* #undef HAVE_SIGSETJMP */ /* Define to 1 if the system has the type `sig_atomic_t'. */ #define HAVE_SIG_ATOMIC_T 1 /* Define to 1 if you have the `snprintf' function. */ /* #undef HAVE_SNPRINTF */ /* Define to 1 if you have spinlocks. */ #define HAVE_SPINLOCKS 1 /* Define to 1 if you have the `srandom' function. */ /* #undef HAVE_SRANDOM */ /* Define to 1 if you have the `SSL_get_current_compression' function. */ /* #undef HAVE_SSL_GET_CURRENT_COMPRESSION */ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `strerror_r' function. */ /* #undef HAVE_STRERROR_R */ /* Define to 1 if you have the header file. */ /* #undef HAVE_STRINGS_H */ /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcat' function. */ /* #undef HAVE_STRLCAT */ /* Define to 1 if you have the `strlcpy' function. */ /* #undef HAVE_STRLCPY */ /* Define to 1 if you have the `strtoll' function. */ #define HAVE_STRTOLL 1 /* Define to 1 if you have the `strtoq' function. */ /* #undef HAVE_STRTOQ */ /* Define to 1 if you have the `strtoull' function. */ #define HAVE_STRTOULL 1 /* Define to 1 if you have the `strtouq' function. */ /* #undef HAVE_STRTOUQ */ /* Define to 1 if the system has the type `struct addrinfo'. */ #define HAVE_STRUCT_ADDRINFO 1 /* Define to 1 if the system has the type `struct cmsgcred'. */ /* #undef HAVE_STRUCT_CMSGCRED */ /* Define to 1 if the system has the type `struct option'. */ #define HAVE_STRUCT_OPTION 1 /* Define to 1 if `sa_len' is a member of `struct sockaddr'. */ /* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */ /* Define to 1 if the system has the type `struct sockaddr_storage'. */ #define HAVE_STRUCT_SOCKADDR_STORAGE 1 /* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ #define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 /* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */ /* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ /* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */ /* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */ /* Define to 1 if `tm_zone' is a member of `struct tm'. */ /* #undef HAVE_STRUCT_TM_TM_ZONE */ /* Define to 1 if you have the `symlink' function. */ #define HAVE_SYMLINK 1 /* Define to 1 if you have the `sync_file_range' function. */ /* #undef HAVE_SYNC_FILE_RANGE */ /* Define to 1 if you have the syslog interface. */ /* #undef HAVE_SYSLOG */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_IOCTL_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_IPC_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_POLL_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_PSTAT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_RESOURCE_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SELECT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SEM_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SHM_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_SOCKET_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SOCKIO_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_TAS_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_UCRED_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_UN_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_TERMIOS_H */ /* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use `HAVE_STRUCT_TM_TM_ZONE' instead. */ /* #undef HAVE_TM_ZONE */ /* Define to 1 if you have the `towlower' function. */ #define HAVE_TOWLOWER 1 /* Define to 1 if you have the external array `tzname'. */ /* #undef HAVE_TZNAME */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UCRED_H */ /* Define to 1 if the system has the type `uint64'. */ /* #undef HAVE_UINT64 */ /* Define to 1 if the system has the type `uint8'. */ /* #undef HAVE_UINT8 */ /* Define to 1 if the system has the type `uintptr_t'. */ #define HAVE_UINTPTR_T 1 /* Define to 1 if the system has the type `union semun'. */ /* #undef HAVE_UNION_SEMUN */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have unix sockets. */ /* #undef HAVE_UNIX_SOCKETS */ /* Define to 1 if you have the `unsetenv' function. */ #define HAVE_UNSETENV 1 /* Define to 1 if the system has the type `unsigned long long int'. */ #define HAVE_UNSIGNED_LONG_LONG_INT 1 /* Define to 1 if you have the `utime' function. */ #define HAVE_UTIME 1 /* Define to 1 if you have the `utimes' function. */ /* #undef HAVE_UTIMES */ /* Define to 1 if you have the header file. */ #define HAVE_UTIME_H 1 /* Define to 1 if you have BSD UUID support. */ /* #undef HAVE_UUID_BSD */ /* Define to 1 if you have E2FS UUID support. */ /* #undef HAVE_UUID_E2FS */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UUID_H */ /* Define to 1 if you have OSSP UUID support. */ /* #undef HAVE_UUID_OSSP */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UUID_UUID_H */ /* Define to 1 if you have the `vsnprintf' function. */ /* #undef HAVE_VSNPRINTF */ /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcstombs' function. */ #define HAVE_WCSTOMBS 1 /* Define to 1 if you have the `wcstombs_l' function. */ /* #undef HAVE_WCSTOMBS_L */ /* Define to 1 if you have the header file. */ #define HAVE_WCTYPE_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_WINLDAP_H */ /* Define to 1 if your compiler understands __builtin_constant_p. */ #define HAVE__BUILTIN_CONSTANT_P 1 /* Define to 1 if your compiler understands __builtin_types_compatible_p. */ #define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1 /* Define to 1 if your compiler understands __builtin_unreachable. */ #define HAVE__BUILTIN_UNREACHABLE 1 /* Define to 1 if your compiler understands _Static_assert. */ #define HAVE__STATIC_ASSERT 1 /* Define to 1 if your compiler understands __VA_ARGS__ in macros. */ #define HAVE__VA_ARGS 1 /* Define to the appropriate snprintf format for 64-bit ints. */ #define INT64_FORMAT "%lld" /* Define to 1 if `locale_t' requires . */ /* #undef LOCALE_T_IN_XLOCALE */ /* Define as the maximum alignment requirement of any C data type. */ #define MAXIMUM_ALIGNOF 8 /* Define bytes to use libc memset(). */ #define MEMSET_LOOP_LIMIT 1024 /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "pgsql-bugs@postgresql.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "PostgreSQL" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "PostgreSQL 9.4.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "postgresql" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "9.4.0" /* Define to the name of a signed 64-bit integer type. */ #define PG_INT64_TYPE long long int /* Define to the name of the default PostgreSQL service principal in Kerberos (GSSAPI). (--with-krb-srvnam=NAME) */ #define PG_KRB_SRVNAM "postgres" /* PostgreSQL major version as a string */ #define PG_MAJORVERSION "9.4" /* Define to 1 if "static inline" works without unwanted warnings from compilations where static inline functions are defined but not called. */ #define PG_USE_INLINE 1 /* PostgreSQL version as a string */ #define PG_VERSION "9.4.0" /* PostgreSQL version as a number */ #define PG_VERSION_NUM 90400 /* A string containing the version number, platform, and C compiler */ #define PG_VERSION_STR "PostgreSQL 9.4.0 on i686-w64-mingw32, compiled by i686-w64-mingw32-gcc (GCC) 4.6.3, 32-bit" /* Define to 1 to allow profiling output to be saved separately for each process. */ /* #undef PROFILE_PID_DIR */ /* Define to the necessary symbol if this constant uses a non-standard name on your system. */ /* #undef PTHREAD_CREATE_JOINABLE */ /* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus, the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be less than your OS' limit on file size. This is often 2 GB or 4GB in a 32-bit operating system, unless you have large file support enabled. By default, we make the limit 1 GB to avoid any possible integer-overflow problems within the OS. A limit smaller than necessary only means we divide a large relation into more chunks than necessary, so it seems best to err in the direction of a small limit. A power-of-2 value is recommended to save a few cycles in md.c, but is not absolutely required. Changing RELSEG_SIZE requires an initdb. */ #define RELSEG_SIZE 131072 /* The size of `long', as computed by sizeof. */ #define SIZEOF_LONG 4 /* The size of `off_t', as computed by sizeof. */ #define SIZEOF_OFF_T 4 /* The size of `size_t', as computed by sizeof. */ #define SIZEOF_SIZE_T 4 /* The size of `void *', as computed by sizeof. */ #define SIZEOF_VOID_P 4 /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define to 1 if strerror_r() returns a int. */ /* #undef STRERROR_R_INT */ /* Define to 1 if your declares `struct tm'. */ /* #undef TM_IN_SYS_TIME */ /* Define to the appropriate snprintf format for unsigned 64-bit ints. */ #define UINT64_FORMAT "%llu" /* Define to 1 to build with assertion checks. (--enable-cassert) */ /* #undef USE_ASSERT_CHECKING */ /* Define to 1 to build with Bonjour support. (--with-bonjour) */ /* #undef USE_BONJOUR */ /* Define to 1 if you want float4 values to be passed by value. (--enable-float4-byval) */ #define USE_FLOAT4_BYVAL 1 /* Define to 1 if you want float8, int8, etc values to be passed by value. (--enable-float8-byval) */ /* #undef USE_FLOAT8_BYVAL */ /* Define to 1 if you want 64-bit integer timestamp and interval support. (--enable-integer-datetimes) */ #define USE_INTEGER_DATETIMES 1 /* Define to 1 to build with LDAP support. (--with-ldap) */ /* #undef USE_LDAP */ /* Define to 1 to build with XML support. (--with-libxml) */ /* #undef USE_LIBXML */ /* Define to 1 to use XSLT support when building contrib/xml2. (--with-libxslt) */ /* #undef USE_LIBXSLT */ /* Define to select named POSIX semaphores. */ /* #undef USE_NAMED_POSIX_SEMAPHORES */ /* Define to 1 to build with PAM support. (--with-pam) */ /* #undef USE_PAM */ /* Use replacement snprintf() functions. */ #define USE_REPL_SNPRINTF 1 /* Define to build with (Open)SSL support. (--with-openssl) */ /* #undef USE_SSL */ /* Define to select SysV-style semaphores. */ /* #undef USE_SYSV_SEMAPHORES */ /* Define to select SysV-style shared memory. */ /* #undef USE_SYSV_SHARED_MEMORY */ /* Define to select unnamed POSIX semaphores. */ /* #undef USE_UNNAMED_POSIX_SEMAPHORES */ /* Define to select Win32-style semaphores. */ #define USE_WIN32_SEMAPHORES 1 /* Define to select Win32-style shared memory. */ #define USE_WIN32_SHARED_MEMORY 1 /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN /* # undef WORDS_BIGENDIAN */ # endif #endif /* Size of a WAL file block. This need have no particular relation to BLCKSZ. XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O, XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb. */ #define XLOG_BLCKSZ 8192 /* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2 and larger than XLOG_BLCKSZ (preferably, a great deal larger than XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */ #define XLOG_SEG_SIZE (16 * 1024 * 1024) /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ /* #undef _LARGEFILE_SOURCE */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to the type of a signed integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ /* #undef intptr_t */ /* Define to empty if the C compiler does not understand signed types. */ /* #undef signed */ /* Define to the type of an unsigned integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ /* #undef uintptr_t */ OrthancPostgreSQL-2.0/Resources/Platforms/pg_config_ext.h0000644000000000000000000000040112627602430021725 0ustar 00000000000000/* * src/include/pg_config_ext.h.in. This is generated manually, not by * autoheader, since we want to limit which symbols get defined here. */ /* Define to the name of a signed 64-bit integer type. */ #include #define PG_INT64_TYPE int64_t OrthancPostgreSQL-2.0/Resources/SyncOrthancFolder.py0000755000000000000000000000365412627602430020753 0ustar 00000000000000#!/usr/bin/python # # This maintenance script updates the content of the "Orthanc" folder # to match the latest version of the Orthanc source code. # import multiprocessing import os import stat import urllib2 TARGET = os.path.join(os.path.dirname(__file__), '..', 'Orthanc') PLUGIN_SDK_VERSION = '0.9.5' REPOSITORY = 'https://bitbucket.org/sjodogne/orthanc/raw' FILES = [ 'Plugins/Samples/Common/ExportedSymbols.list', 'Plugins/Samples/Common/VersionScript.map', 'Resources/CMake/AutoGeneratedCode.cmake', 'Resources/CMake/BoostConfiguration.cmake', 'Resources/CMake/Compiler.cmake', 'Resources/CMake/DownloadPackage.cmake', 'Resources/CMake/GoogleTestConfiguration.cmake', 'Resources/CMake/JsonCppConfiguration.cmake', 'Resources/EmbedResources.py', 'Resources/MinGW-W64-Toolchain32.cmake', 'Resources/MinGW-W64-Toolchain64.cmake', 'Resources/MinGWToolchain.cmake', 'Resources/ThirdParty/VisualStudio/stdint.h', 'Resources/WindowsResources.py', 'Resources/WindowsResources.rc', ] SDK = [ 'orthanc/OrthancCPlugin.h', 'orthanc/OrthancCDatabasePlugin.h', 'orthanc/OrthancCppDatabasePlugin.h', ] EXE = [ ] def Download(x): branch = x[0] source = x[1] target = os.path.join(TARGET, x[2]) print target try: os.makedirs(os.path.dirname(target)) except: pass url = '%s/%s/%s' % (REPOSITORY, branch, source) with open(target, 'w') as f: f.write(urllib2.urlopen(url).read()) commands = [] for f in FILES: commands.append([ 'default', f, f ]) for f in SDK: commands.append([ 'Orthanc-%s' % PLUGIN_SDK_VERSION, 'Plugins/Include/%s' % f, 'Sdk-%s/%s' % (PLUGIN_SDK_VERSION, f) ]) pool = multiprocessing.Pool(10) # simultaneous downloads pool.map(Download, commands) for exe in EXE: path = os.path.join(TARGET, exe) st = os.stat(path) os.chmod(path, st.st_mode | stat.S_IEXEC) OrthancPostgreSQL-2.0/StoragePlugin/Plugin.cpp0000644000000000000000000001262112627602430017554 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include #include "PostgreSQLStorageArea.h" #include "../Core/PostgreSQLException.h" #include "../Core/Configuration.h" static OrthancPluginContext* context_ = NULL; static OrthancPlugins::PostgreSQLStorageArea* storage_ = NULL; #if (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER <= 0 && ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER <= 9 && ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER <= 4) # define RETURN_TYPE int32_t # define RETURN_SUCCESS 0 # define RETURN_FAILURE -1 #else # define RETURN_TYPE OrthancPluginErrorCode # define RETURN_SUCCESS OrthancPluginErrorCode_Success # define RETURN_FAILURE OrthancPluginErrorCode_Plugin #endif static RETURN_TYPE StorageCreate(const char* uuid, const void* content, int64_t size, OrthancPluginContentType type) { try { storage_->Create(uuid, content, static_cast(size), type); return RETURN_SUCCESS; } catch (std::runtime_error& e) { OrthancPluginLogError(context_, e.what()); return RETURN_FAILURE; } } static RETURN_TYPE StorageRead(void** content, int64_t* size, const char* uuid, OrthancPluginContentType type) { try { size_t tmp; storage_->Read(*content, tmp, uuid, type); *size = static_cast(tmp); return RETURN_SUCCESS; } catch (std::runtime_error& e) { OrthancPluginLogError(context_, e.what()); return RETURN_FAILURE; } } static RETURN_TYPE StorageRemove(const char* uuid, OrthancPluginContentType type) { try { storage_->Remove(uuid, type); return RETURN_SUCCESS; } catch (std::runtime_error& e) { OrthancPluginLogError(context_, e.what()); return RETURN_FAILURE; } } extern "C" { ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) { context_ = context; /* Check the version of the Orthanc core */ if (OrthancPluginCheckVersion(context_) == 0) { char info[1024]; sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", context_->orthancVersion, ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); OrthancPluginLogError(context_, info); return -1; } OrthancPluginSetDescription(context_, "Stores the files received by Orthanc into a PostgreSQL database."); Json::Value configuration; if (!OrthancPlugins::ReadConfiguration(configuration, context)) { OrthancPluginLogError(context_, "Unable to read the configuration file"); return -1; } if (!configuration.isMember("PostgreSQL") || configuration["PostgreSQL"].type() != Json::objectValue || !OrthancPlugins::GetBooleanValue(configuration["PostgreSQL"], "EnableStorage", false)) { OrthancPluginLogWarning(context_, "The PostgreSQL storage area is currently disabled, set \"EnableStorage\" to \"true\" in the \"PostgreSQL\" section of the configuration file of Orthanc"); return 0; } else { OrthancPluginLogWarning(context_, "Using PostgreSQL storage area"); } bool allowUnlock = OrthancPlugins::IsFlagInCommandLineArguments(context_, FLAG_UNLOCK); try { /* Create the connection to PostgreSQL */ bool useLock; std::auto_ptr pg(OrthancPlugins::CreateConnection(useLock, context_, configuration)); pg->Open(); //pg->ClearAll(); // Reset the database /* Create the storage area back-end */ storage_ = new OrthancPlugins::PostgreSQLStorageArea(pg.release(), useLock, allowUnlock); /* Register the storage area into Orthanc */ OrthancPluginRegisterStorageArea(context_, StorageCreate, StorageRead, StorageRemove); } catch (std::runtime_error& e) { OrthancPluginLogError(context_, e.what()); return -1; } return 0; } ORTHANC_PLUGINS_API void OrthancPluginFinalize() { OrthancPluginLogWarning(context_, "Storage plugin is finalizing"); if (storage_ != NULL) { delete storage_; storage_ = NULL; } } ORTHANC_PLUGINS_API const char* OrthancPluginGetName() { return "postgresql-storage"; } ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() { return ORTHANC_POSTGRESQL_VERSION; } } OrthancPostgreSQL-2.0/StoragePlugin/PostgreSQLStorageArea.cpp0000644000000000000000000001134712627602430022443 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include "PostgreSQLStorageArea.h" #include "../Core/PostgreSQLTransaction.h" #include "../Core/PostgreSQLResult.h" #include "../Core/PostgreSQLException.h" #include "../Core/Configuration.h" namespace OrthancPlugins { PostgreSQLStorageArea::PostgreSQLStorageArea(PostgreSQLConnection* db, bool useLock, bool allowUnlock) : db_(db), globalProperties_(*db, useLock, GlobalProperty_StorageLock) { globalProperties_.Lock(allowUnlock); Prepare(); } void PostgreSQLStorageArea::Prepare() { PostgreSQLTransaction transaction(*db_); db_->Execute("CREATE TABLE IF NOT EXISTS StorageArea(" "uuid VARCHAR NOT NULL PRIMARY KEY," "content OID NOT NULL," "type INTEGER NOT NULL)"); // Automatically remove the large objects associated with the table db_->Execute("CREATE OR REPLACE RULE StorageAreaDelete AS ON DELETE TO StorageArea DO SELECT lo_unlink(old.content);"); create_.reset(new PostgreSQLStatement(*db_, "INSERT INTO StorageArea VALUES ($1,$2,$3)")); create_->DeclareInputString(0); create_->DeclareInputLargeObject(1); create_->DeclareInputInteger(2); read_.reset(new PostgreSQLStatement(*db_, "SELECT content FROM StorageArea WHERE uuid=$1 AND type=$2")); read_->DeclareInputString(0); read_->DeclareInputInteger(1); remove_.reset(new PostgreSQLStatement(*db_, "DELETE FROM StorageArea WHERE uuid=$1 AND type=$2")); remove_->DeclareInputString(0); remove_->DeclareInputInteger(1); transaction.Commit(); } PostgreSQLStorageArea::~PostgreSQLStorageArea() { globalProperties_.Unlock(); } void PostgreSQLStorageArea::Create(const std::string& uuid, const void* content, size_t size, OrthancPluginContentType type) { boost::mutex::scoped_lock lock(mutex_); PostgreSQLTransaction transaction(*db_); PostgreSQLLargeObject obj(*db_, content, size); create_->BindString(0, uuid); create_->BindLargeObject(1, obj); create_->BindInteger(2, static_cast(type)); create_->Run(); transaction.Commit(); } void PostgreSQLStorageArea::Read(void*& content, size_t& size, const std::string& uuid, OrthancPluginContentType type) { boost::mutex::scoped_lock lock(mutex_); PostgreSQLTransaction transaction(*db_); read_->BindString(0, uuid); read_->BindInteger(1, static_cast(type)); PostgreSQLResult result(*read_); if (result.IsDone()) { throw PostgreSQLException(); } result.GetLargeObject(content, size, 0); transaction.Commit(); } void PostgreSQLStorageArea::Read(std::string& content, const std::string& uuid, OrthancPluginContentType type) { void* tmp = NULL; size_t size; Read(tmp, size, uuid, type); try { content.resize(size); } catch (std::bad_alloc&) { free(tmp); throw; } if (size != 0) { assert(tmp != NULL); memcpy(&content[0], tmp, size); } free(tmp); } void PostgreSQLStorageArea::Remove(const std::string& uuid, OrthancPluginContentType type) { boost::mutex::scoped_lock lock(mutex_); PostgreSQLTransaction transaction(*db_); remove_->BindString(0, uuid); remove_->BindInteger(1, static_cast(type)); remove_->Run(); transaction.Commit(); } void PostgreSQLStorageArea::Clear() { boost::mutex::scoped_lock lock(mutex_); PostgreSQLTransaction transaction(*db_); db_->Execute("DELETE FROM StorageArea"); transaction.Commit(); } } OrthancPostgreSQL-2.0/StoragePlugin/PostgreSQLStorageArea.h0000644000000000000000000000435312627602430022107 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #pragma once #include "../Core/GlobalProperties.h" #include "../Core/PostgreSQLConnection.h" #include "../Core/PostgreSQLStatement.h" #include #include #include namespace OrthancPlugins { class PostgreSQLStorageArea { private: std::auto_ptr db_; GlobalProperties globalProperties_; boost::mutex mutex_; std::auto_ptr create_; std::auto_ptr read_; std::auto_ptr remove_; void Prepare(); public: PostgreSQLStorageArea(PostgreSQLConnection* db, // Takes the ownership bool useLock, bool allowUnlock); ~PostgreSQLStorageArea(); void Create(const std::string& uuid, const void* content, size_t size, OrthancPluginContentType type); void Read(std::string& content, const std::string& uuid, OrthancPluginContentType type); void Read(void*& content, size_t& size, const std::string& uuid, OrthancPluginContentType type); void Remove(const std::string& uuid, OrthancPluginContentType type); void Clear(); // For unit tests only (not thread-safe)! PostgreSQLConnection& GetConnection() { return *db_; } }; } OrthancPostgreSQL-2.0/UnitTestsSources/PostgreSQLTests.cpp0000644000000000000000000002130112627602430022062 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include #include #include "../Core/PostgreSQLTransaction.h" #include "../Core/PostgreSQLResult.h" #include "../Core/PostgreSQLLargeObject.h" #include "../Core/PostgreSQLException.h" #include "../StoragePlugin/PostgreSQLStorageArea.h" using namespace OrthancPlugins; extern PostgreSQLConnection* CreateTestConnection(bool clearAll); static int64_t CountLargeObjects(PostgreSQLConnection& db) { // Count the number of large objects in the DB PostgreSQLTransaction t(db); PostgreSQLStatement s(db, "SELECT COUNT(*) FROM pg_catalog.pg_largeobject"); PostgreSQLResult r(s); return r.GetInteger64(0); } TEST(PostgreSQL, Basic) { std::auto_ptr pg(CreateTestConnection(true)); ASSERT_FALSE(pg->DoesTableExist("Test")); pg->Execute("CREATE TABLE Test(name INTEGER, value BIGINT)"); ASSERT_TRUE(pg->DoesTableExist("Test")); PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)"); s.DeclareInputInteger(0); s.DeclareInputInteger64(1); s.BindInteger(0, 43); s.BindNull(0); s.BindInteger(0, 42); s.BindInteger64(1, -4242); s.Run(); s.BindInteger(0, 43); s.BindNull(1); s.Run(); s.BindNull(0); s.BindInteger64(1, 4444); s.Run(); { PostgreSQLStatement t(*pg, "SELECT name, value FROM Test ORDER BY name"); PostgreSQLResult r(t); ASSERT_FALSE(r.IsDone()); ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(42, r.GetInteger(0)); ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ(-4242, r.GetInteger64(1)); r.Step(); ASSERT_FALSE(r.IsDone()); ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(43, r.GetInteger(0)); ASSERT_TRUE(r.IsNull(1)); r.Step(); ASSERT_FALSE(r.IsDone()); ASSERT_TRUE(r.IsNull(0)); ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ(4444, r.GetInteger64(1)); r.Step(); ASSERT_TRUE(r.IsDone()); } { PostgreSQLStatement t(*pg, "SELECT name, value FROM Test WHERE name=$1"); t.DeclareInputInteger(0); { t.BindInteger(0, 42); PostgreSQLResult r(t); ASSERT_FALSE(r.IsDone()); ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(42, r.GetInteger(0)); ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ(-4242, r.GetInteger64(1)); r.Step(); ASSERT_TRUE(r.IsDone()); } { t.BindInteger(0, 40); PostgreSQLResult r(t); ASSERT_TRUE(r.IsDone()); } } } TEST(PostgreSQL, String) { std::auto_ptr pg(CreateTestConnection(true)); pg->Execute("CREATE TABLE Test(name INTEGER, value VARCHAR(40))"); PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)"); s.DeclareInputInteger(0); s.DeclareInputString(1); s.BindInteger(0, 42); s.BindString(1, "Hello"); s.Run(); s.BindInteger(0, 43); s.BindNull(1); s.Run(); s.BindNull(0); s.BindString(1, ""); s.Run(); { PostgreSQLStatement t(*pg, "SELECT name, value FROM Test ORDER BY name"); PostgreSQLResult r(t); ASSERT_FALSE(r.IsDone()); ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(42, r.GetInteger(0)); ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ("Hello", r.GetString(1)); r.Step(); ASSERT_FALSE(r.IsDone()); ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(43, r.GetInteger(0)); ASSERT_TRUE(r.IsNull(1)); r.Step(); ASSERT_FALSE(r.IsDone()); ASSERT_TRUE(r.IsNull(0)); ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ("", r.GetString(1)); r.Step(); ASSERT_TRUE(r.IsDone()); } } TEST(PostgreSQL, Transaction) { std::auto_ptr pg(CreateTestConnection(true)); pg->Execute("CREATE TABLE Test(name INTEGER, value INTEGER)"); { PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)"); s.DeclareInputInteger(0); s.DeclareInputInteger(1); s.BindInteger(0, 42); s.BindInteger(1, 4242); s.Run(); { PostgreSQLTransaction t(*pg); s.BindInteger(0, 43); s.BindInteger(1, 4343); s.Run(); s.BindInteger(0, 44); s.BindInteger(1, 4444); s.Run(); PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test"); PostgreSQLResult r(u); ASSERT_EQ(3, r.GetInteger64(0)); // No commit } { PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test"); PostgreSQLResult r(u); ASSERT_EQ(1, r.GetInteger64(0)); // Just "1" because of implicit rollback } { PostgreSQLTransaction t(*pg); s.BindInteger(0, 43); s.BindInteger(1, 4343); s.Run(); s.BindInteger(0, 44); s.BindInteger(1, 4444); s.Run(); { PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test"); PostgreSQLResult r(u); ASSERT_EQ(3, r.GetInteger64(0)); t.Commit(); ASSERT_THROW(t.Rollback(), PostgreSQLException); ASSERT_THROW(t.Commit(), PostgreSQLException); } } { PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test"); PostgreSQLResult r(u); ASSERT_EQ(3, r.GetInteger64(0)); } } } TEST(PostgreSQL, LargeObject) { std::auto_ptr pg(CreateTestConnection(true)); ASSERT_EQ(0, CountLargeObjects(*pg)); pg->Execute("CREATE TABLE Test(name VARCHAR, value OID)"); // Automatically remove the large objects associated with the table pg->Execute("CREATE RULE TestDelete AS ON DELETE TO Test DO SELECT lo_unlink(old.value);"); { PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)"); s.DeclareInputString(0); s.DeclareInputLargeObject(1); for (int i = 0; i < 10; i++) { PostgreSQLTransaction t(*pg); std::string value = "Value " + boost::lexical_cast(i * 2); PostgreSQLLargeObject obj(*pg, value); s.BindString(0, "Index " + boost::lexical_cast(i)); s.BindLargeObject(1, obj); s.Run(); std::string tmp; PostgreSQLLargeObject::Read(tmp, *pg, obj.GetOid()); ASSERT_EQ(value, tmp); t.Commit(); } } ASSERT_EQ(10, CountLargeObjects(*pg)); { PostgreSQLTransaction t(*pg); PostgreSQLStatement s(*pg, "SELECT * FROM Test ORDER BY name DESC"); PostgreSQLResult r(s); ASSERT_FALSE(r.IsDone()); ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ("Index 9", r.GetString(0)); std::string data; r.GetLargeObject(data, 1); ASSERT_EQ("Value 18", data); r.Step(); ASSERT_FALSE(r.IsDone()); //ASSERT_TRUE(r.IsString(0)); } { PostgreSQLTransaction t(*pg); PostgreSQLStatement s(*pg, "DELETE FROM Test WHERE name='Index 9'"); s.Run(); t.Commit(); } { // Count the number of items in the DB PostgreSQLTransaction t(*pg); PostgreSQLStatement s(*pg, "SELECT COUNT(*) FROM Test"); PostgreSQLResult r(s); ASSERT_EQ(9, r.GetInteger64(0)); } ASSERT_EQ(9, CountLargeObjects(*pg)); } TEST(PostgreSQL, StorageArea) { std::auto_ptr pg(CreateTestConnection(true)); PostgreSQLStorageArea s(pg.release(), true, true); ASSERT_EQ(0, CountLargeObjects(s.GetConnection())); for (int i = 0; i < 10; i++) { std::string uuid = boost::lexical_cast(i); std::string value = "Value " + boost::lexical_cast(i * 2); s.Create(uuid, value.c_str(), value.size(), OrthancPluginContentType_Unknown); } std::string tmp; ASSERT_THROW(s.Read(tmp, "nope", OrthancPluginContentType_Unknown), PostgreSQLException); ASSERT_EQ(10, CountLargeObjects(s.GetConnection())); s.Remove("5", OrthancPluginContentType_Unknown); ASSERT_EQ(9, CountLargeObjects(s.GetConnection())); for (int i = 0; i < 10; i++) { std::string uuid = boost::lexical_cast(i); std::string expected = "Value " + boost::lexical_cast(i * 2); std::string content; if (i == 5) { ASSERT_THROW(s.Read(content, uuid, OrthancPluginContentType_Unknown), PostgreSQLException); } else { s.Read(content, uuid, OrthancPluginContentType_Unknown); ASSERT_EQ(expected, content); } } s.Clear(); ASSERT_EQ(0, CountLargeObjects(s.GetConnection())); } OrthancPostgreSQL-2.0/UnitTestsSources/PostgreSQLWrapperTests.cpp0000644000000000000000000003715012627602430023434 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include "EmbeddedResources.h" #include #include "../Core/PostgreSQLTransaction.h" #include "../Core/PostgreSQLResult.h" #include "../IndexPlugin/PostgreSQLWrapper.h" using namespace OrthancPlugins; extern PostgreSQLConnection* CreateTestConnection(bool clearAll); // From Orthanc enumerations static const int32_t GlobalProperty_DatabaseSchemaVersion = 1; static const int32_t GlobalProperty_AnonymizationSequence = 3; static const int32_t MetadataType_ModifiedFrom = 5; static const int32_t MetadataType_LastUpdate = 7; static const int32_t FileContentType_Dicom = 1; static const int32_t FileContentType_DicomAsJson = 2; static const int32_t CompressionType_None = 1; static const int32_t CompressionType_Zlib = 2; static std::auto_ptr expectedAttachment; static std::list expectedDicomTags; static std::auto_ptr expectedExported; static void CheckAttachment(const OrthancPluginAttachment& attachment) { ASSERT_STREQ(expectedAttachment->uuid, attachment.uuid); ASSERT_EQ(expectedAttachment->contentType, attachment.contentType); ASSERT_EQ(expectedAttachment->uncompressedSize, attachment.uncompressedSize); ASSERT_STREQ(expectedAttachment->uncompressedHash, attachment.uncompressedHash); ASSERT_EQ(expectedAttachment->compressionType, attachment.compressionType); ASSERT_EQ(expectedAttachment->compressedSize, attachment.compressedSize); ASSERT_STREQ(expectedAttachment->compressedHash, attachment.compressedHash); } static void CheckExportedResource(const OrthancPluginExportedResource& exported) { ASSERT_EQ(expectedExported->seq, exported.seq); ASSERT_EQ(expectedExported->resourceType, exported.resourceType); ASSERT_STREQ(expectedExported->publicId, exported.publicId); ASSERT_STREQ(expectedExported->modality, exported.modality); ASSERT_STREQ(expectedExported->date, exported.date); ASSERT_STREQ(expectedExported->patientId, exported.patientId); ASSERT_STREQ(expectedExported->studyInstanceUid, exported.studyInstanceUid); ASSERT_STREQ(expectedExported->seriesInstanceUid, exported.seriesInstanceUid); ASSERT_STREQ(expectedExported->sopInstanceUid, exported.sopInstanceUid); } static void CheckDicomTag(const OrthancPluginDicomTag& tag) { for (std::list::const_iterator it = expectedDicomTags.begin(); it != expectedDicomTags.end(); it++) { if (it->group == tag.group && it->element == tag.element && !strcmp(it->value, tag.value)) { // OK, match return; } } ASSERT_TRUE(0); // Error } #if (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER <= 0 && ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER <= 9 && ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER <= 3) # define INVOKE_RETURN_TYPE int32_t # define INVOKE_RETURN_VALUE 0 #else # define INVOKE_RETURN_TYPE OrthancPluginErrorCode # define INVOKE_RETURN_VALUE OrthancPluginErrorCode_Success #endif static INVOKE_RETURN_TYPE InvokeService(struct _OrthancPluginContext_t* context, _OrthancPluginService service, const void* params) { if (service == _OrthancPluginService_DatabaseAnswer) { const _OrthancPluginDatabaseAnswer& answer = *reinterpret_cast(params); switch (answer.type) { case _OrthancPluginDatabaseAnswerType_Attachment: { const OrthancPluginAttachment& attachment = *reinterpret_cast(answer.valueGeneric); CheckAttachment(attachment); break; } case _OrthancPluginDatabaseAnswerType_ExportedResource: { const OrthancPluginExportedResource& attachment = *reinterpret_cast(answer.valueGeneric); CheckExportedResource(attachment); break; } case _OrthancPluginDatabaseAnswerType_DicomTag: { const OrthancPluginDicomTag& tag = *reinterpret_cast(answer.valueGeneric); CheckDicomTag(tag); break; } default: printf("Unhandled message: %d\n", answer.type); break; } } return INVOKE_RETURN_VALUE; } TEST(PostgreSQLWrapper, Basic) { std::auto_ptr pg(CreateTestConnection(true)); OrthancPluginContext context; context.pluginsManager = NULL; context.orthancVersion = "mainline"; context.Free = ::free; context.InvokeService = InvokeService; PostgreSQLWrapper db(NULL, pg.release(), true, true); db.RegisterOutput(new DatabaseBackendOutput(&context, NULL)); std::string s; ASSERT_TRUE(db.LookupGlobalProperty(s, GlobalProperty_DatabaseSchemaVersion)); ASSERT_EQ("6", s); ASSERT_FALSE(db.LookupGlobalProperty(s, GlobalProperty_AnonymizationSequence)); db.SetGlobalProperty(GlobalProperty_AnonymizationSequence, "Hello"); ASSERT_TRUE(db.LookupGlobalProperty(s, GlobalProperty_AnonymizationSequence)); ASSERT_EQ("Hello", s); db.SetGlobalProperty(GlobalProperty_AnonymizationSequence, "HelloWorld"); ASSERT_TRUE(db.LookupGlobalProperty(s, GlobalProperty_AnonymizationSequence)); ASSERT_EQ("HelloWorld", s); int64_t a = db.CreateResource("study", OrthancPluginResourceType_Study); ASSERT_TRUE(db.IsExistingResource(a)); ASSERT_FALSE(db.IsExistingResource(a + 1)); int64_t b; OrthancPluginResourceType t; ASSERT_FALSE(db.LookupResource(b, t, "world")); ASSERT_TRUE(db.LookupResource(b, t, "study")); ASSERT_EQ(a, b); ASSERT_EQ(OrthancPluginResourceType_Study, t); b = db.CreateResource("series", OrthancPluginResourceType_Series); ASSERT_NE(a, b); ASSERT_EQ("study", db.GetPublicId(a)); ASSERT_EQ("series", db.GetPublicId(b)); ASSERT_EQ(OrthancPluginResourceType_Study, db.GetResourceType(a)); ASSERT_EQ(OrthancPluginResourceType_Series, db.GetResourceType(b)); db.AttachChild(a, b); int64_t c; ASSERT_FALSE(db.LookupParent(c, a)); ASSERT_TRUE(db.LookupParent(c, b)); ASSERT_EQ(a, c); c = db.CreateResource("series2", OrthancPluginResourceType_Series); db.AttachChild(a, c); ASSERT_EQ(3, db.GetTableRecordCount("Resources")); ASSERT_EQ(0u, db.GetResourceCount(OrthancPluginResourceType_Patient)); ASSERT_EQ(1u, db.GetResourceCount(OrthancPluginResourceType_Study)); ASSERT_EQ(2u, db.GetResourceCount(OrthancPluginResourceType_Series)); ASSERT_FALSE(db.GetParentPublicId(s, a)); ASSERT_TRUE(db.GetParentPublicId(s, b)); ASSERT_EQ("study", s); ASSERT_TRUE(db.GetParentPublicId(s, c)); ASSERT_EQ("study", s); std::list children; db.GetChildren(children, a); ASSERT_EQ(2u, children.size()); db.GetChildren(children, b); ASSERT_EQ(0u, children.size()); db.GetChildren(children, c); ASSERT_EQ(0u, children.size()); std::list cp; db.GetChildrenPublicId(cp, a); ASSERT_EQ(2u, cp.size()); ASSERT_TRUE(cp.front() == "series" || cp.front() == "series2"); ASSERT_TRUE(cp.back() == "series" || cp.back() == "series2"); ASSERT_NE(cp.front(), cp.back()); std::list pub; db.GetAllPublicIds(pub, OrthancPluginResourceType_Patient); ASSERT_EQ(0u, pub.size()); db.GetAllPublicIds(pub, OrthancPluginResourceType_Study); ASSERT_EQ(1u, pub.size()); ASSERT_EQ("study", pub.front()); db.GetAllPublicIds(pub, OrthancPluginResourceType_Series); ASSERT_EQ(2u, pub.size()); ASSERT_TRUE(pub.front() == "series" || pub.front() == "series2"); ASSERT_TRUE(pub.back() == "series" || pub.back() == "series2"); ASSERT_NE(pub.front(), pub.back()); std::list ci; db.GetChildrenInternalId(ci, a); ASSERT_EQ(2u, ci.size()); ASSERT_TRUE(ci.front() == b || ci.front() == c); ASSERT_TRUE(ci.back() == b || ci.back() == c); ASSERT_NE(ci.front(), ci.back()); db.SetMetadata(a, MetadataType_ModifiedFrom, "modified"); db.SetMetadata(a, MetadataType_LastUpdate, "update2"); ASSERT_FALSE(db.LookupMetadata(s, b, MetadataType_LastUpdate)); ASSERT_TRUE(db.LookupMetadata(s, a, MetadataType_LastUpdate)); ASSERT_EQ("update2", s); db.SetMetadata(a, MetadataType_LastUpdate, "update"); ASSERT_TRUE(db.LookupMetadata(s, a, MetadataType_LastUpdate)); ASSERT_EQ("update", s); std::list md; db.ListAvailableMetadata(md, a); ASSERT_EQ(2u, md.size()); ASSERT_TRUE(md.front() == MetadataType_ModifiedFrom || md.back() == MetadataType_ModifiedFrom); ASSERT_TRUE(md.front() == MetadataType_LastUpdate || md.back() == MetadataType_LastUpdate); std::string mdd; ASSERT_TRUE(db.LookupMetadata(mdd, a, MetadataType_ModifiedFrom)); ASSERT_EQ("modified", mdd); ASSERT_TRUE(db.LookupMetadata(mdd, a, MetadataType_LastUpdate)); ASSERT_EQ("update", mdd); db.ListAvailableMetadata(md, b); ASSERT_EQ(0u, md.size()); db.DeleteMetadata(a, MetadataType_LastUpdate); db.DeleteMetadata(b, MetadataType_LastUpdate); ASSERT_FALSE(db.LookupMetadata(s, a, MetadataType_LastUpdate)); db.ListAvailableMetadata(md, a); ASSERT_EQ(1u, md.size()); ASSERT_EQ(MetadataType_ModifiedFrom, md.front()); ASSERT_EQ(0u, db.GetTotalCompressedSize()); ASSERT_EQ(0u, db.GetTotalUncompressedSize()); std::list fc; OrthancPluginAttachment a1; a1.uuid = "uuid1"; a1.contentType = FileContentType_Dicom; a1.uncompressedSize = 42; a1.uncompressedHash = "md5_1"; a1.compressionType = CompressionType_None; a1.compressedSize = 42; a1.compressedHash = "md5_1"; OrthancPluginAttachment a2; a2.uuid = "uuid2"; a2.contentType = FileContentType_DicomAsJson; a2.uncompressedSize = 4242; a2.uncompressedHash = "md5_2"; a2.compressionType = CompressionType_None; a2.compressedSize = 4242; a2.compressedHash = "md5_2"; db.AddAttachment(a, a1); db.ListAvailableAttachments(fc, a); ASSERT_EQ(1u, fc.size()); ASSERT_EQ(FileContentType_Dicom, fc.front()); db.AddAttachment(a, a2); db.ListAvailableAttachments(fc, a); ASSERT_EQ(2u, fc.size()); ASSERT_FALSE(db.LookupAttachment(b, FileContentType_Dicom)); ASSERT_EQ(4284u, db.GetTotalCompressedSize()); ASSERT_EQ(4284u, db.GetTotalUncompressedSize()); expectedAttachment.reset(new OrthancPluginAttachment); expectedAttachment->uuid = "uuid1"; expectedAttachment->contentType = FileContentType_Dicom; expectedAttachment->uncompressedSize = 42; expectedAttachment->uncompressedHash = "md5_1"; expectedAttachment->compressionType = CompressionType_None; expectedAttachment->compressedSize = 42; expectedAttachment->compressedHash = "md5_1"; ASSERT_TRUE(db.LookupAttachment(a, FileContentType_Dicom)); expectedAttachment.reset(new OrthancPluginAttachment); expectedAttachment->uuid = "uuid2"; expectedAttachment->contentType = FileContentType_DicomAsJson; expectedAttachment->uncompressedSize = 4242; expectedAttachment->uncompressedHash = "md5_2"; expectedAttachment->compressionType = CompressionType_None; expectedAttachment->compressedSize = 4242; expectedAttachment->compressedHash = "md5_2"; ASSERT_TRUE(db.LookupAttachment(a, FileContentType_DicomAsJson)); db.ListAvailableAttachments(fc, b); ASSERT_EQ(0u, fc.size()); db.DeleteAttachment(a, FileContentType_Dicom); db.ListAvailableAttachments(fc, a); ASSERT_EQ(1u, fc.size()); ASSERT_EQ(FileContentType_DicomAsJson, fc.front()); db.DeleteAttachment(a, FileContentType_DicomAsJson); db.ListAvailableAttachments(fc, a); ASSERT_EQ(0u, fc.size()); db.SetIdentifierTag(a, 0x0010, 0x0020, "patient"); db.SetIdentifierTag(a, 0x0020, 0x000d, "study"); expectedDicomTags.clear(); expectedDicomTags.push_back(OrthancPluginDicomTag()); expectedDicomTags.push_back(OrthancPluginDicomTag()); expectedDicomTags.front().group = 0x0010; expectedDicomTags.front().element = 0x0020; expectedDicomTags.front().value = "patient"; expectedDicomTags.back().group = 0x0020; expectedDicomTags.back().element = 0x000d; expectedDicomTags.back().value = "study"; db.GetMainDicomTags(a); db.LookupIdentifier(ci, 0x0010, 0x0020, "patient"); ASSERT_EQ(1u, ci.size()); ASSERT_EQ(a, ci.front()); db.LookupIdentifier(ci, 0x0010, 0x0020, "study"); ASSERT_EQ(0u, ci.size()); db.LookupIdentifier(ci, "study"); ASSERT_EQ(1u, ci.size()); ASSERT_EQ(a, ci.front()); OrthancPluginExportedResource exp; exp.seq = -1; exp.resourceType = OrthancPluginResourceType_Study; exp.publicId = "id"; exp.modality = "remote"; exp.date = "date"; exp.patientId = "patient"; exp.studyInstanceUid = "study"; exp.seriesInstanceUid = "series"; exp.sopInstanceUid = "instance"; db.LogExportedResource(exp); expectedExported.reset(new OrthancPluginExportedResource()); *expectedExported = exp; expectedExported->seq = 1; bool done; db.GetExportedResources(done, 0, 10); db.GetAllPublicIds(pub, OrthancPluginResourceType_Patient); ASSERT_EQ(0u, pub.size()); db.GetAllPublicIds(pub, OrthancPluginResourceType_Study); ASSERT_EQ(1u, pub.size()); db.GetAllPublicIds(pub, OrthancPluginResourceType_Series); ASSERT_EQ(2u, pub.size()); db.GetAllPublicIds(pub, OrthancPluginResourceType_Instance); ASSERT_EQ(0u, pub.size()); ASSERT_EQ(3, db.GetTableRecordCount("Resources")); ASSERT_EQ(0, db.GetTableRecordCount("PatientRecyclingOrder")); // No patient was inserted ASSERT_TRUE(db.IsExistingResource(c)); db.DeleteResource(c); ASSERT_FALSE(db.IsExistingResource(c)); ASSERT_TRUE(db.IsExistingResource(a)); ASSERT_TRUE(db.IsExistingResource(b)); ASSERT_EQ(2, db.GetTableRecordCount("Resources")); db.DeleteResource(a); ASSERT_EQ(0, db.GetTableRecordCount("Resources")); ASSERT_FALSE(db.IsExistingResource(a)); ASSERT_FALSE(db.IsExistingResource(b)); ASSERT_FALSE(db.IsExistingResource(c)); ASSERT_EQ(0, db.GetTableRecordCount("Resources")); ASSERT_EQ(0, db.GetTableRecordCount("PatientRecyclingOrder")); int64_t p1 = db.CreateResource("patient1", OrthancPluginResourceType_Patient); int64_t p2 = db.CreateResource("patient2", OrthancPluginResourceType_Patient); int64_t p3 = db.CreateResource("patient3", OrthancPluginResourceType_Patient); ASSERT_EQ(3, db.GetTableRecordCount("PatientRecyclingOrder")); int64_t r; ASSERT_TRUE(db.SelectPatientToRecycle(r)); ASSERT_EQ(p1, r); ASSERT_TRUE(db.SelectPatientToRecycle(r, p1)); ASSERT_EQ(p2, r); ASSERT_FALSE(db.IsProtectedPatient(p1)); db.SetProtectedPatient(p1, true); ASSERT_TRUE(db.IsProtectedPatient(p1)); ASSERT_TRUE(db.SelectPatientToRecycle(r)); ASSERT_EQ(p2, r); db.SetProtectedPatient(p1, false); ASSERT_FALSE(db.IsProtectedPatient(p1)); ASSERT_TRUE(db.SelectPatientToRecycle(r)); ASSERT_EQ(p2, r); db.DeleteResource(p2); ASSERT_TRUE(db.SelectPatientToRecycle(r, p3)); ASSERT_EQ(p1, r); } TEST(PostgreSQLWrapper, Lock) { PostgreSQLWrapper db1(NULL, CreateTestConnection(true), true, false); PostgreSQLWrapper db2(NULL, CreateTestConnection(false), false, false); ASSERT_THROW(OrthancPlugins::PostgreSQLWrapper db3(NULL, CreateTestConnection(false), true, false), std::runtime_error); } OrthancPostgreSQL-2.0/UnitTestsSources/UnitTestsMain.cpp0000644000000000000000000000354212627602430021612 0ustar 00000000000000/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * 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 . **/ #include "../Core/PostgreSQLConnection.h" #include #include #include static int argc_; static char** argv_; OrthancPlugins::PostgreSQLConnection* CreateTestConnection(bool clearAll) { std::auto_ptr pg(new OrthancPlugins::PostgreSQLConnection); pg->SetHost(argv_[1]); pg->SetPortNumber(boost::lexical_cast(argv_[2])); pg->SetUsername(argv_[3]); pg->SetPassword(argv_[4]); pg->SetDatabase(argv_[5]); pg->Open(); if (clearAll) { pg->ClearAll(); } return pg.release(); } int main(int argc, char **argv) { if (argc < 6) { std::cerr << "Usage: " << argv[0] << " " << std::endl << std::endl << "Example: " << argv[0] << " localhost 5432 postgres postgres orthanctest" << std::endl << std::endl; return -1; } argc_ = argc; argv_ = argv; ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }